mirror of https://github.com/python/cpython
Initial revision
This commit is contained in:
parent
69170c5d79
commit
3e395be1ee
|
@ -0,0 +1,283 @@
|
|||
|
||||
# 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:
|
||||
|
||||
def __init__(self, packdialog, option, varclass):
|
||||
self.packdialog = packdialog
|
||||
self.option = option
|
||||
self.master = packdialog.top
|
||||
self.default, self.klass = packdialog.options[option]
|
||||
self.var = varclass(self.master)
|
||||
self.frame = Frame(self.master,
|
||||
{Pack: {'expand': 0, 'fill': 'x'}})
|
||||
self.label = Label(self.frame,
|
||||
{'text': option + ':',
|
||||
Pack: {'side': 'left'},
|
||||
})
|
||||
self.update()
|
||||
|
||||
def refresh(self):
|
||||
self.packdialog.refresh()
|
||||
self.update()
|
||||
|
||||
def update(self):
|
||||
try:
|
||||
self.current = self.packdialog.current[self.option]
|
||||
except KeyError:
|
||||
self.current = self.default
|
||||
self.var.set(self.current)
|
||||
|
||||
def set(self, e=None):
|
||||
pass
|
||||
|
||||
class BooleanOption(Option):
|
||||
|
||||
def __init__(self, packdialog, option):
|
||||
Option.__init__(self, packdialog, option, BooleanVar)
|
||||
self.button = Checkbutton(self.frame,
|
||||
{'text': 'on/off',
|
||||
'onvalue': '1',
|
||||
'offvalue': '0',
|
||||
'variable': self.var,
|
||||
'relief': 'raised',
|
||||
'borderwidth': 2,
|
||||
'command': self.set,
|
||||
Pack: {'side': 'right'},
|
||||
})
|
||||
|
||||
class EnumOption(Option):
|
||||
|
||||
def __init__(self, packdialog, option):
|
||||
Option.__init__(self, packdialog, option, StringVar)
|
||||
self.button = Menubutton(self.frame,
|
||||
{'textvariable': self.var,
|
||||
'relief': 'raised',
|
||||
'borderwidth': 2,
|
||||
Pack: {'side': 'right'},
|
||||
})
|
||||
self.menu = Menu(self.button)
|
||||
self.button['menu'] = self.menu
|
||||
for v in self.packdialog.classes[self.klass]:
|
||||
label = v
|
||||
if v == self.default: label = label + ' (default)'
|
||||
self.menu.add_radiobutton(
|
||||
{'label': label,
|
||||
'variable': self.var,
|
||||
'value': v,
|
||||
'command': self.set,
|
||||
})
|
||||
|
||||
class StringOption(Option):
|
||||
|
||||
def __init__(self, packdialog, option):
|
||||
Option.__init__(self, packdialog, option, StringVar)
|
||||
self.entry = Entry(self.frame,
|
||||
{'textvariable': self.var,
|
||||
'width': 10,
|
||||
'relief': 'sunken',
|
||||
'borderwidth': 2,
|
||||
Pack: {'side': 'right',
|
||||
'fill': 'x', 'expand': 1},
|
||||
})
|
||||
self.entry.bind('<Return>', self.set)
|
||||
|
||||
class PackOption: # Mix-in class
|
||||
|
||||
def set(self, e=None):
|
||||
self.current = self.var.get()
|
||||
try:
|
||||
Pack.config(self.packdialog.widget,
|
||||
{self.option: self.current})
|
||||
except TclError:
|
||||
self.refresh()
|
||||
|
||||
class BooleanPackOption(PackOption, BooleanOption): pass
|
||||
class EnumPackOption(PackOption, EnumOption): pass
|
||||
class StringPackOption(PackOption, StringOption): pass
|
||||
|
||||
class PackDialog:
|
||||
|
||||
options = {
|
||||
'after': (None, 'Widet'),
|
||||
'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'),
|
||||
'Fill': ('none', 'x', 'y', 'both'),
|
||||
'Side': ('top', 'right', 'bottom', 'left'),
|
||||
'Expand': 'boolean',
|
||||
'Pad': 'pixel',
|
||||
'Widget': 'widget',
|
||||
}
|
||||
|
||||
def __init__(self, widget):
|
||||
self.widget = widget
|
||||
self.refresh()
|
||||
self.top = Toplevel(self.widget)
|
||||
self.top.title('Pack: %s' % widget.widgetName)
|
||||
self.top.minsize(1, 1) # XXX
|
||||
self.anchor = EnumPackOption(self, 'anchor')
|
||||
self.side = EnumPackOption(self, 'side')
|
||||
self.fill = EnumPackOption(self, 'fill')
|
||||
self.expand = BooleanPackOption(self, 'expand')
|
||||
self.ipadx = StringPackOption(self, 'ipadx')
|
||||
self.ipady = StringPackOption(self, 'ipady')
|
||||
self.padx = StringPackOption(self, 'padx')
|
||||
self.pady = StringPackOption(self, 'pady')
|
||||
# XXX after, before, in
|
||||
|
||||
def refresh(self):
|
||||
self.current = self.widget.newinfo()
|
||||
|
||||
class WidgetOption: # Mix-in class
|
||||
|
||||
def set(self, e=None):
|
||||
self.current = self.var.get()
|
||||
try:
|
||||
self.packdialog.widget[self.option] = self.current
|
||||
except TclError:
|
||||
self.refresh()
|
||||
|
||||
class BooleanWidgetOption(WidgetOption, BooleanOption): pass
|
||||
class EnumWidgetOption(WidgetOption, EnumOption): pass
|
||||
class StringWidgetOption(WidgetOption, StringOption): pass
|
||||
|
||||
class WidgetDialog:
|
||||
|
||||
# Universal classes
|
||||
classes = {
|
||||
'Anchor': ('n','ne', 'e','se', 's','sw', 'w','nw', 'center'),
|
||||
'Aspect': 'integer',
|
||||
'Background': 'color',
|
||||
'Bitmap': 'bitmap',
|
||||
'BorderWidth': 'pixel',
|
||||
'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',
|
||||
'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,
|
||||
}
|
||||
|
||||
|
||||
def __init__(self, widget):
|
||||
self.widget = widget
|
||||
if self.addclasses.has_key(self.widget.widgetName):
|
||||
classes = {}
|
||||
for c in (self.classes,
|
||||
self.addclasses[self.widget.widgetName]):
|
||||
for k in c.keys():
|
||||
classes[k] = c[k]
|
||||
self.classes = classes
|
||||
self.refresh()
|
||||
self.top = Toplevel(self.widget)
|
||||
self.top.title('Widget: %s' % widget.widgetName)
|
||||
self.top.minsize(1, 1)
|
||||
self.choices = {}
|
||||
for k, (d, c) in self.options.items():
|
||||
try:
|
||||
cl = self.classes[c]
|
||||
except KeyError:
|
||||
cl = 'unknown'
|
||||
if type(cl) == TupleType:
|
||||
cl = EnumWidgetOption
|
||||
elif cl == 'boolean':
|
||||
cl = BooleanWidgetOption
|
||||
else:
|
||||
cl = StringWidgetOption
|
||||
self.choices[k] = cl(self, k)
|
||||
|
||||
def refresh(self):
|
||||
self.configuration = self.widget.config()
|
||||
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
|
||||
|
||||
def test():
|
||||
root = Tk()
|
||||
root.minsize(1, 1)
|
||||
frame = Frame(root, {Pack: {'expand': 1, 'fill': 'both'}})
|
||||
button = Button(frame, {'text': 'button',
|
||||
Pack: {'expand': 1}})
|
||||
canvas = Canvas(frame, {Pack: {}})
|
||||
bpd = PackDialog(button)
|
||||
bwd = WidgetDialog(button)
|
||||
cpd = PackDialog(canvas)
|
||||
cwd = WidgetDialog(canvas)
|
||||
root.mainloop()
|
||||
|
||||
test()
|
Loading…
Reference in New Issue