# Python interface to some of the commands of the 2.1 version of the # BLT extension to tcl. import types import Tkinter # Supported commands: if Tkinter.TkVersion >= 8.0: _busyCommand = 'blt::busy' _vectorCommand = 'blt::vector' _graphCommand = 'blt::graph' else: _busyCommand = 'busy' _vectorCommand = 'vector' _graphCommand = 'graph' # The graph and barchart widgets are essentially the same, so only # graph has been ported. If you want bars, use the element_bar() # method of Graph. _haveBlt = None def _checkForBlt(window): global _haveBlt # Blt may be a package which has not yet been loaded. try: window.tk.call('package', 'require', 'BLT') except Tkinter.TclError: # Another way to try to dynamically load blt: try: window.tk.call('load', '', 'Blt') except Tkinter.TclError: pass try: window.tk.call(_busyCommand, 'windows') _haveBlt = 1 except Tkinter.TclError: _haveBlt = 0 def haveblt(window): if _haveBlt is None: _checkForBlt(window) return _haveBlt def busy_hold(window): window.tk.call(_busyCommand, 'hold', window._w) def busy_release(window): window.tk.call(_busyCommand, 'release', window._w) #============================================================================= # Interface to the blt vector command # The dup, offset and populate methods and the +, -, * and / operations # are not supported. class Vector: _varnum = 0 def __init__(self, size=None, master=None): if master: self._master = master else: self._master = Tkinter._default_root self._tk = self._master.tk self._name = 'PY_VEC' + str(Vector._varnum) Vector._varnum = Vector._varnum + 1 if size is None: self._tk.call(_vectorCommand, self._name) else: self._tk.call(_vectorCommand, self._name + '(' + str(size) + ')') def __del__(self): self._tk.globalunsetvar(self._name) def __str__(self): return self._name def __repr__(self): rtnstr = '[' butFirst = 0 for value in self: if butFirst: rtnstr = rtnstr + ', ' else: butFirst = 1 rtnstr = rtnstr + str(value) rtnstr = rtnstr + ']' return rtnstr def __cmp__(self, list): return cmp(self[:], list) def __len__(self): return self._tk.getint(self._tk.call(self._name, 'length')) def __getitem__(self, key): if key < 0: key = key + len(self) try: return self._tk.getdouble(self._tk.globalgetvar(self._name, str(key))) except Tkinter.TclError: raise IndexError def __setitem__(self, key, value): if key < 0: key = key + len(self) return self._tk.globalsetvar(self._name, str(key), float(value)) def __delitem__(self, key): if key < 0: key = key + len(self) return self._tk.globalunsetvar(self._name, str(key)) def __getslice__(self, start, end): string = self._tk.globalgetvar(self._name, str(start) + ':' + str(end)) return map(self._tk.getdouble, self._tk.splitlist(string)) def __setslice__(self, start, end, list): if end - start == len(list): for count in range(end - start): self[start + count] = list[count] else: self.set(self[:start] + list + self[end:]) def __delslice__(self, start, end): self.unset(start, end - 1) def set(self, list): if type(list) != types.TupleType: list = tuple(list) self._tk.call(self._name, 'set', list) def get(self): # This should be "return self[:]", but there is a bug in blt vector. string = self._tk.call(self._name, 'range', 0, 'end') return map(self._tk.getdouble, self._tk.splitlist(string)) def append(self, value): # This should be as follows, but there is a bug in blt vector unset. # self._tk.call(self._name, 'append', args) (given *args as second param) return self._tk.globalsetvar(self._name, '++end', float(value)) def count(self, start): return len(self._tk.splitlist(self._tk.call(self._name, 'search', start))) def search(self, start, end=None): return self._master._getints(self._tk.call( self._name, 'search', start, end)) def index(self, value): strings = self._tk.splitlist(self._tk.call(self._name, 'search', value)) if len(strings) == 0: raise ValueError, str(value) + ' not in list' return self._tk.getint(strings[0]) def insert(self, index, value): self[index:index] = [value] def remove(self, value): del self[self.index(value)] def reverse(self): s = self[:] s.reverse() self[:] = s def sort(self, *args): apply(self._tk.call, (self._name, 'sort') + args) def sort_reverse(self, *args): apply(self._tk.call, (self._name, 'sort', '-reverse') + args) def min(self): return self._tk.getdouble(self._tk.globalgetvar(self._name, 'min')) def max(self): return self._tk.getdouble(self._tk.globalgetvar(self._name, 'max')) def clear(self): self._tk.call(self._name, 'clear') def delete(self, *args): apply(self._tk.call, (self._name, 'delete') + args) def length(self, newSize=None): return self._tk.getint(self._tk.call(self._name, 'length', newSize)) def range(self, first, last=None): string = self._tk.call(self._name, 'range', first, last) return map(self._tk.getdouble, self._tk.splitlist(string)) #============================================================================= class Graph(Tkinter.Widget): # Wrapper for the blt graph widget, version 2.1. def __init__(self, master=None, cnf={}, **kw): Tkinter.Widget.__init__(self, master, _graphCommand, cnf, kw) def _configure(self, subcommand, option, kw): # Handle configuration of widgets, canvas items, text items, # images, etc. Supports the forms configure() and # configure('font') for querying and configure(font = 'fixed', # text = 'hello') for setting. if not option and not kw: # Return a description of all options. ret = {} options = self.tk.splitlist(apply(self.tk.call, subcommand)) for optionString in options: optionInfo = self.tk.splitlist(optionString) option = optionInfo[0][1:] ret[option] = (option,) + optionInfo[1:] return ret if option: # Return a description of the option given by <option>. if kw: # Having keywords implies setting configuration options. # Can't set and get in one command! raise ValueError, 'cannot have option argument with keywords' option = '-' + option optionInfo = self.tk.splitlist( apply(self.tk.call, subcommand + (option,))) return (optionInfo[0][1:],) + optionInfo[1:] # Otherwise, set the given configuration options. apply(self.tk.call, subcommand + self._options(kw)) def extents(self, item): return self.tk.getint(self.tk.call(self._w, 'extents', item)) def invtransform(self, winX, winY): return self._getdoubles( self.tk.call(self._w, 'invtransform', winX, winY)) def transform(self, x, y): return self._getdoubles(self.tk.call(self._w, 'transform', x, y)) # The axis commands may be called in one of two ways. For example: # axis_cget('x', 'justify') # or # xaxis_cget('justify') def axis_cget(self, axis, key): return self.tk.call(self._w, axis + 'axis', 'cget', '-' + key) def axis_configure(self, axis, option=None, **kw): subcommand = (self._w, axis + 'axis', 'configure') return self._configure(subcommand, option, kw) def axis_invtransform(self, axis, value): return self.tk.getdouble(self.tk.call( self._w, axis + 'axis', 'invtransform', value)) def axis_limits(self, axis): return self._getdoubles(self.tk.call( self._w, axis + 'axis', 'limits')) def axis_transform(self, axis, value): return self.tk.getint(self.tk.call( self._w, axis + 'axis', 'transform', value)) def xaxis_cget(self, key): return self.axis_cget('x', key) def xaxis_configure(self, option=None, **kw): return apply(self.axis_configure, ('x', option), kw) def xaxis_invtransform(self, value): return self.axis_invtransform('x', value) def xaxis_limits(self): return self.axis_limits('x') def xaxis_transform(self, value): return self.axis_transform('x', value) def x2axis_cget(self, key): return self.axis_cget('x2', key) def x2axis_configure(self, option=None, **kw): return apply(self.axis_configure, ('x2', option), kw) def x2axis_invtransform(self, value): return self.axis_invtransform('x2', value) def x2axis_limits(self): return self.axis_limits('x2') def x2axis_transform(self, value): return self.axis_transform('x2', value) def yaxis_cget(self, key): return self.axis_cget('y', key) def yaxis_configure(self, option=None, **kw): return apply(self.axis_configure, ('y', option), kw) def yaxis_invtransform(self, value): return self.axis_invtransform('y', value) def yaxis_limits(self): return self.axis_limits('y') def yaxis_transform(self, value): return self.axis_transform('y', value) def y2axis_cget(self, key): return self.axis_cget('y2', key) def y2axis_configure(self, option=None, **kw): return apply(self.axis_configure, ('y2', option), kw) def y2axis_invtransform(self, value): return self.axis_invtransform('y2', value) def y2axis_limits(self): return self.axis_limits('y2') def y2axis_transform(self, value): return self.axis_transform('y2', value) def crosshairs_cget(self, key): return self.tk.call(self._w, 'crosshairs', 'cget', '-' + key) def crosshairs_configure(self, option=None, **kw): subcommand = (self._w, 'crosshairs', 'configure') return self._configure(subcommand, option, kw) def crosshairs_off(self): self.tk.call(self._w, 'crosshairs', 'off') def crosshairs_on(self): self.tk.call(self._w, 'crosshairs', 'on') def crosshairs_toggle(self): self.tk.call(self._w, 'crosshairs', 'toggle') def element_activate(self, name, *args): apply(self.tk.call, (self._w, 'element', 'activate', name) + args) def element_bar(self, name, **kw): apply(self.tk.call, (self._w, 'element', 'bar', name) + self._options(kw)) def element_cget(self, name, key): return self.tk.call(self._w, 'element', 'cget', name, '-' + key) def element_closest(self, x, y, *args, **kw): success = self.tk.getint(apply(self.tk.call, (self._w, 'element', 'closest', x, y, 'python_private_1') + args + self._options(kw))) if success: rtn = {} rtn['dist'] = self.tk.getdouble(self.tk.globalgetvar('python_private_1', 'dist')) rtn['x'] = self.tk.getdouble(self.tk.globalgetvar('python_private_1', 'x')) rtn['y'] = self.tk.getdouble(self.tk.globalgetvar('python_private_1', 'y')) rtn['index'] = self.tk.getint(self.tk.globalgetvar('python_private_1', 'index')) rtn['name'] = self.tk.globalgetvar('python_private_1', 'name') return rtn else: return None def element_configure(self, name, option=None, **kw): subcommand = (self._w, 'element', 'configure', name) return self._configure(subcommand, option, kw) def element_create(self, name, **kw): apply(self.tk.call, (self._w, 'element', 'create', name) + self._options(kw)) def element_deactivate(self, *args): apply(self.tk.call, (self._w, 'element', 'deactivate') + args) def element_delete(self, *args): apply(self.tk.call, (self._w, 'element', 'delete') + args) def element_exists(self, name): return self.tk.getboolean( self.tk.call(self._w, 'element', 'exists', name)) def element_line(self, name, **kw): apply(self.tk.call, (self._w, 'element', 'line', name) + self._options(kw)) def element_names(self): return self.tk.splitlist(self.tk.call(self._w, 'element', 'names')) def element_show(self, nameList=None): if nameList is not None: nameList = tuple(nameList) return self.tk.splitlist( self.tk.call(self._w, 'element', 'show', nameList)) def element_type(self, name): return self.tk.call(self._w, 'element', 'type', name) def grid_cget(self, key): return self.tk.call(self._w, 'grid', 'cget', '-' + key) def grid_configure(self, option=None, **kw): subcommand = (self._w, 'grid', 'configure') return self._configure(subcommand, option, kw) def grid_off(self): self.tk.call(self._w, 'grid', 'off') def grid_on(self): self.tk.call(self._w, 'grid', 'on') def grid_toggle(self): self.tk.call(self._w, 'grid', 'toggle') def legend_activate(self, *args): apply(self.tk.call, (self._w, 'legend', 'activate') + args) def legend_cget(self, key): return self.tk.call(self._w, 'legend', 'cget', '-' + key) def legend_configure(self, option=None, **kw): subcommand = (self._w, 'legend', 'configure') return self._configure(subcommand, option, kw) def legend_deactivate(self, *args): apply(self.tk.call, (self._w, 'legend', 'deactivate') + args) def legend_get(self, pos): return self.tk.call(self._w, 'legend', 'get', pos) def postscript_cget(self, key): return self.tk.call(self._w, 'postscript', 'cget', '-' + key) def postscript_configure(self, option=None, **kw): subcommand = (self._w, 'postscript', 'configure') return self._configure(subcommand, option, kw) def postscript_output(self, fileName=None, **kw): prefix = (self._w, 'postscript', 'output') if fileName is None: return apply(self.tk.call, prefix + self._options(kw)) else: apply(self.tk.call, prefix + (fileName,) + self._options(kw)) def marker_after(self, first, second=None): self.tk.call(self._w, 'marker', 'after', first, second) def marker_before(self, first, second=None): self.tk.call(self._w, 'marker', 'before', first, second) def marker_cget(self, name, key): return self.tk.call(self._w, 'marker', 'cget', name, '-' + key) def marker_configure(self, name, option=None, **kw): subcommand = (self._w, 'marker', 'configure', name) return self._configure(subcommand, option, kw) def marker_create(self, type, **kw): return apply(self.tk.call, (self._w, 'marker', 'create', type) + self._options(kw)) def marker_delete(self, *args): apply(self.tk.call, (self._w, 'marker', 'delete') + args) def marker_exists(self, name): return self.tk.getboolean( self.tk.call(self._w, 'marker', 'exists', name)) def marker_names(self, pattern=None): return self.tk.splitlist( self.tk.call(self._w, 'marker', 'names', pattern)) def marker_type(self, name): type = self.tk.call(self._w, 'marker', 'type', name) if type == '': type = None return type