# Python interface to some of the commands of the 2.4 version of the # BLT extension to tcl. import string import types import Tkinter # Supported commands: _busyCommand = '::blt::busy' _vectorCommand = '::blt::vector' _graphCommand = '::blt::graph' _testCommand = '::blt::*' _chartCommand = '::blt::stripchart' _tabsetCommand = '::blt::tabset' _haveBlt = None _haveBltBusy = None def _checkForBlt(window): global _haveBlt global _haveBltBusy # Blt may be a package which has not yet been loaded. Try to load it. 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 _haveBlt= (window.tk.call('info', 'commands', _testCommand) != '') _haveBltBusy = (window.tk.call('info', 'commands', _busyCommand) != '') def haveblt(window): if _haveBlt is None: _checkForBlt(window) return _haveBlt def havebltbusy(window): if _haveBlt is None: _checkForBlt(window) return _haveBltBusy def _loadBlt(window): if _haveBlt is None: if window is None: window = Tkinter._default_root if window is None: window = Tkinter.Tk() _checkForBlt(window) def busy_hold(window, cursor = None): _loadBlt(window) if cursor is None: window.tk.call(_busyCommand, 'hold', window._w) else: window.tk.call(_busyCommand, 'hold', window._w, '-cursor', cursor) def busy_release(window): _loadBlt(window) window.tk.call(_busyCommand, 'release', window._w) def busy_forget(window): _loadBlt(window) window.tk.call(_busyCommand, 'forget', window._w) #============================================================================= # Interface to the blt vector command which makes it look like the # builtin python list type. # The -variable, -command, -watchunset creation options are not supported. # The dup, merge, notify, offset, populate, seq and variable methods # and the +, -, * and / operations are not supported. # Blt vector functions: def vector_expr(expression): tk = Tkinter._default_root.tk strList = tk.splitlist(tk.call(_vectorCommand, 'expr', expression)) return tuple(map(string.atof, strList)) def vector_names(pattern = None): tk = Tkinter._default_root.tk return tk.splitlist(tk.call(_vectorCommand, 'names', pattern)) class Vector: _varnum = 0 def __init__(self, size=None, master=None): # can be either an integer size, or a string "first:last". _loadBlt(master) 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, 'create', self._name) else: self.tk.call(_vectorCommand, 'create', '%s(%s)' % (self._name, size)) def __del__(self): self.tk.call(_vectorCommand, 'destroy', self._name) def __str__(self): return self._name def __repr__(self): return '[' + string.join(map(str, self), ', ') + ']' 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): oldkey = 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, oldkey 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): length = len(self) if start < 0: start = 0 if end > length: end = length if start >= end: return [] end = end - 1 # Blt vector slices include end point. text = self.tk.globalgetvar(self._name, str(start) + ':' + str(end)) return map(self.tk.getdouble, self.tk.splitlist(text)) def __setslice__(self, start, end, list): if start > end: end = start self.set(self[:start] + list + self[end:]) def __delslice__(self, start, end): if start < end: self.set(self[:start] + self[end:]) def __add__(self, list): return self[:] + list def __radd__(self, list): return list + self[:] def __mul__(self, n): return self[:] * n __rmul__ = __mul__ # Python builtin list methods: def append(self, *args): self.tk.call(self._name, 'append', args) def count(self, obj): return self[:].count(obj) def index(self, value): return self[:].index(value) 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.set(s) def sort(self, *args): s = self[:] s.sort() self.set(s) # Blt vector instance methods: # append - same as list method above def clear(self): self.tk.call(self._name, 'clear') def delete(self, *args): self.tk.call((self._name, 'delete') + args) def expr(self, expression): self.tk.call(self._name, 'expr', expression) def length(self, newSize=None): return self.tk.getint(self.tk.call(self._name, 'length', newSize)) def range(self, first, last=None): # Note that, unlike self[first:last], this includes the last # item in the returned range. text = self.tk.call(self._name, 'range', first, last) return map(self.tk.getdouble, self.tk.splitlist(text)) def search(self, start, end=None): return self._master._getints(self.tk.call( self._name, 'search', start, end)) def set(self, list): if type(list) != types.TupleType: list = tuple(list) self.tk.call(self._name, 'set', list) # The blt vector sort method has different semantics to the python # list sort method. Call these blt_sort: def blt_sort(self, *args): self.tk.call((self._name, 'sort') + args) def blt_sort_reverse(self, *args): self.tk.call((self._name, 'sort', '-reverse') + args) # Special blt vector indexes: 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')) # Method borrowed from Tkinter.Var class: def get(self): return self[:] #============================================================================= # This is a general purpose configure routine which can handle the # configuration of widgets, items within widgets, etc. Supports the # forms configure() and configure('font') for querying and # configure(font = 'fixed', text = 'hello') for setting. def _doConfigure(widget, subcommand, option, kw): if not option and not kw: # Return a description of all options. ret = {} options = widget.tk.splitlist(widget.tk.call(subcommand)) for optionString in options: optionInfo = widget.tk.splitlist(optionString) option = optionInfo[0][1:] ret[option] = (option,) + optionInfo[1:] return ret if option: # Return a description of the option given by