symbian-qemu-0.9.1-12/python-2.6.1/Demo/tkinter/guido/AttrDialog.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 
       
     2 # The options of a widget are described by the following attributes
       
     3 # of the Pack and Widget dialogs:
       
     4 #
       
     5 # Dialog.current: {name: value}
       
     6 # -- changes during Widget's lifetime
       
     7 #
       
     8 # Dialog.options: {name: (default, klass)}
       
     9 # -- depends on widget class only
       
    10 #
       
    11 # Dialog.classes: {klass: (v0, v1, v2, ...) | 'boolean' | 'other'}
       
    12 # -- totally static, though different between PackDialog and WidgetDialog
       
    13 #    (but even that could be unified)
       
    14 
       
    15 from Tkinter import *
       
    16 
       
    17 class Option:
       
    18 
       
    19     varclass = StringVar            # May be overridden
       
    20 
       
    21     def __init__(self, dialog, option):
       
    22         self.dialog = dialog
       
    23         self.option = option
       
    24         self.master = dialog.top
       
    25         self.default, self.klass = dialog.options[option]
       
    26         self.var = self.varclass(self.master)
       
    27         self.frame = Frame(self.master)
       
    28         self.frame.pack(fill=X)
       
    29         self.label = Label(self.frame, text=(option + ":"))
       
    30         self.label.pack(side=LEFT)
       
    31         self.update()
       
    32         self.addoption()
       
    33 
       
    34     def refresh(self):
       
    35         self.dialog.refresh()
       
    36         self.update()
       
    37 
       
    38     def update(self):
       
    39         try:
       
    40             self.current = self.dialog.current[self.option]
       
    41         except KeyError:
       
    42             self.current = self.default
       
    43         self.var.set(self.current)
       
    44 
       
    45     def set(self, e=None):          # Should be overridden
       
    46         pass
       
    47 
       
    48 class BooleanOption(Option):
       
    49 
       
    50     varclass = BooleanVar
       
    51 
       
    52     def addoption(self):
       
    53         self.button = Checkbutton(self.frame,
       
    54                                  text='on/off',
       
    55                                  onvalue=1,
       
    56                                  offvalue=0,
       
    57                                  variable=self.var,
       
    58                                  relief=RAISED,
       
    59                                  borderwidth=2,
       
    60                                  command=self.set)
       
    61         self.button.pack(side=RIGHT)
       
    62 
       
    63 class EnumOption(Option):
       
    64 
       
    65     def addoption(self):
       
    66         self.button = Menubutton(self.frame,
       
    67                                  textvariable=self.var,
       
    68                                  relief=RAISED, borderwidth=2)
       
    69         self.button.pack(side=RIGHT)
       
    70         self.menu = Menu(self.button)
       
    71         self.button['menu'] = self.menu
       
    72         for v in self.dialog.classes[self.klass]:
       
    73             self.menu.add_radiobutton(
       
    74                 label=v,
       
    75                 variable=self.var,
       
    76                 value=v,
       
    77                 command=self.set)
       
    78 
       
    79 class StringOption(Option):
       
    80 
       
    81     def addoption(self):
       
    82         self.entry = Entry(self.frame,
       
    83                            textvariable=self.var,
       
    84                            width=10,
       
    85                            relief=SUNKEN,
       
    86                            borderwidth=2)
       
    87         self.entry.pack(side=RIGHT, fill=X, expand=1)
       
    88         self.entry.bind('<Return>', self.set)
       
    89 
       
    90 class ReadonlyOption(Option):
       
    91 
       
    92     def addoption(self):
       
    93         self.label = Label(self.frame, textvariable=self.var,
       
    94                            anchor=E)
       
    95         self.label.pack(side=RIGHT)
       
    96 
       
    97 class Dialog:
       
    98 
       
    99     def __init__(self, master):
       
   100         self.master = master
       
   101         self.fixclasses()
       
   102         self.refresh()
       
   103         self.top = Toplevel(self.master)
       
   104         self.top.title(self.__class__.__name__)
       
   105         self.top.minsize(1, 1)
       
   106         self.addchoices()
       
   107 
       
   108     def refresh(self): pass         # Must override
       
   109 
       
   110     def fixclasses(self): pass      # May override
       
   111 
       
   112     def addchoices(self):
       
   113         self.choices = {}
       
   114         list = []
       
   115         for k, dc in self.options.items():
       
   116             list.append((k, dc))
       
   117         list.sort()
       
   118         for k, (d, c) in list:
       
   119             try:
       
   120                 cl = self.classes[c]
       
   121             except KeyError:
       
   122                 cl = 'unknown'
       
   123             if type(cl) == TupleType:
       
   124                 cl = self.enumoption
       
   125             elif cl == 'boolean':
       
   126                 cl = self.booleanoption
       
   127             elif cl == 'readonly':
       
   128                 cl = self.readonlyoption
       
   129             else:
       
   130                 cl = self.stringoption
       
   131             self.choices[k] = cl(self, k)
       
   132 
       
   133     # Must override:
       
   134     options = {}
       
   135     classes = {}
       
   136 
       
   137     # May override:
       
   138     booleanoption = BooleanOption
       
   139     stringoption = StringOption
       
   140     enumoption = EnumOption
       
   141     readonlyoption = ReadonlyOption
       
   142 
       
   143 class PackDialog(Dialog):
       
   144 
       
   145     def __init__(self, widget):
       
   146         self.widget = widget
       
   147         Dialog.__init__(self, widget)
       
   148 
       
   149     def refresh(self):
       
   150         self.current = self.widget.info()
       
   151         self.current['.class'] = self.widget.winfo_class()
       
   152         self.current['.name'] = self.widget._w
       
   153 
       
   154     class packoption: # Mix-in class
       
   155         def set(self, e=None):
       
   156             self.current = self.var.get()
       
   157             try:
       
   158                 apply(self.dialog.widget.pack, (),
       
   159                       {self.option: self.current})
       
   160             except TclError, msg:
       
   161                 print msg
       
   162                 self.refresh()
       
   163 
       
   164     class booleanoption(packoption, BooleanOption): pass
       
   165     class enumoption(packoption, EnumOption): pass
       
   166     class stringoption(packoption, StringOption): pass
       
   167     class readonlyoption(packoption, ReadonlyOption): pass
       
   168 
       
   169     options = {
       
   170             '.class': (None, 'Class'),
       
   171             '.name': (None, 'Name'),
       
   172             'after': (None, 'Widget'),
       
   173             'anchor': ('center', 'Anchor'),
       
   174             'before': (None, 'Widget'),
       
   175             'expand': ('no', 'Boolean'),
       
   176             'fill': ('none', 'Fill'),
       
   177             'in': (None, 'Widget'),
       
   178             'ipadx': (0, 'Pad'),
       
   179             'ipady': (0, 'Pad'),
       
   180             'padx': (0, 'Pad'),
       
   181             'pady': (0, 'Pad'),
       
   182             'side': ('top', 'Side'),
       
   183             }
       
   184 
       
   185     classes = {
       
   186             'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER),
       
   187             'Boolean': 'boolean',
       
   188             'Class': 'readonly',
       
   189             'Expand': 'boolean',
       
   190             'Fill': (NONE, X, Y, BOTH),
       
   191             'Name': 'readonly',
       
   192             'Pad': 'pixel',
       
   193             'Side': (TOP, RIGHT, BOTTOM, LEFT),
       
   194             'Widget': 'readonly',
       
   195             }
       
   196 
       
   197 class RemotePackDialog(PackDialog):
       
   198 
       
   199     def __init__(self, master, app, widget):
       
   200         self.master = master
       
   201         self.app = app
       
   202         self.widget = widget
       
   203         self.refresh()
       
   204         self.top = Toplevel(self.master)
       
   205         self.top.title(self.app + ' PackDialog')
       
   206         self.top.minsize(1, 1)
       
   207         self.addchoices()
       
   208 
       
   209     def refresh(self):
       
   210         try:
       
   211             words = self.master.tk.splitlist(
       
   212                     self.master.send(self.app,
       
   213                                      'pack',
       
   214                                      'info',
       
   215                                      self.widget))
       
   216         except TclError, msg:
       
   217             print msg
       
   218             return
       
   219         dict = {}
       
   220         for i in range(0, len(words), 2):
       
   221             key = words[i][1:]
       
   222             value = words[i+1]
       
   223             dict[key] = value
       
   224         dict['.class'] = self.master.send(self.app,
       
   225                                           'winfo',
       
   226                                           'class',
       
   227                                           self.widget)
       
   228         dict['.name'] = self.widget
       
   229         self.current = dict
       
   230 
       
   231     class remotepackoption: # Mix-in class
       
   232         def set(self, e=None):
       
   233             self.current = self.var.get()
       
   234             try:
       
   235                 self.dialog.master.send(
       
   236                         self.dialog.app,
       
   237                         'pack',
       
   238                         'config',
       
   239                         self.dialog.widget,
       
   240                         '-'+self.option,
       
   241                         self.dialog.master.tk.merge(
       
   242                                 self.current))
       
   243             except TclError, msg:
       
   244                 print msg
       
   245                 self.refresh()
       
   246 
       
   247     class booleanoption(remotepackoption, BooleanOption): pass
       
   248     class enumoption(remotepackoption, EnumOption): pass
       
   249     class stringoption(remotepackoption, StringOption): pass
       
   250     class readonlyoption(remotepackoption, ReadonlyOption): pass
       
   251 
       
   252 class WidgetDialog(Dialog):
       
   253 
       
   254     def __init__(self, widget):
       
   255         self.widget = widget
       
   256         self.klass = widget.winfo_class()
       
   257         Dialog.__init__(self, widget)
       
   258 
       
   259     def fixclasses(self):
       
   260         if self.addclasses.has_key(self.klass):
       
   261             classes = {}
       
   262             for c in (self.classes,
       
   263                       self.addclasses[self.klass]):
       
   264                 for k in c.keys():
       
   265                     classes[k] = c[k]
       
   266             self.classes = classes
       
   267 
       
   268     def refresh(self):
       
   269         self.configuration = self.widget.config()
       
   270         self.update()
       
   271         self.current['.class'] = self.widget.winfo_class()
       
   272         self.current['.name'] = self.widget._w
       
   273 
       
   274     def update(self):
       
   275         self.current = {}
       
   276         self.options = {}
       
   277         for k, v in self.configuration.items():
       
   278             if len(v) > 4:
       
   279                 self.current[k] = v[4]
       
   280                 self.options[k] = v[3], v[2] # default, klass
       
   281         self.options['.class'] = (None, 'Class')
       
   282         self.options['.name'] = (None, 'Name')
       
   283 
       
   284     class widgetoption: # Mix-in class
       
   285         def set(self, e=None):
       
   286             self.current = self.var.get()
       
   287             try:
       
   288                 self.dialog.widget[self.option] = self.current
       
   289             except TclError, msg:
       
   290                 print msg
       
   291                 self.refresh()
       
   292 
       
   293     class booleanoption(widgetoption, BooleanOption): pass
       
   294     class enumoption(widgetoption, EnumOption): pass
       
   295     class stringoption(widgetoption, StringOption): pass
       
   296     class readonlyoption(widgetoption, ReadonlyOption): pass
       
   297 
       
   298     # Universal classes
       
   299     classes = {
       
   300             'Anchor': (N, NE, E, SE, S, SW, W, NW, CENTER),
       
   301             'Aspect': 'integer',
       
   302             'Background': 'color',
       
   303             'Bitmap': 'bitmap',
       
   304             'BorderWidth': 'pixel',
       
   305             'Class': 'readonly',
       
   306             'CloseEnough': 'double',
       
   307             'Command': 'command',
       
   308             'Confine': 'boolean',
       
   309             'Cursor': 'cursor',
       
   310             'CursorWidth': 'pixel',
       
   311             'DisabledForeground': 'color',
       
   312             'ExportSelection': 'boolean',
       
   313             'Font': 'font',
       
   314             'Foreground': 'color',
       
   315             'From': 'integer',
       
   316             'Geometry': 'geometry',
       
   317             'Height': 'pixel',
       
   318             'InsertWidth': 'time',
       
   319             'Justify': (LEFT, CENTER, RIGHT),
       
   320             'Label': 'string',
       
   321             'Length': 'pixel',
       
   322             'MenuName': 'widget',
       
   323             'Name': 'readonly',
       
   324             'OffTime': 'time',
       
   325             'OnTime': 'time',
       
   326             'Orient': (HORIZONTAL, VERTICAL),
       
   327             'Pad': 'pixel',
       
   328             'Relief': (RAISED, SUNKEN, FLAT, RIDGE, GROOVE),
       
   329             'RepeatDelay': 'time',
       
   330             'RepeatInterval': 'time',
       
   331             'ScrollCommand': 'command',
       
   332             'ScrollIncrement': 'pixel',
       
   333             'ScrollRegion': 'rectangle',
       
   334             'ShowValue': 'boolean',
       
   335             'SetGrid': 'boolean',
       
   336             'Sliderforeground': 'color',
       
   337             'SliderLength': 'pixel',
       
   338             'Text': 'string',
       
   339             'TickInterval': 'integer',
       
   340             'To': 'integer',
       
   341             'Underline': 'index',
       
   342             'Variable': 'variable',
       
   343             'Value': 'string',
       
   344             'Width': 'pixel',
       
   345             'Wrap': (NONE, CHAR, WORD),
       
   346             }
       
   347 
       
   348     # Classes that (may) differ per widget type
       
   349     _tristate = {'State': (NORMAL, ACTIVE, DISABLED)}
       
   350     _bistate = {'State': (NORMAL, DISABLED)}
       
   351     addclasses = {
       
   352             'Button': _tristate,
       
   353             'Radiobutton': _tristate,
       
   354             'Checkbutton': _tristate,
       
   355             'Entry': _bistate,
       
   356             'Text': _bistate,
       
   357             'Menubutton': _tristate,
       
   358             'Slider': _bistate,
       
   359             }
       
   360 
       
   361 class RemoteWidgetDialog(WidgetDialog):
       
   362 
       
   363     def __init__(self, master, app, widget):
       
   364         self.app = app
       
   365         self.widget = widget
       
   366         self.klass = master.send(self.app,
       
   367                                  'winfo',
       
   368                                  'class',
       
   369                                  self.widget)
       
   370         Dialog.__init__(self, master)
       
   371 
       
   372     def refresh(self):
       
   373         try:
       
   374             items = self.master.tk.splitlist(
       
   375                     self.master.send(self.app,
       
   376                                      self.widget,
       
   377                                      'config'))
       
   378         except TclError, msg:
       
   379             print msg
       
   380             return
       
   381         dict = {}
       
   382         for item in items:
       
   383             words = self.master.tk.splitlist(item)
       
   384             key = words[0][1:]
       
   385             value = (key,) + words[1:]
       
   386             dict[key] = value
       
   387         self.configuration = dict
       
   388         self.update()
       
   389         self.current['.class'] = self.klass
       
   390         self.current['.name'] = self.widget
       
   391 
       
   392     class remotewidgetoption: # Mix-in class
       
   393         def set(self, e=None):
       
   394             self.current = self.var.get()
       
   395             try:
       
   396                 self.dialog.master.send(
       
   397                         self.dialog.app,
       
   398                         self.dialog.widget,
       
   399                         'config',
       
   400                         '-'+self.option,
       
   401                         self.current)
       
   402             except TclError, msg:
       
   403                 print msg
       
   404                 self.refresh()
       
   405 
       
   406     class booleanoption(remotewidgetoption, BooleanOption): pass
       
   407     class enumoption(remotewidgetoption, EnumOption): pass
       
   408     class stringoption(remotewidgetoption, StringOption): pass
       
   409     class readonlyoption(remotewidgetoption, ReadonlyOption): pass
       
   410 
       
   411 def test():
       
   412     import sys
       
   413     root = Tk()
       
   414     root.minsize(1, 1)
       
   415     if sys.argv[1:]:
       
   416         remotetest(root, sys.argv[1])
       
   417     else:
       
   418         frame = Frame(root, name='frame')
       
   419         frame.pack(expand=1, fill=BOTH)
       
   420         button = Button(frame, name='button', text='button')
       
   421         button.pack(expand=1)
       
   422         canvas = Canvas(frame, name='canvas')
       
   423         canvas.pack()
       
   424         fpd = PackDialog(frame)
       
   425         fwd = WidgetDialog(frame)
       
   426         bpd = PackDialog(button)
       
   427         bwd = WidgetDialog(button)
       
   428         cpd = PackDialog(canvas)
       
   429         cwd = WidgetDialog(canvas)
       
   430     root.mainloop()
       
   431 
       
   432 def remotetest(root, app):
       
   433     from listtree import listtree
       
   434     list = listtree(root, app)
       
   435     list.bind('<Any-Double-1>', opendialogs)
       
   436     list.app = app                  # Pass it on to handler
       
   437 
       
   438 def opendialogs(e):
       
   439     import string
       
   440     list = e.widget
       
   441     sel = list.curselection()
       
   442     for i in sel:
       
   443         item = list.get(i)
       
   444         widget = string.split(item)[0]
       
   445         RemoteWidgetDialog(list, list.app, widget)
       
   446         if widget == '.': continue
       
   447         try:
       
   448             RemotePackDialog(list, list.app, widget)
       
   449         except TclError, msg:
       
   450             print msg
       
   451 
       
   452 test()