diff --git a/bin/subcomposer b/bin/subcomposer --- a/bin/subcomposer +++ b/bin/subcomposer @@ -15,22 +15,54 @@ from light9.rdfdb.syncedgraph import Syn from light9.rdfdb import clientsession from light9.tkdnd import initTkdnd, dragSourceRegister, dropTargetRegister +class _NoNewVal(object): + pass + +class Observable(object): + """ + like knockout's observable. Hopefully this can be replaced by a + better python one + """ + def __init__(self, val): + self.val = val + self.subscribers = set() + + def __call__(self, newVal=_NoNewVal): + if newVal is _NoNewVal: + return self.val + self.val = newVal + for s in self.subscribers: + s(newVal) + + def subscribe(self, cb, callNow=True): + """cb is called with new values, and also right now with the + current value unless you opt out""" + self.subscribers.add(cb) + if callNow: + cb(self.val) + +class Local(object): + """placeholder for the local uri that EditChoice does not + manage. Set resourceObservable to Local to indicate that you're + unlinked""" + class EditChoice(tk.Frame): """ + Observable <-> linker UI + widget for tying some UI to a shared resource for editing, or unlinking it (which means associating it with a local resource that's not named or shared). This object does not own the choice of resource; the caller does. """ - def __init__(self, parent, getResource, onSetResource, onSetLocal): - want to pass an observable uri value and an observable isLocal for 2way sync + def __init__(self, parent, graph, resourceObservable): """ - getResource is called to get the URI of the currently + getResource is called to get the URI of the currently """ - self.frame = tk.Frame(parent) - self.subSelection.pack(side='top') - tk.Label(self.subSelection, text="Editing:").pack(side='left') - self.currentSubFrame = tk.Frame(self.subSelection) + self.frame = tk.Frame(parent, relief='raised',border=8) + self.frame.pack(side='top') + tk.Label(self.frame, text="Editing:").pack(side='left') + self.currentSubFrame = tk.Frame(self.frame) self.currentSubFrame.pack(side='left') self.subIcon = tk.Label(self.currentSubFrame, text="sub1", @@ -38,19 +70,37 @@ class EditChoice(tk.Frame): relief='raised', padx=10, pady=10) self.subIcon.pack() + self.resourceObservable = resourceObservable + resourceObservable.subscribe(self.uriChanged) + dragSourceRegister(self.subIcon, 'copy', 'text/uri-list', - lambda: self.currentSub.uri) - def onEv(*args): - print "ev", args + self.resourceObservable) + def onEv(ev): + self.resourceObservable(ev.data) return "link" self.onEv = onEv - - dropTargetRegister(self, onDrop=onEv, - hoverStyle=dict(background="#555500", bd=3, relief='groove')) + + # it would be nice if I didn't receive my own drags here + dropTargetRegister(self.subIcon, typeList=["*"], onDrop=onEv, + hoverStyle=dict(background="#555500", bd=3, + relief='groove')) tk.Label(self.currentSubFrame, text="local data (drag sub here)").pack() - tk.Button(text="unlink", command=self.switchToLocalSub) - + b=tk.Button(text="unlink", command=self.switchToLocalSub) + b.pack() + + + def uriChanged(self, newUri): + print "chg", newUri + # i guess i show the label and icon for this + if newUri is Local: + self.subIcon.config(text="(local)") + else: + self.subIcon.config(text=newUri) + + def switchToLocalSub(self): + self.resourceObservable(Local) + class Subcomposer(tk.Frame): """ @@ -58,6 +108,8 @@ class Subcomposer(tk.Frame): editing. If we don't have a currentSub, then we're actually editing a session-local sub called l9:currentSub + Contains an EditChoice widget + UI actions: - drag a sub uri on here to make it the one we're editing @@ -77,7 +129,7 @@ class Subcomposer(tk.Frame): although maybe that will be stupid. If you change the name before anyone knows about this uri, we could update the current sub's uri to a slug of the new label. - + - rename this sub: not available if you're on a local sub. Sets the label of a named sub. Might update the uri of the named sub if it's new enough that no one else would have that uri. Not @@ -96,8 +148,14 @@ class Subcomposer(tk.Frame): self.levelbox = Levelbox(self, graph) self.levelbox.pack(side='top') - EditChoice(self).frame.pack(side='top') - + currentUri = Observable("http://curr") + + def pc(val): + print "change viewed sub to", val + currentUri.subscribe(pc) + + EditChoice(self, self.graph, currentUri).frame.pack(side='top') + def alltozero(): for lev in self.levelbox.levels: lev.setlevel(0) @@ -139,9 +197,9 @@ class Subcomposer(tk.Frame): out[lev.channelnum] = lev.currentlevel if not out: return [] - + return [out.get(i, 0) for i in range(max(out.keys()) + 1)] - + def sendupdate(self): dmxclient.outputlevels(self.toDmxLevels(), twisted=True) @@ -153,7 +211,7 @@ class EntryCommand(tk.Frame): self.cmd = cmd self.entry = tk.Entry(self) self.entry.pack(side='left', expand=True, fill='x') - + self.entry.bind("", self.action) tk.Button(self, text=verb, command=self.action).pack(side='left')