0
|
1 from __future__ import division
|
|
2 import Tkinter as tk
|
|
3 from dispatch import dispatcher
|
|
4
|
|
5 class Zoomcontrol(object,tk.Canvas):
|
|
6
|
|
7 def maxtime():
|
|
8 doc = "seconds at the right edge of the bar"
|
|
9 def fget(self): return self._maxtime
|
|
10 def fset(self, value):
|
|
11 self._maxtime = value
|
|
12 self.updatewidget()
|
|
13 return locals()
|
|
14 maxtime = property(**maxtime())
|
|
15
|
|
16 def start():
|
|
17 def fget(self): return self._start
|
|
18 def fset(self,v): self._start = max(0,v)
|
|
19 return locals()
|
|
20 start = property(**start())
|
|
21
|
|
22 def end():
|
|
23 def fget(self): return self._end
|
|
24 def fset(self,v): self._end = min(self.maxtime,v)
|
|
25 return locals()
|
|
26 end = property(**end())
|
|
27
|
|
28
|
|
29 def __init__(self,master,**kw):
|
|
30 self.maxtime=370
|
|
31 self.start=0
|
|
32 self.end=20
|
|
33 tk.Canvas.__init__(self,master,width=250,height=30,
|
|
34 relief='raised',bd=1,bg='gray60',**kw)
|
|
35 self.leftbrack = self.create_line(0,0,0,0,0,0,0,0,width=5)
|
|
36 self.rightbrack = self.create_line(0,0,0,0,0,0,0,0,width=5)
|
|
37 self.shade = self.create_rectangle(0,0,0,0,fill='gray70',outline=None)
|
|
38 self.time = self.create_line(0,0,0,0,fill='red',width=2)
|
|
39 self.updatewidget()
|
|
40 self.bind("<Configure>",self.updatewidget)
|
|
41
|
|
42 self.bind("<ButtonPress-1>",lambda ev: setattr(self,'lastx',ev.x))
|
|
43 self.tag_bind(self.leftbrack,"<B1-Motion>",
|
|
44 lambda ev: self.adjust('start',ev))
|
|
45 self.tag_bind(self.rightbrack,"<B1-Motion>",
|
|
46 lambda ev: self.adjust('end',ev))
|
|
47 self.tag_bind(self.shade,"<B1-Motion>",
|
|
48 lambda ev: self.adjust('offset',ev))
|
|
49 dispatcher.connect(lambda: (self.start,self.end),"zoom area",weak=0)
|
|
50 dispatcher.connect(self.input_time,"input time")
|
|
51 dispatcher.connect(lambda maxtime: (setattr(self,'maxtime',maxtime),
|
|
52 self.updatewidget()),"max time",weak=0)
|
|
53 self.created=1
|
|
54 def input_time(self,val):
|
|
55 t=val
|
|
56 x=self.can_for_t(t)
|
|
57 self.coords(self.time,x,0,x,self.winfo_height())
|
|
58
|
|
59 def adjust(self,attr,ev):
|
|
60 if not hasattr(self,'lastx'):
|
|
61 return
|
|
62 new = self.can_for_t(getattr(self,attr)) + (ev.x - self.lastx)
|
|
63 self.lastx = ev.x
|
|
64 setattr(self,attr,self.t_for_can(new))
|
|
65 self.updatewidget()
|
|
66 dispatcher.send("zoom changed")
|
|
67
|
|
68 def offset():
|
|
69 doc = "virtual attr that adjusts start and end together"
|
|
70 def fget(self):
|
|
71 return self.start
|
|
72 def fset(self, value):
|
|
73 d = self.end-self.start
|
|
74 self.start = value
|
|
75 self.end = self.start+d
|
|
76 return locals()
|
|
77 offset = property(**offset())
|
|
78
|
|
79 def can_for_t(self,t):
|
|
80 return t/self.maxtime*(self.winfo_width()-30)+20
|
|
81 def t_for_can(self,x):
|
|
82 return (x-20)/(self.winfo_width()-30)*self.maxtime
|
|
83
|
|
84 def updatewidget(self,*args):
|
|
85 """redraw pieces based on start/end"""
|
|
86 if not hasattr(self,'created'): return
|
|
87 y1,y2=3,self.winfo_height()-3
|
|
88 lip = 6
|
|
89 scan = self.can_for_t(self.start)
|
|
90 ecan = self.can_for_t(self.end)
|
|
91 self.coords(self.leftbrack,scan+lip,y1,scan,y1,scan,y2,scan+lip,y2)
|
|
92 self.coords(self.rightbrack,ecan-lip,y1,ecan,y1,ecan,y2,ecan-lip,y2)
|
|
93 self.coords(self.shade,scan+3,y1+lip,ecan-3,y2-lip)
|
|
94 self.delete("tics")
|
|
95 lastx=-1000
|
|
96 for t in range(0,int(self.maxtime)):
|
|
97 x = self.can_for_t(t)
|
|
98 if 0<x<self.winfo_width() and x-lastx>30:
|
|
99 txt=str(t)
|
|
100 if lastx==-1000:
|
|
101 txt=txt+"sec"
|
|
102 self.create_line(x,0,x,15,
|
|
103 tags=('tics',))
|
|
104 self.create_text(x,self.winfo_height()-1,anchor='s',
|
|
105 text=txt,tags=('tics',),font='6x13')
|
|
106 lastx = x
|