[Python-checkins] r62714 - sandbox/trunk/ttk-gsoc/Lib/lib-tk/Ttk.py
guilherme.polo
python-checkins at python.org
Mon May 5 00:30:44 CEST 2008
Author: guilherme.polo
Date: Mon May 5 00:30:44 2008
New Revision: 62714
Log:
_format_optdict accepts sequences as values now and format them
correctly according to the script parameter, this function also
accepts an ignore parameter to discard elements (used by
_format_layoutdict).
Renamed LabelFrame to Labelframe.
ttk::style layout has been wrapped (after redoing it several times
this weekend), updated layout's docstring so it matches the current
implementation, updated theme_settings's docstring so it says that
'layout' key is accepted now.
added the function _format_layoutdict which does all the job
related to ttk::style layout.
Modified:
sandbox/trunk/ttk-gsoc/Lib/lib-tk/Ttk.py
Modified: sandbox/trunk/ttk-gsoc/Lib/lib-tk/Ttk.py
==============================================================================
--- sandbox/trunk/ttk-gsoc/Lib/lib-tk/Ttk.py (original)
+++ sandbox/trunk/ttk-gsoc/Lib/lib-tk/Ttk.py Mon May 5 00:30:44 2008
@@ -44,13 +44,27 @@
Tkinter.Tk._loadtk = _loadttk(Tkinter.Tk._loadtk)
-def _format_optdict(optdict):
+def _format_optdict(optdict, script=False, ignore=None):
"""Formats optdict to pass it to tk.call.
- E.g.:
- {'foreground': 'blue'} returns:
- ('-foreground', 'blue')"""
- opts = [("-%s" % opt, value) for opt, value in optdict.iteritems()]
+ E.g. (script=False):
+ {'foreground': 'blue', 'padding': [1, 2, 3, 4]} returns:
+ ('-foreground', 'blue', '-padding', '1 2 3 4')"""
+ format = "%s" if not script else "{%s}"
+
+ opts = []
+ for opt, value in optdict.iteritems():
+ if ignore and opt in ignore:
+ continue
+
+ # hasattr is used to guarantee that value is not an int, and isinstance
+ # guarantees it is not a string too
+ if hasattr(value, "__len__") and not isinstance(value, basestring):
+ # value is expected to be a sequence
+ value = format % ' '.join(map(str, value))
+
+ opts.append(("-%s" % opt, value))
+
return Tkinter._flatten(opts)
def _format_mapdict(mapdict, script=False):
@@ -85,6 +99,63 @@
return Tkinter._flatten(opts)
+def _format_layoutdict(layout, indent=2, child=False):
+ """Formats a layout dict so we can pass the result to ttk::style
+ layout and ttk::style map.
+
+ E.g.:
+ {"Menubutton.background": None,
+ "Menubutton.button": {"children": [("Menubutton.focus",
+ {"children": [("Menubutton.padding",
+ {"children": [("Menubutton.label",
+ {"side": "left", "expand": 1})]
+ })
+ ]})
+ ]},
+ "Menubutton.indicator": {"side": "right"}
+ })
+
+ returns:
+
+ Menubutton.background
+ Menubutton.button -children {
+ Menubutton.focus -children {
+ Menubutton.padding -children {
+ Menubutton.label -side left -expand 1
+ }
+ }
+ }
+ Menubutton.indicator -side right"""
+ # XXX right now I'm concatenating the text a lot of times, I expect
+ # to change this to list appending and then use some joins and
+ # (ab)use some flattening.
+ text = ""
+
+ if child:
+ sublayouts = [layout.pop("children")] # sublayouts needing processing
+ func = sublayouts.pop
+ else:
+ func = layout.iteritems # will find sublayouts for processing
+
+ for elem, opts in func():
+ opts = opts or {}
+ text += "%s%s" % (' ' * indent, elem)
+
+ fopts = ' '.join(map(str, _format_optdict(opts, ignore="children")))
+ text += " %s" % fopts if fopts else ''
+
+ if "children" in opts:
+ text += " -children {\n"
+ indent += 2
+ newtext, indent = _format_layoutdict(opts, indent, True)
+ indent -= 2
+ text += newtext
+ text += '%s}' % (' ' * indent)
+
+ text += '\n'
+
+ return text, indent
+
def _script_from_settings(settings):
"""Returns an appropriate script, based on settings, according to
theme_settings definition to be used by theme_settings and
@@ -95,7 +166,7 @@
for name, opts in settings.iteritems():
# format 'configure' according to Tcl code
if opts.get('configure'):
- s = ' '.join(map(str, _format_optdict(opts['configure'])))
+ s = ' '.join(map(str, _format_optdict(opts['configure'], True)))
script.append("ttk::style configure %s %s;" % (name, s))
# format 'map' according to Tcl code
@@ -103,6 +174,11 @@
s = ' '.join(map(str, _format_mapdict(opts['map'], True)))
script.append("ttk::style map %s %s;" % (name, s))
+ # format 'layout' according to Tcl code
+ if opts.get('layout'):
+ s = _format_layoutdict(opts['layout'])
+ script.append("ttk::style layout %s {\n%s}" % (name, s))
+
return '\n'.join(script)
def _dict_from_tcltuple(t):
@@ -148,8 +224,8 @@
def configure(self, style, **kw):
"""Sets the default value of the specified option(s) in style.
- Each key in kw is an option and each value is a string identifying
- the value for that option."""
+ Each key in kw is an option and each value is either a string or
+ a sequence identifying the value for that option."""
opts = _format_optdict(kw)
return self.tk.call(self._name, "configure", style, *opts)
@@ -183,15 +259,16 @@
"""Define the widget layout for given style. If layoutspec is
omitted, return the layout specification for given style.
- The format of layoutspec is described below:
+ layoutspec is expected to be a dict, where each key is a layout
+ name and the value format is described below:
LAYOUTS
- A layout specifies a list of elements, each followed by
- one or more options specifying how to arrange the element.
+ A layout can contain the value None, if takes no options, or
+ another dict of options specifying how to arrange the element.
The layout mechanism uses a simplified version of the pack
geometry manager: given an initial cavity, each element is
- allocated a parcel. Valid options are:
+ allocated a parcel. Valid options/values are:
side: whichside
Specifies which side of the cavity to place the
@@ -204,11 +281,12 @@
children: [sublayout... ]
Specifies a list of elements to place inside the
- element
+ element. Each element is a tuple (or other sequence)
+ where the first item is the layout name, and the other
+ is a LAYOUT.
"""
- # XXX A more appropriate way of passing layoutspec is needed,
- # right now it is like if we were programming in Tcl
- return self.tk.call(self._name, "layout", style, layoutspec)
+ return self.tk.call(self._name, "layout", style,
+ _format_layoutdict(layoutspec)[0])
def element_create(self, elementName, etype, **kw):
@@ -248,9 +326,9 @@
settings and then restore the previous theme.
Each key in settings is a style and each value may contain the
- keys 'configure' and 'map'. 'configure' and 'map' are expected to
- have the same format as specified by the methods configure and map
- respectively."""
+ keys 'configure', 'map' and 'layout' and they are expected to have
+ the same format as specified by the methods configure, map and
+ layout respectively."""
script = _script_from_settings(settings)
self.tk.call(self._name, "theme", "settings", themeName, script)
@@ -477,7 +555,7 @@
Widget.__init__(self, master, "ttk::label", cnf, kw)
-class LabelFrame(Widget):
+class Labelframe(Widget):
"""Ttk Labelframe widget is a container used to group other widgets
together. It has an optional label, which may be a plain text string
or another widget."""
@@ -495,6 +573,8 @@
"""
Widget.__init__(self, master, "ttk::labelframe", cnf, kw)
+LabelFrame = Labelframe # Tkinter name compatibility
+
class Menubutton(Widget):
"""Ttk Menubutton widget displays a textual label and/or image, and
More information about the Python-checkins
mailing list