]>
git.ipfire.org Git - thirdparty/newt.git/blob - snack.py
1 # snack.py: maps C extension module _snack to proper python types in module
3 # The first section is a very literal mapping.
4 # The second section contains convenience classes that amalgamate
5 # the literal classes and make them more object-oriented.
11 from _snack
import FLAG_DISABLED
, FLAGS_SET
, FLAGS_RESET
, FLAGS_TOGGLE
, FD_READ
, FD_WRITE
, FD_EXCEPT
19 snackArgs
= {"append":-1}
22 def setCallback(self
, obj
, data
= None):
24 self
.w
.setCallback(obj
, data
)
26 self
.w
.setCallback(obj
)
33 def __init__(self
, text
):
34 self
.w
= _snack
.button(text
)
36 class CompactButton(Widget
):
38 def __init__(self
, text
):
39 self
.w
= _snack
.compactbutton(text
)
41 class Checkbox(Widget
):
44 return self
.w
.checkboxValue
47 return self
.w
.checkboxValue
!= 0
49 def setFlags (self
, flag
, sense
):
50 return self
.w
.checkboxSetFlags(flag
, sense
)
52 def setValue (self
, value
):
53 return self
.w
.checkboxSetValue(value
)
55 def __init__(self
, text
, isOn
= 0):
56 self
.w
= _snack
.checkbox(text
, isOn
)
58 class SingleRadioButton(Widget
):
61 return self
.w
.key
== self
.w
.radioValue
;
63 def __init__(self
, text
, group
, isOn
= 0):
65 self
.w
= _snack
.radiobutton(text
, group
.w
, isOn
)
67 self
.w
= _snack
.radiobutton(text
, None, isOn
)
69 class Listbox(Widget
):
71 def append(self
, text
, item
):
72 key
= self
.w
.listboxAddItem(text
)
73 self
.key2item
[key
] = item
74 self
.item2key
[item
] = key
76 def insert(self
, text
, item
, before
):
78 key
= self
.w
.listboxInsertItem(text
, 0)
80 key
= self
.w
.listboxInsertItem(text
, self
.item2key
[before
])
81 self
.key2item
[key
] = item
82 self
.item2key
[item
] = key
84 def delete(self
, item
):
85 self
.w
.listboxDeleteItem(self
.item2key
[item
])
86 del self
.key2item
[self
.item2key
[item
]]
87 del self
.item2key
[item
]
89 def replace(self
, text
, item
):
90 key
= self
.w
.listboxInsertItem(text
, self
.item2key
[item
])
91 self
.w
.listboxDeleteItem(self
.item2key
[item
])
92 del self
.key2item
[self
.item2key
[item
]]
93 self
.item2key
[item
] = key
94 self
.key2item
[key
] = item
97 return self
.key2item
[self
.w
.listboxGetCurrent()]
99 def setCurrent(self
, item
):
100 self
.w
.listboxSetCurrent(self
.item2key
[item
])
105 self
.w
.listboxClear()
107 def __init__(self
, height
, scroll
= 0, returnExit
= 0, width
= 0, showCursor
= 0):
108 self
.w
= _snack
.listbox(height
, scroll
, returnExit
, showCursor
)
112 self
.w
.listboxSetWidth(width
)
114 class Textbox(Widget
):
116 def setText(self
, text
):
117 self
.w
.textboxText(text
)
119 def __init__(self
, width
, height
, text
, scroll
= 0, wrap
= 0):
120 self
.w
= _snack
.textbox(width
, height
, text
, scroll
, wrap
)
122 class TextboxReflowed(Textbox
):
124 def __init__(self
, width
, text
, flexDown
= 5, flexUp
= 10, maxHeight
= -1):
125 (newtext
, width
, height
) = reflow(text
, width
, flexDown
, flexUp
)
126 if maxHeight
!= -1 and height
> maxHeight
:
127 Textbox
.__init
__(self
, width
, maxHeight
, newtext
, 1)
129 Textbox
.__init
__(self
, width
, height
, newtext
, 0)
133 def setText(self
, text
):
134 self
.w
.labelText(text
)
136 def __init__(self
, text
):
137 self
.w
= _snack
.label(text
)
141 def set(self
, amount
):
142 self
.w
.scaleSet(amount
)
144 def __init__(self
, width
, total
):
145 self
.w
= _snack
.scale(width
, total
)
150 return self
.w
.entryValue
153 return self
.w
.entrySetValue(text
)
155 def setFlags (self
, flag
, sense
):
156 return self
.w
.entrySetFlags(flag
, sense
)
158 def __init__(self
, width
, text
= "", hidden
= 0, password
= 0, scroll
= 1,
160 self
.w
= _snack
.entry(width
, text
, hidden
, password
, scroll
, returnExit
)
164 hotkeys
= { "F1" : _snack
.KEY_F1
, "F2" : _snack
.KEY_F2
, "F3" : _snack
.KEY_F3
,
165 "F4" : _snack
.KEY_F4
, "F5" : _snack
.KEY_F5
, "F6" : _snack
.KEY_F6
,
166 "F7" : _snack
.KEY_F7
, "F8" : _snack
.KEY_F8
, "F9" : _snack
.KEY_F9
,
167 "F10" : _snack
.KEY_F10
, "F11" : _snack
.KEY_F11
,
168 "F12" : _snack
.KEY_F12
, " " : ord(" ") }
170 for n
in hotkeys
.keys():
171 hotkeys
[hotkeys
[n
]] = n
175 def addHotKey(self
, keyname
):
176 self
.w
.addhotkey(hotkeys
[keyname
])
178 def add(self
, widget
):
179 if widget
.__dict
__.has_key('hotkeys'):
180 for key
in widget
.hotkeys
.keys():
183 if widget
.__dict
__.has_key('gridmembers'):
184 for w
in widget
.gridmembers
:
186 elif widget
.__dict
__.has_key('w'):
187 self
.trans
[widget
.w
.key
] = widget
188 return self
.w
.add(widget
.w
)
192 (what
, which
) = self
.w
.run()
193 if (what
== _snack
.FORM_EXIT_WIDGET
):
194 return self
.trans
[which
]
195 elif (what
== _snack
.FORM_EXIT_TIMER
):
197 elif (what
== _snack
.FORM_EXIT_FDREADY
):
198 return self
.filemap
[which
]
200 return hotkeys
[which
]
206 def __init__(self
, helpArg
= None):
209 self
.w
= _snack
.form(helpArg
)
210 # we do the reference count for the helpArg in python! gross
211 self
.helpArg
= helpArg
213 def setCurrent (self
, co
):
214 self
.w
.setcurrent (co
.w
)
216 def setTimer (self
, timer
):
217 self
.w
.settimer (timer
)
219 def watchFile (self
, file, flags
):
220 self
.filemap
[file.fileno()] = file
221 self
.w
.watchfd (file.fileno(), flags
)
225 def place(self
, x
, y
):
226 return self
.g
.place(x
, y
)
228 def setField(self
, what
, col
, row
, padding
= (0, 0, 0, 0),
229 anchorLeft
= 0, anchorTop
= 0, anchorRight
= 0,
230 anchorBottom
= 0, growx
= 0, growy
= 0):
231 self
.gridmembers
.append(what
)
234 anchorFlags
= _snack
.ANCHOR_LEFT
236 anchorFlags
= _snack
.ANCHOR_RIGHT
239 anchorFlags
= anchorFlags | _snack
.ANCHOR_TOP
241 anchorFlags
= anchorFlags | _snack
.ANCHOR_BOTTOM
245 gridFlags
= _snack
.GRID_GROWX
247 gridFlags
= gridFlags | _snack
.GRID_GROWY
249 if (what
.__dict
__.has_key('g')):
250 return self
.g
.setfield(col
, row
, what
.g
, padding
, anchorFlags
,
253 return self
.g
.setfield(col
, row
, what
.w
, padding
, anchorFlags
)
255 def __init__(self
, *args
):
256 self
.g
= apply(_snack
.grid
, args
)
257 self
.gridmembers
= []
263 (self
.width
, self
.height
) = _snack
.size()
264 self
.pushHelpLine(None)
267 return _snack
.finish()
275 def doHelpCallback(self
, arg
):
276 self
.helpCb(self
, arg
)
278 def helpCallback(self
, cb
):
280 return _snack
.helpcallback(self
.doHelpCallback
)
282 def suspendCallback(self
, cb
, data
= None):
284 return _snack
.suspendcallback(cb
, data
)
285 return _snack
.suspendcallback(cb
)
287 def openWindow(self
, left
, top
, width
, height
, title
):
288 return _snack
.openwindow(left
, top
, width
, height
, title
)
290 def pushHelpLine(self
, text
):
292 return _snack
.pushhelpline("*default*")
294 return _snack
.pushhelpline(text
)
296 def popHelpLine(self
):
297 return _snack
.pophelpline()
299 def drawRootText(self
, left
, top
, text
):
300 return _snack
.drawroottext(left
, top
, text
)
302 def centeredWindow(self
, width
, height
, title
):
303 return _snack
.centeredwindow(width
, height
, title
)
305 def gridWrappedWindow(self
, grid
, title
, x
= None, y
= None):
307 return _snack
.gridwrappedwindow(grid
.g
, title
, x
, y
)
309 return _snack
.gridwrappedwindow(grid
.g
, title
)
312 return _snack
.popwindow()
315 return _snack
.refresh()
317 # returns a tuple of the wrapped text, the actual width, and the actual height
318 def reflow(text
, width
, flexDown
= 5, flexUp
= 5):
319 return _snack
.reflow(text
, width
, flexDown
, flexUp
)
323 class RadioGroup(Widget
):
329 def add(self
, title
, value
, default
= None):
330 if not self
.prev
and default
== None:
331 # If the first element is not explicitly set to
332 # not be the default, make it be the default
334 b
= SingleRadioButton(title
, self
.prev
, default
)
336 self
.buttonlist
.append((b
, value
))
339 def getSelection(self
):
340 for (b
, value
) in self
.buttonlist
:
341 if b
.selected(): return value
345 class RadioBar(Grid
):
347 def __init__(self
, screen
, buttonlist
):
350 self
.group
= RadioGroup()
351 Grid
.__init
__(self
, 1, len(buttonlist
))
352 for (title
, value
, default
) in buttonlist
:
353 b
= self
.group
.add(title
, value
, default
)
354 self
.list.append((b
, value
))
355 self
.setField(b
, 0, self
.item
, anchorLeft
= 1)
356 self
.item
= self
.item
+ 1
358 def getSelection(self
):
359 return self
.group
.getSelection()
362 # you normally want to pack a ButtonBar with growx = 1
364 class ButtonBar(Grid
):
366 def __init__(self
, screen
, buttonlist
, compact
= 0):
370 Grid
.__init
__(self
, len(buttonlist
), 1)
371 for blist
in buttonlist
:
372 if (type(blist
) == types
.StringType
):
374 value
= string
.lower(blist
)
375 elif len(blist
) == 2:
376 (title
, value
) = blist
378 (title
, value
, hotkey
) = blist
379 self
.hotkeys
[hotkey
] = value
382 b
= CompactButton(title
)
385 self
.list.append((b
, value
))
386 self
.setField(b
, self
.item
, 0, (1, 0, 1, 0))
387 self
.item
= self
.item
+ 1
389 def buttonPressed(self
, result
):
390 """Takes the widget returned by Form.run and looks to see
391 if it was one of the widgets in the ButtonBar."""
393 if self
.hotkeys
.has_key(result
):
394 return self
.hotkeys
[result
]
396 for (button
, value
) in self
.list:
402 class GridFormHelp(Grid
):
404 def __init__(self
, screen
, title
, help, *args
):
407 self
.form
= Form(help)
409 self
.form_created
= 0
412 apply(Grid
.__init
__, tuple(args
))
414 def add(self
, widget
, col
, row
, padding
= (0, 0, 0, 0),
415 anchorLeft
= 0, anchorTop
= 0, anchorRight
= 0,
416 anchorBottom
= 0, growx
= 0, growy
= 0):
417 self
.setField(widget
, col
, row
, padding
, anchorLeft
,
418 anchorTop
, anchorRight
, anchorBottom
,
420 self
.childList
.append(widget
)
422 def runOnce(self
, x
= None, y
= None):
423 result
= self
.run(x
, y
)
424 self
.screen
.popWindow()
427 def addHotKey(self
, keyname
):
428 self
.form
.addHotKey(keyname
)
430 def setTimer(self
, keyname
):
431 self
.form
.setTimer(keyname
)
433 def create(self
, x
= None, y
= None):
434 if not self
.form_created
:
436 for child
in self
.childList
:
438 self
.screen
.gridWrappedWindow(self
, self
.title
, x
, y
)
439 self
.form_created
= 1
441 def run(self
, x
= None, y
= None):
443 return self
.form
.run()
447 return self
.form
.draw()
451 self
.screen
.gridWrappedWindow(self
, self
.title
)
452 result
= self
.form
.run()
453 self
.screen
.popWindow()
456 def setCurrent (self
, co
):
457 self
.form
.setCurrent (co
)
459 class GridForm(GridFormHelp
):
461 def __init__(self
, screen
, title
, *args
):
462 myargs
= (self
, screen
, title
, None) + args
463 apply(GridFormHelp
.__init
__, myargs
)
465 class CheckboxTree(Widget
):
466 def append(self
, text
, item
= None, selected
= 0):
467 self
.addItem(text
, (snackArgs
['append'], ), item
, selected
)
469 def addItem(self
, text
, path
, item
= None, selected
= 0):
472 key
= self
.w
.checkboxtreeAddItem(text
, path
, selected
)
473 self
.key2item
[key
] = item
474 self
.item2key
[item
] = key
476 def getCurrent(self
):
477 curr
= self
.w
.checkboxtreeGetCurrent()
478 return self
.key2item
[curr
]
480 def __init__(self
, height
, scroll
= 0, width
= None, hide_checkbox
= 0, unselectable
= 0):
481 self
.w
= _snack
.checkboxtree(height
, scroll
, hide_checkbox
, unselectable
)
485 self
.w
.checkboxtreeSetWidth(width
)
487 def getSelection(self
):
489 list = self
.w
.checkboxtreeGetSelection()
491 selection
.append(self
.key2item
[key
])
494 def setEntry(self
, item
, text
):
495 self
.w
.checkboxtreeSetEntry(self
.item2key
[item
], text
)
497 def setCurrent(self
, item
):
498 self
.w
.checkboxtreeSetCurrent(self
.item2key
[item
])
500 def setEntryValue(self
, item
, selected
= 1):
501 self
.w
.checkboxtreeSetEntryValue(self
.item2key
[item
], selected
)
503 def getEntryValue(self
, item
):
504 return self
.w
.checkboxtreeGetEntryValue(self
.item2key
[item
])
506 def ListboxChoiceWindow(screen
, title
, text
, items
,
507 buttons
= ('Ok', 'Cancel'),
508 width
= 40, scroll
= 0, height
= -1, default
= None,
510 if (height
== -1): height
= len(items
)
512 bb
= ButtonBar(screen
, buttons
)
513 t
= TextboxReflowed(width
, text
)
514 l
= Listbox(height
, scroll
= scroll
, returnExit
= 1)
517 if (type(item
) == types
.TupleType
):
523 if (default
== count
):
525 elif (default
== item
):
531 if (default
!= None):
532 l
.setCurrent (default
)
534 g
= GridFormHelp(screen
, title
, help, 1, 3)
536 g
.add(l
, 0, 1, padding
= (0, 1, 0, 1))
537 g
.add(bb
, 0, 2, growx
= 1)
541 return (bb
.buttonPressed(rc
), l
.current())
543 def ButtonChoiceWindow(screen
, title
, text
,
544 buttons
= [ 'Ok', 'Cancel' ],
545 width
= 40, x
= None, y
= None, help = None):
546 bb
= ButtonBar(screen
, buttons
)
547 t
= TextboxReflowed(width
, text
, maxHeight
= screen
.height
- 12)
549 g
= GridFormHelp(screen
, title
, help, 1, 2)
550 g
.add(t
, 0, 0, padding
= (0, 0, 0, 1))
551 g
.add(bb
, 0, 1, growx
= 1)
552 return bb
.buttonPressed(g
.runOnce(x
, y
))
554 def EntryWindow(screen
, title
, text
, prompts
, allowCancel
= 1, width
= 40,
555 entryWidth
= 20, buttons
= [ 'Ok', 'Cancel' ], help = None):
556 bb
= ButtonBar(screen
, buttons
);
557 t
= TextboxReflowed(width
, text
)
568 if (type(n
) == types
.TupleType
):
571 e
= Entry(entryWidth
)
573 sg
.setField(Label(n
), 0, count
, padding
= (0, 0, 1, 0), anchorLeft
= 1)
574 sg
.setField(e
, 1, count
, anchorLeft
= 1)
578 g
= GridFormHelp(screen
, title
, help, 1, 3)
580 g
.add(t
, 0, 0, padding
= (0, 0, 0, 1))
581 g
.add(sg
, 0, 1, padding
= (0, 0, 0, 1))
582 g
.add(bb
, 0, 2, growx
= 1)
589 entryValues
.append(entryList
[count
].value())
592 return (bb
.buttonPressed(result
), tuple(entryValues
))
594 class CListbox(Grid
):
595 def __init__(self
, height
, cols
, col_widths
, scroll
= 0, returnExit
= 0,
596 width
= 0, col_pad
= 1, col_text_align
= None,
597 col_labels
= None, col_label_align
= None):
600 self
.col_widths
= col_widths
[:]
601 self
.col_pad
= col_pad
602 self
.col_text_align
= col_text_align
604 if col_labels
!= None:
605 Grid
.__init
__(self
, 1, 2)
608 lstr
= self
.colFormText(col_labels
, col_label_align
)
609 self
.label
= Label(lstr
)
611 self
.setField(self
.label
, 0, 0, anchorLeft
=1)
614 Grid
.__init
__(self
, 1, 1)
618 self
.listbox
= Listbox(height
, scroll
, returnExit
, width
)
619 self
.setField(self
.listbox
, 0, box_y
, anchorRight
=1)
621 def colFormText(self
, col_text
, align
= None):
624 c_len
= len(col_text
)
625 while (i
< self
.cols
) and (i
< c_len
):
627 cstr
= col_text
[i
][:self
.col_widths
[i
]]
628 delta
= self
.col_widths
[i
] - len(cstr
)
636 cstr
= cstr
+ (" " * delta
)
638 cstr
= (" " * (delta
/ 2)) + cstr
+ \
639 (" " * ((delta
+ 1) / 2))
641 cstr
= (" " * delta
) + cstr
644 pstr
= (" " * self
.col_pad
)
648 str = str + cstr
+ pstr
654 def append(self
, col_text
, item
, col_text_align
= None):
655 if col_text_align
== None:
656 col_text_align
= self
.col_text_align
657 text
= self
.colFormText(col_text
, col_text_align
)
658 self
.listbox
.append(text
, item
)
660 def insert(self
, col_text
, item
, before
, col_text_align
= None):
661 if col_text_align
== None:
662 col_text_align
= self
.col_text_align
663 text
= self
.colFormText(col_text
, col_text_align
)
664 self
.listbox
.insert(text
, item
, before
)
666 def delete(self
, item
):
667 self
.listbox
.delete(item
)
669 def replace(self
, col_text
, item
, col_text_align
= None):
670 if col_text_align
== None:
671 col_text_align
= self
.col_text_align
672 text
= self
.colFormText(col_text
, col_text_align
)
673 self
.listbox
.replace(text
, item
)
676 return self
.listbox
.current()
678 def setCurrent(self
, item
):
679 self
.listbox
.setCurrent(item
)