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.
12
snackArgs['append'] = -1
14
FLAG_DISABLED = _snack.FLAG_DISABLED
15
FLAGS_SET = _snack.FLAGS_SET
16
FLAGS_RESET = _snack.FLAGS_RESET
17
FLAGS_TOGGLE = _snack.FLAGS_TOGGLE
20
def setCallback(self, obj, data = None):
22
self.w.setCallback(obj, data)
24
self.w.setCallback(obj)
28
def __init__(self, text):
29
self.w = _snack.button(text)
31
class Checkbox(Widget):
34
return self.w.checkboxValue
37
return self.w.checkboxValue != 0
39
def setFlags (self, flag, sense):
40
return self.w.checkboxSetFlags(flag, sense)
42
def setValue (self, value):
43
return self.w.checkboxSetValue(value)
45
def __init__(self, text, isOn = 0):
46
self.w = _snack.checkbox(text, isOn)
48
class SingleRadioButton(Widget):
51
return self.w.key == self.w.radioValue;
53
def __init__(self, text, group, isOn = 0):
55
self.w = _snack.radiobutton(text, group.w, isOn)
57
self.w = _snack.radiobutton(text, None, isOn)
59
class Listbox(Widget):
61
def append(self, text, item):
62
key = self.w.listboxAddItem(text)
63
self.key2item[key] = item
64
self.item2key[item] = key
66
def insert(self, text, item, before):
68
key = self.w.listboxInsertItem(text, 0)
70
key = self.w.listboxInsertItem(text, self.item2key[before])
71
self.key2item[key] = item
72
self.item2key[item] = key
74
def delete(self, item):
75
self.w.listboxDeleteItem(self.item2key[item])
76
del self.key2item[self.item2key[item]]
77
del self.item2key[item]
79
def replace(self, text, item):
80
key = self.w.listboxInsertItem(text, self.item2key[item])
81
self.w.listboxDeleteItem(self.item2key[item])
82
del self.key2item[self.item2key[item]]
83
self.item2key[item] = key
84
self.key2item[key] = item
87
return self.key2item[self.w.listboxGetCurrent()]
89
def setCurrent(self, item):
90
self.w.listboxSetCurrent(self.item2key[item])
92
def __init__(self, height, scroll = 0, returnExit = 0, width = 0):
93
self.w = _snack.listbox(height, scroll, returnExit)
97
self.w.listboxSetWidth(width)
99
class Textbox(Widget):
101
def setText(self, text):
102
self.w.textboxText(text)
104
def __init__(self, width, height, text, scroll = 0, wrap = 0):
105
self.w = _snack.textbox(width, height, text, scroll, wrap)
107
class TextboxReflowed(Textbox):
109
def __init__(self, width, text, flexDown = 5, flexUp = 10, maxHeight = -1):
110
(newtext, width, height) = reflow(text, width, flexDown, flexUp)
111
if maxHeight != -1 and height > maxHeight:
112
Textbox.__init__(self, width, maxHeight, newtext, 1)
114
Textbox.__init__(self, width, height, newtext, 0)
118
def setText(self, text):
119
self.w.labelText(text)
121
def __init__(self, text):
122
self.w = _snack.label(text)
126
def set(self, amount):
127
self.w.scaleSet(amount)
129
def __init__(self, width, total):
130
self.w = _snack.scale(width, total)
135
return self.w.entryValue
138
return self.w.entrySetValue(text)
140
def setFlags (self, flag, sense):
141
return self.w.entrySetFlags(flag, sense)
143
def __init__(self, width, text = "", hidden = 0, password = 0, scroll = 1,
145
self.w = _snack.entry(width, text, hidden, password, scroll, returnExit)
149
hotkeys = { "F1" : _snack.KEY_F1, "F2" : _snack.KEY_F2, "F3" : _snack.KEY_F3,
150
"F4" : _snack.KEY_F4, "F5" : _snack.KEY_F5, "F6" : _snack.KEY_F6,
151
"F7" : _snack.KEY_F7, "F8" : _snack.KEY_F8, "F9" : _snack.KEY_F9,
152
"F10" : _snack.KEY_F10, "F11" : _snack.KEY_F11,
153
"F12" : _snack.KEY_F12, " " : ord(" ") }
155
for n in hotkeys.keys():
156
hotkeys[hotkeys[n]] = n
160
def addHotKey(self, keyname):
161
self.w.addhotkey(hotkeys[keyname])
163
def add(self, widget):
164
if widget.__dict__.has_key('hotkeys'):
165
for key in widget.hotkeys.keys():
168
if widget.__dict__.has_key('gridmembers'):
169
for w in widget.gridmembers:
171
elif widget.__dict__.has_key('w'):
172
self.trans[widget.w.key] = widget
173
return self.w.add(widget.w)
177
(what, which) = self.w.run()
178
if (what == _snack.FORM_EXIT_WIDGET):
179
return self.trans[which]
180
elif (what == _snack.FORM_EXIT_TIMER):
183
return hotkeys[which]
189
def __init__(self, helpArg = None):
191
self.w = _snack.form(helpArg)
192
# we do the reference count for the helpArg in python! gross
193
self.helpArg = helpArg
195
def setCurrent (self, co):
196
self.w.setcurrent (co.w)
198
def setTimer (self, timer):
199
self.w.settimer (timer)
203
def place(self, x, y):
204
return self.g.place(x, y)
206
def setField(self, what, col, row, padding = (0, 0, 0, 0),
207
anchorLeft = 0, anchorTop = 0, anchorRight = 0,
208
anchorBottom = 0, growx = 0, growy = 0):
209
self.gridmembers.append(what)
212
anchorFlags = _snack.ANCHOR_LEFT
214
anchorFlags = _snack.ANCHOR_RIGHT
217
anchorFlags = anchorFlags | _snack.ANCHOR_TOP
219
anchorFlags = anchorFlags | _snack.ANCHOR_BOTTOM
223
gridFlags = _snack.GRID_GROWX
225
gridFlags = gridFlags | _snack.GRID_GROWY
227
if (what.__dict__.has_key('g')):
228
return self.g.setfield(col, row, what.g, padding, anchorFlags,
231
return self.g.setfield(col, row, what.w, padding, anchorFlags)
233
def __init__(self, *args):
234
self.g = apply(_snack.grid, args)
235
self.gridmembers = []
241
(self.width, self.height) = _snack.size()
242
self.pushHelpLine(None)
245
return _snack.finish()
253
def doHelpCallback(self, arg):
254
self.helpCb(self, arg)
256
def helpCallback(self, cb):
258
return _snack.helpcallback(self.doHelpCallback)
260
def suspendCallback(self, cb, data = None):
262
return _snack.suspendcallback(cb, data)
263
return _snack.suspendcallback(cb)
265
def openWindow(self, left, top, width, height, title):
266
return _snack.openwindow(left, top, width, height, title)
268
def pushHelpLine(self, text):
270
return _snack.pushhelpline("*default*")
272
return _snack.pushhelpline(text)
274
def popHelpLine(self):
275
return _snack.pophelpline()
277
def drawRootText(self, left, top, text):
278
return _snack.drawroottext(left, top, text)
280
def centeredWindow(self, width, height, title):
281
return _snack.centeredwindow(width, height, title)
283
def gridWrappedWindow(self, grid, title, x = None, y = None):
285
return _snack.gridwrappedwindow(grid.g, title, x, y)
287
return _snack.gridwrappedwindow(grid.g, title)
290
return _snack.popwindow()
293
return _snack.refresh()
295
# returns a tuple of the wrapped text, the actual width, and the actual height
296
def reflow(text, width, flexDown = 5, flexUp = 5):
297
return _snack.reflow(text, width, flexDown, flexUp)
301
class RadioGroup(Widget):
307
def add(self, title, value, default = None):
308
if not self.prev and default == None:
309
# If the first element is not explicitly set to
310
# not be the default, make it be the default
312
b = SingleRadioButton(title, self.prev, default)
314
self.buttonlist.append((b, value))
317
def getSelection(self):
318
for (b, value) in self.buttonlist:
319
if b.selected(): return value
323
class RadioBar(Grid):
325
def __init__(self, screen, buttonlist):
328
self.group = RadioGroup()
329
Grid.__init__(self, 1, len(buttonlist))
330
for (title, value, default) in buttonlist:
331
b = self.group.add(title, value, default)
332
self.list.append((b, value))
333
self.setField(b, 0, self.item, anchorLeft = 1)
334
self.item = self.item + 1
336
def getSelection(self):
337
return self.group.getSelection()
340
# you normally want to pack a ButtonBar with growx = 1
342
class ButtonBar(Grid):
344
def __init__(self, screen, buttonlist):
348
Grid.__init__(self, len(buttonlist), 1)
349
for blist in buttonlist:
350
if (type(blist) == types.StringType):
352
value = string.lower(blist)
353
elif len(blist) == 2:
354
(title, value) = blist
356
(title, value, hotkey) = blist
357
self.hotkeys[hotkey] = value
360
self.list.append((b, value))
361
self.setField(b, self.item, 0, (1, 0, 1, 0))
362
self.item = self.item + 1
364
def buttonPressed(self, result):
365
"""Takes the widget returned by Form.run and looks to see
366
if it was one of the widgets in the ButtonBar."""
368
if self.hotkeys.has_key(result):
369
return self.hotkeys[result]
371
for (button, value) in self.list:
377
class GridFormHelp(Grid):
379
def __init__(self, screen, title, help, *args):
382
self.form = Form(help)
384
self.form_created = 0
387
apply(Grid.__init__, tuple(args))
389
def add(self, widget, col, row, padding = (0, 0, 0, 0),
390
anchorLeft = 0, anchorTop = 0, anchorRight = 0,
391
anchorBottom = 0, growx = 0, growy = 0):
392
self.setField(widget, col, row, padding, anchorLeft,
393
anchorTop, anchorRight, anchorBottom,
395
self.childList.append(widget)
397
def runOnce(self, x = None, y = None):
398
result = self.run(x, y)
399
self.screen.popWindow()
402
def addHotKey(self, keyname):
403
self.form.addHotKey(keyname)
405
def setTimer(self, keyname):
406
self.form.setTimer(keyname)
408
def create(self, x = None, y = None):
409
if not self.form_created:
411
for child in self.childList:
413
self.screen.gridWrappedWindow(self, self.title, x, y)
414
self.form_created = 1
416
def run(self, x = None, y = None):
418
return self.form.run()
422
return self.form.draw()
426
self.screen.gridWrappedWindow(self, self.title)
427
result = self.form.run()
428
self.screen.popWindow()
431
def setCurrent (self, co):
432
self.form.setCurrent (co)
434
class GridForm(GridFormHelp):
436
def __init__(self, screen, title, *args):
437
myargs = (self, screen, title, None) + args
438
apply(GridFormHelp.__init__, myargs)
440
class CheckboxTree(Widget):
441
def append(self, text, item = None, selected = 0):
442
self.addItem(text, (snackArgs['append'], ), item, selected)
444
def addItem(self, text, path, item = None, selected = 0):
447
key = self.w.checkboxtreeAddItem(text, path, selected)
448
self.key2item[key] = item
449
self.item2key[item] = key
451
def getCurrent(self):
452
curr = self.w.checkboxtreeGetCurrent()
453
return self.key2item[curr]
455
def __init__(self, height, scroll = 0):
456
self.w = _snack.checkboxtree(height, scroll)
460
def getSelection(self):
462
list = self.w.checkboxtreeGetSelection()
464
selection.append(self.key2item[key])
467
def setEntry(self, item, text):
468
self.w.checkboxtreeSetEntry(self.item2key[item], text)
470
def setEntryValue(self, item, selected = 1):
471
self.w.checkboxtreeSetEntryValue(self.item2key[item], selected)
473
def getEntryValue(self, item):
474
return self.w.checkboxtreeGetEntryValue(self.item2key[item])
476
def ListboxChoiceWindow(screen, title, text, items,
477
buttons = ('Ok', 'Cancel'),
478
width = 40, scroll = 0, height = -1, default = None,
480
if (height == -1): height = len(items)
482
bb = ButtonBar(screen, buttons)
483
t = TextboxReflowed(width, text)
484
l = Listbox(height, scroll = scroll, returnExit = 1)
487
if (type(item) == types.TupleType):
493
if (default == count):
495
elif (default == item):
501
if (default != None):
502
l.setCurrent (default)
504
g = GridFormHelp(screen, title, help, 1, 3)
506
g.add(l, 0, 1, padding = (0, 1, 0, 1))
507
g.add(bb, 0, 2, growx = 1)
511
return (bb.buttonPressed(rc), l.current())
513
def ButtonChoiceWindow(screen, title, text,
514
buttons = [ 'Ok', 'Cancel' ],
515
width = 40, x = None, y = None, help = None):
516
bb = ButtonBar(screen, buttons)
517
t = TextboxReflowed(width, text, maxHeight = screen.height - 12)
519
g = GridFormHelp(screen, title, help, 1, 2)
520
g.add(t, 0, 0, padding = (0, 0, 0, 1))
521
g.add(bb, 0, 1, growx = 1)
522
return bb.buttonPressed(g.runOnce(x, y))
524
def EntryWindow(screen, title, text, prompts, allowCancel = 1, width = 40,
525
entryWidth = 20, buttons = [ 'Ok', 'Cancel' ], help = None):
526
bb = ButtonBar(screen, buttons);
527
t = TextboxReflowed(width, text)
538
if (type(n) == types.TupleType):
541
e = Entry(entryWidth)
543
sg.setField(Label(n), 0, count, padding = (0, 0, 1, 0), anchorLeft = 1)
544
sg.setField(e, 1, count, anchorLeft = 1)
548
g = GridFormHelp(screen, title, help, 1, 3)
550
g.add(t, 0, 0, padding = (0, 0, 0, 1))
551
g.add(sg, 0, 1, padding = (0, 0, 0, 1))
552
g.add(bb, 0, 2, growx = 1)
559
entryValues.append(entryList[count].value())
562
return (bb.buttonPressed(result), tuple(entryValues))