home *** CD-ROM | disk | FTP | other *** search
/ Australian Personal Computer 2000 July / CD 3 / redhat-6.2.iso / RedHat / instimage / usr / lib / python1.5 / snack.py < prev    next >
Encoding:
Python Source  |  2000-02-25  |  13.2 KB  |  536 lines

  1. # snack.py: maps C extension module _snack to proper python types in module
  2. # snack.
  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.
  6.  
  7. import _snack
  8. import types
  9. import string
  10.  
  11. snackArgs = {}
  12. snackArgs['append'] = -1
  13.  
  14. FLAG_DISABLED = _snack.FLAG_DISABLED
  15. FLAGS_SET = _snack.FLAGS_SET
  16. FLAGS_RESET = _snack.FLAGS_RESET
  17. FLAGS_TOGGLE = _snack.FLAGS_TOGGLE
  18.  
  19. class Widget:
  20.     def setCallback(self, obj, data = None):
  21.         if data:
  22.             self.w.setCallback(obj, data)
  23.         else:
  24.             self.w.setCallback(obj)
  25.  
  26. class Button(Widget):
  27.  
  28.     def __init__(self, text):
  29.     self.w = _snack.button(text)
  30.  
  31. class Checkbox(Widget):
  32.  
  33.     def value(self):
  34.     return self.w.checkboxValue
  35.  
  36.     def selected(self):
  37.     return self.w.checkboxValue != 0
  38.  
  39.     def setFlags (self, flag, sense):
  40.         return self.w.checkboxSetFlags(flag, sense)
  41.  
  42.     def __init__(self, text, isOn = 0):
  43.     self.w = _snack.checkbox(text, isOn)
  44.  
  45. class SingleRadioButton(Widget):
  46.  
  47.     def selected(self):
  48.     return self.w.key == self.w.radioValue;
  49.     
  50.     def __init__(self, text, group, isOn = 0):
  51.     if group:
  52.         self.w = _snack.radiobutton(text, group.w, isOn)
  53.     else:
  54.         self.w = _snack.radiobutton(text, None, isOn)
  55.  
  56. class Listbox(Widget):
  57.  
  58.     def append(self, text, item):
  59.     key = self.w.listboxAddItem(text)
  60.     self.key2item[key] = item
  61.     self.item2key[item] = key
  62.  
  63.     def insert(self, text, item, before):
  64.     if (not before):
  65.         key = self.w.listboxInsertItem(text, 0)
  66.     else:
  67.         key = self.w.listboxInsertItem(text, self.item2key[before])
  68.     self.key2item[key] = item
  69.     self.item2key[item] = key
  70.  
  71.     def delete(self, item):
  72.     self.w.listboxDeleteItem(self.item2key[item])
  73.     del self.key2item[self.item2key[item]]
  74.     del self.item2key[item]
  75.  
  76.     def replace(self, text, item):
  77.     key = self.w.listboxInsertItem(text, self.item2key[item])
  78.     self.w.listboxDeleteItem(self.item2key[item])
  79.     del self.key2item[self.item2key[item]]
  80.     self.item2key[item] = key
  81.     self.key2item[key] = item
  82.  
  83.     def current(self):
  84.     return self.key2item[self.w.listboxGetCurrent()]
  85.  
  86.     def setCurrent(self, item):
  87.     self.w.listboxSetCurrent(self.item2key[item])
  88.  
  89.     def __init__(self, height, scroll = 0, returnExit = 0, width = 0):
  90.     self.w = _snack.listbox(height, scroll, returnExit)
  91.     self.key2item = {}
  92.     self.item2key = {}
  93.     if (width):
  94.         self.w.listboxSetWidth(width)
  95.  
  96. class Textbox(Widget):
  97.  
  98.     def setText(self, text):
  99.     self.w.textboxText(text)
  100.  
  101.     def __init__(self, width, height, text, scroll = 0, wrap = 0):
  102.     self.w = _snack.textbox(width, height, text, scroll, wrap)
  103.  
  104. class TextboxReflowed(Textbox):
  105.  
  106.     def __init__(self, width, text, flexDown = 5, flexUp = 10, maxHeight = -1):
  107.     (newtext, width, height) = reflow(text, width, flexDown, flexUp)
  108.         if maxHeight != -1 and height > maxHeight:
  109.             Textbox.__init__(self, width, maxHeight, newtext, 1)
  110.         else:
  111.             Textbox.__init__(self, width, height, newtext, 0)
  112.  
  113. class Label(Widget):
  114.  
  115.     def setText(self, text):
  116.     self.w.labelText(text)
  117.  
  118.     def __init__(self, text):
  119.     self.w = _snack.label(text)
  120.  
  121. class Scale(Widget):
  122.  
  123.     def set(self, amount):
  124.     self.w.scaleSet(amount)
  125.  
  126.     def __init__(self, width, total):
  127.     self.w = _snack.scale(width, total)
  128.  
  129. class Entry(Widget):
  130.  
  131.     def value(self):
  132.     return self.w.entryValue
  133.  
  134.     def set(self, text):
  135.     return self.w.entrySetValue(text)
  136.  
  137.     def setFlags (self, flag, sense):
  138.         return self.w.entrySetFlags(flag, sense)
  139.  
  140.     def __init__(self, width, text = "", hidden = 0, scroll = 1, 
  141.          returnExit = 0):
  142.     self.w = _snack.entry(width, text, hidden, scroll, returnExit)
  143.  
  144.  
  145. # Form uses hotkeys
  146. hotkeys = { "F1" : _snack.KEY_F1, "F2" : _snack.KEY_F2, "F3" : _snack.KEY_F3, 
  147.             "F4" : _snack.KEY_F4, "F5" : _snack.KEY_F5, "F6" : _snack.KEY_F6, 
  148.             "F7" : _snack.KEY_F7, "F8" : _snack.KEY_F8, "F9" : _snack.KEY_F9, 
  149.             "F10" : _snack.KEY_F10, "F11" : _snack.KEY_F11, 
  150.             "F12" : _snack.KEY_F12 }
  151.  
  152. for n in hotkeys.keys():
  153.     hotkeys[hotkeys[n]] = n
  154.  
  155. class Form:
  156.  
  157.     def addHotKey(self, keyname):
  158.     self.w.addhotkey(hotkeys[keyname])
  159.  
  160.     def add(self, widget):
  161.     if widget.__dict__.has_key('hotkeys'):
  162.         for key in widget.hotkeys.keys():
  163.         self.addHotKey(key)
  164.  
  165.     if widget.__dict__.has_key('gridmembers'):
  166.         for w in widget.gridmembers:
  167.         self.add(w)
  168.     elif widget.__dict__.has_key('w'):
  169.         self.trans[widget.w.key] = widget
  170.         return self.w.add(widget.w)
  171.     return None
  172.  
  173.     def run(self):
  174.     (what, which) = self.w.run()
  175.     if (what == _snack.FORM_EXIT_WIDGET):
  176.         return self.trans[which]
  177.     elif (what == _snack.FORM_EXIT_TIMER):
  178.         return "TIMER"
  179.  
  180.     return hotkeys[which]
  181.  
  182.     def draw(self):
  183.     self.w.draw()
  184.     return None
  185.  
  186.     def __init__(self):
  187.     self.trans = {}
  188.     self.w = _snack.form()
  189.  
  190.     def setCurrent (self, co):
  191.         self.w.setcurrent (co.w)
  192.  
  193.     def setTimer (self, timer):
  194.         self.w.settimer (timer)
  195.  
  196. class Grid:
  197.  
  198.     def place(self, x, y):
  199.     return self.g.place(x, y)
  200.  
  201.     def setField(self, what, col, row, padding = (0, 0, 0, 0),
  202.          anchorLeft = 0, anchorTop = 0, anchorRight = 0,
  203.          anchorBottom = 0, growx = 0, growy = 0):
  204.     self.gridmembers.append(what)
  205.     anchorFlags = 0
  206.     if (anchorLeft):
  207.         anchorFlags = _snack.ANCHOR_LEFT
  208.     elif (anchorRight):
  209.         anchorFlags = _snack.ANCHOR_RIGHT
  210.  
  211.     if (anchorTop):
  212.         anchorFlags = anchorFlags | _snack.ANCHOR_TOP
  213.     elif (anchorBottom):
  214.         anchorFlags = anchorFlags | _snack.ANCHOR_BOTTOM
  215.  
  216.     gridFlags = 0
  217.     if (growx):
  218.         gridFlags = _snack.GRID_GROWX
  219.     if (growy):
  220.         gridFlags = gridFlags | _snack.GRID_GROWY
  221.  
  222.     if (what.__dict__.has_key('g')):
  223.         return self.g.setfield(col, row, what.g, padding, anchorFlags,
  224.                    gridFlags)
  225.     else:
  226.         return self.g.setfield(col, row, what.w, padding, anchorFlags)
  227.  
  228.     def __init__(self, *args):
  229.     self.g = apply(_snack.grid, args)
  230.     self.gridmembers = []
  231.  
  232. class SnackScreen:
  233.  
  234.     def __init__(self):
  235.     _snack.init()
  236.     (self.width, self.height) = _snack.size()
  237.     self.pushHelpLine(None)
  238.  
  239.     def finish(self):
  240.     return _snack.finish()
  241.  
  242.     def resume(self):
  243.     _snack.resume()
  244.  
  245.     def suspend(self):
  246.     _snack.suspend()
  247.  
  248.     def suspendCallback(self, cb, data = None):
  249.         if data:
  250.             return _snack.suspendcallback(cb, data)
  251.         return _snack.suspendcallback(cb)
  252.  
  253.     def openWindow(self, left, top, width, height, title):
  254.     return _snack.openwindow(left, top, width, height, title)
  255.  
  256.     def pushHelpLine(self, text):
  257.     if (not text):
  258.         return _snack.pushhelpline("*default*")
  259.     else:
  260.         return _snack.pushhelpline(text)
  261.  
  262.     def popHelpLine(self):
  263.     return _snack.pophelpline()
  264.  
  265.     def drawRootText(self, left, top, text):
  266.     return _snack.drawroottext(left, top, text)
  267.  
  268.     def centeredWindow(self, width, height, title):
  269.     return _snack.centeredwindow(width, height, title)
  270.  
  271.     def gridWrappedWindow(self, grid, title, x = None, y = None):
  272.     if x and y:
  273.         return _snack.gridwrappedwindow(grid.g, title, x, y)
  274.  
  275.     return _snack.gridwrappedwindow(grid.g, title)
  276.  
  277.     def popWindow(self):
  278.     return _snack.popwindow()
  279.  
  280.     def refresh(self):
  281.     return _snack.refresh()
  282.  
  283. # returns a tuple of the wrapped text, the actual width, and the actual height
  284. def reflow(text, width, flexDown = 5, flexUp = 5):
  285.     return _snack.reflow(text, width, flexDown, flexUp)
  286.  
  287. # combo widgets
  288.  
  289. class RadioGroup(Widget):
  290.  
  291.     def __init__(self):
  292.     self.prev = None
  293.     self.buttonlist = []
  294.  
  295.     def add(self, title, value, default = None):
  296.     if not self.prev and default == None:
  297.         # If the first element is not explicitly set to
  298.         # not be the default, make it be the default
  299.         default = 1
  300.     b = SingleRadioButton(title, self.prev, default)
  301.     self.prev = b
  302.     self.buttonlist.append((b, value))
  303.     return b
  304.  
  305.     def getSelection(self):
  306.     for (b, value) in self.buttonlist:
  307.         if b.selected(): return value
  308.     return None
  309.  
  310.  
  311. class RadioBar(Grid):
  312.  
  313.     def __init__(self, screen, buttonlist):
  314.     self.list = []
  315.     self.item = 0
  316.     self.group = RadioGroup()
  317.     Grid.__init__(self, 1, len(buttonlist))
  318.     for (title, value, default) in buttonlist:
  319.         b = self.group.add(title, value, default)
  320.         self.list.append(b, value)
  321.         self.setField(b, 0, self.item, anchorLeft = 1)
  322.         self.item = self.item + 1
  323.  
  324.     def getSelection(self):
  325.     return self.group.getSelection()
  326.     
  327.  
  328. # you normally want to pack a ButtonBar with growx = 1
  329.  
  330. class ButtonBar(Grid):
  331.  
  332.     def __init__(self, screen, buttonlist):
  333.     self.list = []
  334.     self.hotkeys = {}
  335.     self.item = 0
  336.     Grid.__init__(self, len(buttonlist), 1)
  337.     for blist in buttonlist:
  338.         if (type(blist) == types.StringType):
  339.         title = blist
  340.         value = string.lower(blist)
  341.         elif len(blist) == 2:
  342.         (title, value) = blist
  343.         else:
  344.         (title, value, hotkey) = blist
  345.         self.hotkeys[hotkey] = value
  346.  
  347.         b = Button(title)
  348.         self.list.append(b, value)
  349.         self.setField(b, self.item, 0, (1, 0, 1, 0))
  350.         self.item = self.item + 1
  351.  
  352.     def buttonPressed(self, result):
  353.     """Takes the widget returned by Form.run and looks to see
  354.     if it was one of the widgets in the ButtonBar."""
  355.  
  356.     if self.hotkeys.has_key(result):
  357.         return self.hotkeys[result]
  358.  
  359.     for (button, value) in self.list:
  360.         if result == button:
  361.         return value
  362.     return None
  363.  
  364.  
  365. class GridForm(Grid):
  366.  
  367.     def __init__(self, screen, title, *args):
  368.     self.screen = screen
  369.     self.title = title
  370.     self.form = Form()
  371.     self.childList = []
  372.     self.form_created = 0
  373.     args = list(args)
  374.     args[:0] = [self]
  375.     apply(Grid.__init__, tuple(args))
  376.  
  377.     def add(self, widget, col, row, padding = (0, 0, 0, 0),
  378.             anchorLeft = 0, anchorTop = 0, anchorRight = 0,
  379.             anchorBottom = 0, growx = 0, growy = 0):
  380.     self.setField(widget, col, row, padding, anchorLeft,
  381.               anchorTop, anchorRight, anchorBottom,
  382.               growx, growy);
  383.     self.childList.append(widget)
  384.  
  385.     def runOnce(self, x = None, y = None):
  386.     result = self.run(x, y)
  387.     self.screen.popWindow()
  388.     return result
  389.  
  390.     def addHotKey(self, keyname):
  391.     self.form.addHotKey(keyname)
  392.  
  393.     def setTimer(self, keyname):
  394.     self.form.setTimer(keyname)
  395.  
  396.     def create(self, x = None, y = None):
  397.     if not self.form_created:
  398.         self.place(1,1)
  399.         for child in self.childList:
  400.         self.form.add(child)
  401.         self.screen.gridWrappedWindow(self, self.title, x, y)
  402.         self.form_created = 1
  403.  
  404.     def run(self, x = None, y = None):
  405.     self.create(x, y)
  406.     return self.form.run()
  407.  
  408.     def draw(self):
  409.     self.create()
  410.     return self.form.draw()
  411.     
  412.     def runPopup(self):
  413.     self.create()
  414.     self.screen.gridWrappedWindow(self, self.title)
  415.     result = self.form.run()
  416.     self.screen.popWindow()
  417.     return result
  418.  
  419.     def setCurrent (self, co):
  420.         self.form.setCurrent (co)
  421.  
  422. class CheckboxTree(Widget):
  423.     def append(self, text, item = None, selected = 0):
  424.         self.addItem(text, (snackArgs['append'], ), item, selected)
  425.  
  426.     def addItem(self, text, path, item = None, selected = 0):
  427.         if (not item):
  428.         item = text
  429.     key = self.w.checkboxtreeAddItem(text, path, selected)
  430.     self.key2item[key] = item
  431.     self.item2key[item] = key
  432.  
  433.     def getCurrent(self):
  434.     curr = self.w.checkboxtreeGetCurrent()
  435.     return self.key2item[curr]
  436.  
  437.     def __init__(self, height, scroll = 0):
  438.     self.w = _snack.checkboxtree(height, scroll)
  439.     self.key2item = {}
  440.     self.item2key = {}
  441.  
  442.     def getSelection(self):
  443.         selection = []
  444.         list = self.w.checkboxtreeGetSelection()
  445.         for key in list:
  446.             selection.append(self.key2item[key])
  447.     return selection
  448.  
  449.  
  450. def ListboxChoiceWindow(screen, title, text, items, 
  451.             buttons = ('Ok', 'Cancel'), 
  452.             width = 40, scroll = 0, height = -1, default = None):
  453.     if (height == -1): height = len(items)
  454.  
  455.     bb = ButtonBar(screen, buttons)
  456.     t = TextboxReflowed(width, text)
  457.     l = Listbox(height, scroll = scroll, returnExit = 1)
  458.     count = 0
  459.     for item in items:
  460.     if (type(item) == types.TupleType):
  461.         (text, key) = item
  462.     else:
  463.         text = item
  464.         key = count
  465.  
  466.     if (default == count):
  467.         default = key
  468.     elif (default == item):
  469.         default = key
  470.  
  471.     l.append(text, key)
  472.     count = count + 1
  473.  
  474.     if (default != None):
  475.     l.setCurrent (default)
  476.  
  477.     g = GridForm(screen, title, 1, 3)
  478.     g.add(t, 0, 0)
  479.     g.add(l, 0, 1, padding = (0, 1, 0, 1))
  480.     g.add(bb, 0, 2, growx = 1)
  481.  
  482.     rc = g.runOnce()
  483.  
  484.     return (bb.buttonPressed(rc), l.current())
  485.  
  486. def ButtonChoiceWindow(screen, title, text, 
  487.                buttons = [ 'Ok', 'Cancel' ], 
  488.                width = 40, x = None, y = None):
  489.     bb = ButtonBar(screen, buttons)
  490.     t = TextboxReflowed(width, text, maxHeight = screen.height - 12)
  491.  
  492.     g = GridForm(screen, title, 1, 2)
  493.     g.add(t, 0, 0, padding = (0, 0, 0, 1))
  494.     g.add(bb, 0, 1, growx = 1)
  495.     return bb.buttonPressed(g.runOnce(x, y))
  496.  
  497. def EntryWindow(screen, title, text, prompts, allowCancel = 1, width = 40,
  498.         entryWidth = 20, buttons = [ 'Ok', 'Cancel' ]):
  499.     bb = ButtonBar(screen, buttons);
  500.     t = TextboxReflowed(width, text)
  501.  
  502.     count = 0
  503.     for n in prompts:
  504.     count = count + 1
  505.  
  506.     sg = Grid(2, count)
  507.  
  508.     count = 0
  509.     entryList = []
  510.     for n in prompts:
  511.     if (type(n) == types.TupleType):
  512.         (n, e) = n
  513.     else:
  514.         e = Entry(entryWidth)
  515.  
  516.     sg.setField(Label(n), 0, count, padding = (0, 0, 1, 0), anchorLeft = 1)
  517.     sg.setField(e, 1, count, anchorLeft = 1)
  518.     count = count + 1
  519.     entryList.append(e)
  520.  
  521.     g = GridForm(screen, title, 1, 3)
  522.  
  523.     g.add(t, 0, 0, padding = (0, 0, 0, 1))
  524.     g.add(sg, 0, 1, padding = (0, 0, 0, 1))
  525.     g.add(bb, 0, 2, growx = 1)
  526.  
  527.     result = g.runOnce()
  528.  
  529.     entryValues = []
  530.     count = 0
  531.     for n in prompts:
  532.     entryValues.append(entryList[count].value())
  533.     count = count + 1
  534.  
  535.     return (bb.buttonPressed(result), tuple(entryValues))
  536.