1891 lines · 72.4 KB · Python
RawDownload
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-## $Id: Tix.py 52785 2006-11-18 18:42:22Z martin.v.loewis $## Tix.py -- Tix widget wrappers.##       For Tix, see http://tix.sourceforge.net##       - Sudhir Shenoy (sshenoy@gol.com), Dec. 1995.#         based on an idea of Jean-Marc Lugrin (lugrin@ms.com)## NOTE: In order to minimize changes to Tkinter.py, some of the code here#       (TixWidget.__init__) has been taken from Tkinter (Widget.__init__)#       and will break if there are major changes in Tkinter.## The Tix widgets are represented by a class hierarchy in python with proper# inheritance of base classes.## As a result after creating a 'w = StdButtonBox', I can write#              w.ok['text'] = 'Who Cares'#    or              w.ok['bg'] = w['bg']# or even       w.ok.invoke()# etc.## Compare the demo tixwidgets.py to the original Tcl program and you will# appreciate the advantages.# from Tkinter import *from Tkinter import _flatten, _cnfmerge, _default_root # WARNING - TkVersion is a limited precision floating point numberif TkVersion < 3.999:    raise ImportError, "This version of Tix.py requires Tk 4.0 or higher" import _tkinter # If this fails your Python may not be configured for Tk # Some more constants (for consistency with Tkinter)WINDOW = 'window'TEXT = 'text'STATUS = 'status'IMMEDIATE = 'immediate'IMAGE = 'image'IMAGETEXT = 'imagetext'BALLOON = 'balloon'AUTO = 'auto'ACROSSTOP = 'acrosstop' # Some constants used by Tkinter dooneevent()TCL_DONT_WAIT     = 1 << 1TCL_WINDOW_EVENTS = 1 << 2TCL_FILE_EVENTS   = 1 << 3TCL_TIMER_EVENTS  = 1 << 4TCL_IDLE_EVENTS   = 1 << 5TCL_ALL_EVENTS    = 0 # BEWARE - this is implemented by copying some code from the Widget class#          in Tkinter (to override Widget initialization) and is therefore#          liable to break.import Tkinter, os # Could probably add this to Tkinter.Miscclass tixCommand:    """The tix commands provide access to miscellaneous  elements    of  Tix's  internal state and the Tix application context.    Most of the information manipulated by these  commands pertains    to  the  application  as a whole, or to a screen or    display, rather than to a particular window.     This is a mixin class, assumed to be mixed to Tkinter.Tk    that supports the self.tk.call method.    """     def tix_addbitmapdir(self, directory):        """Tix maintains a list of directories under which        the  tix_getimage  and tix_getbitmap commands will        search for image files. The standard bitmap  directory        is $TIX_LIBRARY/bitmaps. The addbitmapdir command        adds directory into this list. By  using  this        command, the  image  files  of an applications can        also be located using the tix_getimage or tix_getbitmap        command.        """        return self.tk.call('tix', 'addbitmapdir', directory)     def tix_cget(self, option):        """Returns  the  current  value  of the configuration        option given by option. Option may be  any  of  the        options described in the CONFIGURATION OPTIONS section.        """        return self.tk.call('tix', 'cget', option)     def tix_configure(self, cnf=None, **kw):        """Query or modify the configuration options of the Tix application        context. If no option is specified, returns a dictionary all of the        available options.  If option is specified with no value, then the        command returns a list describing the one named option (this list        will be identical to the corresponding sublist of the value        returned if no option is specified).  If one or more option-value        pairs are specified, then the command modifies the given option(s)        to have the given value(s); in this case the command returns an        empty string. Option may be any of the configuration options.        """        # Copied from Tkinter.py        if kw:            cnf = _cnfmerge((cnf, kw))        elif cnf:            cnf = _cnfmerge(cnf)        if cnf is None:            cnf = {}            for x in self.tk.split(self.tk.call('tix', 'configure')):                cnf[x[0][1:]] = (x[0][1:],) + x[1:]            return cnf        if isinstance(cnf, StringType):            x = self.tk.split(self.tk.call('tix', 'configure', '-'+cnf))            return (x[0][1:],) + x[1:]        return self.tk.call(('tix', 'configure') + self._options(cnf))     def tix_filedialog(self, dlgclass=None):        """Returns the file selection dialog that may be shared among        different calls from this application.  This command will create a        file selection dialog widget when it is called the first time. This        dialog will be returned by all subsequent calls to tix_filedialog.        An optional dlgclass parameter can be passed to specified what type        of file selection dialog widget is desired. Possible options are        tix FileSelectDialog or tixExFileSelectDialog.        """        if dlgclass is not None:            return self.tk.call('tix', 'filedialog', dlgclass)        else:            return self.tk.call('tix', 'filedialog')     def tix_getbitmap(self, name):        """Locates a bitmap file of the name name.xpm or name in one of the        bitmap directories (see the tix_addbitmapdir command above).  By        using tix_getbitmap, you can avoid hard coding the pathnames of the        bitmap files in your application. When successful, it returns the        complete pathname of the bitmap file, prefixed with the character        '@'.  The returned value can be used to configure the -bitmap        option of the TK and Tix widgets.        """        return self.tk.call('tix', 'getbitmap', name)     def tix_getimage(self, name):        """Locates an image file of the name name.xpm, name.xbm or name.ppm        in one of the bitmap directories (see the addbitmapdir command        above). If more than one file with the same name (but different        extensions) exist, then the image type is chosen according to the        depth of the X display: xbm images are chosen on monochrome        displays and color images are chosen on color displays. By using        tix_ getimage, you can advoid hard coding the pathnames of the        image files in your application. When successful, this command        returns the name of the newly created image, which can be used to        configure the -image option of the Tk and Tix widgets.        """        return self.tk.call('tix', 'getimage', name)     def tix_option_get(self, name):        """Gets  the options  manitained  by  the  Tix        scheme mechanism. Available options include:             active_bg       active_fg      bg            bold_font       dark1_bg       dark1_fg            dark2_bg        dark2_fg       disabled_fg            fg              fixed_font     font            inactive_bg     inactive_fg    input1_bg            input2_bg       italic_font    light1_bg            light1_fg       light2_bg      light2_fg            menu_font       output1_bg     output2_bg            select_bg       select_fg      selector            """        # could use self.tk.globalgetvar('tixOption', name)        return self.tk.call('tix', 'option', 'get', name)     def tix_resetoptions(self, newScheme, newFontSet, newScmPrio=None):        """Resets the scheme and fontset of the Tix application to        newScheme and newFontSet, respectively.  This affects only those        widgets created after this call. Therefore, it is best to call the        resetoptions command before the creation of any widgets in a Tix        application.         The optional parameter newScmPrio can be given to reset the        priority level of the Tk options set by the Tix schemes.         Because of the way Tk handles the X option database, after Tix has        been has imported and inited, it is not possible to reset the color        schemes and font sets using the tix config command.  Instead, the        tix_resetoptions command must be used.        """        if newScmPrio is not None:            return self.tk.call('tix', 'resetoptions', newScheme, newFontSet, newScmPrio)        else:            return self.tk.call('tix', 'resetoptions', newScheme, newFontSet) class Tk(Tkinter.Tk, tixCommand):    """Toplevel widget of Tix which represents mostly the main window    of an application. It has an associated Tcl interpreter."""    def __init__(self, screenName=None, baseName=None, className='Tix'):        Tkinter.Tk.__init__(self, screenName, baseName, className)        tixlib = os.environ.get('TIX_LIBRARY')        self.tk.eval('global auto_path; lappend auto_path [file dir [info nameof]]')        if tixlib is not None:            self.tk.eval('global auto_path; lappend auto_path {%s}' % tixlib)            self.tk.eval('global tcl_pkgPath; lappend tcl_pkgPath {%s}' % tixlib)        # Load Tix - this should work dynamically or statically        # If it's static, tcl/tix8.1/pkgIndex.tcl should have        #               'load {} Tix'        # If it's dynamic under Unix, tcl/tix8.1/pkgIndex.tcl should have        #               'load libtix8.1.8.3.so Tix'        self.tk.eval('package require Tix')     def destroy(self):        # For safety, remove an delete_window binding before destroy        self.protocol("WM_DELETE_WINDOW", "")        Tkinter.Tk.destroy(self) # The Tix 'tixForm' geometry managerclass Form:    """The Tix Form geometry manager     Widgets can be arranged by specifying attachments to other widgets.    See Tix documentation for complete details"""     def config(self, cnf={}, **kw):        self.tk.call('tixForm', self._w, *self._options(cnf, kw))     form = config     def __setitem__(self, key, value):        Form.form(self, {key: value})     def check(self):        return self.tk.call('tixForm', 'check', self._w)     def forget(self):        self.tk.call('tixForm', 'forget', self._w)     def grid(self, xsize=0, ysize=0):        if (not xsize) and (not ysize):            x = self.tk.call('tixForm', 'grid', self._w)            y = self.tk.splitlist(x)            z = ()            for x in y:                z = z + (self.tk.getint(x),)            return z        return self.tk.call('tixForm', 'grid', self._w, xsize, ysize)     def info(self, option=None):        if not option:            return self.tk.call('tixForm', 'info', self._w)        if option[0] != '-':            option = '-' + option        return self.tk.call('tixForm', 'info', self._w, option)     def slaves(self):        return map(self._nametowidget,                   self.tk.splitlist(                       self.tk.call(                       'tixForm', 'slaves', self._w)))   Tkinter.Widget.__bases__ = Tkinter.Widget.__bases__ + (Form,) class TixWidget(Tkinter.Widget):    """A TixWidget class is used to package all (or most) Tix widgets.     Widget initialization is extended in two ways:       1) It is possible to give a list of options which must be part of       the creation command (so called Tix 'static' options). These cannot be       given as a 'config' command later.       2) It is possible to give the name of an existing TK widget. These are       child widgets created automatically by a Tix mega-widget. The Tk call       to create these widgets is therefore bypassed in TixWidget.__init__     Both options are for use by subclasses only.    """    def __init__ (self, master=None, widgetName=None,                static_options=None, cnf={}, kw={}):        # Merge keywords and dictionary arguments        if kw:            cnf = _cnfmerge((cnf, kw))        else:            cnf = _cnfmerge(cnf)         # Move static options into extra. static_options must be        # a list of keywords (or None).        extra=()         # 'options' is always a static option        if static_options:            static_options.append('options')        else:            static_options = ['options']         for k,v in cnf.items()[:]:            if k in static_options:                extra = extra + ('-' + k, v)                del cnf[k]         self.widgetName = widgetName        Widget._setup(self, master, cnf)         # If widgetName is None, this is a dummy creation call where the        # corresponding Tk widget has already been created by Tix        if widgetName:            self.tk.call(widgetName, self._w, *extra)         # Non-static options - to be done via a 'config' command        if cnf:            Widget.config(self, cnf)         # Dictionary to hold subwidget names for easier access. We can't        # use the children list because the public Tix names may not be the        # same as the pathname component        self.subwidget_list = {}     # We set up an attribute access function so that it is possible to    # do w.ok['text'] = 'Hello' rather than w.subwidget('ok')['text'] = 'Hello'    # when w is a StdButtonBox.    # We can even do w.ok.invoke() because w.ok is subclassed from the    # Button class if you go through the proper constructors    def __getattr__(self, name):        if self.subwidget_list.has_key(name):            return self.subwidget_list[name]        raise AttributeError, name     def set_silent(self, value):        """Set a variable without calling its action routine"""        self.tk.call('tixSetSilent', self._w, value)     def subwidget(self, name):        """Return the named subwidget (which must have been created by        the sub-class)."""        n = self._subwidget_name(name)        if not n:            raise TclError, "Subwidget " + name + " not child of " + self._name        # Remove header of name and leading dot        n = n[len(self._w)+1:]        return self._nametowidget(n)     def subwidgets_all(self):        """Return all subwidgets."""        names = self._subwidget_names()        if not names:            return []        retlist = []        for name in names:            name = name[len(self._w)+1:]            try:                retlist.append(self._nametowidget(name))            except:                # some of the widgets are unknown e.g. border in LabelFrame                pass        return retlist     def _subwidget_name(self,name):        """Get a subwidget name (returns a String, not a Widget !)"""        try:            return self.tk.call(self._w, 'subwidget', name)        except TclError:            return None     def _subwidget_names(self):        """Return the name of all subwidgets."""        try:            x = self.tk.call(self._w, 'subwidgets', '-all')            return self.tk.split(x)        except TclError:            return None     def config_all(self, option, value):        """Set configuration options for all subwidgets (and self)."""        if option == '':            return        elif not isinstance(option, StringType):            option = repr(option)        if not isinstance(value, StringType):            value = repr(value)        names = self._subwidget_names()        for name in names:            self.tk.call(name, 'configure', '-' + option, value)    # These are missing from Tkinter    def image_create(self, imgtype, cnf={}, master=None, **kw):        if not master:            master = Tkinter._default_root            if not master:                raise RuntimeError, 'Too early to create image'        if kw and cnf: cnf = _cnfmerge((cnf, kw))        elif kw: cnf = kw        options = ()        for k, v in cnf.items():            if callable(v):                v = self._register(v)            options = options + ('-'+k, v)        return master.tk.call(('image', 'create', imgtype,) + options)    def image_delete(self, imgname):        try:            self.tk.call('image', 'delete', imgname)        except TclError:            # May happen if the root was destroyed            pass # Subwidgets are child widgets created automatically by mega-widgets.# In python, we have to create these subwidgets manually to mirror their# existence in Tk/Tix.class TixSubWidget(TixWidget):    """Subwidget class.     This is used to mirror child widgets automatically created    by Tix/Tk as part of a mega-widget in Python (which is not informed    of this)"""     def __init__(self, master, name,               destroy_physically=1, check_intermediate=1):        if check_intermediate:            path = master._subwidget_name(name)            try:                path = path[len(master._w)+1:]                plist = path.split('.')            except:                plist = []         if not check_intermediate:            # immediate descendant            TixWidget.__init__(self, master, None, None, {'name' : name})        else:            # Ensure that the intermediate widgets exist            parent = master            for i in range(len(plist) - 1):                n = '.'.join(plist[:i+1])                try:                    w = master._nametowidget(n)                    parent = w                except KeyError:                    # Create the intermediate widget                    parent = TixSubWidget(parent, plist[i],                                          destroy_physically=0,                                          check_intermediate=0)            # The Tk widget name is in plist, not in name            if plist:                name = plist[-1]            TixWidget.__init__(self, parent, None, None, {'name' : name})        self.destroy_physically = destroy_physically     def destroy(self):        # For some widgets e.g., a NoteBook, when we call destructors,        # we must be careful not to destroy the frame widget since this        # also destroys the parent NoteBook thus leading to an exception        # in Tkinter when it finally calls Tcl to destroy the NoteBook        for c in self.children.values(): c.destroy()        if self.master.children.has_key(self._name):            del self.master.children[self._name]        if self.master.subwidget_list.has_key(self._name):            del self.master.subwidget_list[self._name]        if self.destroy_physically:            # This is bypassed only for a few widgets            self.tk.call('destroy', self._w)  # Useful func. to split Tcl lists and return as a dict. From Tkinter.pydef _lst2dict(lst):    dict = {}    for x in lst:        dict[x[0][1:]] = (x[0][1:],) + x[1:]    return dict # Useful class to create a display style - later shared by many items.# Contributed by Steffen Kremserclass DisplayStyle:    """DisplayStyle - handle configuration options shared by    (multiple) Display Items"""     def __init__(self, itemtype, cnf={}, **kw):        master = _default_root              # global from Tkinter        if not master and cnf.has_key('refwindow'): master=cnf['refwindow']        elif not master and kw.has_key('refwindow'):  master= kw['refwindow']        elif not master: raise RuntimeError, "Too early to create display style: no root window"        self.tk = master.tk        self.stylename = self.tk.call('tixDisplayStyle', itemtype,                            *self._options(cnf,kw) )     def __str__(self):        return self.stylename     def _options(self, cnf, kw):        if kw and cnf:            cnf = _cnfmerge((cnf, kw))        elif kw:            cnf = kw        opts = ()        for k, v in cnf.items():            opts = opts + ('-'+k, v)        return opts     def delete(self):        self.tk.call(self.stylename, 'delete')     def __setitem__(self,key,value):        self.tk.call(self.stylename, 'configure', '-%s'%key, value)

Lines 1–500 of 1891.