• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Wrapper functions for Tcl/Tk.
2
3Tkinter provides classes which allow the display, positioning and
4control of widgets. Toplevel widgets are Tk and Toplevel. Other
5widgets are Frame, Label, Entry, Text, Canvas, Button, Radiobutton,
6Checkbutton, Scale, Listbox, Scrollbar, OptionMenu, Spinbox
7LabelFrame and PanedWindow.
8
9Properties of the widgets are specified with keyword arguments.
10Keyword arguments have the same name as the corresponding resource
11under Tk.
12
13Widgets are positioned with one of the geometry managers Place, Pack
14or Grid. These managers can be called with methods place, pack, grid
15available in every Widget.
16
17Actions are bound to events by resources (e.g. keyword argument
18command) or with the method bind.
19
20Example (Hello, World):
21import tkinter
22from tkinter.constants import *
23tk = tkinter.Tk()
24frame = tkinter.Frame(tk, relief=RIDGE, borderwidth=2)
25frame.pack(fill=BOTH,expand=1)
26label = tkinter.Label(frame, text="Hello, World")
27label.pack(fill=X, expand=1)
28button = tkinter.Button(frame,text="Exit",command=tk.destroy)
29button.pack(side=BOTTOM)
30tk.mainloop()
31"""
32
33import enum
34import sys
35
36import _tkinter # If this fails your Python may not be configured for Tk
37TclError = _tkinter.TclError
38from tkinter.constants import *
39import re
40
41
42wantobjects = 1
43
44TkVersion = float(_tkinter.TK_VERSION)
45TclVersion = float(_tkinter.TCL_VERSION)
46
47READABLE = _tkinter.READABLE
48WRITABLE = _tkinter.WRITABLE
49EXCEPTION = _tkinter.EXCEPTION
50
51
52_magic_re = re.compile(r'([\\{}])')
53_space_re = re.compile(r'([\s])', re.ASCII)
54
55
56def _join(value):
57    """Internal function."""
58    return ' '.join(map(_stringify, value))
59
60
61def _stringify(value):
62    """Internal function."""
63    if isinstance(value, (list, tuple)):
64        if len(value) == 1:
65            value = _stringify(value[0])
66            if _magic_re.search(value):
67                value = '{%s}' % value
68        else:
69            value = '{%s}' % _join(value)
70    else:
71        value = str(value)
72        if not value:
73            value = '{}'
74        elif _magic_re.search(value):
75            # add '\' before special characters and spaces
76            value = _magic_re.sub(r'\\\1', value)
77            value = value.replace('\n', r'\n')
78            value = _space_re.sub(r'\\\1', value)
79            if value[0] == '"':
80                value = '\\' + value
81        elif value[0] == '"' or _space_re.search(value):
82            value = '{%s}' % value
83    return value
84
85
86def _flatten(seq):
87    """Internal function."""
88    res = ()
89    for item in seq:
90        if isinstance(item, (tuple, list)):
91            res = res + _flatten(item)
92        elif item is not None:
93            res = res + (item,)
94    return res
95
96
97try: _flatten = _tkinter._flatten
98except AttributeError: pass
99
100
101def _cnfmerge(cnfs):
102    """Internal function."""
103    if isinstance(cnfs, dict):
104        return cnfs
105    elif isinstance(cnfs, (type(None), str)):
106        return cnfs
107    else:
108        cnf = {}
109        for c in _flatten(cnfs):
110            try:
111                cnf.update(c)
112            except (AttributeError, TypeError) as msg:
113                print("_cnfmerge: fallback due to:", msg)
114                for k, v in c.items():
115                    cnf[k] = v
116        return cnf
117
118
119try: _cnfmerge = _tkinter._cnfmerge
120except AttributeError: pass
121
122
123def _splitdict(tk, v, cut_minus=True, conv=None):
124    """Return a properly formatted dict built from Tcl list pairs.
125
126    If cut_minus is True, the supposed '-' prefix will be removed from
127    keys. If conv is specified, it is used to convert values.
128
129    Tcl list is expected to contain an even number of elements.
130    """
131    t = tk.splitlist(v)
132    if len(t) % 2:
133        raise RuntimeError('Tcl list representing a dict is expected '
134                           'to contain an even number of elements')
135    it = iter(t)
136    dict = {}
137    for key, value in zip(it, it):
138        key = str(key)
139        if cut_minus and key[0] == '-':
140            key = key[1:]
141        if conv:
142            value = conv(value)
143        dict[key] = value
144    return dict
145
146
147class EventType(str, enum.Enum):
148    KeyPress = '2'
149    Key = KeyPress,
150    KeyRelease = '3'
151    ButtonPress = '4'
152    Button = ButtonPress,
153    ButtonRelease = '5'
154    Motion = '6'
155    Enter = '7'
156    Leave = '8'
157    FocusIn = '9'
158    FocusOut = '10'
159    Keymap = '11'           # undocumented
160    Expose = '12'
161    GraphicsExpose = '13'   # undocumented
162    NoExpose = '14'         # undocumented
163    Visibility = '15'
164    Create = '16'
165    Destroy = '17'
166    Unmap = '18'
167    Map = '19'
168    MapRequest = '20'
169    Reparent = '21'
170    Configure = '22'
171    ConfigureRequest = '23'
172    Gravity = '24'
173    ResizeRequest = '25'
174    Circulate = '26'
175    CirculateRequest = '27'
176    Property = '28'
177    SelectionClear = '29'   # undocumented
178    SelectionRequest = '30' # undocumented
179    Selection = '31'        # undocumented
180    Colormap = '32'
181    ClientMessage = '33'    # undocumented
182    Mapping = '34'          # undocumented
183    VirtualEvent = '35',    # undocumented
184    Activate = '36',
185    Deactivate = '37',
186    MouseWheel = '38',
187
188    def __str__(self):
189        return self.name
190
191
192class Event:
193    """Container for the properties of an event.
194
195    Instances of this type are generated if one of the following events occurs:
196
197    KeyPress, KeyRelease - for keyboard events
198    ButtonPress, ButtonRelease, Motion, Enter, Leave, MouseWheel - for mouse events
199    Visibility, Unmap, Map, Expose, FocusIn, FocusOut, Circulate,
200    Colormap, Gravity, Reparent, Property, Destroy, Activate,
201    Deactivate - for window events.
202
203    If a callback function for one of these events is registered
204    using bind, bind_all, bind_class, or tag_bind, the callback is
205    called with an Event as first argument. It will have the
206    following attributes (in braces are the event types for which
207    the attribute is valid):
208
209        serial - serial number of event
210    num - mouse button pressed (ButtonPress, ButtonRelease)
211    focus - whether the window has the focus (Enter, Leave)
212    height - height of the exposed window (Configure, Expose)
213    width - width of the exposed window (Configure, Expose)
214    keycode - keycode of the pressed key (KeyPress, KeyRelease)
215    state - state of the event as a number (ButtonPress, ButtonRelease,
216                            Enter, KeyPress, KeyRelease,
217                            Leave, Motion)
218    state - state as a string (Visibility)
219    time - when the event occurred
220    x - x-position of the mouse
221    y - y-position of the mouse
222    x_root - x-position of the mouse on the screen
223             (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion)
224    y_root - y-position of the mouse on the screen
225             (ButtonPress, ButtonRelease, KeyPress, KeyRelease, Motion)
226    char - pressed character (KeyPress, KeyRelease)
227    send_event - see X/Windows documentation
228    keysym - keysym of the event as a string (KeyPress, KeyRelease)
229    keysym_num - keysym of the event as a number (KeyPress, KeyRelease)
230    type - type of the event as a number
231    widget - widget in which the event occurred
232    delta - delta of wheel movement (MouseWheel)
233    """
234
235    def __repr__(self):
236        attrs = {k: v for k, v in self.__dict__.items() if v != '??'}
237        if not self.char:
238            del attrs['char']
239        elif self.char != '??':
240            attrs['char'] = repr(self.char)
241        if not getattr(self, 'send_event', True):
242            del attrs['send_event']
243        if self.state == 0:
244            del attrs['state']
245        elif isinstance(self.state, int):
246            state = self.state
247            mods = ('Shift', 'Lock', 'Control',
248                    'Mod1', 'Mod2', 'Mod3', 'Mod4', 'Mod5',
249                    'Button1', 'Button2', 'Button3', 'Button4', 'Button5')
250            s = []
251            for i, n in enumerate(mods):
252                if state & (1 << i):
253                    s.append(n)
254            state = state & ~((1<< len(mods)) - 1)
255            if state or not s:
256                s.append(hex(state))
257            attrs['state'] = '|'.join(s)
258        if self.delta == 0:
259            del attrs['delta']
260        # widget usually is known
261        # serial and time are not very interesting
262        # keysym_num duplicates keysym
263        # x_root and y_root mostly duplicate x and y
264        keys = ('send_event',
265                'state', 'keysym', 'keycode', 'char',
266                'num', 'delta', 'focus',
267                'x', 'y', 'width', 'height')
268        return '<%s event%s>' % (
269            self.type,
270            ''.join(' %s=%s' % (k, attrs[k]) for k in keys if k in attrs)
271        )
272
273
274_support_default_root = 1
275_default_root = None
276
277
278def NoDefaultRoot():
279    """Inhibit setting of default root window.
280
281    Call this function to inhibit that the first instance of
282    Tk is used for windows without an explicit parent window.
283    """
284    global _support_default_root
285    _support_default_root = 0
286    global _default_root
287    _default_root = None
288    del _default_root
289
290
291def _tkerror(err):
292    """Internal function."""
293    pass
294
295
296def _exit(code=0):
297    """Internal function. Calling it will raise the exception SystemExit."""
298    try:
299        code = int(code)
300    except ValueError:
301        pass
302    raise SystemExit(code)
303
304
305_varnum = 0
306
307
308class Variable:
309    """Class to define value holders for e.g. buttons.
310
311    Subclasses StringVar, IntVar, DoubleVar, BooleanVar are specializations
312    that constrain the type of the value returned from get()."""
313    _default = ""
314    _tk = None
315    _tclCommands = None
316
317    def __init__(self, master=None, value=None, name=None):
318        """Construct a variable
319
320        MASTER can be given as master widget.
321        VALUE is an optional value (defaults to "")
322        NAME is an optional Tcl name (defaults to PY_VARnum).
323
324        If NAME matches an existing variable and VALUE is omitted
325        then the existing value is retained.
326        """
327        # check for type of NAME parameter to override weird error message
328        # raised from Modules/_tkinter.c:SetVar like:
329        # TypeError: setvar() takes exactly 3 arguments (2 given)
330        if name is not None and not isinstance(name, str):
331            raise TypeError("name must be a string")
332        global _varnum
333        if not master:
334            master = _default_root
335        self._root = master._root()
336        self._tk = master.tk
337        if name:
338            self._name = name
339        else:
340            self._name = 'PY_VAR' + repr(_varnum)
341            _varnum += 1
342        if value is not None:
343            self.initialize(value)
344        elif not self._tk.getboolean(self._tk.call("info", "exists", self._name)):
345            self.initialize(self._default)
346
347    def __del__(self):
348        """Unset the variable in Tcl."""
349        if self._tk is None:
350            return
351        if self._tk.getboolean(self._tk.call("info", "exists", self._name)):
352            self._tk.globalunsetvar(self._name)
353        if self._tclCommands is not None:
354            for name in self._tclCommands:
355                #print '- Tkinter: deleted command', name
356                self._tk.deletecommand(name)
357            self._tclCommands = None
358
359    def __str__(self):
360        """Return the name of the variable in Tcl."""
361        return self._name
362
363    def set(self, value):
364        """Set the variable to VALUE."""
365        return self._tk.globalsetvar(self._name, value)
366
367    initialize = set
368
369    def get(self):
370        """Return value of variable."""
371        return self._tk.globalgetvar(self._name)
372
373    def _register(self, callback):
374        f = CallWrapper(callback, None, self._root).__call__
375        cbname = repr(id(f))
376        try:
377            callback = callback.__func__
378        except AttributeError:
379            pass
380        try:
381            cbname = cbname + callback.__name__
382        except AttributeError:
383            pass
384        self._tk.createcommand(cbname, f)
385        if self._tclCommands is None:
386            self._tclCommands = []
387        self._tclCommands.append(cbname)
388        return cbname
389
390    def trace_add(self, mode, callback):
391        """Define a trace callback for the variable.
392
393        Mode is one of "read", "write", "unset", or a list or tuple of
394        such strings.
395        Callback must be a function which is called when the variable is
396        read, written or unset.
397
398        Return the name of the callback.
399        """
400        cbname = self._register(callback)
401        self._tk.call('trace', 'add', 'variable',
402                      self._name, mode, (cbname,))
403        return cbname
404
405    def trace_remove(self, mode, cbname):
406        """Delete the trace callback for a variable.
407
408        Mode is one of "read", "write", "unset" or a list or tuple of
409        such strings.  Must be same as were specified in trace_add().
410        cbname is the name of the callback returned from trace_add().
411        """
412        self._tk.call('trace', 'remove', 'variable',
413                      self._name, mode, cbname)
414        for m, ca in self.trace_info():
415            if self._tk.splitlist(ca)[0] == cbname:
416                break
417        else:
418            self._tk.deletecommand(cbname)
419            try:
420                self._tclCommands.remove(cbname)
421            except ValueError:
422                pass
423
424    def trace_info(self):
425        """Return all trace callback information."""
426        splitlist = self._tk.splitlist
427        return [(splitlist(k), v) for k, v in map(splitlist,
428            splitlist(self._tk.call('trace', 'info', 'variable', self._name)))]
429
430    def trace_variable(self, mode, callback):
431        """Define a trace callback for the variable.
432
433        MODE is one of "r", "w", "u" for read, write, undefine.
434        CALLBACK must be a function which is called when
435        the variable is read, written or undefined.
436
437        Return the name of the callback.
438
439        This deprecated method wraps a deprecated Tcl method that will
440        likely be removed in the future.  Use trace_add() instead.
441        """
442        # TODO: Add deprecation warning
443        cbname = self._register(callback)
444        self._tk.call("trace", "variable", self._name, mode, cbname)
445        return cbname
446
447    trace = trace_variable
448
449    def trace_vdelete(self, mode, cbname):
450        """Delete the trace callback for a variable.
451
452        MODE is one of "r", "w", "u" for read, write, undefine.
453        CBNAME is the name of the callback returned from trace_variable or trace.
454
455        This deprecated method wraps a deprecated Tcl method that will
456        likely be removed in the future.  Use trace_remove() instead.
457        """
458        # TODO: Add deprecation warning
459        self._tk.call("trace", "vdelete", self._name, mode, cbname)
460        cbname = self._tk.splitlist(cbname)[0]
461        for m, ca in self.trace_info():
462            if self._tk.splitlist(ca)[0] == cbname:
463                break
464        else:
465            self._tk.deletecommand(cbname)
466            try:
467                self._tclCommands.remove(cbname)
468            except ValueError:
469                pass
470
471    def trace_vinfo(self):
472        """Return all trace callback information.
473
474        This deprecated method wraps a deprecated Tcl method that will
475        likely be removed in the future.  Use trace_info() instead.
476        """
477        # TODO: Add deprecation warning
478        return [self._tk.splitlist(x) for x in self._tk.splitlist(
479            self._tk.call("trace", "vinfo", self._name))]
480
481    def __eq__(self, other):
482        """Comparison for equality (==).
483
484        Note: if the Variable's master matters to behavior
485        also compare self._master == other._master
486        """
487        return self.__class__.__name__ == other.__class__.__name__ \
488            and self._name == other._name
489
490
491class StringVar(Variable):
492    """Value holder for strings variables."""
493    _default = ""
494
495    def __init__(self, master=None, value=None, name=None):
496        """Construct a string variable.
497
498        MASTER can be given as master widget.
499        VALUE is an optional value (defaults to "")
500        NAME is an optional Tcl name (defaults to PY_VARnum).
501
502        If NAME matches an existing variable and VALUE is omitted
503        then the existing value is retained.
504        """
505        Variable.__init__(self, master, value, name)
506
507    def get(self):
508        """Return value of variable as string."""
509        value = self._tk.globalgetvar(self._name)
510        if isinstance(value, str):
511            return value
512        return str(value)
513
514
515class IntVar(Variable):
516    """Value holder for integer variables."""
517    _default = 0
518
519    def __init__(self, master=None, value=None, name=None):
520        """Construct an integer variable.
521
522        MASTER can be given as master widget.
523        VALUE is an optional value (defaults to 0)
524        NAME is an optional Tcl name (defaults to PY_VARnum).
525
526        If NAME matches an existing variable and VALUE is omitted
527        then the existing value is retained.
528        """
529        Variable.__init__(self, master, value, name)
530
531    def get(self):
532        """Return the value of the variable as an integer."""
533        value = self._tk.globalgetvar(self._name)
534        try:
535            return self._tk.getint(value)
536        except (TypeError, TclError):
537            return int(self._tk.getdouble(value))
538
539
540class DoubleVar(Variable):
541    """Value holder for float variables."""
542    _default = 0.0
543
544    def __init__(self, master=None, value=None, name=None):
545        """Construct a float variable.
546
547        MASTER can be given as master widget.
548        VALUE is an optional value (defaults to 0.0)
549        NAME is an optional Tcl name (defaults to PY_VARnum).
550
551        If NAME matches an existing variable and VALUE is omitted
552        then the existing value is retained.
553        """
554        Variable.__init__(self, master, value, name)
555
556    def get(self):
557        """Return the value of the variable as a float."""
558        return self._tk.getdouble(self._tk.globalgetvar(self._name))
559
560
561class BooleanVar(Variable):
562    """Value holder for boolean variables."""
563    _default = False
564
565    def __init__(self, master=None, value=None, name=None):
566        """Construct a boolean variable.
567
568        MASTER can be given as master widget.
569        VALUE is an optional value (defaults to False)
570        NAME is an optional Tcl name (defaults to PY_VARnum).
571
572        If NAME matches an existing variable and VALUE is omitted
573        then the existing value is retained.
574        """
575        Variable.__init__(self, master, value, name)
576
577    def set(self, value):
578        """Set the variable to VALUE."""
579        return self._tk.globalsetvar(self._name, self._tk.getboolean(value))
580
581    initialize = set
582
583    def get(self):
584        """Return the value of the variable as a bool."""
585        try:
586            return self._tk.getboolean(self._tk.globalgetvar(self._name))
587        except TclError:
588            raise ValueError("invalid literal for getboolean()")
589
590
591def mainloop(n=0):
592    """Run the main loop of Tcl."""
593    _default_root.tk.mainloop(n)
594
595
596getint = int
597
598getdouble = float
599
600
601def getboolean(s):
602    """Convert true and false to integer values 1 and 0."""
603    try:
604        return _default_root.tk.getboolean(s)
605    except TclError:
606        raise ValueError("invalid literal for getboolean()")
607
608
609# Methods defined on both toplevel and interior widgets
610
611class Misc:
612    """Internal class.
613
614    Base class which defines methods common for interior widgets."""
615
616    # used for generating child widget names
617    _last_child_ids = None
618
619    # XXX font command?
620    _tclCommands = None
621
622    def destroy(self):
623        """Internal function.
624
625        Delete all Tcl commands created for
626        this widget in the Tcl interpreter."""
627        if self._tclCommands is not None:
628            for name in self._tclCommands:
629                #print '- Tkinter: deleted command', name
630                self.tk.deletecommand(name)
631            self._tclCommands = None
632
633    def deletecommand(self, name):
634        """Internal function.
635
636        Delete the Tcl command provided in NAME."""
637        #print '- Tkinter: deleted command', name
638        self.tk.deletecommand(name)
639        try:
640            self._tclCommands.remove(name)
641        except ValueError:
642            pass
643
644    def tk_strictMotif(self, boolean=None):
645        """Set Tcl internal variable, whether the look and feel
646        should adhere to Motif.
647
648        A parameter of 1 means adhere to Motif (e.g. no color
649        change if mouse passes over slider).
650        Returns the set value."""
651        return self.tk.getboolean(self.tk.call(
652            'set', 'tk_strictMotif', boolean))
653
654    def tk_bisque(self):
655        """Change the color scheme to light brown as used in Tk 3.6 and before."""
656        self.tk.call('tk_bisque')
657
658    def tk_setPalette(self, *args, **kw):
659        """Set a new color scheme for all widget elements.
660
661        A single color as argument will cause that all colors of Tk
662        widget elements are derived from this.
663        Alternatively several keyword parameters and its associated
664        colors can be given. The following keywords are valid:
665        activeBackground, foreground, selectColor,
666        activeForeground, highlightBackground, selectBackground,
667        background, highlightColor, selectForeground,
668        disabledForeground, insertBackground, troughColor."""
669        self.tk.call(('tk_setPalette',)
670              + _flatten(args) + _flatten(list(kw.items())))
671
672    def wait_variable(self, name='PY_VAR'):
673        """Wait until the variable is modified.
674
675        A parameter of type IntVar, StringVar, DoubleVar or
676        BooleanVar must be given."""
677        self.tk.call('tkwait', 'variable', name)
678    waitvar = wait_variable # XXX b/w compat
679
680    def wait_window(self, window=None):
681        """Wait until a WIDGET is destroyed.
682
683        If no parameter is given self is used."""
684        if window is None:
685            window = self
686        self.tk.call('tkwait', 'window', window._w)
687
688    def wait_visibility(self, window=None):
689        """Wait until the visibility of a WIDGET changes
690        (e.g. it appears).
691
692        If no parameter is given self is used."""
693        if window is None:
694            window = self
695        self.tk.call('tkwait', 'visibility', window._w)
696
697    def setvar(self, name='PY_VAR', value='1'):
698        """Set Tcl variable NAME to VALUE."""
699        self.tk.setvar(name, value)
700
701    def getvar(self, name='PY_VAR'):
702        """Return value of Tcl variable NAME."""
703        return self.tk.getvar(name)
704
705    def getint(self, s):
706        try:
707            return self.tk.getint(s)
708        except TclError as exc:
709            raise ValueError(str(exc))
710
711    def getdouble(self, s):
712        try:
713            return self.tk.getdouble(s)
714        except TclError as exc:
715            raise ValueError(str(exc))
716
717    def getboolean(self, s):
718        """Return a boolean value for Tcl boolean values true and false given as parameter."""
719        try:
720            return self.tk.getboolean(s)
721        except TclError:
722            raise ValueError("invalid literal for getboolean()")
723
724    def focus_set(self):
725        """Direct input focus to this widget.
726
727        If the application currently does not have the focus
728        this widget will get the focus if the application gets
729        the focus through the window manager."""
730        self.tk.call('focus', self._w)
731    focus = focus_set # XXX b/w compat?
732
733    def focus_force(self):
734        """Direct input focus to this widget even if the
735        application does not have the focus. Use with
736        caution!"""
737        self.tk.call('focus', '-force', self._w)
738
739    def focus_get(self):
740        """Return the widget which has currently the focus in the
741        application.
742
743        Use focus_displayof to allow working with several
744        displays. Return None if application does not have
745        the focus."""
746        name = self.tk.call('focus')
747        if name == 'none' or not name: return None
748        return self._nametowidget(name)
749
750    def focus_displayof(self):
751        """Return the widget which has currently the focus on the
752        display where this widget is located.
753
754        Return None if the application does not have the focus."""
755        name = self.tk.call('focus', '-displayof', self._w)
756        if name == 'none' or not name: return None
757        return self._nametowidget(name)
758
759    def focus_lastfor(self):
760        """Return the widget which would have the focus if top level
761        for this widget gets the focus from the window manager."""
762        name = self.tk.call('focus', '-lastfor', self._w)
763        if name == 'none' or not name: return None
764        return self._nametowidget(name)
765
766    def tk_focusFollowsMouse(self):
767        """The widget under mouse will get automatically focus. Can not
768        be disabled easily."""
769        self.tk.call('tk_focusFollowsMouse')
770
771    def tk_focusNext(self):
772        """Return the next widget in the focus order which follows
773        widget which has currently the focus.
774
775        The focus order first goes to the next child, then to
776        the children of the child recursively and then to the
777        next sibling which is higher in the stacking order.  A
778        widget is omitted if it has the takefocus resource set
779        to 0."""
780        name = self.tk.call('tk_focusNext', self._w)
781        if not name: return None
782        return self._nametowidget(name)
783
784    def tk_focusPrev(self):
785        """Return previous widget in the focus order. See tk_focusNext for details."""
786        name = self.tk.call('tk_focusPrev', self._w)
787        if not name: return None
788        return self._nametowidget(name)
789
790    def after(self, ms, func=None, *args):
791        """Call function once after given time.
792
793        MS specifies the time in milliseconds. FUNC gives the
794        function which shall be called. Additional parameters
795        are given as parameters to the function call.  Return
796        identifier to cancel scheduling with after_cancel."""
797        if not func:
798            # I'd rather use time.sleep(ms*0.001)
799            self.tk.call('after', ms)
800            return None
801        else:
802            def callit():
803                try:
804                    func(*args)
805                finally:
806                    try:
807                        self.deletecommand(name)
808                    except TclError:
809                        pass
810            callit.__name__ = func.__name__
811            name = self._register(callit)
812            return self.tk.call('after', ms, name)
813
814    def after_idle(self, func, *args):
815        """Call FUNC once if the Tcl main loop has no event to
816        process.
817
818        Return an identifier to cancel the scheduling with
819        after_cancel."""
820        return self.after('idle', func, *args)
821
822    def after_cancel(self, id):
823        """Cancel scheduling of function identified with ID.
824
825        Identifier returned by after or after_idle must be
826        given as first parameter.
827        """
828        if not id:
829            raise ValueError('id must be a valid identifier returned from '
830                             'after or after_idle')
831        try:
832            data = self.tk.call('after', 'info', id)
833            script = self.tk.splitlist(data)[0]
834            self.deletecommand(script)
835        except TclError:
836            pass
837        self.tk.call('after', 'cancel', id)
838
839    def bell(self, displayof=0):
840        """Ring a display's bell."""
841        self.tk.call(('bell',) + self._displayof(displayof))
842
843    # Clipboard handling:
844    def clipboard_get(self, **kw):
845        """Retrieve data from the clipboard on window's display.
846
847        The window keyword defaults to the root window of the Tkinter
848        application.
849
850        The type keyword specifies the form in which the data is
851        to be returned and should be an atom name such as STRING
852        or FILE_NAME.  Type defaults to STRING, except on X11, where the default
853        is to try UTF8_STRING and fall back to STRING.
854
855        This command is equivalent to:
856
857        selection_get(CLIPBOARD)
858        """
859        if 'type' not in kw and self._windowingsystem == 'x11':
860            try:
861                kw['type'] = 'UTF8_STRING'
862                return self.tk.call(('clipboard', 'get') + self._options(kw))
863            except TclError:
864                del kw['type']
865        return self.tk.call(('clipboard', 'get') + self._options(kw))
866
867    def clipboard_clear(self, **kw):
868        """Clear the data in the Tk clipboard.
869
870        A widget specified for the optional displayof keyword
871        argument specifies the target display."""
872        if 'displayof' not in kw: kw['displayof'] = self._w
873        self.tk.call(('clipboard', 'clear') + self._options(kw))
874
875    def clipboard_append(self, string, **kw):
876        """Append STRING to the Tk clipboard.
877
878        A widget specified at the optional displayof keyword
879        argument specifies the target display. The clipboard
880        can be retrieved with selection_get."""
881        if 'displayof' not in kw: kw['displayof'] = self._w
882        self.tk.call(('clipboard', 'append') + self._options(kw)
883              + ('--', string))
884    # XXX grab current w/o window argument
885
886    def grab_current(self):
887        """Return widget which has currently the grab in this application
888        or None."""
889        name = self.tk.call('grab', 'current', self._w)
890        if not name: return None
891        return self._nametowidget(name)
892
893    def grab_release(self):
894        """Release grab for this widget if currently set."""
895        self.tk.call('grab', 'release', self._w)
896
897    def grab_set(self):
898        """Set grab for this widget.
899
900        A grab directs all events to this and descendant
901        widgets in the application."""
902        self.tk.call('grab', 'set', self._w)
903
904    def grab_set_global(self):
905        """Set global grab for this widget.
906
907        A global grab directs all events to this and
908        descendant widgets on the display. Use with caution -
909        other applications do not get events anymore."""
910        self.tk.call('grab', 'set', '-global', self._w)
911
912    def grab_status(self):
913        """Return None, "local" or "global" if this widget has
914        no, a local or a global grab."""
915        status = self.tk.call('grab', 'status', self._w)
916        if status == 'none': status = None
917        return status
918
919    def option_add(self, pattern, value, priority = None):
920        """Set a VALUE (second parameter) for an option
921        PATTERN (first parameter).
922
923        An optional third parameter gives the numeric priority
924        (defaults to 80)."""
925        self.tk.call('option', 'add', pattern, value, priority)
926
927    def option_clear(self):
928        """Clear the option database.
929
930        It will be reloaded if option_add is called."""
931        self.tk.call('option', 'clear')
932
933    def option_get(self, name, className):
934        """Return the value for an option NAME for this widget
935        with CLASSNAME.
936
937        Values with higher priority override lower values."""
938        return self.tk.call('option', 'get', self._w, name, className)
939
940    def option_readfile(self, fileName, priority = None):
941        """Read file FILENAME into the option database.
942
943        An optional second parameter gives the numeric
944        priority."""
945        self.tk.call('option', 'readfile', fileName, priority)
946
947    def selection_clear(self, **kw):
948        """Clear the current X selection."""
949        if 'displayof' not in kw: kw['displayof'] = self._w
950        self.tk.call(('selection', 'clear') + self._options(kw))
951
952    def selection_get(self, **kw):
953        """Return the contents of the current X selection.
954
955        A keyword parameter selection specifies the name of
956        the selection and defaults to PRIMARY.  A keyword
957        parameter displayof specifies a widget on the display
958        to use. A keyword parameter type specifies the form of data to be
959        fetched, defaulting to STRING except on X11, where UTF8_STRING is tried
960        before STRING."""
961        if 'displayof' not in kw: kw['displayof'] = self._w
962        if 'type' not in kw and self._windowingsystem == 'x11':
963            try:
964                kw['type'] = 'UTF8_STRING'
965                return self.tk.call(('selection', 'get') + self._options(kw))
966            except TclError:
967                del kw['type']
968        return self.tk.call(('selection', 'get') + self._options(kw))
969
970    def selection_handle(self, command, **kw):
971        """Specify a function COMMAND to call if the X
972        selection owned by this widget is queried by another
973        application.
974
975        This function must return the contents of the
976        selection. The function will be called with the
977        arguments OFFSET and LENGTH which allows the chunking
978        of very long selections. The following keyword
979        parameters can be provided:
980        selection - name of the selection (default PRIMARY),
981        type - type of the selection (e.g. STRING, FILE_NAME)."""
982        name = self._register(command)
983        self.tk.call(('selection', 'handle') + self._options(kw)
984              + (self._w, name))
985
986    def selection_own(self, **kw):
987        """Become owner of X selection.
988
989        A keyword parameter selection specifies the name of
990        the selection (default PRIMARY)."""
991        self.tk.call(('selection', 'own') +
992                 self._options(kw) + (self._w,))
993
994    def selection_own_get(self, **kw):
995        """Return owner of X selection.
996
997        The following keyword parameter can
998        be provided:
999        selection - name of the selection (default PRIMARY),
1000        type - type of the selection (e.g. STRING, FILE_NAME)."""
1001        if 'displayof' not in kw: kw['displayof'] = self._w
1002        name = self.tk.call(('selection', 'own') + self._options(kw))
1003        if not name: return None
1004        return self._nametowidget(name)
1005
1006    def send(self, interp, cmd, *args):
1007        """Send Tcl command CMD to different interpreter INTERP to be executed."""
1008        return self.tk.call(('send', interp, cmd) + args)
1009
1010    def lower(self, belowThis=None):
1011        """Lower this widget in the stacking order."""
1012        self.tk.call('lower', self._w, belowThis)
1013
1014    def tkraise(self, aboveThis=None):
1015        """Raise this widget in the stacking order."""
1016        self.tk.call('raise', self._w, aboveThis)
1017
1018    lift = tkraise
1019
1020    def winfo_atom(self, name, displayof=0):
1021        """Return integer which represents atom NAME."""
1022        args = ('winfo', 'atom') + self._displayof(displayof) + (name,)
1023        return self.tk.getint(self.tk.call(args))
1024
1025    def winfo_atomname(self, id, displayof=0):
1026        """Return name of atom with identifier ID."""
1027        args = ('winfo', 'atomname') \
1028               + self._displayof(displayof) + (id,)
1029        return self.tk.call(args)
1030
1031    def winfo_cells(self):
1032        """Return number of cells in the colormap for this widget."""
1033        return self.tk.getint(
1034            self.tk.call('winfo', 'cells', self._w))
1035
1036    def winfo_children(self):
1037        """Return a list of all widgets which are children of this widget."""
1038        result = []
1039        for child in self.tk.splitlist(
1040            self.tk.call('winfo', 'children', self._w)):
1041            try:
1042                # Tcl sometimes returns extra windows, e.g. for
1043                # menus; those need to be skipped
1044                result.append(self._nametowidget(child))
1045            except KeyError:
1046                pass
1047        return result
1048
1049    def winfo_class(self):
1050        """Return window class name of this widget."""
1051        return self.tk.call('winfo', 'class', self._w)
1052
1053    def winfo_colormapfull(self):
1054        """Return True if at the last color request the colormap was full."""
1055        return self.tk.getboolean(
1056            self.tk.call('winfo', 'colormapfull', self._w))
1057
1058    def winfo_containing(self, rootX, rootY, displayof=0):
1059        """Return the widget which is at the root coordinates ROOTX, ROOTY."""
1060        args = ('winfo', 'containing') \
1061               + self._displayof(displayof) + (rootX, rootY)
1062        name = self.tk.call(args)
1063        if not name: return None
1064        return self._nametowidget(name)
1065
1066    def winfo_depth(self):
1067        """Return the number of bits per pixel."""
1068        return self.tk.getint(self.tk.call('winfo', 'depth', self._w))
1069
1070    def winfo_exists(self):
1071        """Return true if this widget exists."""
1072        return self.tk.getint(
1073            self.tk.call('winfo', 'exists', self._w))
1074
1075    def winfo_fpixels(self, number):
1076        """Return the number of pixels for the given distance NUMBER
1077        (e.g. "3c") as float."""
1078        return self.tk.getdouble(self.tk.call(
1079            'winfo', 'fpixels', self._w, number))
1080
1081    def winfo_geometry(self):
1082        """Return geometry string for this widget in the form "widthxheight+X+Y"."""
1083        return self.tk.call('winfo', 'geometry', self._w)
1084
1085    def winfo_height(self):
1086        """Return height of this widget."""
1087        return self.tk.getint(
1088            self.tk.call('winfo', 'height', self._w))
1089
1090    def winfo_id(self):
1091        """Return identifier ID for this widget."""
1092        return int(self.tk.call('winfo', 'id', self._w), 0)
1093
1094    def winfo_interps(self, displayof=0):
1095        """Return the name of all Tcl interpreters for this display."""
1096        args = ('winfo', 'interps') + self._displayof(displayof)
1097        return self.tk.splitlist(self.tk.call(args))
1098
1099    def winfo_ismapped(self):
1100        """Return true if this widget is mapped."""
1101        return self.tk.getint(
1102            self.tk.call('winfo', 'ismapped', self._w))
1103
1104    def winfo_manager(self):
1105        """Return the window manager name for this widget."""
1106        return self.tk.call('winfo', 'manager', self._w)
1107
1108    def winfo_name(self):
1109        """Return the name of this widget."""
1110        return self.tk.call('winfo', 'name', self._w)
1111
1112    def winfo_parent(self):
1113        """Return the name of the parent of this widget."""
1114        return self.tk.call('winfo', 'parent', self._w)
1115
1116    def winfo_pathname(self, id, displayof=0):
1117        """Return the pathname of the widget given by ID."""
1118        args = ('winfo', 'pathname') \
1119               + self._displayof(displayof) + (id,)
1120        return self.tk.call(args)
1121
1122    def winfo_pixels(self, number):
1123        """Rounded integer value of winfo_fpixels."""
1124        return self.tk.getint(
1125            self.tk.call('winfo', 'pixels', self._w, number))
1126
1127    def winfo_pointerx(self):
1128        """Return the x coordinate of the pointer on the root window."""
1129        return self.tk.getint(
1130            self.tk.call('winfo', 'pointerx', self._w))
1131
1132    def winfo_pointerxy(self):
1133        """Return a tuple of x and y coordinates of the pointer on the root window."""
1134        return self._getints(
1135            self.tk.call('winfo', 'pointerxy', self._w))
1136
1137    def winfo_pointery(self):
1138        """Return the y coordinate of the pointer on the root window."""
1139        return self.tk.getint(
1140            self.tk.call('winfo', 'pointery', self._w))
1141
1142    def winfo_reqheight(self):
1143        """Return requested height of this widget."""
1144        return self.tk.getint(
1145            self.tk.call('winfo', 'reqheight', self._w))
1146
1147    def winfo_reqwidth(self):
1148        """Return requested width of this widget."""
1149        return self.tk.getint(
1150            self.tk.call('winfo', 'reqwidth', self._w))
1151
1152    def winfo_rgb(self, color):
1153        """Return tuple of decimal values for red, green, blue for
1154        COLOR in this widget."""
1155        return self._getints(
1156            self.tk.call('winfo', 'rgb', self._w, color))
1157
1158    def winfo_rootx(self):
1159        """Return x coordinate of upper left corner of this widget on the
1160        root window."""
1161        return self.tk.getint(
1162            self.tk.call('winfo', 'rootx', self._w))
1163
1164    def winfo_rooty(self):
1165        """Return y coordinate of upper left corner of this widget on the
1166        root window."""
1167        return self.tk.getint(
1168            self.tk.call('winfo', 'rooty', self._w))
1169
1170    def winfo_screen(self):
1171        """Return the screen name of this widget."""
1172        return self.tk.call('winfo', 'screen', self._w)
1173
1174    def winfo_screencells(self):
1175        """Return the number of the cells in the colormap of the screen
1176        of this widget."""
1177        return self.tk.getint(
1178            self.tk.call('winfo', 'screencells', self._w))
1179
1180    def winfo_screendepth(self):
1181        """Return the number of bits per pixel of the root window of the
1182        screen of this widget."""
1183        return self.tk.getint(
1184            self.tk.call('winfo', 'screendepth', self._w))
1185
1186    def winfo_screenheight(self):
1187        """Return the number of pixels of the height of the screen of this widget
1188        in pixel."""
1189        return self.tk.getint(
1190            self.tk.call('winfo', 'screenheight', self._w))
1191
1192    def winfo_screenmmheight(self):
1193        """Return the number of pixels of the height of the screen of
1194        this widget in mm."""
1195        return self.tk.getint(
1196            self.tk.call('winfo', 'screenmmheight', self._w))
1197
1198    def winfo_screenmmwidth(self):
1199        """Return the number of pixels of the width of the screen of
1200        this widget in mm."""
1201        return self.tk.getint(
1202            self.tk.call('winfo', 'screenmmwidth', self._w))
1203
1204    def winfo_screenvisual(self):
1205        """Return one of the strings directcolor, grayscale, pseudocolor,
1206        staticcolor, staticgray, or truecolor for the default
1207        colormodel of this screen."""
1208        return self.tk.call('winfo', 'screenvisual', self._w)
1209
1210    def winfo_screenwidth(self):
1211        """Return the number of pixels of the width of the screen of
1212        this widget in pixel."""
1213        return self.tk.getint(
1214            self.tk.call('winfo', 'screenwidth', self._w))
1215
1216    def winfo_server(self):
1217        """Return information of the X-Server of the screen of this widget in
1218        the form "XmajorRminor vendor vendorVersion"."""
1219        return self.tk.call('winfo', 'server', self._w)
1220
1221    def winfo_toplevel(self):
1222        """Return the toplevel widget of this widget."""
1223        return self._nametowidget(self.tk.call(
1224            'winfo', 'toplevel', self._w))
1225
1226    def winfo_viewable(self):
1227        """Return true if the widget and all its higher ancestors are mapped."""
1228        return self.tk.getint(
1229            self.tk.call('winfo', 'viewable', self._w))
1230
1231    def winfo_visual(self):
1232        """Return one of the strings directcolor, grayscale, pseudocolor,
1233        staticcolor, staticgray, or truecolor for the
1234        colormodel of this widget."""
1235        return self.tk.call('winfo', 'visual', self._w)
1236
1237    def winfo_visualid(self):
1238        """Return the X identifier for the visual for this widget."""
1239        return self.tk.call('winfo', 'visualid', self._w)
1240
1241    def winfo_visualsavailable(self, includeids=False):
1242        """Return a list of all visuals available for the screen
1243        of this widget.
1244
1245        Each item in the list consists of a visual name (see winfo_visual), a
1246        depth and if includeids is true is given also the X identifier."""
1247        data = self.tk.call('winfo', 'visualsavailable', self._w,
1248                            'includeids' if includeids else None)
1249        data = [self.tk.splitlist(x) for x in self.tk.splitlist(data)]
1250        return [self.__winfo_parseitem(x) for x in data]
1251
1252    def __winfo_parseitem(self, t):
1253        """Internal function."""
1254        return t[:1] + tuple(map(self.__winfo_getint, t[1:]))
1255
1256    def __winfo_getint(self, x):
1257        """Internal function."""
1258        return int(x, 0)
1259
1260    def winfo_vrootheight(self):
1261        """Return the height of the virtual root window associated with this
1262        widget in pixels. If there is no virtual root window return the
1263        height of the screen."""
1264        return self.tk.getint(
1265            self.tk.call('winfo', 'vrootheight', self._w))
1266
1267    def winfo_vrootwidth(self):
1268        """Return the width of the virtual root window associated with this
1269        widget in pixel. If there is no virtual root window return the
1270        width of the screen."""
1271        return self.tk.getint(
1272            self.tk.call('winfo', 'vrootwidth', self._w))
1273
1274    def winfo_vrootx(self):
1275        """Return the x offset of the virtual root relative to the root
1276        window of the screen of this widget."""
1277        return self.tk.getint(
1278            self.tk.call('winfo', 'vrootx', self._w))
1279
1280    def winfo_vrooty(self):
1281        """Return the y offset of the virtual root relative to the root
1282        window of the screen of this widget."""
1283        return self.tk.getint(
1284            self.tk.call('winfo', 'vrooty', self._w))
1285
1286    def winfo_width(self):
1287        """Return the width of this widget."""
1288        return self.tk.getint(
1289            self.tk.call('winfo', 'width', self._w))
1290
1291    def winfo_x(self):
1292        """Return the x coordinate of the upper left corner of this widget
1293        in the parent."""
1294        return self.tk.getint(
1295            self.tk.call('winfo', 'x', self._w))
1296
1297    def winfo_y(self):
1298        """Return the y coordinate of the upper left corner of this widget
1299        in the parent."""
1300        return self.tk.getint(
1301            self.tk.call('winfo', 'y', self._w))
1302
1303    def update(self):
1304        """Enter event loop until all pending events have been processed by Tcl."""
1305        self.tk.call('update')
1306
1307    def update_idletasks(self):
1308        """Enter event loop until all idle callbacks have been called. This
1309        will update the display of windows but not process events caused by
1310        the user."""
1311        self.tk.call('update', 'idletasks')
1312
1313    def bindtags(self, tagList=None):
1314        """Set or get the list of bindtags for this widget.
1315
1316        With no argument return the list of all bindtags associated with
1317        this widget. With a list of strings as argument the bindtags are
1318        set to this list. The bindtags determine in which order events are
1319        processed (see bind)."""
1320        if tagList is None:
1321            return self.tk.splitlist(
1322                self.tk.call('bindtags', self._w))
1323        else:
1324            self.tk.call('bindtags', self._w, tagList)
1325
1326    def _bind(self, what, sequence, func, add, needcleanup=1):
1327        """Internal function."""
1328        if isinstance(func, str):
1329            self.tk.call(what + (sequence, func))
1330        elif func:
1331            funcid = self._register(func, self._substitute,
1332                        needcleanup)
1333            cmd = ('%sif {"[%s %s]" == "break"} break\n'
1334                   %
1335                   (add and '+' or '',
1336                funcid, self._subst_format_str))
1337            self.tk.call(what + (sequence, cmd))
1338            return funcid
1339        elif sequence:
1340            return self.tk.call(what + (sequence,))
1341        else:
1342            return self.tk.splitlist(self.tk.call(what))
1343
1344    def bind(self, sequence=None, func=None, add=None):
1345        """Bind to this widget at event SEQUENCE a call to function FUNC.
1346
1347        SEQUENCE is a string of concatenated event
1348        patterns. An event pattern is of the form
1349        <MODIFIER-MODIFIER-TYPE-DETAIL> where MODIFIER is one
1350        of Control, Mod2, M2, Shift, Mod3, M3, Lock, Mod4, M4,
1351        Button1, B1, Mod5, M5 Button2, B2, Meta, M, Button3,
1352        B3, Alt, Button4, B4, Double, Button5, B5 Triple,
1353        Mod1, M1. TYPE is one of Activate, Enter, Map,
1354        ButtonPress, Button, Expose, Motion, ButtonRelease
1355        FocusIn, MouseWheel, Circulate, FocusOut, Property,
1356        Colormap, Gravity Reparent, Configure, KeyPress, Key,
1357        Unmap, Deactivate, KeyRelease Visibility, Destroy,
1358        Leave and DETAIL is the button number for ButtonPress,
1359        ButtonRelease and DETAIL is the Keysym for KeyPress and
1360        KeyRelease. Examples are
1361        <Control-Button-1> for pressing Control and mouse button 1 or
1362        <Alt-A> for pressing A and the Alt key (KeyPress can be omitted).
1363        An event pattern can also be a virtual event of the form
1364        <<AString>> where AString can be arbitrary. This
1365        event can be generated by event_generate.
1366        If events are concatenated they must appear shortly
1367        after each other.
1368
1369        FUNC will be called if the event sequence occurs with an
1370        instance of Event as argument. If the return value of FUNC is
1371        "break" no further bound function is invoked.
1372
1373        An additional boolean parameter ADD specifies whether FUNC will
1374        be called additionally to the other bound function or whether
1375        it will replace the previous function.
1376
1377        Bind will return an identifier to allow deletion of the bound function with
1378        unbind without memory leak.
1379
1380        If FUNC or SEQUENCE is omitted the bound function or list
1381        of bound events are returned."""
1382
1383        return self._bind(('bind', self._w), sequence, func, add)
1384
1385    def unbind(self, sequence, funcid=None):
1386        """Unbind for this widget for event SEQUENCE  the
1387        function identified with FUNCID."""
1388        self.tk.call('bind', self._w, sequence, '')
1389        if funcid:
1390            self.deletecommand(funcid)
1391
1392    def bind_all(self, sequence=None, func=None, add=None):
1393        """Bind to all widgets at an event SEQUENCE a call to function FUNC.
1394        An additional boolean parameter ADD specifies whether FUNC will
1395        be called additionally to the other bound function or whether
1396        it will replace the previous function. See bind for the return value."""
1397        return self._bind(('bind', 'all'), sequence, func, add, 0)
1398
1399    def unbind_all(self, sequence):
1400        """Unbind for all widgets for event SEQUENCE all functions."""
1401        self.tk.call('bind', 'all' , sequence, '')
1402
1403    def bind_class(self, className, sequence=None, func=None, add=None):
1404        """Bind to widgets with bindtag CLASSNAME at event
1405        SEQUENCE a call of function FUNC. An additional
1406        boolean parameter ADD specifies whether FUNC will be
1407        called additionally to the other bound function or
1408        whether it will replace the previous function. See bind for
1409        the return value."""
1410
1411        return self._bind(('bind', className), sequence, func, add, 0)
1412
1413    def unbind_class(self, className, sequence):
1414        """Unbind for all widgets with bindtag CLASSNAME for event SEQUENCE
1415        all functions."""
1416        self.tk.call('bind', className , sequence, '')
1417
1418    def mainloop(self, n=0):
1419        """Call the mainloop of Tk."""
1420        self.tk.mainloop(n)
1421
1422    def quit(self):
1423        """Quit the Tcl interpreter. All widgets will be destroyed."""
1424        self.tk.quit()
1425
1426    def _getints(self, string):
1427        """Internal function."""
1428        if string:
1429            return tuple(map(self.tk.getint, self.tk.splitlist(string)))
1430
1431    def _getdoubles(self, string):
1432        """Internal function."""
1433        if string:
1434            return tuple(map(self.tk.getdouble, self.tk.splitlist(string)))
1435
1436    def _getboolean(self, string):
1437        """Internal function."""
1438        if string:
1439            return self.tk.getboolean(string)
1440
1441    def _displayof(self, displayof):
1442        """Internal function."""
1443        if displayof:
1444            return ('-displayof', displayof)
1445        if displayof is None:
1446            return ('-displayof', self._w)
1447        return ()
1448
1449    @property
1450    def _windowingsystem(self):
1451        """Internal function."""
1452        try:
1453            return self._root()._windowingsystem_cached
1454        except AttributeError:
1455            ws = self._root()._windowingsystem_cached = \
1456                        self.tk.call('tk', 'windowingsystem')
1457            return ws
1458
1459    def _options(self, cnf, kw = None):
1460        """Internal function."""
1461        if kw:
1462            cnf = _cnfmerge((cnf, kw))
1463        else:
1464            cnf = _cnfmerge(cnf)
1465        res = ()
1466        for k, v in cnf.items():
1467            if v is not None:
1468                if k[-1] == '_': k = k[:-1]
1469                if callable(v):
1470                    v = self._register(v)
1471                elif isinstance(v, (tuple, list)):
1472                    nv = []
1473                    for item in v:
1474                        if isinstance(item, int):
1475                            nv.append(str(item))
1476                        elif isinstance(item, str):
1477                            nv.append(_stringify(item))
1478                        else:
1479                            break
1480                    else:
1481                        v = ' '.join(nv)
1482                res = res + ('-'+k, v)
1483        return res
1484
1485    def nametowidget(self, name):
1486        """Return the Tkinter instance of a widget identified by
1487        its Tcl name NAME."""
1488        name = str(name).split('.')
1489        w = self
1490
1491        if not name[0]:
1492            w = w._root()
1493            name = name[1:]
1494
1495        for n in name:
1496            if not n:
1497                break
1498            w = w.children[n]
1499
1500        return w
1501
1502    _nametowidget = nametowidget
1503
1504    def _register(self, func, subst=None, needcleanup=1):
1505        """Return a newly created Tcl function. If this
1506        function is called, the Python function FUNC will
1507        be executed. An optional function SUBST can
1508        be given which will be executed before FUNC."""
1509        f = CallWrapper(func, subst, self).__call__
1510        name = repr(id(f))
1511        try:
1512            func = func.__func__
1513        except AttributeError:
1514            pass
1515        try:
1516            name = name + func.__name__
1517        except AttributeError:
1518            pass
1519        self.tk.createcommand(name, f)
1520        if needcleanup:
1521            if self._tclCommands is None:
1522                self._tclCommands = []
1523            self._tclCommands.append(name)
1524        return name
1525
1526    register = _register
1527
1528    def _root(self):
1529        """Internal function."""
1530        w = self
1531        while w.master: w = w.master
1532        return w
1533    _subst_format = ('%#', '%b', '%f', '%h', '%k',
1534             '%s', '%t', '%w', '%x', '%y',
1535             '%A', '%E', '%K', '%N', '%W', '%T', '%X', '%Y', '%D')
1536    _subst_format_str = " ".join(_subst_format)
1537
1538    def _substitute(self, *args):
1539        """Internal function."""
1540        if len(args) != len(self._subst_format): return args
1541        getboolean = self.tk.getboolean
1542
1543        getint = self.tk.getint
1544        def getint_event(s):
1545            """Tk changed behavior in 8.4.2, returning "??" rather more often."""
1546            try:
1547                return getint(s)
1548            except (ValueError, TclError):
1549                return s
1550
1551        nsign, b, f, h, k, s, t, w, x, y, A, E, K, N, W, T, X, Y, D = args
1552        # Missing: (a, c, d, m, o, v, B, R)
1553        e = Event()
1554        # serial field: valid for all events
1555        # number of button: ButtonPress and ButtonRelease events only
1556        # height field: Configure, ConfigureRequest, Create,
1557        # ResizeRequest, and Expose events only
1558        # keycode field: KeyPress and KeyRelease events only
1559        # time field: "valid for events that contain a time field"
1560        # width field: Configure, ConfigureRequest, Create, ResizeRequest,
1561        # and Expose events only
1562        # x field: "valid for events that contain an x field"
1563        # y field: "valid for events that contain a y field"
1564        # keysym as decimal: KeyPress and KeyRelease events only
1565        # x_root, y_root fields: ButtonPress, ButtonRelease, KeyPress,
1566        # KeyRelease, and Motion events
1567        e.serial = getint(nsign)
1568        e.num = getint_event(b)
1569        try: e.focus = getboolean(f)
1570        except TclError: pass
1571        e.height = getint_event(h)
1572        e.keycode = getint_event(k)
1573        e.state = getint_event(s)
1574        e.time = getint_event(t)
1575        e.width = getint_event(w)
1576        e.x = getint_event(x)
1577        e.y = getint_event(y)
1578        e.char = A
1579        try: e.send_event = getboolean(E)
1580        except TclError: pass
1581        e.keysym = K
1582        e.keysym_num = getint_event(N)
1583        try:
1584            e.type = EventType(T)
1585        except ValueError:
1586            e.type = T
1587        try:
1588            e.widget = self._nametowidget(W)
1589        except KeyError:
1590            e.widget = W
1591        e.x_root = getint_event(X)
1592        e.y_root = getint_event(Y)
1593        try:
1594            e.delta = getint(D)
1595        except (ValueError, TclError):
1596            e.delta = 0
1597        return (e,)
1598
1599    def _report_exception(self):
1600        """Internal function."""
1601        exc, val, tb = sys.exc_info()
1602        root = self._root()
1603        root.report_callback_exception(exc, val, tb)
1604
1605    def _getconfigure(self, *args):
1606        """Call Tcl configure command and return the result as a dict."""
1607        cnf = {}
1608        for x in self.tk.splitlist(self.tk.call(*args)):
1609            x = self.tk.splitlist(x)
1610            cnf[x[0][1:]] = (x[0][1:],) + x[1:]
1611        return cnf
1612
1613    def _getconfigure1(self, *args):
1614        x = self.tk.splitlist(self.tk.call(*args))
1615        return (x[0][1:],) + x[1:]
1616
1617    def _configure(self, cmd, cnf, kw):
1618        """Internal function."""
1619        if kw:
1620            cnf = _cnfmerge((cnf, kw))
1621        elif cnf:
1622            cnf = _cnfmerge(cnf)
1623        if cnf is None:
1624            return self._getconfigure(_flatten((self._w, cmd)))
1625        if isinstance(cnf, str):
1626            return self._getconfigure1(_flatten((self._w, cmd, '-'+cnf)))
1627        self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
1628    # These used to be defined in Widget:
1629
1630    def configure(self, cnf=None, **kw):
1631        """Configure resources of a widget.
1632
1633        The values for resources are specified as keyword
1634        arguments. To get an overview about
1635        the allowed keyword arguments call the method keys.
1636        """
1637        return self._configure('configure', cnf, kw)
1638
1639    config = configure
1640
1641    def cget(self, key):
1642        """Return the resource value for a KEY given as string."""
1643        return self.tk.call(self._w, 'cget', '-' + key)
1644
1645    __getitem__ = cget
1646
1647    def __setitem__(self, key, value):
1648        self.configure({key: value})
1649
1650    def keys(self):
1651        """Return a list of all resource names of this widget."""
1652        splitlist = self.tk.splitlist
1653        return [splitlist(x)[0][1:] for x in
1654                splitlist(self.tk.call(self._w, 'configure'))]
1655
1656    def __str__(self):
1657        """Return the window path name of this widget."""
1658        return self._w
1659
1660    def __repr__(self):
1661        return '<%s.%s object %s>' % (
1662            self.__class__.__module__, self.__class__.__qualname__, self._w)
1663
1664    # Pack methods that apply to the master
1665    _noarg_ = ['_noarg_']
1666
1667    def pack_propagate(self, flag=_noarg_):
1668        """Set or get the status for propagation of geometry information.
1669
1670        A boolean argument specifies whether the geometry information
1671        of the slaves will determine the size of this widget. If no argument
1672        is given the current setting will be returned.
1673        """
1674        if flag is Misc._noarg_:
1675            return self._getboolean(self.tk.call(
1676                'pack', 'propagate', self._w))
1677        else:
1678            self.tk.call('pack', 'propagate', self._w, flag)
1679
1680    propagate = pack_propagate
1681
1682    def pack_slaves(self):
1683        """Return a list of all slaves of this widget
1684        in its packing order."""
1685        return [self._nametowidget(x) for x in
1686                self.tk.splitlist(
1687                   self.tk.call('pack', 'slaves', self._w))]
1688
1689    slaves = pack_slaves
1690
1691    # Place method that applies to the master
1692    def place_slaves(self):
1693        """Return a list of all slaves of this widget
1694        in its packing order."""
1695        return [self._nametowidget(x) for x in
1696                self.tk.splitlist(
1697                   self.tk.call(
1698                       'place', 'slaves', self._w))]
1699
1700    # Grid methods that apply to the master
1701
1702    def grid_anchor(self, anchor=None): # new in Tk 8.5
1703        """The anchor value controls how to place the grid within the
1704        master when no row/column has any weight.
1705
1706        The default anchor is nw."""
1707        self.tk.call('grid', 'anchor', self._w, anchor)
1708
1709    anchor = grid_anchor
1710
1711    def grid_bbox(self, column=None, row=None, col2=None, row2=None):
1712        """Return a tuple of integer coordinates for the bounding
1713        box of this widget controlled by the geometry manager grid.
1714
1715        If COLUMN, ROW is given the bounding box applies from
1716        the cell with row and column 0 to the specified
1717        cell. If COL2 and ROW2 are given the bounding box
1718        starts at that cell.
1719
1720        The returned integers specify the offset of the upper left
1721        corner in the master widget and the width and height.
1722        """
1723        args = ('grid', 'bbox', self._w)
1724        if column is not None and row is not None:
1725            args = args + (column, row)
1726        if col2 is not None and row2 is not None:
1727            args = args + (col2, row2)
1728        return self._getints(self.tk.call(*args)) or None
1729
1730    bbox = grid_bbox
1731
1732    def _gridconvvalue(self, value):
1733        if isinstance(value, (str, _tkinter.Tcl_Obj)):
1734            try:
1735                svalue = str(value)
1736                if not svalue:
1737                    return None
1738                elif '.' in svalue:
1739                    return self.tk.getdouble(svalue)
1740                else:
1741                    return self.tk.getint(svalue)
1742            except (ValueError, TclError):
1743                pass
1744        return value
1745
1746    def _grid_configure(self, command, index, cnf, kw):
1747        """Internal function."""
1748        if isinstance(cnf, str) and not kw:
1749            if cnf[-1:] == '_':
1750                cnf = cnf[:-1]
1751            if cnf[:1] != '-':
1752                cnf = '-'+cnf
1753            options = (cnf,)
1754        else:
1755            options = self._options(cnf, kw)
1756        if not options:
1757            return _splitdict(
1758                self.tk,
1759                self.tk.call('grid', command, self._w, index),
1760                conv=self._gridconvvalue)
1761        res = self.tk.call(
1762                  ('grid', command, self._w, index)
1763                  + options)
1764        if len(options) == 1:
1765            return self._gridconvvalue(res)
1766
1767    def grid_columnconfigure(self, index, cnf={}, **kw):
1768        """Configure column INDEX of a grid.
1769
1770        Valid resources are minsize (minimum size of the column),
1771        weight (how much does additional space propagate to this column)
1772        and pad (how much space to let additionally)."""
1773        return self._grid_configure('columnconfigure', index, cnf, kw)
1774
1775    columnconfigure = grid_columnconfigure
1776
1777    def grid_location(self, x, y):
1778        """Return a tuple of column and row which identify the cell
1779        at which the pixel at position X and Y inside the master
1780        widget is located."""
1781        return self._getints(
1782            self.tk.call(
1783                'grid', 'location', self._w, x, y)) or None
1784
1785    def grid_propagate(self, flag=_noarg_):
1786        """Set or get the status for propagation of geometry information.
1787
1788        A boolean argument specifies whether the geometry information
1789        of the slaves will determine the size of this widget. If no argument
1790        is given, the current setting will be returned.
1791        """
1792        if flag is Misc._noarg_:
1793            return self._getboolean(self.tk.call(
1794                'grid', 'propagate', self._w))
1795        else:
1796            self.tk.call('grid', 'propagate', self._w, flag)
1797
1798    def grid_rowconfigure(self, index, cnf={}, **kw):
1799        """Configure row INDEX of a grid.
1800
1801        Valid resources are minsize (minimum size of the row),
1802        weight (how much does additional space propagate to this row)
1803        and pad (how much space to let additionally)."""
1804        return self._grid_configure('rowconfigure', index, cnf, kw)
1805
1806    rowconfigure = grid_rowconfigure
1807
1808    def grid_size(self):
1809        """Return a tuple of the number of column and rows in the grid."""
1810        return self._getints(
1811            self.tk.call('grid', 'size', self._w)) or None
1812
1813    size = grid_size
1814
1815    def grid_slaves(self, row=None, column=None):
1816        """Return a list of all slaves of this widget
1817        in its packing order."""
1818        args = ()
1819        if row is not None:
1820            args = args + ('-row', row)
1821        if column is not None:
1822            args = args + ('-column', column)
1823        return [self._nametowidget(x) for x in
1824                self.tk.splitlist(self.tk.call(
1825                   ('grid', 'slaves', self._w) + args))]
1826
1827    # Support for the "event" command, new in Tk 4.2.
1828    # By Case Roole.
1829
1830    def event_add(self, virtual, *sequences):
1831        """Bind a virtual event VIRTUAL (of the form <<Name>>)
1832        to an event SEQUENCE such that the virtual event is triggered
1833        whenever SEQUENCE occurs."""
1834        args = ('event', 'add', virtual) + sequences
1835        self.tk.call(args)
1836
1837    def event_delete(self, virtual, *sequences):
1838        """Unbind a virtual event VIRTUAL from SEQUENCE."""
1839        args = ('event', 'delete', virtual) + sequences
1840        self.tk.call(args)
1841
1842    def event_generate(self, sequence, **kw):
1843        """Generate an event SEQUENCE. Additional
1844        keyword arguments specify parameter of the event
1845        (e.g. x, y, rootx, rooty)."""
1846        args = ('event', 'generate', self._w, sequence)
1847        for k, v in kw.items():
1848            args = args + ('-%s' % k, str(v))
1849        self.tk.call(args)
1850
1851    def event_info(self, virtual=None):
1852        """Return a list of all virtual events or the information
1853        about the SEQUENCE bound to the virtual event VIRTUAL."""
1854        return self.tk.splitlist(
1855            self.tk.call('event', 'info', virtual))
1856
1857    # Image related commands
1858
1859    def image_names(self):
1860        """Return a list of all existing image names."""
1861        return self.tk.splitlist(self.tk.call('image', 'names'))
1862
1863    def image_types(self):
1864        """Return a list of all available image types (e.g. photo bitmap)."""
1865        return self.tk.splitlist(self.tk.call('image', 'types'))
1866
1867
1868class CallWrapper:
1869    """Internal class. Stores function to call when some user
1870    defined Tcl function is called e.g. after an event occurred."""
1871
1872    def __init__(self, func, subst, widget):
1873        """Store FUNC, SUBST and WIDGET as members."""
1874        self.func = func
1875        self.subst = subst
1876        self.widget = widget
1877
1878    def __call__(self, *args):
1879        """Apply first function SUBST to arguments, than FUNC."""
1880        try:
1881            if self.subst:
1882                args = self.subst(*args)
1883            return self.func(*args)
1884        except SystemExit:
1885            raise
1886        except:
1887            self.widget._report_exception()
1888
1889
1890class XView:
1891    """Mix-in class for querying and changing the horizontal position
1892    of a widget's window."""
1893
1894    def xview(self, *args):
1895        """Query and change the horizontal position of the view."""
1896        res = self.tk.call(self._w, 'xview', *args)
1897        if not args:
1898            return self._getdoubles(res)
1899
1900    def xview_moveto(self, fraction):
1901        """Adjusts the view in the window so that FRACTION of the
1902        total width of the canvas is off-screen to the left."""
1903        self.tk.call(self._w, 'xview', 'moveto', fraction)
1904
1905    def xview_scroll(self, number, what):
1906        """Shift the x-view according to NUMBER which is measured in "units"
1907        or "pages" (WHAT)."""
1908        self.tk.call(self._w, 'xview', 'scroll', number, what)
1909
1910
1911class YView:
1912    """Mix-in class for querying and changing the vertical position
1913    of a widget's window."""
1914
1915    def yview(self, *args):
1916        """Query and change the vertical position of the view."""
1917        res = self.tk.call(self._w, 'yview', *args)
1918        if not args:
1919            return self._getdoubles(res)
1920
1921    def yview_moveto(self, fraction):
1922        """Adjusts the view in the window so that FRACTION of the
1923        total height of the canvas is off-screen to the top."""
1924        self.tk.call(self._w, 'yview', 'moveto', fraction)
1925
1926    def yview_scroll(self, number, what):
1927        """Shift the y-view according to NUMBER which is measured in
1928        "units" or "pages" (WHAT)."""
1929        self.tk.call(self._w, 'yview', 'scroll', number, what)
1930
1931
1932class Wm:
1933    """Provides functions for the communication with the window manager."""
1934
1935    def wm_aspect(self,
1936              minNumer=None, minDenom=None,
1937              maxNumer=None, maxDenom=None):
1938        """Instruct the window manager to set the aspect ratio (width/height)
1939        of this widget to be between MINNUMER/MINDENOM and MAXNUMER/MAXDENOM. Return a tuple
1940        of the actual values if no argument is given."""
1941        return self._getints(
1942            self.tk.call('wm', 'aspect', self._w,
1943                     minNumer, minDenom,
1944                     maxNumer, maxDenom))
1945
1946    aspect = wm_aspect
1947
1948    def wm_attributes(self, *args):
1949        """This subcommand returns or sets platform specific attributes
1950
1951        The first form returns a list of the platform specific flags and
1952        their values. The second form returns the value for the specific
1953        option. The third form sets one or more of the values. The values
1954        are as follows:
1955
1956        On Windows, -disabled gets or sets whether the window is in a
1957        disabled state. -toolwindow gets or sets the style of the window
1958        to toolwindow (as defined in the MSDN). -topmost gets or sets
1959        whether this is a topmost window (displays above all other
1960        windows).
1961
1962        On Macintosh, XXXXX
1963
1964        On Unix, there are currently no special attribute values.
1965        """
1966        args = ('wm', 'attributes', self._w) + args
1967        return self.tk.call(args)
1968
1969    attributes = wm_attributes
1970
1971    def wm_client(self, name=None):
1972        """Store NAME in WM_CLIENT_MACHINE property of this widget. Return
1973        current value."""
1974        return self.tk.call('wm', 'client', self._w, name)
1975
1976    client = wm_client
1977
1978    def wm_colormapwindows(self, *wlist):
1979        """Store list of window names (WLIST) into WM_COLORMAPWINDOWS property
1980        of this widget. This list contains windows whose colormaps differ from their
1981        parents. Return current list of widgets if WLIST is empty."""
1982        if len(wlist) > 1:
1983            wlist = (wlist,) # Tk needs a list of windows here
1984        args = ('wm', 'colormapwindows', self._w) + wlist
1985        if wlist:
1986            self.tk.call(args)
1987        else:
1988            return [self._nametowidget(x)
1989                    for x in self.tk.splitlist(self.tk.call(args))]
1990
1991    colormapwindows = wm_colormapwindows
1992
1993    def wm_command(self, value=None):
1994        """Store VALUE in WM_COMMAND property. It is the command
1995        which shall be used to invoke the application. Return current
1996        command if VALUE is None."""
1997        return self.tk.call('wm', 'command', self._w, value)
1998
1999    command = wm_command
2000
2001    def wm_deiconify(self):
2002        """Deiconify this widget. If it was never mapped it will not be mapped.
2003        On Windows it will raise this widget and give it the focus."""
2004        return self.tk.call('wm', 'deiconify', self._w)
2005
2006    deiconify = wm_deiconify
2007
2008    def wm_focusmodel(self, model=None):
2009        """Set focus model to MODEL. "active" means that this widget will claim
2010        the focus itself, "passive" means that the window manager shall give
2011        the focus. Return current focus model if MODEL is None."""
2012        return self.tk.call('wm', 'focusmodel', self._w, model)
2013
2014    focusmodel = wm_focusmodel
2015
2016    def wm_forget(self, window): # new in Tk 8.5
2017        """The window will be unmapped from the screen and will no longer
2018        be managed by wm. toplevel windows will be treated like frame
2019        windows once they are no longer managed by wm, however, the menu
2020        option configuration will be remembered and the menus will return
2021        once the widget is managed again."""
2022        self.tk.call('wm', 'forget', window)
2023
2024    forget = wm_forget
2025
2026    def wm_frame(self):
2027        """Return identifier for decorative frame of this widget if present."""
2028        return self.tk.call('wm', 'frame', self._w)
2029
2030    frame = wm_frame
2031
2032    def wm_geometry(self, newGeometry=None):
2033        """Set geometry to NEWGEOMETRY of the form =widthxheight+x+y. Return
2034        current value if None is given."""
2035        return self.tk.call('wm', 'geometry', self._w, newGeometry)
2036
2037    geometry = wm_geometry
2038
2039    def wm_grid(self,
2040         baseWidth=None, baseHeight=None,
2041         widthInc=None, heightInc=None):
2042        """Instruct the window manager that this widget shall only be
2043        resized on grid boundaries. WIDTHINC and HEIGHTINC are the width and
2044        height of a grid unit in pixels. BASEWIDTH and BASEHEIGHT are the
2045        number of grid units requested in Tk_GeometryRequest."""
2046        return self._getints(self.tk.call(
2047            'wm', 'grid', self._w,
2048            baseWidth, baseHeight, widthInc, heightInc))
2049
2050    grid = wm_grid
2051
2052    def wm_group(self, pathName=None):
2053        """Set the group leader widgets for related widgets to PATHNAME. Return
2054        the group leader of this widget if None is given."""
2055        return self.tk.call('wm', 'group', self._w, pathName)
2056
2057    group = wm_group
2058
2059    def wm_iconbitmap(self, bitmap=None, default=None):
2060        """Set bitmap for the iconified widget to BITMAP. Return
2061        the bitmap if None is given.
2062
2063        Under Windows, the DEFAULT parameter can be used to set the icon
2064        for the widget and any descendents that don't have an icon set
2065        explicitly.  DEFAULT can be the relative path to a .ico file
2066        (example: root.iconbitmap(default='myicon.ico') ).  See Tk
2067        documentation for more information."""
2068        if default:
2069            return self.tk.call('wm', 'iconbitmap', self._w, '-default', default)
2070        else:
2071            return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
2072
2073    iconbitmap = wm_iconbitmap
2074
2075    def wm_iconify(self):
2076        """Display widget as icon."""
2077        return self.tk.call('wm', 'iconify', self._w)
2078
2079    iconify = wm_iconify
2080
2081    def wm_iconmask(self, bitmap=None):
2082        """Set mask for the icon bitmap of this widget. Return the
2083        mask if None is given."""
2084        return self.tk.call('wm', 'iconmask', self._w, bitmap)
2085
2086    iconmask = wm_iconmask
2087
2088    def wm_iconname(self, newName=None):
2089        """Set the name of the icon for this widget. Return the name if
2090        None is given."""
2091        return self.tk.call('wm', 'iconname', self._w, newName)
2092
2093    iconname = wm_iconname
2094
2095    def wm_iconphoto(self, default=False, *args): # new in Tk 8.5
2096        """Sets the titlebar icon for this window based on the named photo
2097        images passed through args. If default is True, this is applied to
2098        all future created toplevels as well.
2099
2100        The data in the images is taken as a snapshot at the time of
2101        invocation. If the images are later changed, this is not reflected
2102        to the titlebar icons. Multiple images are accepted to allow
2103        different images sizes to be provided. The window manager may scale
2104        provided icons to an appropriate size.
2105
2106        On Windows, the images are packed into a Windows icon structure.
2107        This will override an icon specified to wm_iconbitmap, and vice
2108        versa.
2109
2110        On X, the images are arranged into the _NET_WM_ICON X property,
2111        which most modern window managers support. An icon specified by
2112        wm_iconbitmap may exist simultaneously.
2113
2114        On Macintosh, this currently does nothing."""
2115        if default:
2116            self.tk.call('wm', 'iconphoto', self._w, "-default", *args)
2117        else:
2118            self.tk.call('wm', 'iconphoto', self._w, *args)
2119
2120    iconphoto = wm_iconphoto
2121
2122    def wm_iconposition(self, x=None, y=None):
2123        """Set the position of the icon of this widget to X and Y. Return
2124        a tuple of the current values of X and X if None is given."""
2125        return self._getints(self.tk.call(
2126            'wm', 'iconposition', self._w, x, y))
2127
2128    iconposition = wm_iconposition
2129
2130    def wm_iconwindow(self, pathName=None):
2131        """Set widget PATHNAME to be displayed instead of icon. Return the current
2132        value if None is given."""
2133        return self.tk.call('wm', 'iconwindow', self._w, pathName)
2134
2135    iconwindow = wm_iconwindow
2136
2137    def wm_manage(self, widget): # new in Tk 8.5
2138        """The widget specified will become a stand alone top-level window.
2139        The window will be decorated with the window managers title bar,
2140        etc."""
2141        self.tk.call('wm', 'manage', widget)
2142
2143    manage = wm_manage
2144
2145    def wm_maxsize(self, width=None, height=None):
2146        """Set max WIDTH and HEIGHT for this widget. If the window is gridded
2147        the values are given in grid units. Return the current values if None
2148        is given."""
2149        return self._getints(self.tk.call(
2150            'wm', 'maxsize', self._w, width, height))
2151
2152    maxsize = wm_maxsize
2153
2154    def wm_minsize(self, width=None, height=None):
2155        """Set min WIDTH and HEIGHT for this widget. If the window is gridded
2156        the values are given in grid units. Return the current values if None
2157        is given."""
2158        return self._getints(self.tk.call(
2159            'wm', 'minsize', self._w, width, height))
2160
2161    minsize = wm_minsize
2162
2163    def wm_overrideredirect(self, boolean=None):
2164        """Instruct the window manager to ignore this widget
2165        if BOOLEAN is given with 1. Return the current value if None
2166        is given."""
2167        return self._getboolean(self.tk.call(
2168            'wm', 'overrideredirect', self._w, boolean))
2169
2170    overrideredirect = wm_overrideredirect
2171
2172    def wm_positionfrom(self, who=None):
2173        """Instruct the window manager that the position of this widget shall
2174        be defined by the user if WHO is "user", and by its own policy if WHO is
2175        "program"."""
2176        return self.tk.call('wm', 'positionfrom', self._w, who)
2177
2178    positionfrom = wm_positionfrom
2179
2180    def wm_protocol(self, name=None, func=None):
2181        """Bind function FUNC to command NAME for this widget.
2182        Return the function bound to NAME if None is given. NAME could be
2183        e.g. "WM_SAVE_YOURSELF" or "WM_DELETE_WINDOW"."""
2184        if callable(func):
2185            command = self._register(func)
2186        else:
2187            command = func
2188        return self.tk.call(
2189            'wm', 'protocol', self._w, name, command)
2190
2191    protocol = wm_protocol
2192
2193    def wm_resizable(self, width=None, height=None):
2194        """Instruct the window manager whether this width can be resized
2195        in WIDTH or HEIGHT. Both values are boolean values."""
2196        return self.tk.call('wm', 'resizable', self._w, width, height)
2197
2198    resizable = wm_resizable
2199
2200    def wm_sizefrom(self, who=None):
2201        """Instruct the window manager that the size of this widget shall
2202        be defined by the user if WHO is "user", and by its own policy if WHO is
2203        "program"."""
2204        return self.tk.call('wm', 'sizefrom', self._w, who)
2205
2206    sizefrom = wm_sizefrom
2207
2208    def wm_state(self, newstate=None):
2209        """Query or set the state of this widget as one of normal, icon,
2210        iconic (see wm_iconwindow), withdrawn, or zoomed (Windows only)."""
2211        return self.tk.call('wm', 'state', self._w, newstate)
2212
2213    state = wm_state
2214
2215    def wm_title(self, string=None):
2216        """Set the title of this widget."""
2217        return self.tk.call('wm', 'title', self._w, string)
2218
2219    title = wm_title
2220
2221    def wm_transient(self, master=None):
2222        """Instruct the window manager that this widget is transient
2223        with regard to widget MASTER."""
2224        return self.tk.call('wm', 'transient', self._w, master)
2225
2226    transient = wm_transient
2227
2228    def wm_withdraw(self):
2229        """Withdraw this widget from the screen such that it is unmapped
2230        and forgotten by the window manager. Re-draw it with wm_deiconify."""
2231        return self.tk.call('wm', 'withdraw', self._w)
2232
2233    withdraw = wm_withdraw
2234
2235
2236class Tk(Misc, Wm):
2237    """Toplevel widget of Tk which represents mostly the main window
2238    of an application. It has an associated Tcl interpreter."""
2239    _w = '.'
2240
2241    def __init__(self, screenName=None, baseName=None, className='Tk',
2242                 useTk=1, sync=0, use=None):
2243        """Return a new Toplevel widget on screen SCREENNAME. A new Tcl interpreter will
2244        be created. BASENAME will be used for the identification of the profile file (see
2245        readprofile).
2246        It is constructed from sys.argv[0] without extensions if None is given. CLASSNAME
2247        is the name of the widget class."""
2248        self.master = None
2249        self.children = {}
2250        self._tkloaded = 0
2251        # to avoid recursions in the getattr code in case of failure, we
2252        # ensure that self.tk is always _something_.
2253        self.tk = None
2254        if baseName is None:
2255            import os
2256            baseName = os.path.basename(sys.argv[0])
2257            baseName, ext = os.path.splitext(baseName)
2258            if ext not in ('.py', '.pyc'):
2259                baseName = baseName + ext
2260        interactive = 0
2261        self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
2262        if useTk:
2263            self._loadtk()
2264        if not sys.flags.ignore_environment:
2265            # Issue #16248: Honor the -E flag to avoid code injection.
2266            self.readprofile(baseName, className)
2267
2268    def loadtk(self):
2269        if not self._tkloaded:
2270            self.tk.loadtk()
2271            self._loadtk()
2272
2273    def _loadtk(self):
2274        self._tkloaded = 1
2275        global _default_root
2276        # Version sanity checks
2277        tk_version = self.tk.getvar('tk_version')
2278        if tk_version != _tkinter.TK_VERSION:
2279            raise RuntimeError("tk.h version (%s) doesn't match libtk.a version (%s)"
2280                               % (_tkinter.TK_VERSION, tk_version))
2281        # Under unknown circumstances, tcl_version gets coerced to float
2282        tcl_version = str(self.tk.getvar('tcl_version'))
2283        if tcl_version != _tkinter.TCL_VERSION:
2284            raise RuntimeError("tcl.h version (%s) doesn't match libtcl.a version (%s)" \
2285                               % (_tkinter.TCL_VERSION, tcl_version))
2286        # Create and register the tkerror and exit commands
2287        # We need to inline parts of _register here, _ register
2288        # would register differently-named commands.
2289        if self._tclCommands is None:
2290            self._tclCommands = []
2291        self.tk.createcommand('tkerror', _tkerror)
2292        self.tk.createcommand('exit', _exit)
2293        self._tclCommands.append('tkerror')
2294        self._tclCommands.append('exit')
2295        if _support_default_root and not _default_root:
2296            _default_root = self
2297        self.protocol("WM_DELETE_WINDOW", self.destroy)
2298
2299    def destroy(self):
2300        """Destroy this and all descendants widgets. This will
2301        end the application of this Tcl interpreter."""
2302        for c in list(self.children.values()): c.destroy()
2303        self.tk.call('destroy', self._w)
2304        Misc.destroy(self)
2305        global _default_root
2306        if _support_default_root and _default_root is self:
2307            _default_root = None
2308
2309    def readprofile(self, baseName, className):
2310        """Internal function. It reads BASENAME.tcl and CLASSNAME.tcl into
2311        the Tcl Interpreter and calls exec on the contents of BASENAME.py and
2312        CLASSNAME.py if such a file exists in the home directory."""
2313        import os
2314        if 'HOME' in os.environ: home = os.environ['HOME']
2315        else: home = os.curdir
2316        class_tcl = os.path.join(home, '.%s.tcl' % className)
2317        class_py = os.path.join(home, '.%s.py' % className)
2318        base_tcl = os.path.join(home, '.%s.tcl' % baseName)
2319        base_py = os.path.join(home, '.%s.py' % baseName)
2320        dir = {'self': self}
2321        exec('from tkinter import *', dir)
2322        if os.path.isfile(class_tcl):
2323            self.tk.call('source', class_tcl)
2324        if os.path.isfile(class_py):
2325            exec(open(class_py).read(), dir)
2326        if os.path.isfile(base_tcl):
2327            self.tk.call('source', base_tcl)
2328        if os.path.isfile(base_py):
2329            exec(open(base_py).read(), dir)
2330
2331    def report_callback_exception(self, exc, val, tb):
2332        """Report callback exception on sys.stderr.
2333
2334        Applications may want to override this internal function, and
2335        should when sys.stderr is None."""
2336        import traceback
2337        print("Exception in Tkinter callback", file=sys.stderr)
2338        sys.last_type = exc
2339        sys.last_value = val
2340        sys.last_traceback = tb
2341        traceback.print_exception(exc, val, tb)
2342
2343    def __getattr__(self, attr):
2344        "Delegate attribute access to the interpreter object"
2345        return getattr(self.tk, attr)
2346
2347# Ideally, the classes Pack, Place and Grid disappear, the
2348# pack/place/grid methods are defined on the Widget class, and
2349# everybody uses w.pack_whatever(...) instead of Pack.whatever(w,
2350# ...), with pack(), place() and grid() being short for
2351# pack_configure(), place_configure() and grid_columnconfigure(), and
2352# forget() being short for pack_forget().  As a practical matter, I'm
2353# afraid that there is too much code out there that may be using the
2354# Pack, Place or Grid class, so I leave them intact -- but only as
2355# backwards compatibility features.  Also note that those methods that
2356# take a master as argument (e.g. pack_propagate) have been moved to
2357# the Misc class (which now incorporates all methods common between
2358# toplevel and interior widgets).  Again, for compatibility, these are
2359# copied into the Pack, Place or Grid class.
2360
2361
2362def Tcl(screenName=None, baseName=None, className='Tk', useTk=0):
2363    return Tk(screenName, baseName, className, useTk)
2364
2365
2366class Pack:
2367    """Geometry manager Pack.
2368
2369    Base class to use the methods pack_* in every widget."""
2370
2371    def pack_configure(self, cnf={}, **kw):
2372        """Pack a widget in the parent widget. Use as options:
2373        after=widget - pack it after you have packed widget
2374        anchor=NSEW (or subset) - position widget according to
2375                                  given direction
2376        before=widget - pack it before you will pack widget
2377        expand=bool - expand widget if parent size grows
2378        fill=NONE or X or Y or BOTH - fill widget if widget grows
2379        in=master - use master to contain this widget
2380        in_=master - see 'in' option description
2381        ipadx=amount - add internal padding in x direction
2382        ipady=amount - add internal padding in y direction
2383        padx=amount - add padding in x direction
2384        pady=amount - add padding in y direction
2385        side=TOP or BOTTOM or LEFT or RIGHT -  where to add this widget.
2386        """
2387        self.tk.call(
2388              ('pack', 'configure', self._w)
2389              + self._options(cnf, kw))
2390
2391    pack = configure = config = pack_configure
2392
2393    def pack_forget(self):
2394        """Unmap this widget and do not use it for the packing order."""
2395        self.tk.call('pack', 'forget', self._w)
2396
2397    forget = pack_forget
2398
2399    def pack_info(self):
2400        """Return information about the packing options
2401        for this widget."""
2402        d = _splitdict(self.tk, self.tk.call('pack', 'info', self._w))
2403        if 'in' in d:
2404            d['in'] = self.nametowidget(d['in'])
2405        return d
2406
2407    info = pack_info
2408    propagate = pack_propagate = Misc.pack_propagate
2409    slaves = pack_slaves = Misc.pack_slaves
2410
2411
2412class Place:
2413    """Geometry manager Place.
2414
2415    Base class to use the methods place_* in every widget."""
2416
2417    def place_configure(self, cnf={}, **kw):
2418        """Place a widget in the parent widget. Use as options:
2419        in=master - master relative to which the widget is placed
2420        in_=master - see 'in' option description
2421        x=amount - locate anchor of this widget at position x of master
2422        y=amount - locate anchor of this widget at position y of master
2423        relx=amount - locate anchor of this widget between 0.0 and 1.0
2424                      relative to width of master (1.0 is right edge)
2425        rely=amount - locate anchor of this widget between 0.0 and 1.0
2426                      relative to height of master (1.0 is bottom edge)
2427        anchor=NSEW (or subset) - position anchor according to given direction
2428        width=amount - width of this widget in pixel
2429        height=amount - height of this widget in pixel
2430        relwidth=amount - width of this widget between 0.0 and 1.0
2431                          relative to width of master (1.0 is the same width
2432                          as the master)
2433        relheight=amount - height of this widget between 0.0 and 1.0
2434                           relative to height of master (1.0 is the same
2435                           height as the master)
2436        bordermode="inside" or "outside" - whether to take border width of
2437                                           master widget into account
2438        """
2439        self.tk.call(
2440              ('place', 'configure', self._w)
2441              + self._options(cnf, kw))
2442
2443    place = configure = config = place_configure
2444
2445    def place_forget(self):
2446        """Unmap this widget."""
2447        self.tk.call('place', 'forget', self._w)
2448
2449    forget = place_forget
2450
2451    def place_info(self):
2452        """Return information about the placing options
2453        for this widget."""
2454        d = _splitdict(self.tk, self.tk.call('place', 'info', self._w))
2455        if 'in' in d:
2456            d['in'] = self.nametowidget(d['in'])
2457        return d
2458
2459    info = place_info
2460    slaves = place_slaves = Misc.place_slaves
2461
2462
2463class Grid:
2464    """Geometry manager Grid.
2465
2466    Base class to use the methods grid_* in every widget."""
2467    # Thanks to Masazumi Yoshikawa (yosikawa@isi.edu)
2468
2469    def grid_configure(self, cnf={}, **kw):
2470        """Position a widget in the parent widget in a grid. Use as options:
2471        column=number - use cell identified with given column (starting with 0)
2472        columnspan=number - this widget will span several columns
2473        in=master - use master to contain this widget
2474        in_=master - see 'in' option description
2475        ipadx=amount - add internal padding in x direction
2476        ipady=amount - add internal padding in y direction
2477        padx=amount - add padding in x direction
2478        pady=amount - add padding in y direction
2479        row=number - use cell identified with given row (starting with 0)
2480        rowspan=number - this widget will span several rows
2481        sticky=NSEW - if cell is larger on which sides will this
2482                      widget stick to the cell boundary
2483        """
2484        self.tk.call(
2485              ('grid', 'configure', self._w)
2486              + self._options(cnf, kw))
2487
2488    grid = configure = config = grid_configure
2489    bbox = grid_bbox = Misc.grid_bbox
2490    columnconfigure = grid_columnconfigure = Misc.grid_columnconfigure
2491
2492    def grid_forget(self):
2493        """Unmap this widget."""
2494        self.tk.call('grid', 'forget', self._w)
2495
2496    forget = grid_forget
2497
2498    def grid_remove(self):
2499        """Unmap this widget but remember the grid options."""
2500        self.tk.call('grid', 'remove', self._w)
2501
2502    def grid_info(self):
2503        """Return information about the options
2504        for positioning this widget in a grid."""
2505        d = _splitdict(self.tk, self.tk.call('grid', 'info', self._w))
2506        if 'in' in d:
2507            d['in'] = self.nametowidget(d['in'])
2508        return d
2509
2510    info = grid_info
2511    location = grid_location = Misc.grid_location
2512    propagate = grid_propagate = Misc.grid_propagate
2513    rowconfigure = grid_rowconfigure = Misc.grid_rowconfigure
2514    size = grid_size = Misc.grid_size
2515    slaves = grid_slaves = Misc.grid_slaves
2516
2517
2518class BaseWidget(Misc):
2519    """Internal class."""
2520
2521    def _setup(self, master, cnf):
2522        """Internal function. Sets up information about children."""
2523        if _support_default_root:
2524            global _default_root
2525            if not master:
2526                if not _default_root:
2527                    _default_root = Tk()
2528                master = _default_root
2529        self.master = master
2530        self.tk = master.tk
2531        name = None
2532        if 'name' in cnf:
2533            name = cnf['name']
2534            del cnf['name']
2535        if not name:
2536            name = self.__class__.__name__.lower()
2537            if master._last_child_ids is None:
2538                master._last_child_ids = {}
2539            count = master._last_child_ids.get(name, 0) + 1
2540            master._last_child_ids[name] = count
2541            if count == 1:
2542                name = '!%s' % (name,)
2543            else:
2544                name = '!%s%d' % (name, count)
2545        self._name = name
2546        if master._w=='.':
2547            self._w = '.' + name
2548        else:
2549            self._w = master._w + '.' + name
2550        self.children = {}
2551        if self._name in self.master.children:
2552            self.master.children[self._name].destroy()
2553        self.master.children[self._name] = self
2554
2555    def __init__(self, master, widgetName, cnf={}, kw={}, extra=()):
2556        """Construct a widget with the parent widget MASTER, a name WIDGETNAME
2557        and appropriate options."""
2558        if kw:
2559            cnf = _cnfmerge((cnf, kw))
2560        self.widgetName = widgetName
2561        BaseWidget._setup(self, master, cnf)
2562        if self._tclCommands is None:
2563            self._tclCommands = []
2564        classes = [(k, v) for k, v in cnf.items() if isinstance(k, type)]
2565        for k, v in classes:
2566            del cnf[k]
2567        self.tk.call(
2568            (widgetName, self._w) + extra + self._options(cnf))
2569        for k, v in classes:
2570            k.configure(self, v)
2571
2572    def destroy(self):
2573        """Destroy this and all descendants widgets."""
2574        for c in list(self.children.values()): c.destroy()
2575        self.tk.call('destroy', self._w)
2576        if self._name in self.master.children:
2577            del self.master.children[self._name]
2578        Misc.destroy(self)
2579
2580    def _do(self, name, args=()):
2581        # XXX Obsolete -- better use self.tk.call directly!
2582        return self.tk.call((self._w, name) + args)
2583
2584
2585class Widget(BaseWidget, Pack, Place, Grid):
2586    """Internal class.
2587
2588    Base class for a widget which can be positioned with the geometry managers
2589    Pack, Place or Grid."""
2590    pass
2591
2592
2593class Toplevel(BaseWidget, Wm):
2594    """Toplevel widget, e.g. for dialogs."""
2595
2596    def __init__(self, master=None, cnf={}, **kw):
2597        """Construct a toplevel widget with the parent MASTER.
2598
2599        Valid resource names: background, bd, bg, borderwidth, class,
2600        colormap, container, cursor, height, highlightbackground,
2601        highlightcolor, highlightthickness, menu, relief, screen, takefocus,
2602        use, visual, width."""
2603        if kw:
2604            cnf = _cnfmerge((cnf, kw))
2605        extra = ()
2606        for wmkey in ['screen', 'class_', 'class', 'visual',
2607                  'colormap']:
2608            if wmkey in cnf:
2609                val = cnf[wmkey]
2610                # TBD: a hack needed because some keys
2611                # are not valid as keyword arguments
2612                if wmkey[-1] == '_': opt = '-'+wmkey[:-1]
2613                else: opt = '-'+wmkey
2614                extra = extra + (opt, val)
2615                del cnf[wmkey]
2616        BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
2617        root = self._root()
2618        self.iconname(root.iconname())
2619        self.title(root.title())
2620        self.protocol("WM_DELETE_WINDOW", self.destroy)
2621
2622
2623class Button(Widget):
2624    """Button widget."""
2625
2626    def __init__(self, master=None, cnf={}, **kw):
2627        """Construct a button widget with the parent MASTER.
2628
2629        STANDARD OPTIONS
2630
2631            activebackground, activeforeground, anchor,
2632            background, bitmap, borderwidth, cursor,
2633            disabledforeground, font, foreground
2634            highlightbackground, highlightcolor,
2635            highlightthickness, image, justify,
2636            padx, pady, relief, repeatdelay,
2637            repeatinterval, takefocus, text,
2638            textvariable, underline, wraplength
2639
2640        WIDGET-SPECIFIC OPTIONS
2641
2642            command, compound, default, height,
2643            overrelief, state, width
2644        """
2645        Widget.__init__(self, master, 'button', cnf, kw)
2646
2647    def flash(self):
2648        """Flash the button.
2649
2650        This is accomplished by redisplaying
2651        the button several times, alternating between active and
2652        normal colors. At the end of the flash the button is left
2653        in the same normal/active state as when the command was
2654        invoked. This command is ignored if the button's state is
2655        disabled.
2656        """
2657        self.tk.call(self._w, 'flash')
2658
2659    def invoke(self):
2660        """Invoke the command associated with the button.
2661
2662        The return value is the return value from the command,
2663        or an empty string if there is no command associated with
2664        the button. This command is ignored if the button's state
2665        is disabled.
2666        """
2667        return self.tk.call(self._w, 'invoke')
2668
2669
2670class Canvas(Widget, XView, YView):
2671    """Canvas widget to display graphical elements like lines or text."""
2672
2673    def __init__(self, master=None, cnf={}, **kw):
2674        """Construct a canvas widget with the parent MASTER.
2675
2676        Valid resource names: background, bd, bg, borderwidth, closeenough,
2677        confine, cursor, height, highlightbackground, highlightcolor,
2678        highlightthickness, insertbackground, insertborderwidth,
2679        insertofftime, insertontime, insertwidth, offset, relief,
2680        scrollregion, selectbackground, selectborderwidth, selectforeground,
2681        state, takefocus, width, xscrollcommand, xscrollincrement,
2682        yscrollcommand, yscrollincrement."""
2683        Widget.__init__(self, master, 'canvas', cnf, kw)
2684
2685    def addtag(self, *args):
2686        """Internal function."""
2687        self.tk.call((self._w, 'addtag') + args)
2688
2689    def addtag_above(self, newtag, tagOrId):
2690        """Add tag NEWTAG to all items above TAGORID."""
2691        self.addtag(newtag, 'above', tagOrId)
2692
2693    def addtag_all(self, newtag):
2694        """Add tag NEWTAG to all items."""
2695        self.addtag(newtag, 'all')
2696
2697    def addtag_below(self, newtag, tagOrId):
2698        """Add tag NEWTAG to all items below TAGORID."""
2699        self.addtag(newtag, 'below', tagOrId)
2700
2701    def addtag_closest(self, newtag, x, y, halo=None, start=None):
2702        """Add tag NEWTAG to item which is closest to pixel at X, Y.
2703        If several match take the top-most.
2704        All items closer than HALO are considered overlapping (all are
2705        closests). If START is specified the next below this tag is taken."""
2706        self.addtag(newtag, 'closest', x, y, halo, start)
2707
2708    def addtag_enclosed(self, newtag, x1, y1, x2, y2):
2709        """Add tag NEWTAG to all items in the rectangle defined
2710        by X1,Y1,X2,Y2."""
2711        self.addtag(newtag, 'enclosed', x1, y1, x2, y2)
2712
2713    def addtag_overlapping(self, newtag, x1, y1, x2, y2):
2714        """Add tag NEWTAG to all items which overlap the rectangle
2715        defined by X1,Y1,X2,Y2."""
2716        self.addtag(newtag, 'overlapping', x1, y1, x2, y2)
2717
2718    def addtag_withtag(self, newtag, tagOrId):
2719        """Add tag NEWTAG to all items with TAGORID."""
2720        self.addtag(newtag, 'withtag', tagOrId)
2721
2722    def bbox(self, *args):
2723        """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle
2724        which encloses all items with tags specified as arguments."""
2725        return self._getints(
2726            self.tk.call((self._w, 'bbox') + args)) or None
2727
2728    def tag_unbind(self, tagOrId, sequence, funcid=None):
2729        """Unbind for all items with TAGORID for event SEQUENCE  the
2730        function identified with FUNCID."""
2731        self.tk.call(self._w, 'bind', tagOrId, sequence, '')
2732        if funcid:
2733            self.deletecommand(funcid)
2734
2735    def tag_bind(self, tagOrId, sequence=None, func=None, add=None):
2736        """Bind to all items with TAGORID at event SEQUENCE a call to function FUNC.
2737
2738        An additional boolean parameter ADD specifies whether FUNC will be
2739        called additionally to the other bound function or whether it will
2740        replace the previous function. See bind for the return value."""
2741        return self._bind((self._w, 'bind', tagOrId),
2742                  sequence, func, add)
2743
2744    def canvasx(self, screenx, gridspacing=None):
2745        """Return the canvas x coordinate of pixel position SCREENX rounded
2746        to nearest multiple of GRIDSPACING units."""
2747        return self.tk.getdouble(self.tk.call(
2748            self._w, 'canvasx', screenx, gridspacing))
2749
2750    def canvasy(self, screeny, gridspacing=None):
2751        """Return the canvas y coordinate of pixel position SCREENY rounded
2752        to nearest multiple of GRIDSPACING units."""
2753        return self.tk.getdouble(self.tk.call(
2754            self._w, 'canvasy', screeny, gridspacing))
2755
2756    def coords(self, *args):
2757        """Return a list of coordinates for the item given in ARGS."""
2758        # XXX Should use _flatten on args
2759        return [self.tk.getdouble(x) for x in
2760                           self.tk.splitlist(
2761                   self.tk.call((self._w, 'coords') + args))]
2762
2763    def _create(self, itemType, args, kw): # Args: (val, val, ..., cnf={})
2764        """Internal function."""
2765        args = _flatten(args)
2766        cnf = args[-1]
2767        if isinstance(cnf, (dict, tuple)):
2768            args = args[:-1]
2769        else:
2770            cnf = {}
2771        return self.tk.getint(self.tk.call(
2772            self._w, 'create', itemType,
2773            *(args + self._options(cnf, kw))))
2774
2775    def create_arc(self, *args, **kw):
2776        """Create arc shaped region with coordinates x1,y1,x2,y2."""
2777        return self._create('arc', args, kw)
2778
2779    def create_bitmap(self, *args, **kw):
2780        """Create bitmap with coordinates x1,y1."""
2781        return self._create('bitmap', args, kw)
2782
2783    def create_image(self, *args, **kw):
2784        """Create image item with coordinates x1,y1."""
2785        return self._create('image', args, kw)
2786
2787    def create_line(self, *args, **kw):
2788        """Create line with coordinates x1,y1,...,xn,yn."""
2789        return self._create('line', args, kw)
2790
2791    def create_oval(self, *args, **kw):
2792        """Create oval with coordinates x1,y1,x2,y2."""
2793        return self._create('oval', args, kw)
2794
2795    def create_polygon(self, *args, **kw):
2796        """Create polygon with coordinates x1,y1,...,xn,yn."""
2797        return self._create('polygon', args, kw)
2798
2799    def create_rectangle(self, *args, **kw):
2800        """Create rectangle with coordinates x1,y1,x2,y2."""
2801        return self._create('rectangle', args, kw)
2802
2803    def create_text(self, *args, **kw):
2804        """Create text with coordinates x1,y1."""
2805        return self._create('text', args, kw)
2806
2807    def create_window(self, *args, **kw):
2808        """Create window with coordinates x1,y1,x2,y2."""
2809        return self._create('window', args, kw)
2810
2811    def dchars(self, *args):
2812        """Delete characters of text items identified by tag or id in ARGS (possibly
2813        several times) from FIRST to LAST character (including)."""
2814        self.tk.call((self._w, 'dchars') + args)
2815
2816    def delete(self, *args):
2817        """Delete items identified by all tag or ids contained in ARGS."""
2818        self.tk.call((self._w, 'delete') + args)
2819
2820    def dtag(self, *args):
2821        """Delete tag or id given as last arguments in ARGS from items
2822        identified by first argument in ARGS."""
2823        self.tk.call((self._w, 'dtag') + args)
2824
2825    def find(self, *args):
2826        """Internal function."""
2827        return self._getints(
2828            self.tk.call((self._w, 'find') + args)) or ()
2829
2830    def find_above(self, tagOrId):
2831        """Return items above TAGORID."""
2832        return self.find('above', tagOrId)
2833
2834    def find_all(self):
2835        """Return all items."""
2836        return self.find('all')
2837
2838    def find_below(self, tagOrId):
2839        """Return all items below TAGORID."""
2840        return self.find('below', tagOrId)
2841
2842    def find_closest(self, x, y, halo=None, start=None):
2843        """Return item which is closest to pixel at X, Y.
2844        If several match take the top-most.
2845        All items closer than HALO are considered overlapping (all are
2846        closest). If START is specified the next below this tag is taken."""
2847        return self.find('closest', x, y, halo, start)
2848
2849    def find_enclosed(self, x1, y1, x2, y2):
2850        """Return all items in rectangle defined
2851        by X1,Y1,X2,Y2."""
2852        return self.find('enclosed', x1, y1, x2, y2)
2853
2854    def find_overlapping(self, x1, y1, x2, y2):
2855        """Return all items which overlap the rectangle
2856        defined by X1,Y1,X2,Y2."""
2857        return self.find('overlapping', x1, y1, x2, y2)
2858
2859    def find_withtag(self, tagOrId):
2860        """Return all items with TAGORID."""
2861        return self.find('withtag', tagOrId)
2862
2863    def focus(self, *args):
2864        """Set focus to the first item specified in ARGS."""
2865        return self.tk.call((self._w, 'focus') + args)
2866
2867    def gettags(self, *args):
2868        """Return tags associated with the first item specified in ARGS."""
2869        return self.tk.splitlist(
2870            self.tk.call((self._w, 'gettags') + args))
2871
2872    def icursor(self, *args):
2873        """Set cursor at position POS in the item identified by TAGORID.
2874        In ARGS TAGORID must be first."""
2875        self.tk.call((self._w, 'icursor') + args)
2876
2877    def index(self, *args):
2878        """Return position of cursor as integer in item specified in ARGS."""
2879        return self.tk.getint(self.tk.call((self._w, 'index') + args))
2880
2881    def insert(self, *args):
2882        """Insert TEXT in item TAGORID at position POS. ARGS must
2883        be TAGORID POS TEXT."""
2884        self.tk.call((self._w, 'insert') + args)
2885
2886    def itemcget(self, tagOrId, option):
2887        """Return the resource value for an OPTION for item TAGORID."""
2888        return self.tk.call(
2889            (self._w, 'itemcget') + (tagOrId, '-'+option))
2890
2891    def itemconfigure(self, tagOrId, cnf=None, **kw):
2892        """Configure resources of an item TAGORID.
2893
2894        The values for resources are specified as keyword
2895        arguments. To get an overview about
2896        the allowed keyword arguments call the method without arguments.
2897        """
2898        return self._configure(('itemconfigure', tagOrId), cnf, kw)
2899
2900    itemconfig = itemconfigure
2901
2902    # lower, tkraise/lift hide Misc.lower, Misc.tkraise/lift,
2903    # so the preferred name for them is tag_lower, tag_raise
2904    # (similar to tag_bind, and similar to the Text widget);
2905    # unfortunately can't delete the old ones yet (maybe in 1.6)
2906    def tag_lower(self, *args):
2907        """Lower an item TAGORID given in ARGS
2908        (optional below another item)."""
2909        self.tk.call((self._w, 'lower') + args)
2910
2911    lower = tag_lower
2912
2913    def move(self, *args):
2914        """Move an item TAGORID given in ARGS."""
2915        self.tk.call((self._w, 'move') + args)
2916
2917    def moveto(self, tagOrId, x='', y=''):
2918        """Move the items given by TAGORID in the canvas coordinate
2919        space so that the first coordinate pair of the bottommost
2920        item with tag TAGORID is located at position (X,Y).
2921        X and Y may be the empty string, in which case the
2922        corresponding coordinate will be unchanged. All items matching
2923        TAGORID remain in the same positions relative to each other."""
2924        self.tk.call(self._w, 'moveto', tagOrId, x, y)
2925
2926    def postscript(self, cnf={}, **kw):
2927        """Print the contents of the canvas to a postscript
2928        file. Valid options: colormap, colormode, file, fontmap,
2929        height, pageanchor, pageheight, pagewidth, pagex, pagey,
2930        rotate, width, x, y."""
2931        return self.tk.call((self._w, 'postscript') +
2932                    self._options(cnf, kw))
2933
2934    def tag_raise(self, *args):
2935        """Raise an item TAGORID given in ARGS
2936        (optional above another item)."""
2937        self.tk.call((self._w, 'raise') + args)
2938
2939    lift = tkraise = tag_raise
2940
2941    def scale(self, *args):
2942        """Scale item TAGORID with XORIGIN, YORIGIN, XSCALE, YSCALE."""
2943        self.tk.call((self._w, 'scale') + args)
2944
2945    def scan_mark(self, x, y):
2946        """Remember the current X, Y coordinates."""
2947        self.tk.call(self._w, 'scan', 'mark', x, y)
2948
2949    def scan_dragto(self, x, y, gain=10):
2950        """Adjust the view of the canvas to GAIN times the
2951        difference between X and Y and the coordinates given in
2952        scan_mark."""
2953        self.tk.call(self._w, 'scan', 'dragto', x, y, gain)
2954
2955    def select_adjust(self, tagOrId, index):
2956        """Adjust the end of the selection near the cursor of an item TAGORID to index."""
2957        self.tk.call(self._w, 'select', 'adjust', tagOrId, index)
2958
2959    def select_clear(self):
2960        """Clear the selection if it is in this widget."""
2961        self.tk.call(self._w, 'select', 'clear')
2962
2963    def select_from(self, tagOrId, index):
2964        """Set the fixed end of a selection in item TAGORID to INDEX."""
2965        self.tk.call(self._w, 'select', 'from', tagOrId, index)
2966
2967    def select_item(self):
2968        """Return the item which has the selection."""
2969        return self.tk.call(self._w, 'select', 'item') or None
2970
2971    def select_to(self, tagOrId, index):
2972        """Set the variable end of a selection in item TAGORID to INDEX."""
2973        self.tk.call(self._w, 'select', 'to', tagOrId, index)
2974
2975    def type(self, tagOrId):
2976        """Return the type of the item TAGORID."""
2977        return self.tk.call(self._w, 'type', tagOrId) or None
2978
2979
2980class Checkbutton(Widget):
2981    """Checkbutton widget which is either in on- or off-state."""
2982
2983    def __init__(self, master=None, cnf={}, **kw):
2984        """Construct a checkbutton widget with the parent MASTER.
2985
2986        Valid resource names: activebackground, activeforeground, anchor,
2987        background, bd, bg, bitmap, borderwidth, command, cursor,
2988        disabledforeground, fg, font, foreground, height,
2989        highlightbackground, highlightcolor, highlightthickness, image,
2990        indicatoron, justify, offvalue, onvalue, padx, pady, relief,
2991        selectcolor, selectimage, state, takefocus, text, textvariable,
2992        underline, variable, width, wraplength."""
2993        Widget.__init__(self, master, 'checkbutton', cnf, kw)
2994
2995    def deselect(self):
2996        """Put the button in off-state."""
2997        self.tk.call(self._w, 'deselect')
2998
2999    def flash(self):
3000        """Flash the button."""
3001        self.tk.call(self._w, 'flash')
3002
3003    def invoke(self):
3004        """Toggle the button and invoke a command if given as resource."""
3005        return self.tk.call(self._w, 'invoke')
3006
3007    def select(self):
3008        """Put the button in on-state."""
3009        self.tk.call(self._w, 'select')
3010
3011    def toggle(self):
3012        """Toggle the button."""
3013        self.tk.call(self._w, 'toggle')
3014
3015
3016class Entry(Widget, XView):
3017    """Entry widget which allows displaying simple text."""
3018
3019    def __init__(self, master=None, cnf={}, **kw):
3020        """Construct an entry widget with the parent MASTER.
3021
3022        Valid resource names: background, bd, bg, borderwidth, cursor,
3023        exportselection, fg, font, foreground, highlightbackground,
3024        highlightcolor, highlightthickness, insertbackground,
3025        insertborderwidth, insertofftime, insertontime, insertwidth,
3026        invalidcommand, invcmd, justify, relief, selectbackground,
3027        selectborderwidth, selectforeground, show, state, takefocus,
3028        textvariable, validate, validatecommand, vcmd, width,
3029        xscrollcommand."""
3030        Widget.__init__(self, master, 'entry', cnf, kw)
3031
3032    def delete(self, first, last=None):
3033        """Delete text from FIRST to LAST (not included)."""
3034        self.tk.call(self._w, 'delete', first, last)
3035
3036    def get(self):
3037        """Return the text."""
3038        return self.tk.call(self._w, 'get')
3039
3040    def icursor(self, index):
3041        """Insert cursor at INDEX."""
3042        self.tk.call(self._w, 'icursor', index)
3043
3044    def index(self, index):
3045        """Return position of cursor."""
3046        return self.tk.getint(self.tk.call(
3047            self._w, 'index', index))
3048
3049    def insert(self, index, string):
3050        """Insert STRING at INDEX."""
3051        self.tk.call(self._w, 'insert', index, string)
3052
3053    def scan_mark(self, x):
3054        """Remember the current X, Y coordinates."""
3055        self.tk.call(self._w, 'scan', 'mark', x)
3056
3057    def scan_dragto(self, x):
3058        """Adjust the view of the canvas to 10 times the
3059        difference between X and Y and the coordinates given in
3060        scan_mark."""
3061        self.tk.call(self._w, 'scan', 'dragto', x)
3062
3063    def selection_adjust(self, index):
3064        """Adjust the end of the selection near the cursor to INDEX."""
3065        self.tk.call(self._w, 'selection', 'adjust', index)
3066
3067    select_adjust = selection_adjust
3068
3069    def selection_clear(self):
3070        """Clear the selection if it is in this widget."""
3071        self.tk.call(self._w, 'selection', 'clear')
3072
3073    select_clear = selection_clear
3074
3075    def selection_from(self, index):
3076        """Set the fixed end of a selection to INDEX."""
3077        self.tk.call(self._w, 'selection', 'from', index)
3078
3079    select_from = selection_from
3080
3081    def selection_present(self):
3082        """Return True if there are characters selected in the entry, False
3083        otherwise."""
3084        return self.tk.getboolean(
3085            self.tk.call(self._w, 'selection', 'present'))
3086
3087    select_present = selection_present
3088
3089    def selection_range(self, start, end):
3090        """Set the selection from START to END (not included)."""
3091        self.tk.call(self._w, 'selection', 'range', start, end)
3092
3093    select_range = selection_range
3094
3095    def selection_to(self, index):
3096        """Set the variable end of a selection to INDEX."""
3097        self.tk.call(self._w, 'selection', 'to', index)
3098
3099    select_to = selection_to
3100
3101
3102class Frame(Widget):
3103    """Frame widget which may contain other widgets and can have a 3D border."""
3104
3105    def __init__(self, master=None, cnf={}, **kw):
3106        """Construct a frame widget with the parent MASTER.
3107
3108        Valid resource names: background, bd, bg, borderwidth, class,
3109        colormap, container, cursor, height, highlightbackground,
3110        highlightcolor, highlightthickness, relief, takefocus, visual, width."""
3111        cnf = _cnfmerge((cnf, kw))
3112        extra = ()
3113        if 'class_' in cnf:
3114            extra = ('-class', cnf['class_'])
3115            del cnf['class_']
3116        elif 'class' in cnf:
3117            extra = ('-class', cnf['class'])
3118            del cnf['class']
3119        Widget.__init__(self, master, 'frame', cnf, {}, extra)
3120
3121
3122class Label(Widget):
3123    """Label widget which can display text and bitmaps."""
3124
3125    def __init__(self, master=None, cnf={}, **kw):
3126        """Construct a label widget with the parent MASTER.
3127
3128        STANDARD OPTIONS
3129
3130            activebackground, activeforeground, anchor,
3131            background, bitmap, borderwidth, cursor,
3132            disabledforeground, font, foreground,
3133            highlightbackground, highlightcolor,
3134            highlightthickness, image, justify,
3135            padx, pady, relief, takefocus, text,
3136            textvariable, underline, wraplength
3137
3138        WIDGET-SPECIFIC OPTIONS
3139
3140            height, state, width
3141
3142        """
3143        Widget.__init__(self, master, 'label', cnf, kw)
3144
3145
3146class Listbox(Widget, XView, YView):
3147    """Listbox widget which can display a list of strings."""
3148
3149    def __init__(self, master=None, cnf={}, **kw):
3150        """Construct a listbox widget with the parent MASTER.
3151
3152        Valid resource names: background, bd, bg, borderwidth, cursor,
3153        exportselection, fg, font, foreground, height, highlightbackground,
3154        highlightcolor, highlightthickness, relief, selectbackground,
3155        selectborderwidth, selectforeground, selectmode, setgrid, takefocus,
3156        width, xscrollcommand, yscrollcommand, listvariable."""
3157        Widget.__init__(self, master, 'listbox', cnf, kw)
3158
3159    def activate(self, index):
3160        """Activate item identified by INDEX."""
3161        self.tk.call(self._w, 'activate', index)
3162
3163    def bbox(self, index):
3164        """Return a tuple of X1,Y1,X2,Y2 coordinates for a rectangle
3165        which encloses the item identified by the given index."""
3166        return self._getints(self.tk.call(self._w, 'bbox', index)) or None
3167
3168    def curselection(self):
3169        """Return the indices of currently selected item."""
3170        return self._getints(self.tk.call(self._w, 'curselection')) or ()
3171
3172    def delete(self, first, last=None):
3173        """Delete items from FIRST to LAST (included)."""
3174        self.tk.call(self._w, 'delete', first, last)
3175
3176    def get(self, first, last=None):
3177        """Get list of items from FIRST to LAST (included)."""
3178        if last is not None:
3179            return self.tk.splitlist(self.tk.call(
3180                self._w, 'get', first, last))
3181        else:
3182            return self.tk.call(self._w, 'get', first)
3183
3184    def index(self, index):
3185        """Return index of item identified with INDEX."""
3186        i = self.tk.call(self._w, 'index', index)
3187        if i == 'none': return None
3188        return self.tk.getint(i)
3189
3190    def insert(self, index, *elements):
3191        """Insert ELEMENTS at INDEX."""
3192        self.tk.call((self._w, 'insert', index) + elements)
3193
3194    def nearest(self, y):
3195        """Get index of item which is nearest to y coordinate Y."""
3196        return self.tk.getint(self.tk.call(
3197            self._w, 'nearest', y))
3198
3199    def scan_mark(self, x, y):
3200        """Remember the current X, Y coordinates."""
3201        self.tk.call(self._w, 'scan', 'mark', x, y)
3202
3203    def scan_dragto(self, x, y):
3204        """Adjust the view of the listbox to 10 times the
3205        difference between X and Y and the coordinates given in
3206        scan_mark."""
3207        self.tk.call(self._w, 'scan', 'dragto', x, y)
3208
3209    def see(self, index):
3210        """Scroll such that INDEX is visible."""
3211        self.tk.call(self._w, 'see', index)
3212
3213    def selection_anchor(self, index):
3214        """Set the fixed end oft the selection to INDEX."""
3215        self.tk.call(self._w, 'selection', 'anchor', index)
3216
3217    select_anchor = selection_anchor
3218
3219    def selection_clear(self, first, last=None):
3220        """Clear the selection from FIRST to LAST (included)."""
3221        self.tk.call(self._w,
3222                 'selection', 'clear', first, last)
3223
3224    select_clear = selection_clear
3225
3226    def selection_includes(self, index):
3227        """Return True if INDEX is part of the selection."""
3228        return self.tk.getboolean(self.tk.call(
3229            self._w, 'selection', 'includes', index))
3230
3231    select_includes = selection_includes
3232
3233    def selection_set(self, first, last=None):
3234        """Set the selection from FIRST to LAST (included) without
3235        changing the currently selected elements."""
3236        self.tk.call(self._w, 'selection', 'set', first, last)
3237
3238    select_set = selection_set
3239
3240    def size(self):
3241        """Return the number of elements in the listbox."""
3242        return self.tk.getint(self.tk.call(self._w, 'size'))
3243
3244    def itemcget(self, index, option):
3245        """Return the resource value for an ITEM and an OPTION."""
3246        return self.tk.call(
3247            (self._w, 'itemcget') + (index, '-'+option))
3248
3249    def itemconfigure(self, index, cnf=None, **kw):
3250        """Configure resources of an ITEM.
3251
3252        The values for resources are specified as keyword arguments.
3253        To get an overview about the allowed keyword arguments
3254        call the method without arguments.
3255        Valid resource names: background, bg, foreground, fg,
3256        selectbackground, selectforeground."""
3257        return self._configure(('itemconfigure', index), cnf, kw)
3258
3259    itemconfig = itemconfigure
3260
3261
3262class Menu(Widget):
3263    """Menu widget which allows displaying menu bars, pull-down menus and pop-up menus."""
3264
3265    def __init__(self, master=None, cnf={}, **kw):
3266        """Construct menu widget with the parent MASTER.
3267
3268        Valid resource names: activebackground, activeborderwidth,
3269        activeforeground, background, bd, bg, borderwidth, cursor,
3270        disabledforeground, fg, font, foreground, postcommand, relief,
3271        selectcolor, takefocus, tearoff, tearoffcommand, title, type."""
3272        Widget.__init__(self, master, 'menu', cnf, kw)
3273
3274    def tk_popup(self, x, y, entry=""):
3275        """Post the menu at position X,Y with entry ENTRY."""
3276        self.tk.call('tk_popup', self._w, x, y, entry)
3277
3278    def activate(self, index):
3279        """Activate entry at INDEX."""
3280        self.tk.call(self._w, 'activate', index)
3281
3282    def add(self, itemType, cnf={}, **kw):
3283        """Internal function."""
3284        self.tk.call((self._w, 'add', itemType) +
3285                 self._options(cnf, kw))
3286
3287    def add_cascade(self, cnf={}, **kw):
3288        """Add hierarchical menu item."""
3289        self.add('cascade', cnf or kw)
3290
3291    def add_checkbutton(self, cnf={}, **kw):
3292        """Add checkbutton menu item."""
3293        self.add('checkbutton', cnf or kw)
3294
3295    def add_command(self, cnf={}, **kw):
3296        """Add command menu item."""
3297        self.add('command', cnf or kw)
3298
3299    def add_radiobutton(self, cnf={}, **kw):
3300        """Addd radio menu item."""
3301        self.add('radiobutton', cnf or kw)
3302
3303    def add_separator(self, cnf={}, **kw):
3304        """Add separator."""
3305        self.add('separator', cnf or kw)
3306
3307    def insert(self, index, itemType, cnf={}, **kw):
3308        """Internal function."""
3309        self.tk.call((self._w, 'insert', index, itemType) +
3310                 self._options(cnf, kw))
3311
3312    def insert_cascade(self, index, cnf={}, **kw):
3313        """Add hierarchical menu item at INDEX."""
3314        self.insert(index, 'cascade', cnf or kw)
3315
3316    def insert_checkbutton(self, index, cnf={}, **kw):
3317        """Add checkbutton menu item at INDEX."""
3318        self.insert(index, 'checkbutton', cnf or kw)
3319
3320    def insert_command(self, index, cnf={}, **kw):
3321        """Add command menu item at INDEX."""
3322        self.insert(index, 'command', cnf or kw)
3323
3324    def insert_radiobutton(self, index, cnf={}, **kw):
3325        """Addd radio menu item at INDEX."""
3326        self.insert(index, 'radiobutton', cnf or kw)
3327
3328    def insert_separator(self, index, cnf={}, **kw):
3329        """Add separator at INDEX."""
3330        self.insert(index, 'separator', cnf or kw)
3331
3332    def delete(self, index1, index2=None):
3333        """Delete menu items between INDEX1 and INDEX2 (included)."""
3334        if index2 is None:
3335            index2 = index1
3336
3337        num_index1, num_index2 = self.index(index1), self.index(index2)
3338        if (num_index1 is None) or (num_index2 is None):
3339            num_index1, num_index2 = 0, -1
3340
3341        for i in range(num_index1, num_index2 + 1):
3342            if 'command' in self.entryconfig(i):
3343                c = str(self.entrycget(i, 'command'))
3344                if c:
3345                    self.deletecommand(c)
3346        self.tk.call(self._w, 'delete', index1, index2)
3347
3348    def entrycget(self, index, option):
3349        """Return the resource value of a menu item for OPTION at INDEX."""
3350        return self.tk.call(self._w, 'entrycget', index, '-' + option)
3351
3352    def entryconfigure(self, index, cnf=None, **kw):
3353        """Configure a menu item at INDEX."""
3354        return self._configure(('entryconfigure', index), cnf, kw)
3355
3356    entryconfig = entryconfigure
3357
3358    def index(self, index):
3359        """Return the index of a menu item identified by INDEX."""
3360        i = self.tk.call(self._w, 'index', index)
3361        if i == 'none': return None
3362        return self.tk.getint(i)
3363
3364    def invoke(self, index):
3365        """Invoke a menu item identified by INDEX and execute
3366        the associated command."""
3367        return self.tk.call(self._w, 'invoke', index)
3368
3369    def post(self, x, y):
3370        """Display a menu at position X,Y."""
3371        self.tk.call(self._w, 'post', x, y)
3372
3373    def type(self, index):
3374        """Return the type of the menu item at INDEX."""
3375        return self.tk.call(self._w, 'type', index)
3376
3377    def unpost(self):
3378        """Unmap a menu."""
3379        self.tk.call(self._w, 'unpost')
3380
3381    def xposition(self, index): # new in Tk 8.5
3382        """Return the x-position of the leftmost pixel of the menu item
3383        at INDEX."""
3384        return self.tk.getint(self.tk.call(self._w, 'xposition', index))
3385
3386    def yposition(self, index):
3387        """Return the y-position of the topmost pixel of the menu item at INDEX."""
3388        return self.tk.getint(self.tk.call(
3389            self._w, 'yposition', index))
3390
3391
3392class Menubutton(Widget):
3393    """Menubutton widget, obsolete since Tk8.0."""
3394
3395    def __init__(self, master=None, cnf={}, **kw):
3396        Widget.__init__(self, master, 'menubutton', cnf, kw)
3397
3398
3399class Message(Widget):
3400    """Message widget to display multiline text. Obsolete since Label does it too."""
3401
3402    def __init__(self, master=None, cnf={}, **kw):
3403        Widget.__init__(self, master, 'message', cnf, kw)
3404
3405
3406class Radiobutton(Widget):
3407    """Radiobutton widget which shows only one of several buttons in on-state."""
3408
3409    def __init__(self, master=None, cnf={}, **kw):
3410        """Construct a radiobutton widget with the parent MASTER.
3411
3412        Valid resource names: activebackground, activeforeground, anchor,
3413        background, bd, bg, bitmap, borderwidth, command, cursor,
3414        disabledforeground, fg, font, foreground, height,
3415        highlightbackground, highlightcolor, highlightthickness, image,
3416        indicatoron, justify, padx, pady, relief, selectcolor, selectimage,
3417        state, takefocus, text, textvariable, underline, value, variable,
3418        width, wraplength."""
3419        Widget.__init__(self, master, 'radiobutton', cnf, kw)
3420
3421    def deselect(self):
3422        """Put the button in off-state."""
3423
3424        self.tk.call(self._w, 'deselect')
3425
3426    def flash(self):
3427        """Flash the button."""
3428        self.tk.call(self._w, 'flash')
3429
3430    def invoke(self):
3431        """Toggle the button and invoke a command if given as resource."""
3432        return self.tk.call(self._w, 'invoke')
3433
3434    def select(self):
3435        """Put the button in on-state."""
3436        self.tk.call(self._w, 'select')
3437
3438
3439class Scale(Widget):
3440    """Scale widget which can display a numerical scale."""
3441
3442    def __init__(self, master=None, cnf={}, **kw):
3443        """Construct a scale widget with the parent MASTER.
3444
3445        Valid resource names: activebackground, background, bigincrement, bd,
3446        bg, borderwidth, command, cursor, digits, fg, font, foreground, from,
3447        highlightbackground, highlightcolor, highlightthickness, label,
3448        length, orient, relief, repeatdelay, repeatinterval, resolution,
3449        showvalue, sliderlength, sliderrelief, state, takefocus,
3450        tickinterval, to, troughcolor, variable, width."""
3451        Widget.__init__(self, master, 'scale', cnf, kw)
3452
3453    def get(self):
3454        """Get the current value as integer or float."""
3455        value = self.tk.call(self._w, 'get')
3456        try:
3457            return self.tk.getint(value)
3458        except (ValueError, TypeError, TclError):
3459            return self.tk.getdouble(value)
3460
3461    def set(self, value):
3462        """Set the value to VALUE."""
3463        self.tk.call(self._w, 'set', value)
3464
3465    def coords(self, value=None):
3466        """Return a tuple (X,Y) of the point along the centerline of the
3467        trough that corresponds to VALUE or the current value if None is
3468        given."""
3469
3470        return self._getints(self.tk.call(self._w, 'coords', value))
3471
3472    def identify(self, x, y):
3473        """Return where the point X,Y lies. Valid return values are "slider",
3474        "though1" and "though2"."""
3475        return self.tk.call(self._w, 'identify', x, y)
3476
3477
3478class Scrollbar(Widget):
3479    """Scrollbar widget which displays a slider at a certain position."""
3480
3481    def __init__(self, master=None, cnf={}, **kw):
3482        """Construct a scrollbar widget with the parent MASTER.
3483
3484        Valid resource names: activebackground, activerelief,
3485        background, bd, bg, borderwidth, command, cursor,
3486        elementborderwidth, highlightbackground,
3487        highlightcolor, highlightthickness, jump, orient,
3488        relief, repeatdelay, repeatinterval, takefocus,
3489        troughcolor, width."""
3490        Widget.__init__(self, master, 'scrollbar', cnf, kw)
3491
3492    def activate(self, index=None):
3493        """Marks the element indicated by index as active.
3494        The only index values understood by this method are "arrow1",
3495        "slider", or "arrow2".  If any other value is specified then no
3496        element of the scrollbar will be active.  If index is not specified,
3497        the method returns the name of the element that is currently active,
3498        or None if no element is active."""
3499        return self.tk.call(self._w, 'activate', index) or None
3500
3501    def delta(self, deltax, deltay):
3502        """Return the fractional change of the scrollbar setting if it
3503        would be moved by DELTAX or DELTAY pixels."""
3504        return self.tk.getdouble(
3505            self.tk.call(self._w, 'delta', deltax, deltay))
3506
3507    def fraction(self, x, y):
3508        """Return the fractional value which corresponds to a slider
3509        position of X,Y."""
3510        return self.tk.getdouble(self.tk.call(self._w, 'fraction', x, y))
3511
3512    def identify(self, x, y):
3513        """Return the element under position X,Y as one of
3514        "arrow1","slider","arrow2" or ""."""
3515        return self.tk.call(self._w, 'identify', x, y)
3516
3517    def get(self):
3518        """Return the current fractional values (upper and lower end)
3519        of the slider position."""
3520        return self._getdoubles(self.tk.call(self._w, 'get'))
3521
3522    def set(self, first, last):
3523        """Set the fractional values of the slider position (upper and
3524        lower ends as value between 0 and 1)."""
3525        self.tk.call(self._w, 'set', first, last)
3526
3527
3528class Text(Widget, XView, YView):
3529    """Text widget which can display text in various forms."""
3530
3531    def __init__(self, master=None, cnf={}, **kw):
3532        """Construct a text widget with the parent MASTER.
3533
3534        STANDARD OPTIONS
3535
3536            background, borderwidth, cursor,
3537            exportselection, font, foreground,
3538            highlightbackground, highlightcolor,
3539            highlightthickness, insertbackground,
3540            insertborderwidth, insertofftime,
3541            insertontime, insertwidth, padx, pady,
3542            relief, selectbackground,
3543            selectborderwidth, selectforeground,
3544            setgrid, takefocus,
3545            xscrollcommand, yscrollcommand,
3546
3547        WIDGET-SPECIFIC OPTIONS
3548
3549            autoseparators, height, maxundo,
3550            spacing1, spacing2, spacing3,
3551            state, tabs, undo, width, wrap,
3552
3553        """
3554        Widget.__init__(self, master, 'text', cnf, kw)
3555
3556    def bbox(self, index):
3557        """Return a tuple of (x,y,width,height) which gives the bounding
3558        box of the visible part of the character at the given index."""
3559        return self._getints(
3560                self.tk.call(self._w, 'bbox', index)) or None
3561
3562    def compare(self, index1, op, index2):
3563        """Return whether between index INDEX1 and index INDEX2 the
3564        relation OP is satisfied. OP is one of <, <=, ==, >=, >, or !=."""
3565        return self.tk.getboolean(self.tk.call(
3566            self._w, 'compare', index1, op, index2))
3567
3568    def count(self, index1, index2, *args): # new in Tk 8.5
3569        """Counts the number of relevant things between the two indices.
3570        If index1 is after index2, the result will be a negative number
3571        (and this holds for each of the possible options).
3572
3573        The actual items which are counted depends on the options given by
3574        args. The result is a list of integers, one for the result of each
3575        counting option given. Valid counting options are "chars",
3576        "displaychars", "displayindices", "displaylines", "indices",
3577        "lines", "xpixels" and "ypixels". There is an additional possible
3578        option "update", which if given then all subsequent options ensure
3579        that any possible out of date information is recalculated."""
3580        args = ['-%s' % arg for arg in args if not arg.startswith('-')]
3581        args += [index1, index2]
3582        res = self.tk.call(self._w, 'count', *args) or None
3583        if res is not None and len(args) <= 3:
3584            return (res, )
3585        else:
3586            return res
3587
3588    def debug(self, boolean=None):
3589        """Turn on the internal consistency checks of the B-Tree inside the text
3590        widget according to BOOLEAN."""
3591        if boolean is None:
3592            return self.tk.getboolean(self.tk.call(self._w, 'debug'))
3593        self.tk.call(self._w, 'debug', boolean)
3594
3595    def delete(self, index1, index2=None):
3596        """Delete the characters between INDEX1 and INDEX2 (not included)."""
3597        self.tk.call(self._w, 'delete', index1, index2)
3598
3599    def dlineinfo(self, index):
3600        """Return tuple (x,y,width,height,baseline) giving the bounding box
3601        and baseline position of the visible part of the line containing
3602        the character at INDEX."""
3603        return self._getints(self.tk.call(self._w, 'dlineinfo', index))
3604
3605    def dump(self, index1, index2=None, command=None, **kw):
3606        """Return the contents of the widget between index1 and index2.
3607
3608        The type of contents returned in filtered based on the keyword
3609        parameters; if 'all', 'image', 'mark', 'tag', 'text', or 'window' are
3610        given and true, then the corresponding items are returned. The result
3611        is a list of triples of the form (key, value, index). If none of the
3612        keywords are true then 'all' is used by default.
3613
3614        If the 'command' argument is given, it is called once for each element
3615        of the list of triples, with the values of each triple serving as the
3616        arguments to the function. In this case the list is not returned."""
3617        args = []
3618        func_name = None
3619        result = None
3620        if not command:
3621            # Never call the dump command without the -command flag, since the
3622            # output could involve Tcl quoting and would be a pain to parse
3623            # right. Instead just set the command to build a list of triples
3624            # as if we had done the parsing.
3625            result = []
3626            def append_triple(key, value, index, result=result):
3627                result.append((key, value, index))
3628            command = append_triple
3629        try:
3630            if not isinstance(command, str):
3631                func_name = command = self._register(command)
3632            args += ["-command", command]
3633            for key in kw:
3634                if kw[key]: args.append("-" + key)
3635            args.append(index1)
3636            if index2:
3637                args.append(index2)
3638            self.tk.call(self._w, "dump", *args)
3639            return result
3640        finally:
3641            if func_name:
3642                self.deletecommand(func_name)
3643
3644    ## new in tk8.4
3645    def edit(self, *args):
3646        """Internal method
3647
3648        This method controls the undo mechanism and
3649        the modified flag. The exact behavior of the
3650        command depends on the option argument that
3651        follows the edit argument. The following forms
3652        of the command are currently supported:
3653
3654        edit_modified, edit_redo, edit_reset, edit_separator
3655        and edit_undo
3656
3657        """
3658        return self.tk.call(self._w, 'edit', *args)
3659
3660    def edit_modified(self, arg=None):
3661        """Get or Set the modified flag
3662
3663        If arg is not specified, returns the modified
3664        flag of the widget. The insert, delete, edit undo and
3665        edit redo commands or the user can set or clear the
3666        modified flag. If boolean is specified, sets the
3667        modified flag of the widget to arg.
3668        """
3669        return self.edit("modified", arg)
3670
3671    def edit_redo(self):
3672        """Redo the last undone edit
3673
3674        When the undo option is true, reapplies the last
3675        undone edits provided no other edits were done since
3676        then. Generates an error when the redo stack is empty.
3677        Does nothing when the undo option is false.
3678        """
3679        return self.edit("redo")
3680
3681    def edit_reset(self):
3682        """Clears the undo and redo stacks
3683        """
3684        return self.edit("reset")
3685
3686    def edit_separator(self):
3687        """Inserts a separator (boundary) on the undo stack.
3688
3689        Does nothing when the undo option is false
3690        """
3691        return self.edit("separator")
3692
3693    def edit_undo(self):
3694        """Undoes the last edit action
3695
3696        If the undo option is true. An edit action is defined
3697        as all the insert and delete commands that are recorded
3698        on the undo stack in between two separators. Generates
3699        an error when the undo stack is empty. Does nothing
3700        when the undo option is false
3701        """
3702        return self.edit("undo")
3703
3704    def get(self, index1, index2=None):
3705        """Return the text from INDEX1 to INDEX2 (not included)."""
3706        return self.tk.call(self._w, 'get', index1, index2)
3707    # (Image commands are new in 8.0)
3708
3709    def image_cget(self, index, option):
3710        """Return the value of OPTION of an embedded image at INDEX."""
3711        if option[:1] != "-":
3712            option = "-" + option
3713        if option[-1:] == "_":
3714            option = option[:-1]
3715        return self.tk.call(self._w, "image", "cget", index, option)
3716
3717    def image_configure(self, index, cnf=None, **kw):
3718        """Configure an embedded image at INDEX."""
3719        return self._configure(('image', 'configure', index), cnf, kw)
3720
3721    def image_create(self, index, cnf={}, **kw):
3722        """Create an embedded image at INDEX."""
3723        return self.tk.call(
3724                 self._w, "image", "create", index,
3725                 *self._options(cnf, kw))
3726
3727    def image_names(self):
3728        """Return all names of embedded images in this widget."""
3729        return self.tk.call(self._w, "image", "names")
3730
3731    def index(self, index):
3732        """Return the index in the form line.char for INDEX."""
3733        return str(self.tk.call(self._w, 'index', index))
3734
3735    def insert(self, index, chars, *args):
3736        """Insert CHARS before the characters at INDEX. An additional
3737        tag can be given in ARGS. Additional CHARS and tags can follow in ARGS."""
3738        self.tk.call((self._w, 'insert', index, chars) + args)
3739
3740    def mark_gravity(self, markName, direction=None):
3741        """Change the gravity of a mark MARKNAME to DIRECTION (LEFT or RIGHT).
3742        Return the current value if None is given for DIRECTION."""
3743        return self.tk.call(
3744            (self._w, 'mark', 'gravity', markName, direction))
3745
3746    def mark_names(self):
3747        """Return all mark names."""
3748        return self.tk.splitlist(self.tk.call(
3749            self._w, 'mark', 'names'))
3750
3751    def mark_set(self, markName, index):
3752        """Set mark MARKNAME before the character at INDEX."""
3753        self.tk.call(self._w, 'mark', 'set', markName, index)
3754
3755    def mark_unset(self, *markNames):
3756        """Delete all marks in MARKNAMES."""
3757        self.tk.call((self._w, 'mark', 'unset') + markNames)
3758
3759    def mark_next(self, index):
3760        """Return the name of the next mark after INDEX."""
3761        return self.tk.call(self._w, 'mark', 'next', index) or None
3762
3763    def mark_previous(self, index):
3764        """Return the name of the previous mark before INDEX."""
3765        return self.tk.call(self._w, 'mark', 'previous', index) or None
3766
3767    def peer_create(self, newPathName, cnf={}, **kw): # new in Tk 8.5
3768        """Creates a peer text widget with the given newPathName, and any
3769        optional standard configuration options. By default the peer will
3770        have the same start and end line as the parent widget, but
3771        these can be overridden with the standard configuration options."""
3772        self.tk.call(self._w, 'peer', 'create', newPathName,
3773            *self._options(cnf, kw))
3774
3775    def peer_names(self): # new in Tk 8.5
3776        """Returns a list of peers of this widget (this does not include
3777        the widget itself)."""
3778        return self.tk.splitlist(self.tk.call(self._w, 'peer', 'names'))
3779
3780    def replace(self, index1, index2, chars, *args): # new in Tk 8.5
3781        """Replaces the range of characters between index1 and index2 with
3782        the given characters and tags specified by args.
3783
3784        See the method insert for some more information about args, and the
3785        method delete for information about the indices."""
3786        self.tk.call(self._w, 'replace', index1, index2, chars, *args)
3787
3788    def scan_mark(self, x, y):
3789        """Remember the current X, Y coordinates."""
3790        self.tk.call(self._w, 'scan', 'mark', x, y)
3791
3792    def scan_dragto(self, x, y):
3793        """Adjust the view of the text to 10 times the
3794        difference between X and Y and the coordinates given in
3795        scan_mark."""
3796        self.tk.call(self._w, 'scan', 'dragto', x, y)
3797
3798    def search(self, pattern, index, stopindex=None,
3799           forwards=None, backwards=None, exact=None,
3800           regexp=None, nocase=None, count=None, elide=None):
3801        """Search PATTERN beginning from INDEX until STOPINDEX.
3802        Return the index of the first character of a match or an
3803        empty string."""
3804        args = [self._w, 'search']
3805        if forwards: args.append('-forwards')
3806        if backwards: args.append('-backwards')
3807        if exact: args.append('-exact')
3808        if regexp: args.append('-regexp')
3809        if nocase: args.append('-nocase')
3810        if elide: args.append('-elide')
3811        if count: args.append('-count'); args.append(count)
3812        if pattern and pattern[0] == '-': args.append('--')
3813        args.append(pattern)
3814        args.append(index)
3815        if stopindex: args.append(stopindex)
3816        return str(self.tk.call(tuple(args)))
3817
3818    def see(self, index):
3819        """Scroll such that the character at INDEX is visible."""
3820        self.tk.call(self._w, 'see', index)
3821
3822    def tag_add(self, tagName, index1, *args):
3823        """Add tag TAGNAME to all characters between INDEX1 and index2 in ARGS.
3824        Additional pairs of indices may follow in ARGS."""
3825        self.tk.call(
3826            (self._w, 'tag', 'add', tagName, index1) + args)
3827
3828    def tag_unbind(self, tagName, sequence, funcid=None):
3829        """Unbind for all characters with TAGNAME for event SEQUENCE  the
3830        function identified with FUNCID."""
3831        self.tk.call(self._w, 'tag', 'bind', tagName, sequence, '')
3832        if funcid:
3833            self.deletecommand(funcid)
3834
3835    def tag_bind(self, tagName, sequence, func, add=None):
3836        """Bind to all characters with TAGNAME at event SEQUENCE a call to function FUNC.
3837
3838        An additional boolean parameter ADD specifies whether FUNC will be
3839        called additionally to the other bound function or whether it will
3840        replace the previous function. See bind for the return value."""
3841        return self._bind((self._w, 'tag', 'bind', tagName),
3842                  sequence, func, add)
3843
3844    def tag_cget(self, tagName, option):
3845        """Return the value of OPTION for tag TAGNAME."""
3846        if option[:1] != '-':
3847            option = '-' + option
3848        if option[-1:] == '_':
3849            option = option[:-1]
3850        return self.tk.call(self._w, 'tag', 'cget', tagName, option)
3851
3852    def tag_configure(self, tagName, cnf=None, **kw):
3853        """Configure a tag TAGNAME."""
3854        return self._configure(('tag', 'configure', tagName), cnf, kw)
3855
3856    tag_config = tag_configure
3857
3858    def tag_delete(self, *tagNames):
3859        """Delete all tags in TAGNAMES."""
3860        self.tk.call((self._w, 'tag', 'delete') + tagNames)
3861
3862    def tag_lower(self, tagName, belowThis=None):
3863        """Change the priority of tag TAGNAME such that it is lower
3864        than the priority of BELOWTHIS."""
3865        self.tk.call(self._w, 'tag', 'lower', tagName, belowThis)
3866
3867    def tag_names(self, index=None):
3868        """Return a list of all tag names."""
3869        return self.tk.splitlist(
3870            self.tk.call(self._w, 'tag', 'names', index))
3871
3872    def tag_nextrange(self, tagName, index1, index2=None):
3873        """Return a list of start and end index for the first sequence of
3874        characters between INDEX1 and INDEX2 which all have tag TAGNAME.
3875        The text is searched forward from INDEX1."""
3876        return self.tk.splitlist(self.tk.call(
3877            self._w, 'tag', 'nextrange', tagName, index1, index2))
3878
3879    def tag_prevrange(self, tagName, index1, index2=None):
3880        """Return a list of start and end index for the first sequence of
3881        characters between INDEX1 and INDEX2 which all have tag TAGNAME.
3882        The text is searched backwards from INDEX1."""
3883        return self.tk.splitlist(self.tk.call(
3884            self._w, 'tag', 'prevrange', tagName, index1, index2))
3885
3886    def tag_raise(self, tagName, aboveThis=None):
3887        """Change the priority of tag TAGNAME such that it is higher
3888        than the priority of ABOVETHIS."""
3889        self.tk.call(
3890            self._w, 'tag', 'raise', tagName, aboveThis)
3891
3892    def tag_ranges(self, tagName):
3893        """Return a list of ranges of text which have tag TAGNAME."""
3894        return self.tk.splitlist(self.tk.call(
3895            self._w, 'tag', 'ranges', tagName))
3896
3897    def tag_remove(self, tagName, index1, index2=None):
3898        """Remove tag TAGNAME from all characters between INDEX1 and INDEX2."""
3899        self.tk.call(
3900            self._w, 'tag', 'remove', tagName, index1, index2)
3901
3902    def window_cget(self, index, option):
3903        """Return the value of OPTION of an embedded window at INDEX."""
3904        if option[:1] != '-':
3905            option = '-' + option
3906        if option[-1:] == '_':
3907            option = option[:-1]
3908        return self.tk.call(self._w, 'window', 'cget', index, option)
3909
3910    def window_configure(self, index, cnf=None, **kw):
3911        """Configure an embedded window at INDEX."""
3912        return self._configure(('window', 'configure', index), cnf, kw)
3913
3914    window_config = window_configure
3915
3916    def window_create(self, index, cnf={}, **kw):
3917        """Create a window at INDEX."""
3918        self.tk.call(
3919              (self._w, 'window', 'create', index)
3920              + self._options(cnf, kw))
3921
3922    def window_names(self):
3923        """Return all names of embedded windows in this widget."""
3924        return self.tk.splitlist(
3925            self.tk.call(self._w, 'window', 'names'))
3926
3927    def yview_pickplace(self, *what):
3928        """Obsolete function, use see."""
3929        self.tk.call((self._w, 'yview', '-pickplace') + what)
3930
3931
3932class _setit:
3933    """Internal class. It wraps the command in the widget OptionMenu."""
3934
3935    def __init__(self, var, value, callback=None):
3936        self.__value = value
3937        self.__var = var
3938        self.__callback = callback
3939
3940    def __call__(self, *args):
3941        self.__var.set(self.__value)
3942        if self.__callback:
3943            self.__callback(self.__value, *args)
3944
3945
3946class OptionMenu(Menubutton):
3947    """OptionMenu which allows the user to select a value from a menu."""
3948
3949    def __init__(self, master, variable, value, *values, **kwargs):
3950        """Construct an optionmenu widget with the parent MASTER, with
3951        the resource textvariable set to VARIABLE, the initially selected
3952        value VALUE, the other menu values VALUES and an additional
3953        keyword argument command."""
3954        kw = {"borderwidth": 2, "textvariable": variable,
3955              "indicatoron": 1, "relief": RAISED, "anchor": "c",
3956              "highlightthickness": 2}
3957        Widget.__init__(self, master, "menubutton", kw)
3958        self.widgetName = 'tk_optionMenu'
3959        menu = self.__menu = Menu(self, name="menu", tearoff=0)
3960        self.menuname = menu._w
3961        # 'command' is the only supported keyword
3962        callback = kwargs.get('command')
3963        if 'command' in kwargs:
3964            del kwargs['command']
3965        if kwargs:
3966            raise TclError('unknown option -'+kwargs.keys()[0])
3967        menu.add_command(label=value,
3968                 command=_setit(variable, value, callback))
3969        for v in values:
3970            menu.add_command(label=v,
3971                     command=_setit(variable, v, callback))
3972        self["menu"] = menu
3973
3974    def __getitem__(self, name):
3975        if name == 'menu':
3976            return self.__menu
3977        return Widget.__getitem__(self, name)
3978
3979    def destroy(self):
3980        """Destroy this widget and the associated menu."""
3981        Menubutton.destroy(self)
3982        self.__menu = None
3983
3984
3985class Image:
3986    """Base class for images."""
3987    _last_id = 0
3988
3989    def __init__(self, imgtype, name=None, cnf={}, master=None, **kw):
3990        self.name = None
3991        if not master:
3992            master = _default_root
3993            if not master:
3994                raise RuntimeError('Too early to create image')
3995        self.tk = getattr(master, 'tk', master)
3996        if not name:
3997            Image._last_id += 1
3998            name = "pyimage%r" % (Image._last_id,) # tk itself would use image<x>
3999        if kw and cnf: cnf = _cnfmerge((cnf, kw))
4000        elif kw: cnf = kw
4001        options = ()
4002        for k, v in cnf.items():
4003            if callable(v):
4004                v = self._register(v)
4005            options = options + ('-'+k, v)
4006        self.tk.call(('image', 'create', imgtype, name,) + options)
4007        self.name = name
4008
4009    def __str__(self): return self.name
4010
4011    def __del__(self):
4012        if self.name:
4013            try:
4014                self.tk.call('image', 'delete', self.name)
4015            except TclError:
4016                # May happen if the root was destroyed
4017                pass
4018
4019    def __setitem__(self, key, value):
4020        self.tk.call(self.name, 'configure', '-'+key, value)
4021
4022    def __getitem__(self, key):
4023        return self.tk.call(self.name, 'configure', '-'+key)
4024
4025    def configure(self, **kw):
4026        """Configure the image."""
4027        res = ()
4028        for k, v in _cnfmerge(kw).items():
4029            if v is not None:
4030                if k[-1] == '_': k = k[:-1]
4031                if callable(v):
4032                    v = self._register(v)
4033                res = res + ('-'+k, v)
4034        self.tk.call((self.name, 'config') + res)
4035
4036    config = configure
4037
4038    def height(self):
4039        """Return the height of the image."""
4040        return self.tk.getint(
4041            self.tk.call('image', 'height', self.name))
4042
4043    def type(self):
4044        """Return the type of the image, e.g. "photo" or "bitmap"."""
4045        return self.tk.call('image', 'type', self.name)
4046
4047    def width(self):
4048        """Return the width of the image."""
4049        return self.tk.getint(
4050            self.tk.call('image', 'width', self.name))
4051
4052
4053class PhotoImage(Image):
4054    """Widget which can display images in PGM, PPM, GIF, PNG format."""
4055
4056    def __init__(self, name=None, cnf={}, master=None, **kw):
4057        """Create an image with NAME.
4058
4059        Valid resource names: data, format, file, gamma, height, palette,
4060        width."""
4061        Image.__init__(self, 'photo', name, cnf, master, **kw)
4062
4063    def blank(self):
4064        """Display a transparent image."""
4065        self.tk.call(self.name, 'blank')
4066
4067    def cget(self, option):
4068        """Return the value of OPTION."""
4069        return self.tk.call(self.name, 'cget', '-' + option)
4070    # XXX config
4071
4072    def __getitem__(self, key):
4073        return self.tk.call(self.name, 'cget', '-' + key)
4074    # XXX copy -from, -to, ...?
4075
4076    def copy(self):
4077        """Return a new PhotoImage with the same image as this widget."""
4078        destImage = PhotoImage(master=self.tk)
4079        self.tk.call(destImage, 'copy', self.name)
4080        return destImage
4081
4082    def zoom(self, x, y=''):
4083        """Return a new PhotoImage with the same image as this widget
4084        but zoom it with a factor of x in the X direction and y in the Y
4085        direction.  If y is not given, the default value is the same as x.
4086        """
4087        destImage = PhotoImage(master=self.tk)
4088        if y=='': y=x
4089        self.tk.call(destImage, 'copy', self.name, '-zoom',x,y)
4090        return destImage
4091
4092    def subsample(self, x, y=''):
4093        """Return a new PhotoImage based on the same image as this widget
4094        but use only every Xth or Yth pixel.  If y is not given, the
4095        default value is the same as x.
4096        """
4097        destImage = PhotoImage(master=self.tk)
4098        if y=='': y=x
4099        self.tk.call(destImage, 'copy', self.name, '-subsample',x,y)
4100        return destImage
4101
4102    def get(self, x, y):
4103        """Return the color (red, green, blue) of the pixel at X,Y."""
4104        return self.tk.call(self.name, 'get', x, y)
4105
4106    def put(self, data, to=None):
4107        """Put row formatted colors to image starting from
4108        position TO, e.g. image.put("{red green} {blue yellow}", to=(4,6))"""
4109        args = (self.name, 'put', data)
4110        if to:
4111            if to[0] == '-to':
4112                to = to[1:]
4113            args = args + ('-to',) + tuple(to)
4114        self.tk.call(args)
4115    # XXX read
4116
4117    def write(self, filename, format=None, from_coords=None):
4118        """Write image to file FILENAME in FORMAT starting from
4119        position FROM_COORDS."""
4120        args = (self.name, 'write', filename)
4121        if format:
4122            args = args + ('-format', format)
4123        if from_coords:
4124            args = args + ('-from',) + tuple(from_coords)
4125        self.tk.call(args)
4126
4127    def transparency_get(self, x, y):
4128        """Return True if the pixel at x,y is transparent."""
4129        return self.tk.getboolean(self.tk.call(
4130            self.name, 'transparency', 'get', x, y))
4131
4132    def transparency_set(self, x, y, boolean):
4133        """Set the transparency of the pixel at x,y."""
4134        self.tk.call(self.name, 'transparency', 'set', x, y, boolean)
4135
4136
4137class BitmapImage(Image):
4138    """Widget which can display images in XBM format."""
4139
4140    def __init__(self, name=None, cnf={}, master=None, **kw):
4141        """Create a bitmap with NAME.
4142
4143        Valid resource names: background, data, file, foreground, maskdata, maskfile."""
4144        Image.__init__(self, 'bitmap', name, cnf, master, **kw)
4145
4146
4147def image_names():
4148    return _default_root.tk.splitlist(_default_root.tk.call('image', 'names'))
4149
4150
4151def image_types():
4152    return _default_root.tk.splitlist(_default_root.tk.call('image', 'types'))
4153
4154
4155class Spinbox(Widget, XView):
4156    """spinbox widget."""
4157
4158    def __init__(self, master=None, cnf={}, **kw):
4159        """Construct a spinbox widget with the parent MASTER.
4160
4161        STANDARD OPTIONS
4162
4163            activebackground, background, borderwidth,
4164            cursor, exportselection, font, foreground,
4165            highlightbackground, highlightcolor,
4166            highlightthickness, insertbackground,
4167            insertborderwidth, insertofftime,
4168            insertontime, insertwidth, justify, relief,
4169            repeatdelay, repeatinterval,
4170            selectbackground, selectborderwidth
4171            selectforeground, takefocus, textvariable
4172            xscrollcommand.
4173
4174        WIDGET-SPECIFIC OPTIONS
4175
4176            buttonbackground, buttoncursor,
4177            buttondownrelief, buttonuprelief,
4178            command, disabledbackground,
4179            disabledforeground, format, from,
4180            invalidcommand, increment,
4181            readonlybackground, state, to,
4182            validate, validatecommand values,
4183            width, wrap,
4184        """
4185        Widget.__init__(self, master, 'spinbox', cnf, kw)
4186
4187    def bbox(self, index):
4188        """Return a tuple of X1,Y1,X2,Y2 coordinates for a
4189        rectangle which encloses the character given by index.
4190
4191        The first two elements of the list give the x and y
4192        coordinates of the upper-left corner of the screen
4193        area covered by the character (in pixels relative
4194        to the widget) and the last two elements give the
4195        width and height of the character, in pixels. The
4196        bounding box may refer to a region outside the
4197        visible area of the window.
4198        """
4199        return self._getints(self.tk.call(self._w, 'bbox', index)) or None
4200
4201    def delete(self, first, last=None):
4202        """Delete one or more elements of the spinbox.
4203
4204        First is the index of the first character to delete,
4205        and last is the index of the character just after
4206        the last one to delete. If last isn't specified it
4207        defaults to first+1, i.e. a single character is
4208        deleted.  This command returns an empty string.
4209        """
4210        return self.tk.call(self._w, 'delete', first, last)
4211
4212    def get(self):
4213        """Returns the spinbox's string"""
4214        return self.tk.call(self._w, 'get')
4215
4216    def icursor(self, index):
4217        """Alter the position of the insertion cursor.
4218
4219        The insertion cursor will be displayed just before
4220        the character given by index. Returns an empty string
4221        """
4222        return self.tk.call(self._w, 'icursor', index)
4223
4224    def identify(self, x, y):
4225        """Returns the name of the widget at position x, y
4226
4227        Return value is one of: none, buttondown, buttonup, entry
4228        """
4229        return self.tk.call(self._w, 'identify', x, y)
4230
4231    def index(self, index):
4232        """Returns the numerical index corresponding to index
4233        """
4234        return self.tk.call(self._w, 'index', index)
4235
4236    def insert(self, index, s):
4237        """Insert string s at index
4238
4239         Returns an empty string.
4240        """
4241        return self.tk.call(self._w, 'insert', index, s)
4242
4243    def invoke(self, element):
4244        """Causes the specified element to be invoked
4245
4246        The element could be buttondown or buttonup
4247        triggering the action associated with it.
4248        """
4249        return self.tk.call(self._w, 'invoke', element)
4250
4251    def scan(self, *args):
4252        """Internal function."""
4253        return self._getints(
4254            self.tk.call((self._w, 'scan') + args)) or ()
4255
4256    def scan_mark(self, x):
4257        """Records x and the current view in the spinbox window;
4258
4259        used in conjunction with later scan dragto commands.
4260        Typically this command is associated with a mouse button
4261        press in the widget. It returns an empty string.
4262        """
4263        return self.scan("mark", x)
4264
4265    def scan_dragto(self, x):
4266        """Compute the difference between the given x argument
4267        and the x argument to the last scan mark command
4268
4269        It then adjusts the view left or right by 10 times the
4270        difference in x-coordinates. This command is typically
4271        associated with mouse motion events in the widget, to
4272        produce the effect of dragging the spinbox at high speed
4273        through the window. The return value is an empty string.
4274        """
4275        return self.scan("dragto", x)
4276
4277    def selection(self, *args):
4278        """Internal function."""
4279        return self._getints(
4280            self.tk.call((self._w, 'selection') + args)) or ()
4281
4282    def selection_adjust(self, index):
4283        """Locate the end of the selection nearest to the character
4284        given by index,
4285
4286        Then adjust that end of the selection to be at index
4287        (i.e including but not going beyond index). The other
4288        end of the selection is made the anchor point for future
4289        select to commands. If the selection isn't currently in
4290        the spinbox, then a new selection is created to include
4291        the characters between index and the most recent selection
4292        anchor point, inclusive.
4293        """
4294        return self.selection("adjust", index)
4295
4296    def selection_clear(self):
4297        """Clear the selection
4298
4299        If the selection isn't in this widget then the
4300        command has no effect.
4301        """
4302        return self.selection("clear")
4303
4304    def selection_element(self, element=None):
4305        """Sets or gets the currently selected element.
4306
4307        If a spinbutton element is specified, it will be
4308        displayed depressed.
4309        """
4310        return self.tk.call(self._w, 'selection', 'element', element)
4311
4312    def selection_from(self, index):
4313        """Set the fixed end of a selection to INDEX."""
4314        self.selection('from', index)
4315
4316    def selection_present(self):
4317        """Return True if there are characters selected in the spinbox, False
4318        otherwise."""
4319        return self.tk.getboolean(
4320            self.tk.call(self._w, 'selection', 'present'))
4321
4322    def selection_range(self, start, end):
4323        """Set the selection from START to END (not included)."""
4324        self.selection('range', start, end)
4325
4326    def selection_to(self, index):
4327        """Set the variable end of a selection to INDEX."""
4328        self.selection('to', index)
4329
4330###########################################################################
4331
4332
4333class LabelFrame(Widget):
4334    """labelframe widget."""
4335
4336    def __init__(self, master=None, cnf={}, **kw):
4337        """Construct a labelframe widget with the parent MASTER.
4338
4339        STANDARD OPTIONS
4340
4341            borderwidth, cursor, font, foreground,
4342            highlightbackground, highlightcolor,
4343            highlightthickness, padx, pady, relief,
4344            takefocus, text
4345
4346        WIDGET-SPECIFIC OPTIONS
4347
4348            background, class, colormap, container,
4349            height, labelanchor, labelwidget,
4350            visual, width
4351        """
4352        Widget.__init__(self, master, 'labelframe', cnf, kw)
4353
4354########################################################################
4355
4356
4357class PanedWindow(Widget):
4358    """panedwindow widget."""
4359
4360    def __init__(self, master=None, cnf={}, **kw):
4361        """Construct a panedwindow widget with the parent MASTER.
4362
4363        STANDARD OPTIONS
4364
4365            background, borderwidth, cursor, height,
4366            orient, relief, width
4367
4368        WIDGET-SPECIFIC OPTIONS
4369
4370            handlepad, handlesize, opaqueresize,
4371            sashcursor, sashpad, sashrelief,
4372            sashwidth, showhandle,
4373        """
4374        Widget.__init__(self, master, 'panedwindow', cnf, kw)
4375
4376    def add(self, child, **kw):
4377        """Add a child widget to the panedwindow in a new pane.
4378
4379        The child argument is the name of the child widget
4380        followed by pairs of arguments that specify how to
4381        manage the windows. The possible options and values
4382        are the ones accepted by the paneconfigure method.
4383        """
4384        self.tk.call((self._w, 'add', child) + self._options(kw))
4385
4386    def remove(self, child):
4387        """Remove the pane containing child from the panedwindow
4388
4389        All geometry management options for child will be forgotten.
4390        """
4391        self.tk.call(self._w, 'forget', child)
4392
4393    forget = remove
4394
4395    def identify(self, x, y):
4396        """Identify the panedwindow component at point x, y
4397
4398        If the point is over a sash or a sash handle, the result
4399        is a two element list containing the index of the sash or
4400        handle, and a word indicating whether it is over a sash
4401        or a handle, such as {0 sash} or {2 handle}. If the point
4402        is over any other part of the panedwindow, the result is
4403        an empty list.
4404        """
4405        return self.tk.call(self._w, 'identify', x, y)
4406
4407    def proxy(self, *args):
4408        """Internal function."""
4409        return self._getints(
4410            self.tk.call((self._w, 'proxy') + args)) or ()
4411
4412    def proxy_coord(self):
4413        """Return the x and y pair of the most recent proxy location
4414        """
4415        return self.proxy("coord")
4416
4417    def proxy_forget(self):
4418        """Remove the proxy from the display.
4419        """
4420        return self.proxy("forget")
4421
4422    def proxy_place(self, x, y):
4423        """Place the proxy at the given x and y coordinates.
4424        """
4425        return self.proxy("place", x, y)
4426
4427    def sash(self, *args):
4428        """Internal function."""
4429        return self._getints(
4430            self.tk.call((self._w, 'sash') + args)) or ()
4431
4432    def sash_coord(self, index):
4433        """Return the current x and y pair for the sash given by index.
4434
4435        Index must be an integer between 0 and 1 less than the
4436        number of panes in the panedwindow. The coordinates given are
4437        those of the top left corner of the region containing the sash.
4438        pathName sash dragto index x y This command computes the
4439        difference between the given coordinates and the coordinates
4440        given to the last sash coord command for the given sash. It then
4441        moves that sash the computed difference. The return value is the
4442        empty string.
4443        """
4444        return self.sash("coord", index)
4445
4446    def sash_mark(self, index):
4447        """Records x and y for the sash given by index;
4448
4449        Used in conjunction with later dragto commands to move the sash.
4450        """
4451        return self.sash("mark", index)
4452
4453    def sash_place(self, index, x, y):
4454        """Place the sash given by index at the given coordinates
4455        """
4456        return self.sash("place", index, x, y)
4457
4458    def panecget(self, child, option):
4459        """Query a management option for window.
4460
4461        Option may be any value allowed by the paneconfigure subcommand
4462        """
4463        return self.tk.call(
4464            (self._w, 'panecget') + (child, '-'+option))
4465
4466    def paneconfigure(self, tagOrId, cnf=None, **kw):
4467        """Query or modify the management options for window.
4468
4469        If no option is specified, returns a list describing all
4470        of the available options for pathName.  If option is
4471        specified with no value, then the command returns a list
4472        describing the one named option (this list will be identical
4473        to the corresponding sublist of the value returned if no
4474        option is specified). If one or more option-value pairs are
4475        specified, then the command modifies the given widget
4476        option(s) to have the given value(s); in this case the
4477        command returns an empty string. The following options
4478        are supported:
4479
4480        after window
4481            Insert the window after the window specified. window
4482            should be the name of a window already managed by pathName.
4483        before window
4484            Insert the window before the window specified. window
4485            should be the name of a window already managed by pathName.
4486        height size
4487            Specify a height for the window. The height will be the
4488            outer dimension of the window including its border, if
4489            any. If size is an empty string, or if -height is not
4490            specified, then the height requested internally by the
4491            window will be used initially; the height may later be
4492            adjusted by the movement of sashes in the panedwindow.
4493            Size may be any value accepted by Tk_GetPixels.
4494        minsize n
4495            Specifies that the size of the window cannot be made
4496            less than n. This constraint only affects the size of
4497            the widget in the paned dimension -- the x dimension
4498            for horizontal panedwindows, the y dimension for
4499            vertical panedwindows. May be any value accepted by
4500            Tk_GetPixels.
4501        padx n
4502            Specifies a non-negative value indicating how much
4503            extra space to leave on each side of the window in
4504            the X-direction. The value may have any of the forms
4505            accepted by Tk_GetPixels.
4506        pady n
4507            Specifies a non-negative value indicating how much
4508            extra space to leave on each side of the window in
4509            the Y-direction. The value may have any of the forms
4510            accepted by Tk_GetPixels.
4511        sticky style
4512            If a window's pane is larger than the requested
4513            dimensions of the window, this option may be used
4514            to position (or stretch) the window within its pane.
4515            Style is a string that contains zero or more of the
4516            characters n, s, e or w. The string can optionally
4517            contains spaces or commas, but they are ignored. Each
4518            letter refers to a side (north, south, east, or west)
4519            that the window will "stick" to. If both n and s
4520            (or e and w) are specified, the window will be
4521            stretched to fill the entire height (or width) of
4522            its cavity.
4523        width size
4524            Specify a width for the window. The width will be
4525            the outer dimension of the window including its
4526            border, if any. If size is an empty string, or
4527            if -width is not specified, then the width requested
4528            internally by the window will be used initially; the
4529            width may later be adjusted by the movement of sashes
4530            in the panedwindow. Size may be any value accepted by
4531            Tk_GetPixels.
4532
4533        """
4534        if cnf is None and not kw:
4535            return self._getconfigure(self._w, 'paneconfigure', tagOrId)
4536        if isinstance(cnf, str) and not kw:
4537            return self._getconfigure1(
4538                self._w, 'paneconfigure', tagOrId, '-'+cnf)
4539        self.tk.call((self._w, 'paneconfigure', tagOrId) +
4540                 self._options(cnf, kw))
4541
4542    paneconfig = paneconfigure
4543
4544    def panes(self):
4545        """Returns an ordered list of the child panes."""
4546        return self.tk.splitlist(self.tk.call(self._w, 'panes'))
4547
4548# Test:
4549
4550
4551def _test():
4552    root = Tk()
4553    text = "This is Tcl/Tk version %s" % TclVersion
4554    text += "\nThis should be a cedilla: \xe7"
4555    label = Label(root, text=text)
4556    label.pack()
4557    test = Button(root, text="Click me!",
4558              command=lambda root=root: root.test.configure(
4559                  text="[%s]" % root.test['text']))
4560    test.pack()
4561    root.test = test
4562    quit = Button(root, text="QUIT", command=root.destroy)
4563    quit.pack()
4564    # The following three commands are needed so the window pops
4565    # up on top on Windows...
4566    root.iconify()
4567    root.update()
4568    root.deiconify()
4569    root.mainloop()
4570
4571
4572if __name__ == '__main__':
4573    _test()
4574