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