Mercurial > code > home > repos > light9
changeset 699:d12bc8919d6e
ported the zoom control
Ignore-this: edce8350a21280aebf2a0e69cd7335ea
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Sun, 10 Jun 2012 05:33:25 +0000 |
parents | 2aac2ef23495 |
children | d5692ab6bc2a |
files | bin/curvecalc light9/curvecalc/curvecalc.glade light9/curvecalc/curveview.py light9/curvecalc/zoomcontrol.py |
diffstat | 4 files changed, 236 insertions(+), 323 deletions(-) [+] |
line wrap: on
line diff
--- a/bin/curvecalc Sun Jun 10 04:03:00 2012 +0000 +++ b/bin/curvecalc Sun Jun 10 05:33:25 2012 +0000 @@ -26,7 +26,6 @@ import run_local from light9 import showconfig, prof -from light9.curvecalc.zoomcontrol import Zoomcontrol from light9.curvecalc.curve import Curveset from light9.curvecalc import curveview from light9.curvecalc.musicaccess import Music, currentlyPlayingSong @@ -64,19 +63,26 @@ ) def refreshCurveView(): - m = os.path.getmtime(curveview.__file__.replace('.pyc', '.py')) + mtimes = [os.path.getmtime(f) for f in [ + 'light9/curvecalc/curveview.py', + 'light9/curvecalc/zoomcontrol.py', + ]] - if not hasattr(self, 'curvesetView') or self.curvesetView._mtime != m: + if (not hasattr(self, 'curvesetView') or + self.curvesetView._mtimes != mtimes): print "reload curveview.py" curvesVBox = wtree.get_object("curves") + zoomControlBox = wtree.get_object("zoomControlBox") [curvesVBox.remove(c) for c in curvesVBox.get_children()] + [zoomControlBox.remove(c) for c in + zoomControlBox.get_children()] try: linecache.clearcache() reload(curveview) # mem problem somewhere; need to hold a ref to this self.curvesetView = curveview.Curvesetview( - curvesVBox, curveset) - self.curvesetView._mtime = m + curvesVBox, zoomControlBox, curveset) + self.curvesetView._mtimes = mtimes # curvesetview must already exist, since this # makes 'add_curve' signals for all the initial @@ -97,7 +103,14 @@ self.makeStatusLines(wtree.get_object("status")) - #zc = Zoomcontrol(root) + def onSeeCurrentTime(self, item): + dispatcher.send("see time") + + def onSeeTimeUntilEnd(self, item): + dispatcher.send("see time until end") + + def onZoomAll(self, item): + dispatcher.send("show all") def onPlayPause(self, item): # since the X coord in a curveview affects the handling, one
--- a/light9/curvecalc/curvecalc.glade Sun Jun 10 04:03:00 2012 +0000 +++ b/light9/curvecalc/curvecalc.glade Sun Jun 10 05:33:25 2012 +0000 @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <interface> - <!-- interface-requires gtk+ 3.0 --> + <requires lib="gtk+" version="2.24"/> + <!-- interface-naming-policy toplevel-contextual --> <object class="GtkWindow" id="MainWindow"> <property name="can_focus">False</property> <child> @@ -13,9 +14,9 @@ <property name="can_focus">False</property> <child> <object class="GtkMenuItem" id="menuitem1"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_Curvecalc</property> <property name="use_underline">True</property> <child type="submenu"> @@ -25,9 +26,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem2"> <property name="label">gtk-save</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -35,9 +36,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem5"> <property name="label">gtk-quit</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -48,9 +49,9 @@ </child> <child> <object class="GtkMenuItem" id="menuitem7"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_Edit</property> <property name="use_underline">True</property> <child type="submenu"> @@ -60,9 +61,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem1"> <property name="label">gtk-cut</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -70,9 +71,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem3"> <property name="label">gtk-copy</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -80,9 +81,9 @@ <child> <object class="GtkImageMenuItem" id="imagemenuitem4"> <property name="label">gtk-paste</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="use_underline">True</property> <property name="use_stock">True</property> </object> @@ -93,9 +94,9 @@ </child> <child> <object class="GtkMenuItem" id="menuitem2"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_View</property> <property name="use_underline">True</property> <child type="submenu"> @@ -104,45 +105,51 @@ <property name="can_focus">False</property> <child> <object class="GtkMenuItem" id="menuitem8"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">See current time (esc)</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">See current time</property> <property name="use_underline">True</property> + <accelerator key="Escape" signal="activate"/> + <signal name="activate" handler="onSeeCurrentTime" swapped="no"/> </object> </child> <child> <object class="GtkMenuItem" id="menuitem9"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">See from current time -> end (S-Esc)</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">See from current time -> end</property> <property name="use_underline">True</property> + <accelerator key="Escape" signal="activate" modifiers="GDK_SHIFT_MASK"/> + <signal name="activate" handler="onSeeTimeUntilEnd" swapped="no"/> </object> </child> <child> <object class="GtkMenuItem" id="menuitem10"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="label" translatable="yes">Zoom all (C-Esc)</property> + <property name="use_action_appearance">False</property> + <property name="label" translatable="yes">Zoom all</property> <property name="use_underline">True</property> + <accelerator key="Escape" signal="activate" modifiers="GDK_CONTROL_MASK"/> + <signal name="activate" handler="onZoomAll" swapped="no"/> </object> </child> <child> <object class="GtkMenuItem" id="menuitem11"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Zoom in (wheel up)</property> <property name="use_underline">True</property> </object> </child> <child> <object class="GtkMenuItem" id="menuitem12"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Zoom out (wheel down)</property> <property name="use_underline">True</property> </object> @@ -153,9 +160,9 @@ </child> <child> <object class="GtkMenuItem" id="menuitem3"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_Playback</property> <property name="use_underline">True</property> <child type="submenu"> @@ -164,9 +171,9 @@ <property name="can_focus">False</property> <child> <object class="GtkMenuItem" id="menuitem5"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">_Play/pause</property> <property name="use_underline">True</property> <accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/> @@ -179,9 +186,9 @@ </child> <child> <object class="GtkMenuItem" id="menuitem4"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Poin_ts</property> <property name="use_underline">True</property> <signal name="activate" handler="onPlayPause" swapped="no"/> @@ -191,9 +198,9 @@ <property name="can_focus">False</property> <child> <object class="GtkMenuItem" id="menuitem6"> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">False</property> + <property name="use_action_appearance">False</property> <property name="label" translatable="yes">Delete (del)</property> <property name="use_underline">True</property> </object> @@ -249,6 +256,8 @@ <property name="invisible_char_set">True</property> <property name="primary_icon_activatable">False</property> <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> </object> <packing> <property name="expand">True</property> @@ -264,6 +273,29 @@ </packing> </child> <child> + <object class="GtkVBox" id="zoomControlBox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <child> + <object class="GtkLabel" id="zoomControl"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="label" translatable="yes">[zoom control]</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> <object class="GtkScrolledWindow" id="scrolledwindow1"> <property name="visible">True</property> <property name="can_focus">True</property> @@ -293,7 +325,7 @@ <packing> <property name="expand">True</property> <property name="fill">True</property> - <property name="position">1</property> + <property name="position">2</property> </packing> </child> </object> @@ -325,7 +357,6 @@ <object class="GtkScrolledWindow" id="scrolledwindow2"> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="vscrollbar_policy">always</property> <child> <object class="GtkViewport" id="viewport1"> <property name="visible">True</property> @@ -343,42 +374,6 @@ <child> <placeholder/> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> </child> </object> @@ -397,7 +392,6 @@ <child> <object class="GtkButton" id="button1"> <property name="label" translatable="yes">Reload subs (C-r)</property> - <property name="use_action_appearance">False</property> <property name="visible">True</property> <property name="can_focus">True</property> <property name="receives_default">True</property> @@ -429,6 +423,10 @@ <property name="can_focus">True</property> <property name="invisible_char">●</property> <property name="invisible_char_set">True</property> + <property name="primary_icon_activatable">False</property> + <property name="secondary_icon_activatable">False</property> + <property name="primary_icon_sensitive">True</property> + <property name="secondary_icon_sensitive">True</property> </object> <packing> <property name="expand">False</property> @@ -486,24 +484,6 @@ <child> <placeholder/> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> </child> <child type="label"> @@ -608,131 +588,6 @@ <property name="can_focus">False</property> <property name="stock">gtk-refresh</property> </object> - <object class="GtkOffscreenWindow" id="offscreenwindow1"> - <property name="can_focus">False</property> - <child> - <object class="GtkVBox" id="vbox3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkHandleBox" id="handlebox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkHBox" id="hbox5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkFrame" id="frame1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">5</property> - <property name="label_xalign">0</property> - <property name="label_yalign">0</property> - <property name="shadow_type">out</property> - <child> - <object class="GtkVBox" id="vbox8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkLabel" id="label9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">curve 'music'</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox6"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkCheckButton" id="checkbutton1"> - <property name="label" translatable="yes">C</property> - <property name="use_action_appearance">False</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkbutton2"> - <property name="label" translatable="yes">M</property> - <property name="use_action_appearance">False</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_action_appearance">False</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - <child type="label_item"> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkImage" id="image4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-media-forward</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - </object> <object class="GtkTextBuffer" id="textbuffer1"> <property name="text" translatable="yes">song01(t)</property> </object>
--- a/light9/curvecalc/curveview.py Sun Jun 10 04:03:00 2012 +0000 +++ b/light9/curvecalc/curveview.py Sun Jun 10 05:33:25 2012 +0000 @@ -71,12 +71,12 @@ """ graphical curve widget only. Please pack .widget """ - def __init__(self, curve, knobEnabled=False, isMusic=False, **kw): + def __init__(self, curve, knobEnabled=False, isMusic=False, zoomControl=None, **kw): """knobEnabled=True highlights the previous key and ties it to a hardware knob""" - print "new curveview" + print "new curveview" self.widget = goocanvas.Canvas() - self.widget.set_property("background-color", "gray20") + self.widget.set_property("background-color", "black") self.widget.set_size_request(-1, 100) self.root = self.widget.get_root_item() @@ -84,6 +84,7 @@ self.curve = curve self.knobEnabled = knobEnabled self._isMusic = isMusic + self.zoomControl = zoomControl self._time = 0 self.last_mouse_world = None self.entered = False # is the mouse currently over this widget @@ -106,6 +107,7 @@ self.widget.connect("leave-notify-event", self.onLeave) self.widget.connect("enter-notify-event", self.onEnter) self.widget.connect("motion-notify-event", self.onMotion) + self.widget.connect("scroll-event", self.onScroll) self.widget.connect("button-release-event", self.onRelease) if 0: @@ -116,25 +118,6 @@ self.bind("<Key-%s>" % x, add_kb_marker_point) - - for butnum,factor in (5, 1.5),(4, 1/1.5): - def onMouseWheel(ev,factor=factor): - dispatcher.send("zoom about mouse", - t=self.world_from_screen(ev.x,0)[0], - factor=factor) - # this is supposed to make the canvases redraw more - # visibly, so we don't waste line redraws that never - # get seen. I'm not sure if it works. - self.update() - self.bind("<ButtonPress-%s>" % butnum, onMouseWheel) - self.bind("<Key-Escape>", lambda ev: - dispatcher.send("see time", - t=self.current_time())) - self.bind("<Shift-Escape>", lambda ev: - dispatcher.send("see time until end", - t=self.current_time())) - self.bind("<Control-Escape>", lambda ev: dispatcher.send("show all")) - # this binds on c-a-b1, etc if 0: self.regionzoom = RegionZoom(self, self.world_from_screen, @@ -167,14 +150,17 @@ user has pressed ctrl-p over a curve view, possibly this one. Returns the time under the mouse if we know it, or else None + + todo: there should be a faint timecursor line under the mouse + so it's more obvious that we use that time for some + events. Rt-click should include Ctrl+P as 'play/pause from + here' """ - print id(self), "checking", self.entered + # maybe self.widget.get_pointer would be ok for this? i didn't try it if self.entered: t = self.world_from_screen(self.lastMouseX, 0)[0] - print self.lastMouseX, t return t return None - #dispatcher.send("music seek", t=self.world_from_screen(ev.x,0)[0]) def goLive(self): """this is for startup performance only, since the curves were @@ -265,14 +251,14 @@ return self._time def screen_from_world(self,p): - start,end = self.zoom + z = self.zoomControl ht = self.size.height - return (p[0]-start)/(end-start)*self.size.width, (ht-5)-p[1]*(ht-10) + return (p[0]-z.start)/(z.end-z.start)*self.size.width, (ht-5)-p[1]*(ht-10) def world_from_screen(self,x,y): - start,end = self.zoom + z = self.zoomControl ht = self.size.height - return x/self.size.width*(end-start)+start, ((ht-5)-y)/(ht-10) + return x/self.size.width*(z.end-z.start)+z.start, ((ht-5)-y)/(ht-10) def input_time(self, val, forceUpdate=False): # i tried various things to make this not update like crazy, @@ -310,9 +296,7 @@ return self.size = self.widget.get_allocation() - self.zoom = 0, 228#dispatcher.send("zoom area")[0][1] cp = self.curve.points - visible_x = (self.world_from_screen(0,0)[0], self.world_from_screen(self.size.width, 0)[0]) @@ -345,7 +329,7 @@ """are we one of the music curves (which might be drawn a bit differently)""" return self._isMusic - + def _draw_gradient(self): print "no grad" return @@ -408,18 +392,19 @@ stroke_color='gray70') goocanvas.Text(parent=self.curveGroup, fill_color="white", - font="ubuntu 9", + anchor=gtk.ANCHOR_SOUTH, + font="ubuntu 7", x=x+3, y=ht-20, text=label) def _draw_line(self,visible_points): linepts=[] step=1 - linewidth = 3 - # 800? maybe this should be related to self.width - if len(visible_points) > 800: - step = int(len(visible_points) / 800) - linewidth = .5 + linewidth = 1.5 + maxPointsToDraw = self.size.width / 2 + if len(visible_points) > maxPointsToDraw: + step = int(len(visible_points) / maxPointsToDraw) + linewidth = .8 for p in visible_points[::step]: linepts.append(self.screen_from_world(p)) @@ -459,15 +444,15 @@ ) if worldp[1] == 0: rad += 3 - dot2 = goocanvas.Ellipse(parent=self.curveGroup, - center_x=p[0], - center_y=p[1], - radius_x=rad, - radius_y=rad, - line_width=.8, - stroke_color='darkgreen', - #tags=('curve','point', 'handle%d' % i) - ) + goocanvas.Ellipse(parent=self.curveGroup, + center_x=p[0], + center_y=p[1], + radius_x=rad, + radius_y=rad, + line_width=2, + stroke_color='#00a000', + #tags=('curve','point', 'handle%d' % i) + ) dot.connect("button-press-event", self.dotpress, i) #self.tag_bind('handle%d' % i,"<ButtonPress-1>", # lambda ev,i=i: self.dotpress(ev,i)) @@ -596,6 +581,11 @@ def unselect(self): self.selected_points=[] self.highlight_selected_dots() + + def onScroll(self, widget, event): + t = self.world_from_screen(event.x, 0)[0] + self.zoomControl.zoom_about_mouse( + t, factor=1.5 if event.direction == gtk.gdk.SCROLL_DOWN else 1/1.5) def onRelease(self, widget, event): self.print_state("dotrelease") @@ -610,8 +600,7 @@ please pack self.box """ - def __init__(self, name, curve, slider, knobEnabled): - + def __init__(self, name, curve, slider, knobEnabled, zoomControl): self.box = gtk.HandleBox() self.box.set_border_width(1) @@ -625,7 +614,8 @@ self.setupControls(controls, name, curve, slider) self.curveView = Curveview(curve, knobEnabled=knobEnabled, - isMusic=name in ['music', 'smooth_music']) + isMusic=name in ['music', 'smooth_music'], + zoomControl=zoomControl) cols.pack_start(self.curveView.widget, expand=True) def setupControls(self, controls, name, curve, slider): @@ -711,14 +701,21 @@ """ """ - def __init__(self, curvesVBox, curveset): + def __init__(self, curvesVBox, zoomControlBox, curveset): self.curvesVBox = curvesVBox self.curveset = curveset self.allCurveRows = set() + import light9.curvecalc.zoomcontrol + reload(light9.curvecalc.zoomcontrol) + self.zoomControl = light9.curvecalc.zoomcontrol.ZoomControl() + zoomControlBox.add(self.zoomControl.widget) + self.zoomControl.widget.show_all() + dispatcher.connect(self.add_curve, "add_curve", sender=self.curveset) self.newcurvename = gtk.EntryBuffer("", 0) + return entry = tk.Entry(f, textvariable=self.newcurvename) @@ -728,6 +725,7 @@ dispatcher.connect(self.focus_entry, "focus new curve") + def focus_entry(self): self.entry.focus() @@ -737,7 +735,7 @@ def add_curve(self, name, slider=None, knobEnabled=False): curve = self.curveset.curves[name] - f = CurveRow(name, curve, slider, knobEnabled) + f = CurveRow(name, curve, slider, knobEnabled, self.zoomControl) self.curvesVBox.pack_end(f.box) f.box.show_all() self.allCurveRows.add(f)
--- a/light9/curvecalc/zoomcontrol.py Sun Jun 10 04:03:00 2012 +0000 +++ b/light9/curvecalc/zoomcontrol.py Sun Jun 10 05:33:25 2012 +0000 @@ -1,9 +1,12 @@ from __future__ import division -import Tkinter as tk +import gtk, goocanvas import louie as dispatcher from light9.curvecalc import cursors -class Zoomcontrol(object,tk.Canvas): +class ZoomControl(object): + """ + please pack .widget + """ mintime = 0 @@ -48,51 +51,57 @@ return locals() offset = property(**offset()) - def __init__(self,master,**kw): - self.maxtime=370 + def __init__(self, **kw): + self.widget = goocanvas.Canvas(bounds_padding=5) + self.widget.set_property("background-color", "gray60") + self.widget.set_size_request(-1, 30) + + endtimes = dispatcher.send("get max time") + if endtimes: + self.maxtime = endtimes[0][1] + else: + self.maxtime = 0 + self.start=0 self.end=20 - tk.Canvas.__init__(self,master,width=250,height=30, - relief='raised',bd=1,bg='gray60',**kw) - self.leftbrack = self.create_line(0,0,0,0,0,0,0,0,width=5) - self.rightbrack = self.create_line(0,0,0,0,0,0,0,0,width=5) - self.shade = self.create_rectangle(0,0,0,0,fill='gray70',outline=None) - self.time = self.create_line(0,0,0,0,fill='red',width=2) - self.redrawzoom() - self.bind("<Configure>",self.redrawzoom) - if 0: - # works, but you have to stay in the widget while you drag - self.bind("<ButtonPress-1>",self.press) - self.tag_bind(self.leftbrack,"<B1-Motion>", - lambda ev: self.adjust(ev,'start')) - self.tag_bind(self.rightbrack,"<B1-Motion>", - lambda ev: self.adjust(ev,'end')) - self.tag_bind(self.shade,"<B1-Motion>", - lambda ev: self.adjust(ev,'offset')) - else: - # works better - # bind to buttonpress wasnt working, but Enter is good enough - self.tag_bind(self.leftbrack,"<Enter>", - lambda ev: self.press(ev,'start')) - self.tag_bind(self.shade,"<Enter>", - lambda ev: self.press(ev,'offset')) - self.tag_bind(self.rightbrack,"<Enter>", - lambda ev: self.press(ev,'end')) - self.bind("<B1-Motion>",self.adjust) - self.bind("<ButtonRelease-1>",self.release) + self.root = self.widget.get_root_item() + self.leftbrack = goocanvas.Polyline(parent=self.root, + line_width=5, stroke_color='black') + self.rightbrack = goocanvas.Polyline(parent=self.root, + line_width=5, stroke_color='black') + self.shade = goocanvas.Rect(parent=self.root, + fill_color='gray70', + line_width=.5) + self.time = goocanvas.Polyline(parent=self.root, + line_width=2, + stroke_color='red') + self.redrawzoom() + self.widget.connect("size-allocate", self.redrawzoom) + + self.widget.connect("motion-notify-event", self.adjust) + self.widget.connect("button-release-event", self.release) + self.leftbrack.connect("button-press-event", + lambda i, t, ev: self.press(ev, 'start')) + self.rightbrack.connect("button-press-event", + lambda i, t, ev: self.press(ev, 'end')) + self.shade.connect("button-press-event", + lambda i, t, ev: self.press(ev, 'offset')) - dispatcher.connect(lambda: (self.start,self.end),"zoom area",weak=0) dispatcher.connect(self.input_time,"input time") - dispatcher.connect(lambda maxtime: (setattr(self,'maxtime',maxtime), - self.redrawzoom()), - "max time",weak=0) + dispatcher.connect(self.max_time, "max time") dispatcher.connect(self.zoom_about_mouse, "zoom about mouse") dispatcher.connect(self.see_time, "see time") dispatcher.connect(self.see_time_until_end, "see time until end") dispatcher.connect(self.show_all, "show all") dispatcher.connect(self.zoom_to_range, "zoom to range") self.created=1 + self.lastTime = 0 + + def max_time(self, maxtime): + self.maxtime = maxtime + self.redrawzoom() + def zoom_to_range(self,start,end): self.start = start self.end = end @@ -108,7 +117,10 @@ self.end = t + factor*(self.end-t) self.redrawzoom() - def see_time(self, t): + def see_time(self, t=None): + """defaults to current time""" + if t is None: + t = self.lastTime vis_seconds = self.end - self.start margin = vis_seconds * .1 if t < self.start or t > (self.end - vis_seconds * .3): @@ -116,24 +128,32 @@ self.redrawzoom() - def see_time_until_end(self, t): + def see_time_until_end(self, t=None): + """defaults to current time""" + if t is None: + t = self.lastTime self.start = t - 2 self.end = self.maxtime self.redrawzoom() def input_time(self,val): - t=val - x=self.can_for_t(t) - self.coords(self.time,x,0,x,self.winfo_height()) + self.lastTime = val + x = self.can_for_t(self.lastTime) + self.time.set_property("points", + goocanvas.Points([(x, 0), + (x, self.size.height)])) + def press(self,ev,attr): self.adjustingattr = attr - def release(self,ev): - if hasattr(self,'adjustingattr'): del self.adjustingattr - if hasattr(self,'lastx'): del self.lastx + def release(self, widget, ev): + if hasattr(self,'adjustingattr'): + del self.adjustingattr + if hasattr(self,'lastx'): + del self.lastx - def adjust(self,ev,attr=None): + def adjust(self, widget, ev): if not hasattr(self,'adjustingattr'): return @@ -147,36 +167,63 @@ self.redrawzoom() def can_for_t(self,t): - return (t-self.mintime)/(self.maxtime-self.mintime)*(self.winfo_width()-30)+20 + a, b = self.mintime, self.maxtime + return (t - a) / (b - a) * (self.size.width - 30) + 20 def t_for_can(self,x): - return (x-20)/(self.winfo_width()-30)*(self.maxtime-self.mintime)+self.mintime + a, b = self.mintime, self.maxtime + return (x - 20) / (self.size.width - 30) * (b - a) + a def redrawzoom(self,*args): """redraw pieces based on start/end""" + self.size = self.widget.get_allocation() dispatcher.send("zoom changed") - if not hasattr(self,'created'): return - y1,y2=3,self.winfo_height()-3 + if not hasattr(self,'created'): + return + y1, y2 = 3, self.size.height - 3 lip = 6 scan = self.can_for_t(self.start) ecan = self.can_for_t(self.end) - self.coords(self.leftbrack,scan+lip,y1,scan,y1,scan,y2,scan+lip,y2) - self.coords(self.rightbrack,ecan-lip,y1,ecan,y1,ecan,y2,ecan-lip,y2) - self.coords(self.shade,scan+5,y1+lip,ecan-5,y2-lip) + + self.leftbrack.set_property("points", goocanvas.Points([ + (scan + lip, y1), + (scan, y1), + (scan, y2), + (scan + lip, y2)])) + self.rightbrack.set_property("points", goocanvas.Points([ + (ecan - lip, y1), + (ecan, y1), + (ecan, y2), + (ecan - lip, y2)])) + self.shade.set_properties( + x=scan + 5, + y=y1 + lip, + width=max(0, ecan - 5 - (scan + 5)), + height=max(0, y2 - lip - (y1 + lip))) + self.redrawTics() def redrawTics(self): - self.delete("tics") - lastx=-1000 + if hasattr(self, 'ticsGroup'): + self.ticsGroup.remove() + self.ticsGroup = goocanvas.Group(parent=self.root) + + lastx =- 1000 + for t in range(0,int(self.maxtime)): x = self.can_for_t(t) - if 0 < x < self.winfo_width() and x-lastx>30: - txt=str(t) - if lastx==-1000: - txt=txt+"sec" - self.create_line(x,0,x,15, - tags=('tics',)) - self.create_text(x, self.winfo_height()-1, anchor='s', - text=txt, tags=('tics',), font='arial 7') + if 0 < x < self.size.width and x - lastx > 30: + txt = str(t) + if lastx == -1000: + txt = txt + "sec" + goocanvas.Polyline(parent=self.ticsGroup, + points=goocanvas.Points([(x, 0), (x, 15)]), + line_width=.8, + stroke_color='black') + goocanvas.Text(parent=self.ticsGroup, + x=x, y=self.size.height-1, + anchor=gtk.ANCHOR_SOUTH, + text=txt, + font='ubuntu 7') lastx = x