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