# -*-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. Load more
# -*-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 number if 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 << 1 TCL_WINDOW_EVENTS = 1 << 2 TCL_FILE_EVENTS = 1 << 3 TCL_TIMER_EVENTS = 1 << 4 TCL_IDLE_EVENTS = 1 << 5 TCL_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.Misc class 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 manager class 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.py def _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 Kremser class 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)