diff --git a/bin/curvecalc b/bin/curvecalc --- a/bin/curvecalc +++ b/bin/curvecalc @@ -10,12 +10,14 @@ todo: curveview should preserve more obj """ from __future__ import division + from twisted.internet import gtk2reactor -import time,textwrap,os,optparse, urllib2, gtk, gobject +gtk2reactor.install() +from twisted.internet import reactor + +import time, textwrap, os, optparse, urllib2, gtk, gobject import louie as dispatcher - from twisted.python.util import sibpath - from rdflib import URIRef from rdflib import Graph import rdflib @@ -32,28 +34,9 @@ from light9.wavelength import wavelength from light9.uihelpers import toplevelat from light9.namespaces import L9 from light9.curvecalc.subterm import read_all_subs, savekey, graphPathForSubterms -from light9.curvecalc.subtermview import makeSubtermCommandRow, add_one_subterm +from light9.curvecalc.subtermview import add_one_subterm from light9.curvecalc.output import Output -def makeStatusLines(master): - """various labels that listen for dispatcher signals""" - for signame,textfilter in [ - ('input time',lambda t: "%.2fs"%t), - ('output levels', - lambda levels: textwrap.fill("; ".join(["%s:%.2f"%(n,v) - for n,v in - levels.items()[:5] - if v>0]),70)), - ('update period',lambda t: "%.1fms"%(t*1000)), - ('update status',lambda t: str(t)), - ]: - l = tk.Label(master, anchor='w', justify='left', text='%s:' % signame) - l.pack(side='top',fill='x') - dispatcher.connect(lambda val,l=l,sn=signame,tf=textfilter: - l.config(text=sn+": "+tf(val)), - signame, weak=False) - - def makeGraph(): graphOrig = showconfig.getGraph() graph = Graph() # a copy, since we're going to add subs into it @@ -62,62 +45,8 @@ def makeGraph(): read_all_subs(graph) return graph -def setupKeyBindings(root, song, subterms, curveset): - root.bind("", - lambda *args: savekey(song, subterms, curveset)) - root.bind("", lambda evt: dispatcher.send('reload all subs')) - root.bind("", - lambda evt: dispatcher.send('focus new subterm')) - root.bind("", lambda evt: dispatcher.send('focus new curve')) - root.bind("",lambda ev: reactor.stop) - root.bind("",lambda ev: reactor.stop) - root.protocol('WM_DELETE_WINDOW', reactor.stop) - -def setupMenubar(barFrame, root, song, subterms, curveset): - class newMenu(object): - def __init__(self, name): - self.name = name - def __enter__(self): - m = tk.Menubutton(barFrame, text=self.name) - m.pack(side='left') - mm = tk.Menu(m) - m.config(menu=mm) - return mm - def __exit__(self, type, value, traceback): - return False - - def notImpl(*args): - print "sorry, menu command binding isn't done yet. Use the keyboard shortcut" - - with newMenu("Curvecalc") as m: - m.add_command(label='Save', underline=0, accelerator="Ctrl+s", - command=lambda *args: savekey(song, subterms, curveset)) - m.add_command(label='Quit', command=root.destroy) - - with newMenu("View") as m: - m.add_command(label="See current time", accelerator="Esc", command=notImpl) - m.add_command(label="See from current time -> end", accelerator="Shift+Esc", command=notImpl) - m.add_command(label="Zoom all", accelerator="Ctrl+Esc", command=notImpl) - m.add_command(label="Zoom in", accelerator="Wheel up", command=notImpl) - m.add_command(label="Zoom out", accelerator="Wheel down", command=notImpl) - - with newMenu("Playback") as m: - m.add_command(label="Play/pause at mouse", accelerator="Ctrl+P", command=notImpl) - - with newMenu("Points") as m: - m.add_command(label="Delete", accelerator="Del", command=notImpl) - - -def createHelpLines(root): - for helpline in ["Mousewheel zoom; C-p play/pause music at mouse", - "Curve point bindings: B1 drag point; C-B1 curve add point; S-B1 sketch points; 1..5 add point at time; B1 drag select points", - "Available in functions: nsin/ncos period=amp=1; within(a,b) bef(x) aft(x) compare to time; smoove(x) cubic smoothstep; chan(name); curvename(t) eval curve"]: - line = tk.Label(root, text=helpline, font="Helvetica -12 italic", - anchor='w') - line.pack(side='top',fill='x') - class Main(object): - def __init__(self, graph, song, curveset, subterms): + def __init__(self, graph, opts, song, curveset, subterms): self.graph = graph wtree = gtk.Builder() wtree.add_from_file(sibpath(__file__, "../light9/curvecalc/curvecalc.glade")) @@ -125,14 +54,36 @@ class Main(object): mainwin.connect("destroy", gtk.main_quit) wtree.connect_signals(self) mainwin.show_all() - #gobject.timeout_add(1000 // framerate, self.updateLoop) + mainwin.connect("delete-event", lambda *args: reactor.crash()) mainwin.set_title("curvecalc - %s" % graph.label(song)) - + mainwin.parse_geometry("1000x1000") + self.add_subterms_for_song(song, curveset, subterms, wtree.get_object("subterms") ) + + curvesetView = Curvesetview(wtree.get_object("curves"), curveset) + + # curvesetview must already exist, since this makes 'add_curve' + # signals for all the initial curves + curveset.load(basename=os.path.join( + showconfig.curvesDir(), + showconfig.songFilenameFromURI(song)), + skipMusic=opts.skip_music) + # this is scheduled after some tk shuffling, to try to minimize + # the number of times we redraw the curve at startup. If tk is + # very slow, it's ok. You'll just get some wasted redraws. + curvesetView.goLive() + + self.makeStatusLines(wtree.get_object("status")) + + #zc = Zoomcontrol(root) + + def onSave(self, *args): + savekey(song, subterms, curveset) + def add_subterms_for_song(self, song, curveset, subterms, master): for st in self.graph.objects(song, L9['subterm']): log.info("song %s has subterm %s", song, st) @@ -144,6 +95,46 @@ class Main(object): self.graph.value(st, L9['expression'])) master.show_all() + def makeStatusLines(self, master): + """various labels that listen for dispatcher signals""" + for row, (signame, textfilter) in enumerate([ + ('input time', lambda t: "%.2fs"%t), + ('output levels', + lambda levels: textwrap.fill("; ".join(["%s:%.2f"%(n,v) + for n,v in + levels.items()[:5] + if v>0]),70)), + ('update period', lambda t: "%.1fms"%(t*1000)), + ('update status', lambda x: str(x)), + ]): + key = gtk.Label("%s:" % signame) + value = gtk.Label("") + master.resize(row + 1, 2) + master.attach(key, 0, 1, row, row + 1) + master.attach(value, 1, 2, row, row + 1) + key.set_alignment(1, 0) + value.set_alignment(0, 0) + + dispatcher.connect(lambda val, value=value, tf=textfilter: + value.set_text(tf(val)), + signame, weak=False) + master.show_all() + + + def onReloadSubs(self): # wants to be ctrl-r too + dispatcher.send('reload all subs') + + def onAddSubterm(self): + uri = L9['sub/%s' % newname.get()] + graph.add((uri, RDF.type, L9.Subterm)) + graph.add((uri, RDFS.label, Literal(newname.get()))) + add_one_subterm(graph, uri, + curveset, subterms, ssv, None) + if evt.state & 4: # control key modifier + curveset.new_curve(newname.get()) + newname.set('') + + def main(): startTime = time.time() parser = optparse.OptionParser() @@ -188,63 +179,15 @@ def main(): maxtime = wavelength(musicfilename) dispatcher.connect(lambda: maxtime, "get max time", weak=False) - start = Main(graph, song, curveset, subterms) - #gtk2reactor.install() + start = Main(graph, opts, song, curveset, subterms) + dispatcher.send("max time", maxtime=maxtime) + dispatcher.send("show all") + if opts.startup_only: log.debug("quitting now because of --startup-only") return - gtk.main() - 1/0 - ################### - - - if 'fixed top rows': - zc = Zoomcontrol(root) - zc.pack(side='top', fill='x') - - if 'panes': - panes = tk.PanedWindow(root, height=1) - panes.add('curvesetView') - panes.add('subterms') - panes.pack(side='top', fill='both', expand=True) - - curvesetView = Curvesetview(panes.subwidget('curvesetView'), curveset, - height=600) - curvesetView.pack(fill='both', expand=True) - - subtermArea = tk.Frame(panes.subwidget('subterms'), height=100) - subtermArea.pack(fill='both', expand=True) - - subtermScroll = tk.ScrolledWindow(subtermArea) - subtermScroll.pack(fill='both') - - if 'fixed bottom rows': - makeSubtermCommandRow(root, curveset, subterms, root, subtermArea, - graph).pack(side='top', fill='x') - makeStatusLines(root) - - helpBox = tk.Frame(root) - createHelpLines(helpBox) - helpBox.pack(side='top', fill='x') - - setupKeyBindings(root, song, subterms, curveset) - setupMenubar(menubar, root, song, subterms, curveset) - - # curvesetview must already exist, since this makes 'add_curve' - # signals for all the initial curves - curveset.load(basename=os.path.join(showconfig.curvesDir(), - showconfig.songFilenameFromURI(song)), - skipMusic=opts.skip_music) - - dispatcher.send("max time",maxtime=maxtime) - dispatcher.send("show all") - - # this is scheduled after some tk shuffling, to try to minimize - # the number of times we redraw the curve at startup. If tk is - # very slow, it's ok. You'll just get some wasted redraws. - reactor.callLater(.1, curvesetView.goLive) - + reactor.run() main() diff --git a/light9/curvecalc/curve.py b/light9/curvecalc/curve.py --- a/light9/curvecalc/curve.py +++ b/light9/curvecalc/curve.py @@ -114,7 +114,7 @@ class Sliders(BCF2000): self.knobButtonCallback(int(name[11:])) -class Curveset: +class Curveset(object): curves = None # curvename : curve def __init__(self, sliders=False): @@ -172,7 +172,7 @@ class Curveset: num = None dispatcher.send("add_curve", slider=num, knobEnabled=num is not None, - sender=self,name=name) + sender=self, name=name) def globalsdict(self): return self.curves.copy() diff --git a/light9/curvecalc/curvecalc.glade b/light9/curvecalc/curvecalc.glade --- a/light9/curvecalc/curvecalc.glade +++ b/light9/curvecalc/curvecalc.glade @@ -2,6 +2,8 @@ + 530 + 380 False @@ -24,6 +26,7 @@ False + gtk-save False True False @@ -32,12 +35,6 @@ - - True - False - - - gtk-quit False @@ -47,16 +44,6 @@ True - - - gtk-about - False - True - False - True - True - - @@ -113,6 +100,57 @@ False _View True + + + True + False + + + False + True + False + See current time (esc) + True + + + + + False + True + False + See from current time -> end (S-Esc) + True + + + + + False + True + False + Zoom all (C-Esc) + True + + + + + False + True + False + Zoom in (wheel up) + True + + + + + False + True + False + Zoom out (wheel down) + True + + + + @@ -131,7 +169,7 @@ False True False - Play/pause + Play/pause (C-p) True @@ -155,7 +193,7 @@ False True False - menuitem6 + Delete (del) True @@ -171,155 +209,169 @@ - + + 200 True - False + True - - True - False - - - True - False - new curve named (C-N): - - - True - True - 0 - - - - - True - True - - False - False - - - True - True - 1 - - - - - False - True - 0 - - - - + True True - never + True - + + 100 True False - + True False - + + True + False + new curve named (C-N): + + + True + True + 0 + + + + + True + True + + True + False + False + + + True + True + 1 + + + + + False + True + 0 + + + + + True + True + never + + True False - + True False - 5 - 0 - 0 - out + + + - - True - False - - - True - False - curve 'music' - - - False - False - 0 - - - - - True - False - - - C - False - True - True - False - False - 0.5 - True - - - True - True - 0 - - - - - M - False - True - True - False - False - 0.5 - True - - - True - True - 1 - - - - - False - False - 1 - - - + - + - - False - False - 0 - + + + + + True + True + 1 + + + + + + + True + False + Curves + + + + + False + True + + + + + True + True + True + + + True + False + + + True + True + always + + + True + False + natural + none - + + 90 True False - samplecurve.png + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - True - True - 1 - @@ -331,18 +383,71 @@ - + + True + False + + + Reload subs (C-r) + False + True + True + True + False + image2 + + + + False + True + 0 + + + + + True + False + new subterm named (C-Enter for curve too, C-n for focus): + + + False + True + 1 + + + + + True + True + + True + + + False + True + 2 + + + + + False + False + 1 + - - - + + + + + True + False + Subterms - True - True - 1 + True + True @@ -353,194 +458,47 @@ - - True - True - True - - - True - True - always - - - True - False - none - - - True - False - 2 - - - - - - - - - - - - - - - True - False - Subterms - - - - - True - True - 2 - - - True False - + True False + 0 + none - + True False + 2 - - True - False - input time: - - - True - True - 0 - + - - True - False - - - True - True - 1 - + - - - True - True - 0 - - - - - True - False - - True - False - output levels: - - - True - True - 0 - + - - True - False - - - True - True - 1 - + + + + + + + - - True - True - 1 - - - + + True False - - - True - False - update period: - - - True - True - 0 - - - - - True - False - - - True - True - 1 - - + Status + True - - True - True - 2 - - - - - True - False - - - True - False - update status: - - - True - True - 0 - - - - - True - False - - - True - True - 1 - - - - - True - True - 3 - @@ -605,6 +563,20 @@ False False 5 + 2 + + + + + True + True + False + word + help + + + False + False 3 @@ -612,6 +584,141 @@ + + Mousewheel zoom; C-p play/pause music at mouse +Curve point bindings: B1 drag point; C-B1 curve add point; S-B1 sketch points; 1..5 add point at time; B1 drag select points +Available in functions: nsin/ncos period=amp=1; within(a,b) bef(x) aft(x) compare to time; smoove(x) cubic smoothstep; chan(name); curvename(t) eval curve + + + True + False + gtk-refresh + + + False + + + True + False + + + True + False + + + True + False + + + True + False + 5 + 0 + 0 + out + + + True + False + + + True + False + curve 'music' + + + False + False + 0 + + + + + True + False + + + C + False + True + True + False + False + 0 + True + + + True + True + 0 + + + + + M + False + True + True + False + False + 0 + True + + + True + True + 1 + + + + + False + False + 1 + + + + + + + + + + False + False + 0 + + + + + True + False + gtk-media-forward + + + True + True + 1 + + + + + + + True + True + 0 + + + + + + + + + + + song01(t) diff --git a/light9/curvecalc/curveview.py b/light9/curvecalc/curveview.py --- a/light9/curvecalc/curveview.py +++ b/light9/curvecalc/curveview.py @@ -1,6 +1,6 @@ from __future__ import division import math, time, logging -import Tix as tk +import gtk, goocanvas import louie as dispatcher from light9.curvecalc.zoomcontrol import RegionZoom from light9.curvecalc import cursors @@ -67,19 +67,22 @@ class Sketch: self.curveview.update_curve() -class Curveview(tk.Canvas): - def __init__(self, master, curve, knobEnabled=False, isMusic=False, **kw): +class Curveview(object): + """ + graphical curve widget only. Please pack .widget + """ + def __init__(self, curve, knobEnabled=False, isMusic=False, **kw): """knobEnabled=True highlights the previous key and ties it to a hardware knob""" + self.widget = goocanvas.Canvas() + self.root = self.widget.get_root_item() + self.redrawsEnabled = False self.curve = curve self.knobEnabled = knobEnabled self._isMusic = isMusic self._time = 0 self.last_mouse_world = None - tk.Canvas.__init__(self,master,width=10,height=10, - relief='sunken',bd=1, - closeenough=5,takefocus=1, **kw) self.selected_points=[] # idx of points being dragged # self.bind("",self.focus) dispatcher.connect(self.input_time, "input time") @@ -92,64 +95,70 @@ class Curveview(tk.Canvas): if self.knobEnabled: dispatcher.connect(self.knob_in, "knob in") dispatcher.connect(self.slider_in, "set key") - self.bind("",self.update_curve) - for x in range(1, 6): - def add_kb_marker_point(evt, x=x): - self.add_point((self.current_time(), (x - 1) / 4.0)) + print "setup alloc", self.__dict__ + self.widget.connect("size-allocate", self.update_curve) + if 0: - self.bind("" % x, add_kb_marker_point) + for x in range(1, 6): + def add_kb_marker_point(evt, x=x): + self.add_point((self.current_time(), (x - 1) / 4.0)) + + self.bind("" % 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("" % butnum, onMouseWheel) - self.bind("", lambda ev: - dispatcher.send("see time", - t=self.current_time())) - self.bind("", lambda ev: - dispatcher.send("see time until end", - t=self.current_time())) - self.bind("", lambda ev: dispatcher.send("show all")) - self.bind("", lambda ev: - dispatcher.send("music seek", - t=self.world_from_screen(ev.x,0)[0])) + 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("" % butnum, onMouseWheel) + self.bind("", lambda ev: + dispatcher.send("see time", + t=self.current_time())) + self.bind("", lambda ev: + dispatcher.send("see time until end", + t=self.current_time())) + self.bind("", lambda ev: dispatcher.send("show all")) + self.bind("", lambda ev: + dispatcher.send("music seek", + t=self.world_from_screen(ev.x,0)[0])) - self.bind("", - self.dotmotion, add=True) - self.bind("", - self.dotrelease, add=True) + self.bind("", + self.dotmotion, add=True) + self.bind("", + self.dotrelease, add=True) # this binds on c-a-b1, etc - self.regionzoom = RegionZoom(self, self.world_from_screen, - self.screen_from_world) + if 0: + self.regionzoom = RegionZoom(self, self.world_from_screen, + self.screen_from_world) self.sketch = None # an in-progress sketch - self.bind("", self.sketch_press) - self.bind("", self.sketch_motion) - self.bind("", self.sketch_release) + if 0: + self.bind("", self.sketch_press) + self.bind("", self.sketch_motion) + self.bind("", self.sketch_release) self.dragging_dots = False self.selecting = False - self.bind("",#"", - self.select_press, add=True) - self.bind("", self.select_motion, add=True) - self.bind("", #"", - self.select_release, add=True) + if 0: + self.bind("",#"", + self.select_press, add=True) + self.bind("", self.select_motion, add=True) + self.bind("", #"", + self.select_release, add=True) - self.bind("", self.check_deselect, add=True) + self.bind("", self.check_deselect, add=True) - self.bind("", lambda *args: self.curve.toggleMute()) - self.bind("", lambda *args: dispatcher.send('toggle collapse', - sender=self.curve)) + self.bind("", lambda *args: self.curve.toggleMute()) + self.bind("", lambda *args: dispatcher.send('toggle collapse', + sender=self.curve)) def goLive(self): """this is for startup performance only, since the curves were @@ -241,13 +250,13 @@ class Curveview(tk.Canvas): def screen_from_world(self,p): start,end = self.zoom - ht = self.height - return (p[0]-start)/(end-start)*self.width, (ht-5)-p[1]*(ht-10) + ht = self.size.height + return (p[0]-start)/(end-start)*self.size.width, (ht-5)-p[1]*(ht-10) def world_from_screen(self,x,y): start,end = self.zoom - ht = self.height - return x/self.width*(end-start)+start, ((ht-5)-y)/(ht-10) + ht = self.size.height + return x/self.size.width*(end-start)+start, ((ht-5)-y)/(ht-10) def input_time(self, val, forceUpdate=False): # i tried various things to make this not update like crazy, @@ -255,7 +264,7 @@ class Curveview(tk.Canvas): # scared that things were getting built in a funny order. #if self._time == val: # return - + return t=val pts = self.screen_from_world((val,0))+self.screen_from_world((val,1)) self.delete('timecursor') @@ -273,29 +282,33 @@ class Curveview(tk.Canvas): tags=('knob',)) dispatcher.send("knob out", value=prevKey[1], curve=self.curve) - def update_curve(self,*args): - if not self.redrawsEnabled: + def update_curve(self, _widget=None, _rect=None): + print "update curve on", self, id(self), self.__dict__ + if not getattr(self, 'redrawsEnabled', False): return - self.width, self.height = self.winfo_width(), self.winfo_height() + self.size = self.widget.get_allocation() - self.zoom = dispatcher.send("zoom area")[0][1] + self.zoom = 0, 3#dispatcher.send("zoom area")[0][1] cp = self.curve.points visible_x = (self.world_from_screen(0,0)[0], - self.world_from_screen(self.width, 0)[0]) + self.world_from_screen(self.size.width, 0)[0]) visible_idxs = self.curve.indices_between(visible_x[0], visible_x[1], beyond=1) visible_points = [cp[i] for i in visible_idxs] - - self.delete('curve') + + if getattr(self, 'curveGroup', None): + self.curveGroup.remove() + self.curveGroup = goocanvas.Group(parent=self.root) - if self.curve.muted: - self['bg'] = 'grey20' - else: - self['bg'] = 'black' + if 0: + if self.curve.muted: + self['bg'] = 'grey20' + else: + self['bg'] = 'black' - if self.height < 40: + if self.size.height < .40: self._draw_gradient() else: self._draw_markers(visible_x) @@ -312,11 +325,13 @@ class Curveview(tk.Canvas): return self._isMusic def _draw_gradient(self): + print "no grad" + return t1 = time.time() gradient_res = 6 if self.is_music() else 3 startX = startColor = None rects = 0 - for x in range(0, self.width, gradient_res): + for x in range(0, self.size.width, gradient_res): wx = self.world_from_screen(x,0)[0] mag = self.curve.eval(wx, allow_muting=False) if self.curve.muted: @@ -334,7 +349,7 @@ class Curveview(tk.Canvas): startColor = color if startColor is not None: - self._draw_gradient_slice(startX, self.width, startColor) + self._draw_gradient_slice(startX, self.size.width, startColor) rects += 1 log.debug("redraw %s rects in %.02f ms", rects, 1000 * (time.time()-t1)) @@ -343,6 +358,7 @@ class Curveview(tk.Canvas): fill=color, width=0, tags='curve') def _draw_markers(self,visible_x): + return mark = self._draw_one_marker mark(0,"0") @@ -360,8 +376,8 @@ class Curveview(tk.Canvas): def _draw_one_marker(self,t,label): x = self.screen_from_world((t,0))[0] - ht = self.height - if not 0 <= x < self.winfo_width(): + ht = self.size.height + if not 0 <= x < self.size.width: return x = max(5, x) # cheat left-edge stuff onscreen self.create_line(x, ht, @@ -380,26 +396,32 @@ class Curveview(tk.Canvas): step = int(len(visible_points)/800) linewidth=1 for p in visible_points[::step]: - linepts.extend(self.screen_from_world(p)) + linepts.append(self.screen_from_world(p)) if len(linepts)<4: return if self.curve.muted: fill = 'grey34' else: fill = 'white' - kwargs = dict(width=linewidth, tags='curve', fill=fill) - line = self.create_line(*linepts, **kwargs) + goocanvas.Polyline(parent=self.curveGroup, + points=goocanvas.Points(linepts), + width=linewidth, + stroke_color=fill, + ) + # canvas doesnt have keyboard focus, so i can't easily change the # cursor when ctrl is pressed # def curs(ev): # print ev.state # self.bind("",curs) # self.bind("",lambda ev: curs(0)) - self.tag_bind(line,"",self.new_point_at_mouse) + if 0: + self.tag_bind(line,"",self.new_point_at_mouse) def _draw_handle_points(self,visible_idxs,visible_points): + return for i,p in zip(visible_idxs,visible_points): rad=3 worldp = p @@ -539,61 +561,69 @@ class Curveview(tk.Canvas): self.last_mouse_world = None self.dragging_dots = False -class CurveRow(tk.Frame): +class CurveRow(object): """ one of the repeating curve rows (including widgets on the left) - """ - def __init__(self, master, name, curve, slider, knobEnabled): - tk.Frame.__init__(self, master, relief='raised', bd=1) - self.collapsed = tk.IntVar() - self.muted = tk.IntVar() + please pack self.box + """ + def __init__(self, name, curve, slider, knobEnabled): - labelFont = "arial 8" + self.box = gtk.HandleBox() - leftside = tk.Frame(self) - leftside.pack(side='left') + cols = gtk.HBox() + self.box.add(cols) + + controls = gtk.Frame() + controls.set_size_request(115, -1) + controls.set_shadow_type(gtk.SHADOW_OUT) + cols.pack_start(controls, expand=False) + self.setupControls(controls, name, curve, slider) - self.curveView = Curveview(self, curve, knobEnabled=knobEnabled, + self.curveView = Curveview(curve, knobEnabled=knobEnabled, isMusic=name in ['music', 'smooth_music']) - self.curveView.pack(side='left', fill='both', expand=True) - self.curveView.config(height=100) - + cols.pack_start(self.curveView.widget, expand=True) + + def setupControls(self, controls, name, curve, slider): + box = gtk.VBox() + controls.add(box) + txt = "curve '%s'" % name if len(name) > 7: txt = name - curve_name_label = tk.Label(leftside, text=txt, font=labelFont,width=15) - curve_name_label.pack(side='top') + curve_name_label = gtk.Label(txt) + box.pack_start(curve_name_label) + - bools = tk.Frame(leftside) - bools.pack(side='top') - collapsed_cb = tk.Checkbutton(bools, text="C", - font=labelFont, variable=self.collapsed) - collapsed_cb.pack(side='left') - self.collapsed.trace('w', self.update_ui_to_collapsed_state) +# self.collapsed = tk.IntVar() +# self.muted = tk.IntVar() + + bools = gtk.HBox() + box.pack_start(bools) + collapsed_cb = gtk.CheckButton("C") + bools.pack_start(collapsed_cb) + #self.collapsed.trace('w', self.update_ui_to_collapsed_state) dispatcher.connect(self.toggleCollapsed, "toggle collapse", sender=curve) - self.default_bg = leftside['bg'] - muted_cb = tk.Checkbutton(bools, text="M", font=labelFont, - variable=self.muted) - muted_cb.pack(side='left') - self.muted.trace('w', self.sync_mute_to_curve) + muted_cb = gtk.CheckButton("M") + + bools.pack_start(muted_cb) + #self.muted.trace('w', self.sync_mute_to_curve) dispatcher.connect(self.mute_changed, 'mute changed', sender=curve) self.sliderLabel = None if slider is not None: # slider should have a checkbutton, defaults to off for # music tracks - self.sliderLabel = tk.Label(leftside, text="Slider %s" % slider, - fg='#800000', font=labelFont) - self.sliderLabel.pack(side='top') + self.sliderLabel = gtk.Label("Slider %s" % slider) + box.pack_start(self.sliderLabel) # widgets that need recoloring when we tint the row: - self.widgets = [leftside, collapsed_cb, muted_cb, - curve_name_label, self] - if self.sliderLabel: - self.widgets.append(self.sliderLabel) + #self.widgets = [leftside, collapsed_cb, muted_cb, + # curve_name_label, self] + #if self.sliderLabel: + # self.widgets.append(self.sliderLabel) def toggleCollapsed(self): self.collapsed.set(not self.collapsed.get()) @@ -633,18 +663,20 @@ class CurveRow(tk.Frame): self.update_mute_look() -class Curvesetview(tk.ScrolledWindow): - def __init__(self, master, curveset, **kw): +class Curvesetview(object): + """ + + """ + def __init__(self, curvesVBox, curveset): + self.curvesVBox = curvesVBox self.curveset = curveset self.allCurveRows = set() - tk.ScrolledWindow.__init__(self,master,**kw) + + dispatcher.connect(self.add_curve, "add_curve", sender=self.curveset) - f = tk.Frame(self.window,relief='raised',bd=1) - f.pack(side='top',fill='x') - tk.Label(f, text="new curve named: (C-N)").pack(side='left') - - self.newcurvename = tk.StringVar() - + self.newcurvename = gtk.EntryBuffer("", 0) + return + entry = tk.Entry(f, textvariable=self.newcurvename) entry.pack(side='left', fill='x',exp=1) entry.bind("", self.new_curve) @@ -652,7 +684,7 @@ class Curvesetview(tk.ScrolledWindow): def focus_entry(): entry.focus() - dispatcher.connect(self.add_curve, "add_curve", sender=self.curveset) + dispatcher.connect(focus_entry, "focus new curve", weak=False) def new_curve(self, event): @@ -661,11 +693,13 @@ class Curvesetview(tk.ScrolledWindow): def add_curve(self, name, slider=None, knobEnabled=False): curve = self.curveset.curves[name] - f = CurveRow(self.window, name, curve, slider, knobEnabled) - f.pack(side='top', fill='both') + f = CurveRow(name, curve, slider, knobEnabled) + self.curvesVBox.pack_end(f.box) + f.box.show_all() self.allCurveRows.add(f) f.curveView.goLive() + def goLive(self): """for startup performance, none of the curves redraw themselves until this is called once (and then they're normal)""" diff --git a/light9/curvecalc/musicaccess.py b/light9/curvecalc/musicaccess.py --- a/light9/curvecalc/musicaccess.py +++ b/light9/curvecalc/musicaccess.py @@ -63,7 +63,7 @@ class Music: return done def _bodyReceived(self, data): - dispatcher.send("input time",val=data['t']) + dispatcher.send("input time", val=data['t']) return data['t'] # pass along to the real receiver def seekplay_or_pause(self,t): diff --git a/light9/curvecalc/output.py b/light9/curvecalc/output.py --- a/light9/curvecalc/output.py +++ b/light9/curvecalc/output.py @@ -22,16 +22,15 @@ class Output: def updateerr(self,e): print e.getTraceback() - dispatcher.send("update status",val=e.getErrorMessage()) + dispatcher.send("update status", val=e.getErrorMessage()) if self.later and not self.later.cancelled and not self.later.called: self.later.cancel() - self.later = reactor.callLater(1,self.update) + self.later = reactor.callLater(1, self.update) def update2(self,t): # spot alsa soundcard offset is always 0, we get times about a # second ahead of what's really getting played #t = t - .7 - dispatcher.send("update status", val="ok: receiving time from music player") if self.later and not self.later.cancelled and not self.later.called: diff --git a/light9/curvecalc/subtermview.py b/light9/curvecalc/subtermview.py --- a/light9/curvecalc/subtermview.py +++ b/light9/curvecalc/subtermview.py @@ -68,43 +68,9 @@ def add_one_subterm(graph, subUri, curve stv = Subtermview(graph, term) y = master.get_property('n-rows') master.resize(y + 1, columns=2) - master.attach(stv.label, 0, 1, y, y + 1, xoptions=0) - master.attach(stv.exprView, 1, 2, y, y + 1) + master.attach(stv.label, 0, 1, y, y + 1, xoptions=0, yoptions=0) + master.attach(stv.exprView, 1, 2, y, y + 1, yoptions=0) return term - -def makeSubtermCommandRow(master, curveset, subterms, root, ssv, graph): - """ - the row that starts with 'reload subs' button - """ - f=tk.Frame(master,relief='raised',bd=1) - newname = tk.StringVar() - - def add_cmd(evt): - uri = L9['sub/%s' % newname.get()] - graph.add((uri, RDF.type, L9.Subterm)) - graph.add((uri, RDFS.label, Literal(newname.get()))) - add_one_subterm(graph, uri, - curveset, subterms, ssv, None) - if evt.state & 4: # control key modifier - curveset.new_curve(newname.get()) - newname.set('') - - def reload_subs(): - dispatcher.send('reload all subs') - - tk.Button(f, text="reload subs (C-r)", - command=reload_subs).pack(side='left') - tk.Label(f, text="new subterm named (C-Enter for curve too, C-n for focus):").pack(side='left') - entry = tk.Entry(f, textvariable=newname) - entry.pack(side='left', fill='x', exp=1) - entry.bind("", add_cmd) - - def focus_entry(): - entry.focus() - - dispatcher.connect(focus_entry, "focus new subterm", weak=False) - - return f