Changeset - bf728997bfde
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 12 years ago 2013-01-12 20:51:20
drewp@bigasterisk.com
start the observable between editchoice and the editor
Ignore-this: 23094325e4b13df6a7b5d3b1325d509d
1 file changed with 79 insertions and 21 deletions:
0 comments (0 inline, 0 general)
bin/subcomposer
Show inline comments
 
@@ -12,55 +12,107 @@ from light9.dmxchanedit import Levelbox
 
from light9 import dmxclient, Patch, Submaster, showconfig, prof
 
from light9.uihelpers import toplevelat
 
from light9.rdfdb.syncedgraph import SyncedGraph
 
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",
 
                                borderwidth=2,
 
                                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):
 
    """
 
    <session> l9:currentSub ?sub is the URI of the sub we're tied to for displaying and
 
    editing. If we don't have a currentSub, then we're actually
 
    editing a session-local sub called <session> l9:currentSub <sessionLocalSub>
 

	
 
    Contains an EditChoice widget
 

	
 
    UI actions:
 
    - drag a sub uri on here to make it the one we're editing
 

	
 
    - button to clear the currentSub (putting it back to
 
      sessionLocalSub, and also resetting sessionLocalSub to be empty
 
      again)
 
@@ -74,13 +126,13 @@ class Subcomposer(tk.Frame):
 
      pretty distinct, readable, and based on the lights that are
 
      on. If you're on a named sub, the new one starts with a
 
      'namedsub 2' style name. The uri can also be with a '2' suffix,
 
      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
 
      sure where we measure that 'new enough' value. Maybe track if
 
      the sub has 'never been dragged out of this subcomposer
 
      session'? But subs will also show up in other viewers and
 
@@ -93,14 +145,20 @@ class Subcomposer(tk.Frame):
 
        self.session = session
 
        self.currentSub = Submaster.PersistentSubmaster(graph, URIRef('http://hello'))
 

	
 
        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)
 

	
 
        tk.Button(self, text="all to zero", command=alltozero).pack(side='top')
 

	
 
@@ -136,27 +194,27 @@ class Subcomposer(tk.Frame):
 
        # the 0 element)
 
        out = {}
 
        for lev in self.levelbox.levels:
 
            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)
 

	
 

	
 
class EntryCommand(tk.Frame):
 
    def __init__(self, master, verb="Save", cmd=None):
 
        tk.Frame.__init__(self, master, bd=2, relief='raised')
 
        tk.Label(self, text="Sub name:").pack(side='left')
 
        self.cmd = cmd
 
        self.entry = tk.Entry(self)
 
        self.entry.pack(side='left', expand=True, fill='x')
 
        
 

	
 
        self.entry.bind("<Return>", self.action)
 
        tk.Button(self, text=verb, command=self.action).pack(side='left')
 

	
 
    def action(self, *args):
 
        subname = self.entry.get()
 
        self.cmd(subname)
0 comments (0 inline, 0 general)