comparison flax/CueFaders.py @ 161:0803fb42109d

we now have TkCueList, which is really cool. it doesn't provide editing we now have TkCueList, which is really cool. it doesn't provide editing yet, but you could almost nearly probably maybe run a show with it. heck, i hope so. some of the shifting/drawing problems were probably fixed. cuelist1 got more bogus data to help populate the TkCueList.
author dmcc
date Mon, 07 Jul 2003 17:18:26 +0000
parents 5c7ac46e33d3
children 6c5753bad783
comparison
equal deleted inserted replaced
160:c1c0f5854f8f 161:0803fb42109d
1 from __future__ import division, nested_scopes 1 from __future__ import division, nested_scopes
2 import Tix as Tk 2 import Tix as Tk
3 import time 3 import time
4 from TreeDict import TreeDict, allow_class_to_be_pickled 4 from TreeDict import TreeDict, allow_class_to_be_pickled
5 from TLUtility import enumerate
6
7 cue_state_indicator_colors = {
8 # bg fg
9 'prev' : ('blue', 'white'),
10 'cur' : ('yellow', 'black'),
11 'next' : ('red', 'white'),
12 }
5 13
6 class LabelledScale(Tk.Frame): 14 class LabelledScale(Tk.Frame):
7 """Scale with two labels: a name and current value""" 15 """Scale with two labels: a name and current value"""
8 def __init__(self, master, label, **opts): 16 def __init__(self, master, label, **opts):
9 Tk.Frame.__init__(self, master, bd=2, relief='raised') 17 Tk.Frame.__init__(self, master, bd=2, relief='raised')
10 opts.setdefault('variable', Tk.DoubleVar()) 18 opts.setdefault('variable', Tk.DoubleVar())
11 opts.setdefault('showvalue', 0) 19 opts.setdefault('showvalue', 0)
20
21 self.normaltrough = opts.get('troughcolor', 'black')
22 self.flashtrough = opts.get('flashtroughcolor', 'red')
23 del opts['flashtroughcolor']
24
12 self.scale_var = opts['variable'] 25 self.scale_var = opts['variable']
13 self.scale = Tk.Scale(self, **opts) 26 self.scale = Tk.Scale(self, **opts)
14 self.scale.pack(side='top', expand=1, fill='both') 27 self.scale.pack(side='top', expand=1, fill='both')
15 self.name = Tk.Label(self, text=label) 28 self.name = Tk.Label(self, text=label)
16 self.name.pack(side='bottom') 29 self.name.pack(side='bottom')
22 def set_label(self, label): 35 def set_label(self, label):
23 self.name['text'] = label 36 self.name['text'] = label
24 def update_value_label(self, *args): 37 def update_value_label(self, *args):
25 val = self.scale_var.get() * 100 38 val = self.scale_var.get() * 100
26 self.scale_value['text'] = "%0.2f" % val 39 self.scale_value['text'] = "%0.2f" % val
40 if val != 0:
41 self.scale['troughcolor'] = self.flashtrough
42 else:
43 self.scale['troughcolor'] = self.normaltrough
27 def disable(self): 44 def disable(self):
28 if not self.disabled: 45 if not self.disabled:
29 self.scale['state'] = 'disabled' 46 self.scale['state'] = 'disabled'
30 self.scale_var.set(0) 47 self.scale_var.set(0)
31 self.disabled = 1 48 self.disabled = 1
34 self.scale['state'] = 'normal' 51 self.scale['state'] = 'normal'
35 self.disabled = 0 52 self.disabled = 0
36 53
37 class TimedGoButton(Tk.Frame): 54 class TimedGoButton(Tk.Frame):
38 """Go button, fade time entry, and time fader""" 55 """Go button, fade time entry, and time fader"""
39 def __init__(self, master, name, scale_to_fade): 56 def __init__(self, master, name, scale_to_fade, **kw):
40 Tk.Frame.__init__(self, master) 57 Tk.Frame.__init__(self, master)
41 self.name = name 58 self.name = name
42 self.scale_to_fade = scale_to_fade 59 self.scale_to_fade = scale_to_fade
43 self.button = Tk.Button(self, text=name, command=self.start_fade) 60 self.button = Tk.Button(self, text=name, command=self.start_fade, **kw)
44 self.button.pack(fill='both', expand=1, side='left') 61 self.button.pack(fill='both', expand=1, side='left')
45 self.timer_var = Tk.StringVar() 62 self.timer_var = Tk.StringVar()
46 self.timer_entry = Tk.Entry(self, textvariable=self.timer_var, width=5) 63 self.timer_entry = Tk.Entry(self, textvariable=self.timer_var, width=5)
47 self.timer_entry.pack(fill='y', side='left') 64 self.timer_entry.pack(fill='y', side='left')
48 self.timer_var.set("2") 65 self.timer_var.set("2")
86 Tk.Frame.__init__(self, master) 103 Tk.Frame.__init__(self, master)
87 self.cuelist = cuelist 104 self.cuelist = cuelist
88 self.auto_shift = Tk.IntVar() 105 self.auto_shift = Tk.IntVar()
89 self.auto_shift.set(1) 106 self.auto_shift.set(1)
90 107
108 # this is a mechanism to stop Tk from autoshifting too much.
109 # if this variable is true, the mouse button is down. we don't want
110 # to shift until they release it. when it is released, we will
111 # set it to false and then call autoshift.
112 self.no_shifts_until_release = 0
113
91 self.scales = {} 114 self.scales = {}
92 self.shift_buttons = {} 115 self.shift_buttons = {}
93 self.go_buttons = {} 116 self.go_buttons = {}
94 117
95 topframe = Tk.Frame(self) 118 topframe = Tk.Frame(self)
96 self.current_cues = Tk.Label(topframe) 119
97 self.current_cues.pack() 120 self.set_prev_button = Tk.Button(topframe, text='Set Prev',
98 self.update_cue_display() 121 command=lambda: cuelist.set_selection_as_prev(),
99 topframe.pack() 122 fg='white', bg='blue')
100 123 self.set_prev_button.pack(side='left')
101 bottomframe = Tk.Frame(self) 124
102 self.auto_shift_checkbutton = Tk.Checkbutton(self, 125 self.auto_shift_checkbutton = Tk.Checkbutton(topframe,
103 variable=self.auto_shift, text='Autoshift', 126 variable=self.auto_shift, text='Autoshift',
104 command=self.toggle_autoshift) 127 command=self.toggle_autoshift)
105 self.auto_shift_checkbutton.pack() 128 self.auto_shift_checkbutton.pack(side='left')
106 bottomframe.pack(side='bottom') 129
107 130 self.set_next_button = Tk.Button(topframe, text='Set Next',
108 middleframe = Tk.Frame(self) 131 command=lambda: cuelist.set_selection_as_next(),
109 for name, start, end, side in (('Prev', 1, 0, 'left'), 132 fg='white', bg='red')
110 ('Next', 0, 1, 'right')): 133 self.set_next_button.pack(side='left')
134
135 topframe.pack(side='top')
136
137 faderframe = Tk.Frame(self)
138 self.direction_info = (('Prev', 1, 0, 'left', 'blue'),
139 ('Next', 0, 1, 'right', 'red'))
140 for name, start, end, side, color in self.direction_info:
111 frame = Tk.Frame(self) 141 frame = Tk.Frame(self)
112 scale = LabelledScale(frame, name, from_=start, to_=end, 142 scale = LabelledScale(frame, name, from_=start, to_=end,
113 res=0.01, orient='horiz') 143 res=0.0001, orient='horiz', flashtroughcolor=color)
114 scale.pack(fill='both', expand=1) 144 scale.pack(fill='x', expand=0)
115 go = TimedGoButton(frame, 'Go %s' % name, scale) 145 go = TimedGoButton(frame, 'Go %s' % name, scale, bg=color,
146 fg='white')
116 go.pack(fill='both', expand=1) 147 go.pack(fill='both', expand=1)
117 frame.pack(side=side, fill='both', expand=1) 148 frame.pack(side=side, fill='both', expand=1)
118 149
119 shift = Tk.Button(frame, text="Shift %s" % name, state='disabled', 150 shift = Tk.Button(frame, text="Shift %s" % name, state='disabled',
120 command=lambda name=name: self.shift(name)) 151 command=lambda name=name: self.shift(name), fg=color,
152 bg='black')
121 153
122 self.scales[name] = scale 154 self.scales[name] = scale
123 self.shift_buttons[name] = shift 155 self.shift_buttons[name] = shift
124 self.go_buttons[name] = go 156 self.go_buttons[name] = go
125 157
126 scale.scale_var.trace('w', \ 158 scale.scale_var.trace('w', \
127 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale)) 159 lambda x, y, z, name=name, scale=scale: self.xfade(name, scale))
128 middleframe.pack(side='bottom', fill='both', expand=1) 160
161 def button_press(event, name=name, scale=scale):
162 self.no_shifts_until_release = 1 # prevent shifts until release
163 def button_release(event, name=name, scale=scale):
164 self.no_shifts_until_release = 0
165 self.autoshift(name, scale)
166
167 scale.scale.bind("<ButtonPress>", button_press)
168 scale.scale.bind("<ButtonRelease>", button_release)
169 faderframe.pack(side='bottom', fill='both', expand=1)
129 def toggle_autoshift(self): 170 def toggle_autoshift(self):
130 for name, button in self.shift_buttons.items(): 171 for name, button in self.shift_buttons.items():
131 if not self.auto_shift.get(): 172 if not self.auto_shift.get():
132 button.pack(side='bottom', fill='both', expand=1) 173 button.pack(side='bottom', fill='both', expand=1)
133 else: 174 else:
134 button.pack_forget() 175 button.pack_forget()
135
136 def shift(self, name): 176 def shift(self, name):
137 print "shift", name 177 # to prevent overshifting
178 if self.no_shifts_until_release:
179 return
180
138 for scale_name, scale in self.scales.items(): 181 for scale_name, scale in self.scales.items():
139 scale.scale_var.set(0) 182 scale.scale.set(0)
140 self.cuelist.shift((-1, 1)[name == 'Next']) 183 self.cuelist.shift((-1, 1)[name == 'Next'])
141 self.update_cue_display() 184 def autoshift(self, name, scale):
142 def update_cue_display(self):
143 current_cues = [cue.name for cue in self.cuelist.get_current_cues()]
144 self.current_cues['text'] = ', '.join(current_cues)
145 def xfade(self, name, scale):
146 scale_val = scale.scale_var.get() 185 scale_val = scale.scale_var.get()
147 # print "xfade", name, scale_val
148 186
149 if scale_val == 1: 187 if scale_val == 1:
150 if self.auto_shift.get(): 188 if self.auto_shift.get():
151 print "autoshifting", name
152 self.shift(name) 189 self.shift(name)
153 scale_val = scale.scale_var.get() # this needs to be refreshed 190 def xfade(self, name, scale):
191 if self.auto_shift.get():
192 self.autoshift(name, scale)
193 scale_val = scale.scale_var.get()
194 else:
195 scale_val = scale.scale_var.get()
196 if scale_val == 1:
197 self.shift_buttons[name]['state'] = 'normal'
154 else: 198 else:
155 self.shift_buttons[name]['state'] = 'normal' 199 # disable any dangerous shifting
156 else: 200 self.shift_buttons[name]['state'] = 'disabled'
157 # disable any dangerous shifting
158 self.shift_buttons[name]['state'] = 'disabled'
159 201
160 d = self.opposite_direction(name) 202 d = self.opposite_direction(name)
161 if scale_val != 0: 203 if scale_val != 0:
162 # disable illegal three part crossfades 204 # disable illegal three part crossfades
163 self.scales[d].disable() 205 self.scales[d].disable()
247 return empty_cue 289 return empty_cue
248 def __del__(self): 290 def __del__(self):
249 self.save() 291 self.save()
250 def save(self): 292 def save(self):
251 self.treedict.save(self.filename) 293 self.treedict.save(self.filename)
294 def reload(self):
295 # TODO: we probably will need to make sure that indices still make
296 # sense, etc.
297 self.treedict.load(self.filename)
298
299 class TkCueList(CueList, Tk.Frame):
300 def __init__(self, master, filename):
301 CueList.__init__(self, filename)
302 Tk.Frame.__init__(self, master)
303
304 self.columns = ('name', 'time', 'page', 'desc')
305
306 self.scrolled_hlist = Tk.ScrolledHList(self,
307 options='hlist.columns %d hlist.header 1' % len(self.columns))
308 self.hlist = self.scrolled_hlist.hlist
309 self.hlist.configure(fg='white', bg='black',
310 command=self.select_callback)
311 self.scrolled_hlist.pack(fill='both', expand=1)
312
313 boldfont = self.tk.call('tix', 'option', 'get',
314 'bold_font')
315 header_style = Tk.DisplayStyle('text', refwindow=self,
316 anchor='center', padx=8, pady=2, font=boldfont)
317
318 for count, header in enumerate(self.columns):
319 self.hlist.header_create(count, itemtype='text',
320 text=header, style=header_style)
321
322 self.cue_label_windows = {}
323 for count, cue in enumerate(self.cues):
324 self.display_cue(count, cue)
325 self.update_cue_indicators()
326 def display_cue(self, cue_count, cue):
327 # cue_count is the path in the hlist -- this probably isn't ideal
328 for col, header in enumerate(self.columns):
329 try:
330 text = getattr(cue, header)
331 except AttributeError:
332 text = ''
333
334 if col == 0:
335 lab = Tk.Label(self.hlist, text=text, fg='white', bg='black')
336 def select_and_highlight(event):
337 self.select_callback(cue_count)
338 self.hlist.selection_clear()
339 self.hlist.selection_set(cue_count)
340
341 lab.bind("<Double-1>", select_and_highlight)
342 self.hlist.add(cue_count, itemtype='window', window=lab)
343 self.cue_label_windows[cue_count] = lab
344 else:
345 self.hlist.item_create(cue_count, col, text=text)
346 def reset_cue_indicators(self, cue_indices=None):
347 """If cue_indices is None, we'll reset all of them."""
348 cue_indices = cue_indices or self.cue_label_windows.keys()
349 for key in cue_indices:
350 window = self.cue_label_windows[key]
351 window.configure(fg='white', bg='black')
352 def update_cue_indicators(self):
353 states = dict(zip(self.get_current_cue_indices(),
354 ('prev', 'cur', 'next')))
355
356 for count, state in states.items():
357 window = self.cue_label_windows[count]
358 bg, fg = cue_state_indicator_colors[state]
359 window.configure(bg=bg, fg=fg)
360 def shift(self, diff):
361 self.reset_cue_indicators(self.get_current_cue_indices())
362 CueList.shift(self, diff)
363 self.update_cue_indicators()
364 # try to see all indices, but next takes priority over all, and cur
365 # over prev
366 for index in self.get_current_cue_indices():
367 self.hlist.see(index)
368 def select_callback(self, index):
369 new_next = int(index)
370 self.set_next(new_next)
371 def set_next(self, index):
372 prev, cur, next = self.get_current_cue_indices()
373 self.reset_cue_indicators((next,))
374 CueList.set_next(self, index)
375 self.update_cue_indicators()
376 def set_prev(self, index):
377 prev, cur, next = self.get_current_cue_indices()
378 self.reset_cue_indicators((prev,))
379 CueList.set_prev(self, index)
380 self.update_cue_indicators()
381 def set_selection_as_prev(self):
382 sel = self.hlist.info_selection()
383 if sel:
384 self.set_prev(int(sel[0]))
385 def set_selection_as_next(self):
386 sel = self.hlist.info_selection()
387 if sel:
388 self.set_next(int(sel[0]))
252 389
253 if __name__ == "__main__": 390 if __name__ == "__main__":
254 cl = CueList('cues/cuelist1') 391 root = Tk.Tk()
392 cl = TkCueList(root, 'cues/cuelist1')
393 cl.pack(fill='both', expand=1)
255 394
256 # to populate cue list 395 # to populate cue list
257 if 0: 396 if 0:
258 for x in range(20): 397 for x in range(20):
259 cl.add_cue(Cue('cue %d' % x, time=x, some_attribute=3)) 398 cl.add_cue(Cue('cue %d' % x, time=x, some_attribute=3))
260 399
261 root = Tk.Tk()
262 fader = CueFader(root, cl) 400 fader = CueFader(root, cl)
263 fader.pack(fill='both', expand=1) 401 fader.pack(fill='both', expand=1)
264 Tk.mainloop() 402 Tk.mainloop()