# 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