#!/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 (noboru.yamamoto@kek.jp)
 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()
