2 # The options of a widget are described by the following attributes
3 # of the Pack and Widget dialogs:
5 # Dialog.current: {name: value}
6 # -- changes during Widget's lifetime
8 # Dialog.options: {name: (default, klass)}
9 # -- depends on widget class only
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)
19 varclass
= StringVar
# May be overridden
21 def __init__(self
, dialog
, 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
)
40 self
.current
= self
.dialog
.current
[self
.option
]
42 self
.current
= self
.default
43 self
.var
.set(self
.current
)
45 def set(self
, e
=None): # Should be overridden
48 class BooleanOption(Option
):
53 self
.button
= Checkbutton(self
.frame
,
61 self
.button
.pack(side
=RIGHT
)
63 class EnumOption(Option
):
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(
79 class StringOption(Option
):
82 self
.entry
= Entry(self
.frame
,
83 textvariable
=self
.var
,
87 self
.entry
.pack(side
=RIGHT
, fill
=X
, expand
=1)
88 self
.entry
.bind('<Return>', self
.set)
90 class ReadonlyOption(Option
):
93 self
.label
= Label(self
.frame
, textvariable
=self
.var
,
95 self
.label
.pack(side
=RIGHT
)
99 def __init__(self
, master
):
103 self
.top
= Toplevel(self
.master
)
104 self
.top
.title(self
.__class
__.__name
__)
105 self
.top
.minsize(1, 1)
108 def refresh(self
): pass # Must override
110 def fixclasses(self
): pass # May override
112 def addchoices(self
):
115 for k
, dc
in self
.options
.items():
118 for k
, (d
, c
) in list:
123 if type(cl
) == TupleType
:
125 elif cl
== 'boolean':
126 cl
= self
.booleanoption
127 elif cl
== 'readonly':
128 cl
= self
.readonlyoption
130 cl
= self
.stringoption
131 self
.choices
[k
] = cl(self
, k
)
138 booleanoption
= BooleanOption
139 stringoption
= StringOption
140 enumoption
= EnumOption
141 readonlyoption
= ReadonlyOption
143 class PackDialog(Dialog
):
145 def __init__(self
, widget
):
147 Dialog
.__init
__(self
, widget
)
150 self
.current
= self
.widget
.info()
151 self
.current
['.class'] = self
.widget
.winfo_class()
152 self
.current
['.name'] = self
.widget
._w
154 class packoption
: # Mix-in class
155 def set(self
, e
=None):
156 self
.current
= self
.var
.get()
158 apply(self
.dialog
.widget
.pack
, (),
159 {self
.option
: self
.current
})
160 except TclError
, msg
:
164 class booleanoption(packoption
, BooleanOption
): pass
165 class enumoption(packoption
, EnumOption
): pass
166 class stringoption(packoption
, StringOption
): pass
167 class readonlyoption(packoption
, ReadonlyOption
): pass
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'),
182 'side': ('top', 'Side'),
186 'Anchor': (N
, NE
, E
, SE
, S
, SW
, W
, NW
, CENTER
),
187 'Boolean': 'boolean',
190 'Fill': (NONE
, X
, Y
, BOTH
),
193 'Side': (TOP
, RIGHT
, BOTTOM
, LEFT
),
194 'Widget': 'readonly',
197 class RemotePackDialog(PackDialog
):
199 def __init__(self
, master
, app
, widget
):
204 self
.top
= Toplevel(self
.master
)
205 self
.top
.title(self
.app
+ ' PackDialog')
206 self
.top
.minsize(1, 1)
211 words
= self
.master
.tk
.splitlist(
212 self
.master
.send(self
.app
,
216 except TclError
, msg
:
220 for i
in range(0, len(words
), 2):
224 dict['.class'] = self
.master
.send(self
.app
,
228 dict['.name'] = self
.widget
231 class remotepackoption
: # Mix-in class
232 def set(self
, e
=None):
233 self
.current
= self
.var
.get()
235 self
.dialog
.master
.send(
241 self
.dialog
.master
.tk
.merge(
243 except TclError
, msg
:
247 class booleanoption(remotepackoption
, BooleanOption
): pass
248 class enumoption(remotepackoption
, EnumOption
): pass
249 class stringoption(remotepackoption
, StringOption
): pass
250 class readonlyoption(remotepackoption
, ReadonlyOption
): pass
252 class WidgetDialog(Dialog
):
254 def __init__(self
, widget
):
256 self
.klass
= widget
.winfo_class()
257 Dialog
.__init
__(self
, widget
)
259 def fixclasses(self
):
260 if self
.addclasses
.has_key(self
.klass
):
262 for c
in (self
.classes
,
263 self
.addclasses
[self
.klass
]):
266 self
.classes
= classes
269 self
.configuration
= self
.widget
.config()
271 self
.current
['.class'] = self
.widget
.winfo_class()
272 self
.current
['.name'] = self
.widget
._w
277 for k
, v
in self
.configuration
.items():
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')
284 class widgetoption
: # Mix-in class
285 def set(self
, e
=None):
286 self
.current
= self
.var
.get()
288 self
.dialog
.widget
[self
.option
] = self
.current
289 except TclError
, msg
:
293 class booleanoption(widgetoption
, BooleanOption
): pass
294 class enumoption(widgetoption
, EnumOption
): pass
295 class stringoption(widgetoption
, StringOption
): pass
296 class readonlyoption(widgetoption
, ReadonlyOption
): pass
300 'Anchor': (N
, NE
, E
, SE
, S
, SW
, W
, NW
, CENTER
),
302 'Background': 'color',
304 'BorderWidth': 'pixel',
306 'CloseEnough': 'double',
307 'Command': 'command',
308 'Confine': 'boolean',
310 'CursorWidth': 'pixel',
311 'DisabledForeground': 'color',
312 'ExportSelection': 'boolean',
314 'Foreground': 'color',
316 'Geometry': 'geometry',
318 'InsertWidth': 'time',
319 'Justify': (LEFT
, CENTER
, RIGHT
),
322 'MenuName': 'widget',
326 'Orient': (HORIZONTAL
, VERTICAL
),
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',
339 'TickInterval': 'integer',
341 'Underline': 'index',
342 'Variable': 'variable',
345 'Wrap': (NONE
, CHAR
, WORD
),
348 # Classes that (may) differ per widget type
349 _tristate
= {'State': (NORMAL
, ACTIVE
, DISABLED
)}
350 _bistate
= {'State': (NORMAL
, DISABLED
)}
353 'Radiobutton': _tristate
,
354 'Checkbutton': _tristate
,
357 'Menubutton': _tristate
,
361 class RemoteWidgetDialog(WidgetDialog
):
363 def __init__(self
, master
, app
, widget
):
366 self
.klass
= master
.send(self
.app
,
370 Dialog
.__init
__(self
, master
)
374 items
= self
.master
.tk
.splitlist(
375 self
.master
.send(self
.app
,
378 except TclError
, msg
:
383 words
= self
.master
.tk
.splitlist(item
)
385 value
= (key
,) + words
[1:]
387 self
.configuration
= dict
389 self
.current
['.class'] = self
.klass
390 self
.current
['.name'] = self
.widget
392 class remotewidgetoption
: # Mix-in class
393 def set(self
, e
=None):
394 self
.current
= self
.var
.get()
396 self
.dialog
.master
.send(
402 except TclError
, msg
:
406 class booleanoption(remotewidgetoption
, BooleanOption
): pass
407 class enumoption(remotewidgetoption
, EnumOption
): pass
408 class stringoption(remotewidgetoption
, StringOption
): pass
409 class readonlyoption(remotewidgetoption
, ReadonlyOption
): pass
416 remotetest(root
, sys
.argv
[1])
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')
424 fpd
= PackDialog(frame
)
425 fwd
= WidgetDialog(frame
)
426 bpd
= PackDialog(button
)
427 bwd
= WidgetDialog(button
)
428 cpd
= PackDialog(canvas
)
429 cwd
= WidgetDialog(canvas
)
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
441 sel
= list.curselection()
444 widget
= string
.split(item
)[0]
445 RemoteWidgetDialog(list, list.app
, widget
)
446 if widget
== '.': continue
448 RemotePackDialog(list, list.app
, widget
)
449 except TclError
, msg
: