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