diff options
Diffstat (limited to 'Lib/irix6/panel.py')
-rw-r--r-- | Lib/irix6/panel.py | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/Lib/irix6/panel.py b/Lib/irix6/panel.py new file mode 100644 index 0000000..2c0365c --- /dev/null +++ b/Lib/irix6/panel.py @@ -0,0 +1,281 @@ +# Module 'panel' +# +# Support for the Panel library. +# Uses built-in module 'pnl'. +# Applciations should use 'panel.function' instead of 'pnl.function'; +# most 'pnl' functions are transparently exported by 'panel', +# but dopanel() is overridden and you have to use this version +# if you want to use callbacks. + + +import pnl + + +debug = 0 + + +# Test if an object is a list. +# +def is_list(x): + return type(x) == type([]) + + +# Reverse a list. +# +def reverse(list): + res = [] + for item in list: + res.insert(0, item) + return res + + +# Get an attribute of a list, which may itself be another list. +# Don't use 'prop' for name. +# +def getattrlist(list, name): + for item in list: + if item and is_list(item) and item[0] == name: + return item[1:] + return [] + + +# Get a property of a list, which may itself be another list. +# +def getproplist(list, name): + for item in list: + if item and is_list(item) and item[0] == 'prop': + if len(item) > 1 and item[1] == name: + return item[2:] + return [] + + +# Test if an actuator description contains the property 'end-of-group' +# +def is_endgroup(list): + x = getproplist(list, 'end-of-group') + return (x and x[0] == '#t') + + +# Neatly display an actuator definition given as S-expression +# the prefix string is printed before each line. +# +def show_actuator(prefix, a): + for item in a: + if not is_list(item): + print prefix, item + elif item and item[0] == 'al': + print prefix, 'Subactuator list:' + for a in item[1:]: + show_actuator(prefix + ' ', a) + elif len(item) == 2: + print prefix, item[0], '=>', item[1] + elif len(item) == 3 and item[0] == 'prop': + print prefix, 'Prop', item[1], '=>', + print item[2] + else: + print prefix, '?', item + + +# Neatly display a panel. +# +def show_panel(prefix, p): + for item in p: + if not is_list(item): + print prefix, item + elif item and item[0] == 'al': + print prefix, 'Actuator list:' + for a in item[1:]: + show_actuator(prefix + ' ', a) + elif len(item) == 2: + print prefix, item[0], '=>', item[1] + elif len(item) == 3 and item[0] == 'prop': + print prefix, 'Prop', item[1], '=>', + print item[2] + else: + print prefix, '?', item + + +# Exception raised by build_actuator or build_panel. +# +panel_error = 'panel error' + + +# Dummy callback used to initialize the callbacks. +# +def dummy_callback(arg): + pass + + +# Assign attributes to members of the target. +# Attribute names in exclist are ignored. +# The member name is the attribute name prefixed with the prefix. +# +def assign_members(target, attrlist, exclist, prefix): + for item in attrlist: + if is_list(item) and len(item) == 2 and item[0] not in exclist: + name, value = item[0], item[1] + ok = 1 + if value[0] in '-0123456789': + value = eval(value) + elif value[0] == '"': + value = value[1:-1] + elif value == 'move-then-resize': + # Strange default set by Panel Editor... + ok = 0 + else: + print 'unknown value', value, 'for', name + ok = 0 + if ok: + lhs = 'target.' + prefix + name + stmt = lhs + '=' + `value` + if debug: print 'exec', stmt + try: + exec stmt + '\n' + except KeyboardInterrupt: # Don't catch this! + raise KeyboardInterrupt + except: + print 'assign failed:', stmt + + +# Build a real actuator from an actuator descriptior. +# Return a pair (actuator, name). +# +def build_actuator(descr): + namelist = getattrlist(descr, 'name') + if namelist: + # Assume it is a string + actuatorname = namelist[0][1:-1] + else: + actuatorname = '' + type = descr[0] + if type[:4] == 'pnl_': type = type[4:] + act = pnl.mkact(type) + act.downfunc = act.activefunc = act.upfunc = dummy_callback + # + assign_members(act, descr[1:], ['al', 'data', 'name'], '') + # + # Treat actuator-specific data + # + datalist = getattrlist(descr, 'data') + prefix = '' + if type[-4:] == 'puck': + prefix = 'puck_' + elif type == 'mouse': + prefix = 'mouse_' + assign_members(act, datalist, [], prefix) + # + return act, actuatorname + + +# Build all sub-actuators and add them to the super-actuator. +# The super-actuator must already have been added to the panel. +# Sub-actuators with defined names are added as members to the panel +# so they can be referenced as p.name. +# +# Note: I have no idea how panel.endgroup() works when applied +# to a sub-actuator. +# +def build_subactuators(panel, super_act, al): + # + # This is nearly the same loop as below in build_panel(), + # except a call is made to addsubact() instead of addact(). + # + for a in al: + act, name = build_actuator(a) + act.addsubact(super_act) + if name: + stmt = 'panel.' + name + ' = act' + if debug: print 'exec', stmt + exec stmt + '\n' + if is_endgroup(a): + panel.endgroup() + sub_al = getattrlist(a, 'al') + if sub_al: + build_subactuators(panel, act, sub_al) + # + # Fix the actuator to which whe just added subactuators. + # This can't hurt (I hope) and is needed for the scroll actuator. + # + super_act.fixact() + + +# Build a real panel from a panel definition. +# Return a panel object p, where for each named actuator a, p.name is a +# reference to a. +# +def build_panel(descr): + # + # Sanity check + # + if (not descr) or descr[0] <> 'panel': + raise panel_error, 'panel description must start with "panel"' + # + if debug: show_panel('', descr) + # + # Create an empty panel + # + panel = pnl.mkpanel() + # + # Assign panel attributes + # + assign_members(panel, descr[1:], ['al'], '') + # + # Look for actuator list + # + al = getattrlist(descr, 'al') + # + # The order in which actuators are created is important + # because of the endgroup() operator. + # Unfortunately the Panel Editor outputs the actuator list + # in reverse order, so we reverse it here. + # + al = reverse(al) + # + for a in al: + act, name = build_actuator(a) + act.addact(panel) + if name: + stmt = 'panel.' + name + ' = act' + exec stmt + '\n' + if is_endgroup(a): + panel.endgroup() + sub_al = getattrlist(a, 'al') + if sub_al: + build_subactuators(panel, act, sub_al) + # + return panel + + +# Wrapper around pnl.dopanel() which calls call-back functions. +# +def my_dopanel(): + # Extract only the first 4 elements to allow for future expansion + a, down, active, up = pnl.dopanel()[:4] + if down: + down.downfunc(down) + if active: + active.activefunc(active) + if up: + up.upfunc(up) + return a + + +# Create one or more panels from a description file (S-expressions) +# generated by the Panel Editor. +# +def defpanellist(file): + import panelparser + descrlist = panelparser.parse_file(open(file, 'r')) + panellist = [] + for descr in descrlist: + panellist.append(build_panel(descr)) + return panellist + + +# Import everything from built-in method pnl, so the user can always +# use panel.foo() instead of pnl.foo(). +# This gives *no* performance penalty once this module is imported. +# +from pnl import * # for export + +dopanel = my_dopanel # override pnl.dopanel |