1 # Python interface to some of the commands of the 2.4 version of the
2 # BLT extension to tcl.
9 _busyCommand = '::blt::busy'
10 _vectorCommand = '::blt::vector'
11 _graphCommand = '::blt::graph'
12 _testCommand = '::blt::*'
13 _chartCommand = '::blt::stripchart'
14 _tabsetCommand = '::blt::tabset'
19 def _checkForBlt(window):
23 # Blt may be a package which has not yet been loaded. Try to load it.
25 window.tk.call('package', 'require', 'BLT')
26 except Tkinter.TclError:
27 # Another way to try to dynamically load blt:
29 window.tk.call('load', '', 'Blt')
30 except Tkinter.TclError:
33 _haveBlt= (window.tk.call('info', 'commands', _testCommand) != '')
34 _haveBltBusy = (window.tk.call('info', 'commands', _busyCommand) != '')
41 def havebltbusy(window):
49 window = Tkinter._default_root
54 def busy_hold(window, cursor = None):
57 window.tk.call(_busyCommand, 'hold', window._w)
59 window.tk.call(_busyCommand, 'hold', window._w, '-cursor', cursor)
61 def busy_release(window):
63 window.tk.call(_busyCommand, 'release', window._w)
65 def busy_forget(window):
67 window.tk.call(_busyCommand, 'forget', window._w)
69 #=============================================================================
70 # Interface to the blt vector command which makes it look like the
71 # builtin python list type.
72 # The -variable, -command, -watchunset creation options are not supported.
73 # The dup, merge, notify, offset, populate, seq and variable methods
74 # and the +, -, * and / operations are not supported.
76 # Blt vector functions:
77 def vector_expr(expression):
78 tk = Tkinter._default_root.tk
79 strList = tk.splitlist(tk.call(_vectorCommand, 'expr', expression))
80 return tuple(map(string.atof, strList))
82 def vector_names(pattern = None):
83 tk = Tkinter._default_root.tk
84 return tk.splitlist(tk.call(_vectorCommand, 'names', pattern))
88 def __init__(self, size=None, master=None):
89 # <size> can be either an integer size, or a string "first:last".
94 self._master = Tkinter._default_root
95 self.tk = self._master.tk
96 self._name = 'PY_VEC' + str(Vector._varnum)
97 Vector._varnum = Vector._varnum + 1
99 self.tk.call(_vectorCommand, 'create', self._name)
101 self.tk.call(_vectorCommand, 'create', '%s(%s)' % (self._name, size))
103 self.tk.call(_vectorCommand, 'destroy', self._name)
108 return '[' + string.join(map(str, self), ', ') + ']'
109 def __cmp__(self, list):
110 return cmp(self[:], list)
113 return self.tk.getint(self.tk.call(self._name, 'length'))
114 def __getitem__(self, key):
117 key = key + len(self)
119 return self.tk.getdouble(self.tk.globalgetvar(self._name, str(key)))
120 except Tkinter.TclError:
121 raise IndexError, oldkey
122 def __setitem__(self, key, value):
124 key = key + len(self)
125 return self.tk.globalsetvar(self._name, str(key), float(value))
127 def __delitem__(self, key):
129 key = key + len(self)
130 return self.tk.globalunsetvar(self._name, str(key))
132 def __getslice__(self, start, end):
140 end = end - 1 # Blt vector slices include end point.
141 text = self.tk.globalgetvar(self._name, str(start) + ':' + str(end))
142 return map(self.tk.getdouble, self.tk.splitlist(text))
144 def __setslice__(self, start, end, list):
147 self.set(self[:start] + list + self[end:])
149 def __delslice__(self, start, end):
151 self.set(self[:start] + self[end:])
153 def __add__(self, list):
154 return self[:] + list
155 def __radd__(self, list):
156 return list + self[:]
157 def __mul__(self, n):
161 # Python builtin list methods:
162 def append(self, *args):
163 self.tk.call(self._name, 'append', args)
164 def count(self, obj):
165 return self[:].count(obj)
166 def index(self, value):
167 return self[:].index(value)
168 def insert(self, index, value):
169 self[index:index] = [value]
170 def remove(self, value):
171 del self[self.index(value)]
176 def sort(self, *args):
181 # Blt vector instance methods:
182 # append - same as list method above
184 self.tk.call(self._name, 'clear')
185 def delete(self, *args):
186 self.tk.call((self._name, 'delete') + args)
187 def expr(self, expression):
188 self.tk.call(self._name, 'expr', expression)
189 def length(self, newSize=None):
190 return self.tk.getint(self.tk.call(self._name, 'length', newSize))
191 def range(self, first, last=None):
192 # Note that, unlike self[first:last], this includes the last
193 # item in the returned range.
194 text = self.tk.call(self._name, 'range', first, last)
195 return map(self.tk.getdouble, self.tk.splitlist(text))
196 def search(self, start, end=None):
197 return self._master._getints(self.tk.call(
198 self._name, 'search', start, end))
200 if type(list) != types.TupleType:
202 self.tk.call(self._name, 'set', list)
204 # The blt vector sort method has different semantics to the python
205 # list sort method. Call these blt_sort:
206 def blt_sort(self, *args):
207 self.tk.call((self._name, 'sort') + args)
208 def blt_sort_reverse(self, *args):
209 self.tk.call((self._name, 'sort', '-reverse') + args)
211 # Special blt vector indexes:
213 return self.tk.getdouble(self.tk.globalgetvar(self._name, 'min'))
215 return self.tk.getdouble(self.tk.globalgetvar(self._name, 'max'))
217 # Method borrowed from Tkinter.Var class:
221 #=============================================================================
223 # This is a general purpose configure routine which can handle the
224 # configuration of widgets, items within widgets, etc. Supports the
225 # forms configure() and configure('font') for querying and
226 # configure(font = 'fixed', text = 'hello') for setting.
228 def _doConfigure(widget, subcommand, option, kw):
230 if not option and not kw:
231 # Return a description of all options.
233 options = widget.tk.splitlist(widget.tk.call(subcommand))
234 for optionString in options:
235 optionInfo = widget.tk.splitlist(optionString)
236 option = optionInfo[0][1:]
237 ret[option] = (option,) + optionInfo[1:]
241 # Return a description of the option given by <option>.
243 # Having keywords implies setting configuration options.
244 # Can't set and get in one command!
245 raise ValueError, 'cannot have option argument with keywords'
246 option = '-' + option
247 optionInfo = widget.tk.splitlist(widget.tk.call(subcommand + (option,)))
248 return (optionInfo[0][1:],) + optionInfo[1:]
250 # Otherwise, set the given configuration options.
251 widget.tk.call(subcommand + widget._options(kw))
253 #=============================================================================
255 class Graph(Tkinter.Widget):
256 # Wrapper for the blt graph widget, version 2.4.
258 def __init__(self, master=None, cnf={}, **kw):
260 Tkinter.Widget.__init__(self, master, _graphCommand, cnf, kw)
262 def bar_create(self, name, **kw):
263 self.tk.call((self._w, 'bar', 'create', name) + self._options(kw))
265 def line_create(self, name, **kw):
266 self.tk.call((self._w, 'line', 'create', name) + self._options(kw))
268 def extents(self, item):
269 return self.tk.getint(self.tk.call(self._w, 'extents', item))
271 def invtransform(self, winX, winY):
272 return self._getdoubles(
273 self.tk.call(self._w, 'invtransform', winX, winY))
275 def inside(self, x, y):
276 return self.tk.getint(self.tk.call(self._w, 'inside', x, y))
278 def snap(self, photoName):
279 self.tk.call(self._w, 'snap', photoName)
281 def transform(self, x, y):
282 return self._getdoubles(self.tk.call(self._w, 'transform', x, y))
284 def axis_cget(self, axisName, key):
285 return self.tk.call(self._w, 'axis', 'cget', axisName, '-' + key)
286 def axis_configure(self, axes, option=None, **kw):
287 # <axes> may be a list of axisNames.
288 if type(axes) == types.StringType:
290 subcommand = (self._w, 'axis', 'configure') + tuple(axes)
291 return _doConfigure(self, subcommand, option, kw)
292 def axis_create(self, axisName, **kw):
293 self.tk.call((self._w, 'axis', 'create', axisName) + self._options(kw))
294 def axis_delete(self, *args):
295 self.tk.call((self._w, 'axis', 'delete') + args)
296 def axis_invtransform(self, axisName, value):
297 return self.tk.getdouble(self.tk.call(
298 self._w, 'axis', 'invtransform', axisName, value))
299 def axis_limits(self, axisName):
300 return self._getdoubles(self.tk.call(
301 self._w, 'axis', 'limits', axisName))
302 def axis_names(self, *args):
303 return self.tk.splitlist(
304 self.tk.call((self._w, 'axis', 'names') + args))
305 def axis_transform(self, axisName, value):
306 return self.tk.getint(self.tk.call(
307 self._w, 'axis', 'transform', axisName, value))
309 def xaxis_cget(self, key):
310 return self.tk.call(self._w, 'xaxis', 'cget', '-' + key)
311 def xaxis_configure(self, option=None, **kw):
312 subcommand = (self._w, 'xaxis', 'configure')
313 return _doConfigure(self, subcommand, option, kw)
314 def xaxis_invtransform(self, value):
315 return self.tk.getdouble(self.tk.call(
316 self._w, 'xaxis', 'invtransform', value))
317 def xaxis_limits(self):
318 return self._getdoubles(self.tk.call(self._w, 'xaxis', 'limits'))
319 def xaxis_transform(self, value):
320 return self.tk.getint(self.tk.call(
321 self._w, 'xaxis', 'transform', value))
322 def xaxis_use(self, axisName = None):
323 return self.tk.call(self._w, 'xaxis', 'use', axisName)
325 def x2axis_cget(self, key):
326 return self.tk.call(self._w, 'x2axis', 'cget', '-' + key)
327 def x2axis_configure(self, option=None, **kw):
328 subcommand = (self._w, 'x2axis', 'configure')
329 return _doConfigure(self, subcommand, option, kw)
330 def x2axis_invtransform(self, value):
331 return self.tk.getdouble(self.tk.call(
332 self._w, 'x2axis', 'invtransform', value))
333 def x2axis_limits(self):
334 return self._getdoubles(self.tk.call(self._w, 'x2axis', 'limits'))
335 def x2axis_transform(self, value):
336 return self.tk.getint(self.tk.call(
337 self._w, 'x2axis', 'transform', value))
338 def x2axis_use(self, axisName = None):
339 return self.tk.call(self._w, 'x2axis', 'use', axisName)
341 def yaxis_cget(self, key):
342 return self.tk.call(self._w, 'yaxis', 'cget', '-' + key)
343 def yaxis_configure(self, option=None, **kw):
344 subcommand = (self._w, 'yaxis', 'configure')
345 return _doConfigure(self, subcommand, option, kw)
346 def yaxis_invtransform(self, value):
347 return self.tk.getdouble(self.tk.call(
348 self._w, 'yaxis', 'invtransform', value))
349 def yaxis_limits(self):
350 return self._getdoubles(self.tk.call(self._w, 'yaxis', 'limits'))
351 def yaxis_transform(self, value):
352 return self.tk.getint(self.tk.call(
353 self._w, 'yaxis', 'transform', value))
354 def yaxis_use(self, axisName = None):
355 return self.tk.call(self._w, 'yaxis', 'use', axisName)
357 def y2axis_cget(self, key):
358 return self.tk.call(self._w, 'y2axis', 'cget', '-' + key)
359 def y2axis_configure(self, option=None, **kw):
360 subcommand = (self._w, 'y2axis', 'configure')
361 return _doConfigure(self, subcommand, option, kw)
362 def y2axis_invtransform(self, value):
363 return self.tk.getdouble(self.tk.call(
364 self._w, 'y2axis', 'invtransform', value))
365 def y2axis_limits(self):
366 return self._getdoubles(self.tk.call(self._w, 'y2axis', 'limits'))
367 def y2axis_transform(self, value):
368 return self.tk.getint(self.tk.call(
369 self._w, 'y2axis', 'transform', value))
370 def y2axis_use(self, axisName = None):
371 return self.tk.call(self._w, 'y2axis', 'use', axisName)
373 def crosshairs_cget(self, key):
374 return self.tk.call(self._w, 'crosshairs', 'cget', '-' + key)
375 def crosshairs_configure(self, option=None, **kw):
376 subcommand = (self._w, 'crosshairs', 'configure')
377 return _doConfigure(self, subcommand, option, kw)
378 def crosshairs_off(self):
379 self.tk.call(self._w, 'crosshairs', 'off')
380 def crosshairs_on(self):
381 self.tk.call(self._w, 'crosshairs', 'on')
382 def crosshairs_toggle(self):
383 self.tk.call(self._w, 'crosshairs', 'toggle')
385 def element_activate(self, name, *args):
386 self.tk.call((self._w, 'element', 'activate', name) + args)
387 def element_bind(self, tagName, sequence=None, func=None, add=None):
388 return self._bind((self._w, 'element', 'bind', tagName),
390 def element_unbind(self, tagName, sequence, funcid=None):
391 self.tk.call(self._w, 'element', 'bind', tagName, sequence, '')
393 self.deletecommand(funcid)
395 def element_cget(self, name, key):
396 return self.tk.call(self._w, 'element', 'cget', name, '-' + key)
398 def element_closest(self, x, y, *args, **kw):
399 var = 'python_private_1'
400 success = self.tk.getint(self.tk.call(
401 (self._w, 'element', 'closest', x, y, var) +
402 self._options(kw) + args))
405 rtn['dist'] = self.tk.getdouble(self.tk.globalgetvar(var, 'dist'))
406 rtn['x'] = self.tk.getdouble(self.tk.globalgetvar(var, 'x'))
407 rtn['y'] = self.tk.getdouble(self.tk.globalgetvar(var, 'y'))
408 rtn['index'] = self.tk.getint(self.tk.globalgetvar(var, 'index'))
409 rtn['name'] = self.tk.globalgetvar(var, 'name')
414 def element_configure(self, names, option=None, **kw):
415 # <names> may be a list of elemNames.
416 if type(names) == types.StringType:
418 subcommand = (self._w, 'element', 'configure') + tuple(names)
419 return _doConfigure(self, subcommand, option, kw)
421 def element_deactivate(self, *args):
422 self.tk.call((self._w, 'element', 'deactivate') + args)
424 def element_delete(self, *args):
425 self.tk.call((self._w, 'element', 'delete') + args)
426 def element_exists(self, name):
427 return self.tk.getboolean(
428 self.tk.call(self._w, 'element', 'exists', name))
430 def element_names(self, *args):
431 return self.tk.splitlist(
432 self.tk.call((self._w, 'element', 'names') + args))
433 def element_show(self, nameList=None):
434 if nameList is not None:
435 nameList = tuple(nameList)
436 return self.tk.splitlist(
437 self.tk.call(self._w, 'element', 'show', nameList))
438 def element_type(self, name):
439 return self.tk.call(self._w, 'element', 'type', name)
441 def grid_cget(self, key):
442 return self.tk.call(self._w, 'grid', 'cget', '-' + key)
443 def grid_configure(self, option=None, **kw):
444 subcommand = (self._w, 'grid', 'configure')
445 return _doConfigure(self, subcommand, option, kw)
448 self.tk.call(self._w, 'grid', 'off')
450 self.tk.call(self._w, 'grid', 'on')
451 def grid_toggle(self):
452 self.tk.call(self._w, 'grid', 'toggle')
454 def legend_activate(self, *args):
455 self.tk.call((self._w, 'legend', 'activate') + args)
456 def legend_bind(self, tagName, sequence=None, func=None, add=None):
457 return self._bind((self._w, 'legend', 'bind', tagName),
459 def legend_unbind(self, tagName, sequence, funcid=None):
460 self.tk.call(self._w, 'legend', 'bind', tagName, sequence, '')
462 self.deletecommand(funcid)
464 def legend_cget(self, key):
465 return self.tk.call(self._w, 'legend', 'cget', '-' + key)
466 def legend_configure(self, option=None, **kw):
467 subcommand = (self._w, 'legend', 'configure')
468 return _doConfigure(self, subcommand, option, kw)
469 def legend_deactivate(self, *args):
470 self.tk.call((self._w, 'legend', 'deactivate') + args)
471 def legend_get(self, pos):
472 return self.tk.call(self._w, 'legend', 'get', pos)
474 def pen_cget(self, name, key):
475 return self.tk.call(self._w, 'pen', 'cget', name, '-' + key)
476 def pen_configure(self, names, option=None, **kw):
477 # <names> may be a list of penNames.
478 if type(names) == types.StringType:
480 subcommand = (self._w, 'pen', 'configure') + tuple(names)
481 return _doConfigure(self, subcommand, option, kw)
482 def pen_create(self, name, **kw):
483 self.tk.call((self._w, 'pen', 'create', name) + self._options(kw))
484 def pen_delete(self, *args):
485 self.tk.call((self._w, 'pen', 'delete') + args)
486 def pen_names(self, *args):
487 return self.tk.splitlist(self.tk.call((self._w, 'pen', 'names') + args))
489 def postscript_cget(self, key):
490 return self.tk.call(self._w, 'postscript', 'cget', '-' + key)
491 def postscript_configure(self, option=None, **kw):
492 subcommand = (self._w, 'postscript', 'configure')
493 return _doConfigure(self, subcommand, option, kw)
494 def postscript_output(self, fileName=None, **kw):
495 prefix = (self._w, 'postscript', 'output')
497 return self.tk.call(prefix + self._options(kw))
499 self.tk.call(prefix + (fileName,) + self._options(kw))
501 def marker_after(self, first, second=None):
502 self.tk.call(self._w, 'marker', 'after', first, second)
503 def marker_before(self, first, second=None):
504 self.tk.call(self._w, 'marker', 'before', first, second)
505 def marker_bind(self, tagName, sequence=None, func=None, add=None):
506 return self._bind((self._w, 'marker', 'bind', tagName),
508 def marker_unbind(self, tagName, sequence, funcid=None):
509 self.tk.call(self._w, 'marker', 'bind', tagName, sequence, '')
511 self.deletecommand(funcid)
513 def marker_cget(self, name, key):
514 return self.tk.call(self._w, 'marker', 'cget', name, '-' + key)
515 def marker_configure(self, names, option=None, **kw):
516 # <names> may be a list of markerIds.
517 if type(names) == types.StringType:
519 subcommand = (self._w, 'marker', 'configure') + tuple(names)
520 return _doConfigure(self, subcommand, option, kw)
521 def marker_create(self, type, **kw):
523 (self._w, 'marker', 'create', type) + self._options(kw))
525 def marker_delete(self, *args):
526 self.tk.call((self._w, 'marker', 'delete') + args)
527 def marker_exists(self, name):
528 return self.tk.getboolean(
529 self.tk.call(self._w, 'marker', 'exists', name))
530 def marker_names(self, *args):
531 return self.tk.splitlist(
532 self.tk.call((self._w, 'marker', 'names') + args))
533 def marker_type(self, name):
534 type = self.tk.call(self._w, 'marker', 'type', name)
539 #=============================================================================
540 class Stripchart(Graph):
541 # Wrapper for the blt stripchart widget, version 2.4.
543 def __init__(self, master=None, cnf={}, **kw):
545 Tkinter.Widget.__init__(self, master, _chartCommand, cnf, kw)
547 #=============================================================================
548 class Tabset(Tkinter.Widget):
550 # Wrapper for the blt TabSet widget, version 2.4.
552 def __init__(self, master=None, cnf={}, **kw):
554 Tkinter.Widget.__init__(self, master, _tabsetCommand, cnf, kw)
556 def activate(self, tabIndex):
557 self.tk.call(self._w, 'activate', tabIndex)
559 # This is the 'bind' sub-command:
560 def tag_bind(self, tagName, sequence=None, func=None, add=None):
561 return self._bind((self._w, 'bind', tagName), sequence, func, add)
563 def tag_unbind(self, tagName, sequence, funcid=None):
564 self.tk.call(self._w, 'bind', tagName, sequence, '')
566 self.deletecommand(funcid)
568 def delete(self, first, last = None):
569 self.tk.call(self._w, 'delete', first, last)
571 # This is the 'focus' sub-command:
572 def tab_focus(self, tabIndex):
573 self.tk.call(self._w, 'focus', tabIndex)
575 def get(self, tabIndex):
576 return self.tk.call(self._w, 'get', tabIndex)
578 def index(self, tabIndex):
579 index = self.tk.call(self._w, 'index', tabIndex)
583 return self.tk.getint(self.tk.call(self._w, 'index', tabIndex))
585 def insert(self, position, name1, *names, **kw):
587 (self._w, 'insert', position, name1) + names + self._options(kw))
589 def invoke(self, tabIndex):
590 return self.tk.call(self._w, 'invoke', tabIndex)
592 def move(self, tabIndex1, beforeOrAfter, tabIndex2):
593 self.tk.call(self._w, 'move', tabIndex1, beforeOrAfter, tabIndex2)
595 def nearest(self, x, y):
596 return self.tk.call(self._w, 'nearest', x, y)
598 def scan_mark(self, x, y):
599 self.tk.call(self._w, 'scan', 'mark', x, y)
601 def scan_dragto(self, x, y):
602 self.tk.call(self._w, 'scan', 'dragto', x, y)
604 def see(self, index):
605 self.tk.call(self._w, 'see', index)
607 def see(self, tabIndex):
608 self.tk.call(self._w,'see',tabIndex)
611 return self.tk.getint(self.tk.call(self._w, 'size'))
613 def tab_cget(self, tabIndex, option):
614 if option[:1] != '-':
615 option = '-' + option
616 if option[-1:] == '_':
618 return self.tk.call(self._w, 'tab', 'cget', tabIndex, option)
620 def tab_configure(self, tabIndexes, option=None, **kw):
621 # <tabIndexes> may be a list of tabs.
622 if type(tabIndexes) in (types.StringType, types.IntType):
623 tabIndexes = [tabIndexes]
624 subcommand = (self._w, 'tab', 'configure') + tuple(tabIndexes)
625 return _doConfigure(self, subcommand, option, kw)
627 def tab_names(self, *args):
628 return self.tk.splitlist(self.tk.call((self._w, 'tab', 'names') + args))
630 def tab_tearoff(self, tabIndex, newName = None):
632 name = self.tk.call(self._w, 'tab', 'tearoff', tabIndex)
633 return self.nametowidget(name)
635 self.tk.call(self._w, 'tab', 'tearoff', tabIndex, newName)
638 s = self.tk.call(self._w, 'view')
639 return tuple(map(self.tk.getint, self.tk.splitlist(s)))
640 def view_moveto(self, fraction):
641 self.tk.call(self._w, 'view', 'moveto', fraction)
642 def view_scroll(self, number, what):
643 self.tk.call(self._w, 'view', 'scroll', number, what)