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