symbian-qemu-0.9.1-12/python-2.6.1/Demo/tkinter/guido/AttrDialog.py
author Gareth Stockwell <gareth.stockwell@accenture.com>
Wed, 22 Sep 2010 15:40:40 +0100
branchgraphics-phase-3
changeset 111 345f1c88c950
parent 1 2fb8b9db1c86
permissions -rw-r--r--
Fixes to syborg-graphicswrapper.vcproj These changes allow syborg-graphicswrapper to link against the hostthreadadapter and khronosapiwrapper libraries built by the graphics.simulator component. The .vcproj file uses relative paths, which requires that the following three packages are laid out as follows: os/ graphics adapt/ graphics.simulator qemu


# The options of a widget are described by the following attributes
# of the Pack and Widget dialogs:
#
# Dialog.current: {name: value}
# -- changes during Widget's lifetime
#
# Dialog.options: {name: (default, klass)}
# -- depends on widget class only
#
# Dialog.classes: {klass: (v0, v1, v2, ...) | 'boolean' | 'other'}
# -- totally static, though different between PackDialog and WidgetDialog
#    (but even that could be unified)

from Tkinter import *

class Option:

    varclass = StringVar            # May be overridden

    def __init__(self, dialog, option):
        self.dialog = dialog
        self.option = option
        self.master = dialog.top
        self.default, self.klass = dialog.options[option]
        self.var = self.varclass(self.master)
        self.frame = Frame(self.master)
        self.frame.pack(fill=X)
        self.label = Label(self.frame, text=(option + ":"))
        self.label.pack(side=LEFT)
        self.update()
        self.addoption()

    def refresh(self):
        self.dialog.refresh()
        self.update()

    def update(self):
        try:
            self.current = self.dialog.current[self.option]
        except KeyError:
            self.current = self.default
        self.var.set(self.current)

    def set(self, e=None):          # Should be overridden
        pass

class BooleanOption(Option):

    varclass = BooleanVar

    def addoption(self):
        self.button = Checkbutton(self.frame,
                                 text='on/off',
                                 onvalue=1,
                                 offvalue=0,
                                 variable=self.var,
                                 relief=RAISED,
                                 borderwidth=2,
                                 command=self.set)
        self.button.pack(side=RIGHT)

class EnumOption(Option):

    def addoption(self):
        self.button = Menubutton(self.frame,
                                 textvariable=self.var,
                                 relief=RAISED, borderwidth=2)
        self.button.pack(side=RIGHT)
        self.menu = Menu(self.button)
        self.button['menu'] = self.menu
        for v in self.dialog.classes[self.klass]:
            self.menu.add_radiobutton(
                label=v,
                variable=self.var,
                value=v,
                command=self.set)

class StringOption(Option):

    def addoption(self):
        self.entry = Entry(self.frame,
                           textvariable=self.var,
                           width=10,
                           relief=SUNKEN,
                           borderwidth=2)
        self.entry.pack(side=RIGHT, fill=X, expand=1)
        self.entry.bind('<Return>', self.set)

class ReadonlyOption(Option):

    def addoption(self):
        self.label = Label(self.frame, textvariable=self.var,
                           anchor=E)
        self.label.pack(side=RIGHT)

class Dialog:

    def __init__(self, master):
        self.master = master
        self.fixclasses()
        self.refresh()
        self.top = Toplevel(self.master)
        self.top.title(self.__class__.__name__)
        self.top.minsize(1, 1)
        self.addchoices()

    def refresh(self): pass         # Must override

    def fixclasses(self): pass      # May override

    def addchoices(self):
        self.choices = {}
        list = []
        for k, dc in self.options.items():
            list.append((k, dc))
        list.sort()
        for k, (d, c) in list:
            try:
                cl = self.classes[c]
            except KeyError:
                cl = 'unknown'
            if type(cl) == TupleType:
                cl = self.enumoption
            elif cl == 'boolean':
                cl = self.booleanoption
            elif cl == 'readonly':
                cl = self.readonlyoption
            else:
                cl = self.stringoption
            self.choices[k] = cl(self, k)

    # Must override:
    options = {}
    classes = {}

    # May override:
    booleanoption = BooleanOption
    stringoption = StringOption
    enumoption = EnumOption
    readonlyoption = ReadonlyOption

class PackDialog(Dialog):

    def __init__(self, widget):
        self.widget = widget
        Dialog.__init__(self, widget)

    def refresh(self):
        self.current = self.widget.info()
        self.current['.class'] = self.widget.winfo_class()
        self.current['.name'] = self.widget._w

    class packoption: # Mix-in class
        def set(self, e=None):
            self.current = self.var.get()
            try:
                apply(self.dialog.widget.pack, (),
                      {self.option: self.current})
            except TclError, msg:
                print msg
                self.refresh()

    class booleanoption(packoption, BooleanOption): pass
    class enumoption(packoption, EnumOption): pass
    class stringoption(packoption, StringOption): pass
    class readonlyoption(packoption, ReadonlyOption): pass

    options = {
            '.class': (None, 'Class'),
            '.name': (None, 'Name'),
            'after': (None, 'Widget'),
            'anchor': ('center', 'Anchor'),
            'before': (None, 'Widget'),
            'expand': ('no', 'Boolean'),
            'fill': ('none', 'Fill'),
            'in': (None, 'Widget'),
            'ipadx': (0, 'Pad'),
            'ipady': (0, 'Pad'),
            'padx': (0, 'Pad'),
            'pady': (0, 'Pad'),
            'side': ('top', 'Side'),
            }

    classes = {
            'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER),
            'Boolean': 'boolean',
            'Class': 'readonly',
            'Expand': 'boolean',
            'Fill': (NONE, X, Y, BOTH),
            'Name': 'readonly',
            'Pad': 'pixel',
            'Side': (TOP, RIGHT, BOTTOM, LEFT),
            'Widget': 'readonly',
            }

class RemotePackDialog(PackDialog):

    def __init__(self, master, app, widget):
        self.master = master
        self.app = app
        self.widget = widget
        self.refresh()
        self.top = Toplevel(self.master)
        self.top.title(self.app + ' PackDialog')
        self.top.minsize(1, 1)
        self.addchoices()

    def refresh(self):
        try:
            words = self.master.tk.splitlist(
                    self.master.send(self.app,
                                     'pack',
                                     'info',
                                     self.widget))
        except TclError, msg:
            print msg
            return
        dict = {}
        for i in range(0, len(words), 2):
            key = words[i][1:]
            value = words[i+1]
            dict[key] = value
        dict['.class'] = self.master.send(self.app,
                                          'winfo',
                                          'class',
                                          self.widget)
        dict['.name'] = self.widget
        self.current = dict

    class remotepackoption: # Mix-in class
        def set(self, e=None):
            self.current = self.var.get()
            try:
                self.dialog.master.send(
                        self.dialog.app,
                        'pack',
                        'config',
                        self.dialog.widget,
                        '-'+self.option,
                        self.dialog.master.tk.merge(
                                self.current))
            except TclError, msg:
                print msg
                self.refresh()

    class booleanoption(remotepackoption, BooleanOption): pass
    class enumoption(remotepackoption, EnumOption): pass
    class stringoption(remotepackoption, StringOption): pass
    class readonlyoption(remotepackoption, ReadonlyOption): pass

class WidgetDialog(Dialog):

    def __init__(self, widget):
        self.widget = widget
        self.klass = widget.winfo_class()
        Dialog.__init__(self, widget)

    def fixclasses(self):
        if self.addclasses.has_key(self.klass):
            classes = {}
            for c in (self.classes,
                      self.addclasses[self.klass]):
                for k in c.keys():
                    classes[k] = c[k]
            self.classes = classes

    def refresh(self):
        self.configuration = self.widget.config()
        self.update()
        self.current['.class'] = self.widget.winfo_class()
        self.current['.name'] = self.widget._w

    def update(self):
        self.current = {}
        self.options = {}
        for k, v in self.configuration.items():
            if len(v) > 4:
                self.current[k] = v[4]
                self.options[k] = v[3], v[2] # default, klass
        self.options['.class'] = (None, 'Class')
        self.options['.name'] = (None, 'Name')

    class widgetoption: # Mix-in class
        def set(self, e=None):
            self.current = self.var.get()
            try:
                self.dialog.widget[self.option] = self.current
            except TclError, msg:
                print msg
                self.refresh()

    class booleanoption(widgetoption, BooleanOption): pass
    class enumoption(widgetoption, EnumOption): pass
    class stringoption(widgetoption, StringOption): pass
    class readonlyoption(widgetoption, ReadonlyOption): pass

    # Universal classes
    classes = {
            'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER),
            'Aspect': 'integer',
            'Background': 'color',
            'Bitmap': 'bitmap',
            'BorderWidth': 'pixel',
            'Class': 'readonly',
            'CloseEnough': 'double',
            'Command': 'command',
            'Confine': 'boolean',
            'Cursor': 'cursor',
            'CursorWidth': 'pixel',
            'DisabledForeground': 'color',
            'ExportSelection': 'boolean',
            'Font': 'font',
            'Foreground': 'color',
            'From': 'integer',
            'Geometry': 'geometry',
            'Height': 'pixel',
            'InsertWidth': 'time',
            'Justify': (LEFT, CENTER, RIGHT),
            'Label': 'string',
            'Length': 'pixel',
            'MenuName': 'widget',
            'Name': 'readonly',
            'OffTime': 'time',
            'OnTime': 'time',
            'Orient': (HORIZONTAL, VERTICAL),
            'Pad': 'pixel',
            'Relief': (RAISED, SUNKEN, FLAT, RIDGE, GROOVE),
            'RepeatDelay': 'time',
            'RepeatInterval': 'time',
            'ScrollCommand': 'command',
            'ScrollIncrement': 'pixel',
            'ScrollRegion': 'rectangle',
            'ShowValue': 'boolean',
            'SetGrid': 'boolean',
            'Sliderforeground': 'color',
            'SliderLength': 'pixel',
            'Text': 'string',
            'TickInterval': 'integer',
            'To': 'integer',
            'Underline': 'index',
            'Variable': 'variable',
            'Value': 'string',
            'Width': 'pixel',
            'Wrap': (NONE, CHAR, WORD),
            }

    # Classes that (may) differ per widget type
    _tristate = {'State': (NORMAL, ACTIVE, DISABLED)}
    _bistate = {'State': (NORMAL, DISABLED)}
    addclasses = {
            'Button': _tristate,
            'Radiobutton': _tristate,
            'Checkbutton': _tristate,
            'Entry': _bistate,
            'Text': _bistate,
            'Menubutton': _tristate,
            'Slider': _bistate,
            }

class RemoteWidgetDialog(WidgetDialog):

    def __init__(self, master, app, widget):
        self.app = app
        self.widget = widget
        self.klass = master.send(self.app,
                                 'winfo',
                                 'class',
                                 self.widget)
        Dialog.__init__(self, master)

    def refresh(self):
        try:
            items = self.master.tk.splitlist(
                    self.master.send(self.app,
                                     self.widget,
                                     'config'))
        except TclError, msg:
            print msg
            return
        dict = {}
        for item in items:
            words = self.master.tk.splitlist(item)
            key = words[0][1:]
            value = (key,) + words[1:]
            dict[key] = value
        self.configuration = dict
        self.update()
        self.current['.class'] = self.klass
        self.current['.name'] = self.widget

    class remotewidgetoption: # Mix-in class
        def set(self, e=None):
            self.current = self.var.get()
            try:
                self.dialog.master.send(
                        self.dialog.app,
                        self.dialog.widget,
                        'config',
                        '-'+self.option,
                        self.current)
            except TclError, msg:
                print msg
                self.refresh()

    class booleanoption(remotewidgetoption, BooleanOption): pass
    class enumoption(remotewidgetoption, EnumOption): pass
    class stringoption(remotewidgetoption, StringOption): pass
    class readonlyoption(remotewidgetoption, ReadonlyOption): pass

def test():
    import sys
    root = Tk()
    root.minsize(1, 1)
    if sys.argv[1:]:
        remotetest(root, sys.argv[1])
    else:
        frame = Frame(root, name='frame')
        frame.pack(expand=1, fill=BOTH)
        button = Button(frame, name='button', text='button')
        button.pack(expand=1)
        canvas = Canvas(frame, name='canvas')
        canvas.pack()
        fpd = PackDialog(frame)
        fwd = WidgetDialog(frame)
        bpd = PackDialog(button)
        bwd = WidgetDialog(button)
        cpd = PackDialog(canvas)
        cwd = WidgetDialog(canvas)
    root.mainloop()

def remotetest(root, app):
    from listtree import listtree
    list = listtree(root, app)
    list.bind('<Any-Double-1>', opendialogs)
    list.app = app                  # Pass it on to handler

def opendialogs(e):
    import string
    list = e.widget
    sel = list.curselection()
    for i in sel:
        item = list.get(i)
        widget = string.split(item)[0]
        RemoteWidgetDialog(list, list.app, widget)
        if widget == '.': continue
        try:
            RemotePackDialog(list, list.app, widget)
        except TclError, msg:
            print msg

test()