#!/cont/Python-1.4/python
"""

This is a module to add blt functionality to Tkinter.  So far, implemented
is
Graph
Barchart
Bell
================================================================
This file is based on blt.py developed by  Peter J. Godman.
Modification to work with BLT2.1 was made by
Noboru Yamamoto ([email protected])
KEK, Accelerator Dept.
JAPAN

Vector class is introduced in this version.

Test environment:
Host OS: Digital Unix (aka DEC OSF1) 3.2c
Python 1.4
Tcl 7.6/Tk 4.2/ blt2.1
"""

from Tkinter import *
from Tkinter import _default_root
import string

class Graph (Widget) :
       """
       blt_graph widget
       """

       def __init__(self,master=None,cnf={}, **kw):
               Widget.__init__(self,master,'graph',cnf,kw)

       def crosshairs_configure (self, cnf={}, **kw):
               return apply(self.tk.call,
                            (self._w, 'crosshairs', 'configure')
                            + self._options(cnf, kw))
       def crosshairs_toggle (self) :
               self.tk.call(self._w,'crosshairs','toggle')

       def element_activate (self, name, index=None) :
               return self.tk.call,(self._w,'element',
                                          'activate',name,index)

#       def element_append (self,name,coords) :# does not exist in blt2.1
#               self.tk.call(self._w,'element',
#                            'append',name, coords)

       def element_closest (self,x,y,cnf={},name=None) :
               return apply(self.tk.call,(self._w,'element','closest',x,y)+
               self._options(cnf)+(name))

       def element_configure (self,name,cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'element', 'configure', name)
                     + self._options(cnf, kw))

       def element_create (self,name,cnf={},**kw) :
               apply(self.tk.call,
                     (self._w, 'element', 'create', name)
                     + self._options(cnf, kw))

       def element_deactivate (self,name, *names) :
               apply(self.tk.call,(self._w,'element','deactivate',
                                   name) + names)

       def element_delete (self,name ,*names) :
               apply(self.tk.call,(self._w,'element','delete',
                                   name) + names)
       def element_names (self) :
               return string.split(self.tk.call(self._w, 'element','names'))

       def element_show (self,*names) :
               return apply(self.tk.call,(self._w,'element','show') + names)

       def invtransform (self, winx, winy) :
               return string.split(self.tk.call(self._w,'invtransform',winx,
                                                winy))
       def legend_activate (self,name, *names) :
               apply(self.tk.call,(self._w,'legend','activate',
                                   name) + names)
       def legend_configure (self,cnf={},**kw) :
               apply(self.tk.call,
                     (self._w, 'legend', 'configure', name)
                     + self._options(cnf, kw))
       def legend_deactivate (self,name) :
               self.tk.call(self._w,name)

       def legend_get (self,x,y) :
               self.tk.call(self._w,x,y)

       def postscript (self,filename=None) :
               return self.tk.call(self._w,'postscript',filename)
       def psconfigure (self,cnf={},**kw) :
               apply(self.tk.call,
                     (self._w, 'psconfigure', name)
                     + self._options(cnf, kw))
       def tag_after (self,tagid1, tagid2=None) :
               self.tk.call(self._w,'tag','after',tagid1,tagid2)
       def tag_before (self,tagid1, tagid2=None) :
               self.tk.call(self._w,'tag','before',tagid1,tagid2)
       def tag_configure(self,tagid, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'tag', 'configure', name)
                     + self._options(cnf, kw))
       def tag_coords(self,tagid, coords=None) :
               return string.split(self.tk.call(self._w,tagid,coords))
       def tag_create(self,type,coords=None) :
               self.tk.call(self._w,'tag','create',coords)
       def tag_delete(self,tagid, *tagids) :
               apply(self.tk.call,(self._w,'tag','delete',
                                   tag) + tags)
       def tag_ids (self,pattern=None) :
               return string.split(self.tk.call(self._w, 'tag', 'ids',
                                                pattern))
       def tag_type (self, tagid) :
               return self.tk.call(self._w, 'tag', 'type')
       def transform (self, x, y) :
               self.tk.call(self._w,'transform',x,y)
       def xaxis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'xaxis', 'configure')
                     + self._options(cnf, kw))
       def yaxis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'yaxis', 'configure')
                     + self._options(cnf, kw))
       def x2axis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'x2axis', 'configure')
                     + self._options(cnf, kw))
       def y2axis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'y2axis', 'configure')
                     + self._options(cnf, kw))
       def xaxis_limits (self) :
               return string.split (self.tk.call(self._w,'xaxis','limits'))
       def yaxis_limits (self) :
               return string.split (self.tk.call(self._w,'yaxis','limits'))
       def x2axis_limits (self) :
               return string.split (self.tk.call(self._w,'x2axis','limits'))
       def y2axis_limits (self) :
               return string.split (self.tk.call(self._w,'y2axis','limits'))

class Barchart (Widget) :
       """
       blt_barchart widget
       """

       def __init__(self,master=None,cnf={}, **kw):
               Widget.__init__(self,master,'barchart',cnf,kw)

       def crosshairs_configure (self, cnf={}, **kw):
               return apply(self.tk.call,
                            (self._w, 'crosshairs', 'configure')
                            + self._options(cnf, kw))
       def crosshairs_toggle (self) :
               self.tk.call(self._w,'crosshairs','toggle')

       #def element_activate (self, name, index=None) :
       #       return self.tk.call,(self._w,'element',
       #                                  'activate',name,index)

       def element_append (self,name,coords) :
               self.tk.call(self._w,'element',
                            'append',name, coords)
       #def element_closest (self,x,y,name=None) :
       #       return self.tk.call(self._w,'element','closest',x,y,name)

       def element_configure (self,name,cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'element', 'configure', name)
                     + self._options(cnf, kw))
       def element_create (self,name,cnf={},**kw) :
               apply(self.tk.call,
                     (self._w, 'element', 'create', name)
                     + self._options(cnf, kw))
       #def element_deactivate (self,name, *names) :
       #       apply(self.tk.call,(self._w,'element','deactivate',
       #                           name) + names)

       def element_delete (self,name ,*names) :
               apply(self.tk.call,(self._w,'element','delete',
                                   name) + names)
       def element_names (self) :
               return string.split(self.tk.call(self._w, 'element','names'))
       def element_show (self,*names) :
               return apply(self.tk.call,(self._w,'element','show') + names)
       def invtransform (self, winx, winy) :
               return string.split(self.tk.call(self._w,'invtransform',winx,
                                                winy))
       def legend_activate (self,name, *names) :
               apply(self.tk.call,(self._w,'legend','activate',
                                   name) + names)
       def legend_configure (self,cnf={},**kw) :
               apply(self.tk.call,
                     (self._w, 'legend', 'configure', name)
                     + self._options(cnf, kw))
       def legend_deactivate (self,name) :
               self.tk.call(self._w,name)

       def legend_get (self,x,y) :
               self.tk.call(self._w,x,y)

       def postscript (self,filename=None) :
               return self.tk.call(self._w,'postscript',filename)
       def psconfigure (self,cnf={},**kw) :
               apply(self.tk.call,
                     (self._w, 'psconfigure', name)
                     + self._options(cnf, kw))
       def tag_after (self,tagid1, tagid2=None) :
               self.tk.call(self._w,'tag','after',tagid1,tagid2)
       def tag_before (self,tagid1, tagid2=None) :
               self.tk.call(self._w,'tag','before',tagid1,tagid2)
       def tag_configure(self,tagid, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'tag', 'configure', name)
                     + self._options(cnf, kw))
       def tag_coords(self,tagid, coords=None) :
               return string.split(self.tk.call(self._w,tagid,coords))
       def tag_create(self,type,coords=None) :
               self.tk.call(self._w,'tag','create',coords)
       def tag_delete(self,tagid, *tagids) :
               apply(self.tk.call,(self._w,'tag','delete',
                                   tag) + tags)
       def tag_ids (self,pattern=None) :
               return string.split(self.tk.call(self._w, 'tag', 'ids',
                                                pattern))
       def tag_type (self, tagid) :
               return self.tk.call(self._w, 'tag', 'type')
       def transform (self, x, y) :
               self.tk.call(self._w,'transform',x,y)
       def xaxis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'xaxis', 'configure')
                     + self._options(cnf, kw))
       def yaxis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'yaxis', 'configure')
                     + self._options(cnf, kw))
       def x2axis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'x2axis', 'configure')
                     + self._options(cnf, kw))
       def y2axis_configure(self, cnf={}, **kw) :
               apply(self.tk.call,
                     (self._w, 'y2axis', 'configure')
                     + self._options(cnf, kw))
       def xaxis_limits (self) :
               return string.split (self.tk.call(self._w,'xaxis','limits'))
       def yaxis_limits (self) :
               return string.split (self.tk.call(self._w,'yaxis','limits'))
       def x2axis_limits (self) :
               return string.split (self.tk.call(self._w,'x2axis','limits'))
       def y2axis_limits (self) :
               return string.split (self.tk.call(self._w,'y2axis','limits'))

# symbol starting wiht "_" will not be exported with "from *" statement.
_vecnum=0

class Vector:
       _default=""
       def __init__(self,master=None,*val):
               global _vecnum
               global _default_root
               if not master:
                       if not _default_root:
                               _default_root = Tk()
                       master=_default_root
               self._tk=master.tk
               self._name='BLT_VEC_'+`_vecnum`
               _vecnum=_vecnum+1
               self._tk.call('vector',self._name)
               if val:
                       self._tk.call(self._name,'set',val)
       def set(self,*v):
               if(v == ()):
                       val=self.val
               else:
                       val=v
               self._tk.call(self._name,'set',val )

       def get(self):
               return self._tk.splitlist(self._tk.call(self._name, '+',0))

       def append(self,*items):
               self._tk.call(self._name, 'append', items)

       def clear(self):
               self._tk.call(self._name, 'clear' )

       def delete(self,index):
               self._tk.call(self._name, 'delete', index)

       def dup(self,vec):
               self._tk.call(self._name,'dup',vec._name)

       def length(self,newsize=None):
               if newsize:
                       return string.atoi(self._tk.call(self._name,'length', newsize))
               else:
                       return string.atoi(self._tk.call(self._name,'length'))

       def merge(self,*vectors):
               for v in vectors:
                       self._tk.call(self._name,'merge', v._name)

       def notify(self,keyword):
               if keyword in ('always','never','whenide','now','cancel','pendingReturns'):
                       self._tk.call(self._name,'notify',keyword)

       def offset(self, offset=None):
               if offset:
                       self._tk.call(self._name,'offset', offset)
               else:
                       return self._tk.call(self._name,'offset')

       def populate(self, vecname, density=None):
               self._tk.call(self._name,'populate', vecname._name,density)

       def range(self,firstIndex,*lastIndex):
               if lastIndex:
                       return self._tk.call(self._name,'range',firstIndex,lastIndex)
               else:
                       return self._tk.call(self._name,'range', firstIndex,firstIndex)

       def search(self,*values):
               return self._tk.call(self._name,'search', values)

       def sort(self,reverse=None,*args):
               if reverse :
                       self._tk.call(self._name,'sort','-reverse',args)
               else:
                       self._tk.call(self._name,'sort',args)
       def __repr__(self):
               return self._name

       def __add__(self,item):
               return self._tk.splitlist(self._tk.call(self._name,'+',item))

       def __sub__(self,item):
               return self._tk.splitlist(
                       self._tk.call(self._name,'-',item)
               )

       def __mul__(self,item):
               return self._tk.splitlist(
                       self._tk.call(self._name,'*',item)
               )
       def __div__(self,item):
               return self._tk.splitlist(
                       self._tk.call(self._name,'/',item)
               )
       def __getslice__(self,low,high):
               return self.range(low,high)

       def __getitem__(self,index):
                       self._tk.call(self._name,'range',index,index)

       def __setitem__(self,index,val):
               if(index < self.length()):
                       self._tk.call('set', "%s(%d)"%(self._name,index),val)

def test1 () :
       r=Toplevel(root)
       g=Graph(r)
       g.pack()
       x=range(1,300,5)
       y=map(lambda x:math.sin(float(x)/30),x)
       g.element_create('pete',xdata=tuple(x),ydata=tuple(y))
       y=map(lambda x:math.cos(float(x)/30),x)
       g.element_create('stacey',xdata=tuple(x),ydata=tuple(y))
       g.element_configure('pete',color='red',symbol='circle',scale=1,
                           linewidth=2)
       g.element_configure('stacey',color='blue',symbol='square',scale=1,
                           linewidth=2)
       g.crosshairs_configure(mapped=1)
       g.element_activate('pete')
       g.xaxis_configure(logscale=0,showticks=1)
       b=Button(r, text="Quit", command=root.quit)
       b.pack()
       print g.element_names()

def testv () :
       r=Toplevel(root)
       g=Graph(r)
       g.pack()
       x=Vector(g)
       y1=Vector(g)
       y2=Vector(g)
       g.element_create('pete', xdata=x,ydata=y1)
       g.element_create('stacey',xdata=x,ydata=y2)
       g.element_configure('pete',color='red',symbol='circle',scale=1,
                           linewidth=2)
       g.element_configure('stacey',color='blue',symbol='square',scale=1,
                           linewidth=2)
       apply(y1.set,tuple(map(lambda x:math.sin(float(x)/30),range(1,300,5))))
       apply(y2.set,tuple(map(lambda x:math.cos(float(x)/30),range(1,300,5))))
       apply(x.set, tuple(range(1,300,5)))
       g.crosshairs_configure(mapped=1)
       g.element_activate('pete')
       g.xaxis_configure(logscale=0,showticks=1)
       b=Button(r, text="Quit", command=root.quit)
       b.pack()
       print g.element_names()

def test2 () :
       r=Toplevel(root)
       g=Barchart(r,barmode="aligned")
       g.pack()
       g.element_create('stacey',xdata=(2,1),ydata=(4,4),barwidth=0.7)
       g.element_create('pete',xdata=(1,2),ydata=(5,3),barwidth=0.7)
       g.xaxis_configure(command=names)
       g.element_configure('pete',fg='red')
       g.element_configure('stacey',fg='blue')
       g.crosshairs_configure(mapped=1)
       g.xaxis_configure(logscale=0,showticks=1)
       b=Button(r, text="Quit", command=root.quit)
       b.pack()
       print g.element_names()

def bell(percent=100) :
       Tkinter._default_root.tk.call('bell')

def names (crap,id) :
       names={1:'Pete',2:'Stacey'}
       return names[int(Tkinter.getdouble(id))]

if __name__=='__main__' :
       import Tkinter
       import math
       import sys
       root=Tkinter.Tk()
       b=Button(root,text='graph',command=test1)
       v=Button(root,text='graph with Vector',command=testv)
       c=Button(root,text='chart',command=test2)
       b.pack()
       v.pack()
       c.pack()
       bell(10)
       root.mainloop()