changeset 1328:e4825767a4bf

fixes to RDF adjusters. put graph load in an element. Ignore-this: dfe48e2553769b4dfe17fc9041798e51
author Drew Perttula <drewp@bigasterisk.com>
date Sat, 04 Jun 2016 07:43:45 +0000
parents d6396679c121
children 44558087d3f6
files light9/web/adjustable.coffee light9/web/graph.coffee light9/web/timeline-elements.html light9/web/timeline.coffee
diffstat 4 files changed, 123 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/light9/web/adjustable.coffee	Sat Jun 04 06:30:33 2016 +0000
+++ b/light9/web/adjustable.coffee	Sat Jun 04 07:43:45 2016 +0000
@@ -45,6 +45,22 @@
   endDrag: () ->
     0
 
+  _editorCoordinates: () -> # vec2 of mouse relative to <l9-t-editor>
+    ev = d3.event.sourceEvent
+
+    if ev.target.tagName == "LIGHT9-TIMELINE-EDITOR"
+      rootElem = ev.target
+    else
+      rootElem = ev.target.closest('light9-timeline-editor')
+
+    # storing root on the object to remember it across calls in case
+    # you drag outside the editor.
+    @root = rootElem.getBoundingClientRect() if rootElem
+    offsetParentPos = $V([ev.pageX - @root.left, ev.pageY - @root.top])
+
+    setMouse(offsetParentPos) # for debugging
+    return offsetParentPos 
+
 class window.AdjustableFloatObservable extends Adjustable
   constructor: (@config) ->
     # config also has:
@@ -54,27 +70,11 @@
 
   _getValue: () ->
     @config.observable()
-
-  _editorCoordinates: () -> # vec2 of mouse relative to <l9-t-editor>
-    ev = d3.event.sourceEvent
-
-    if ev.target.tagName == "LIGHT9-TIMELINE-EDITOR"
-      rootElem = ev.target
-    else
-      rootElem = ev.target.closest('light9-timeline-editor')
-    
-    @root = rootElem.getBoundingClientRect() if rootElem
-    offsetParentPos = $V([ev.pageX - @root.left, ev.pageY - @root.top])
-
-    setMouse(offsetParentPos)
-    return offsetParentPos 
     
   continueDrag: (pos) ->
     # pos is vec2 of pixels relative to the drag start.
 
     epos = @_editorCoordinates()
-    log('offsetParentPos', epos.elements)
-    
     newValue = @config.getValueForPos(epos)
     @config.observable(newValue)
 
@@ -85,15 +85,22 @@
 
 class window.AdjustableFloatObject extends Adjustable
   constructor: (@config) ->
-    # config has graph, subj, pred, ctx, getSuggestedTargetOffset
+    # config also has:
+    #   graph
+    #   subj
+    #   pred
+    #   ctx
+    #   getTargetTransform(value) -> getTarget result for value
+    #   getValueForPos
+
     super(@config)
 
-  _getValue: () -> # for drag math
+  _getValue: () ->
     @config.graph.floatValue(@config.subj, @config.pred)
 
-  getCenter: () ->    
-    $V([100 + 200 * @_getValue(), 200])
-
+  getTarget: () ->
+    @config.getTargetTransform(@_getValue())
+    
   subscribe: (onChange) ->
     @config.graph.subscribe @config.subj, @config.pred, null, (patch) =>
       onChange()
@@ -101,5 +108,5 @@
   continueDrag: (pos) ->
     # pos is vec2 of pixels relative to the drag start
     
-    newValue = @dragStartValue + pos.e(1) / 200
+    newValue = @config.getValueForPos(@_editorCoordinates())
     @config.graph.patchObject(@config.subj, @config.pred, @config.graph.Literal(newValue), @_ctx)
--- a/light9/web/graph.coffee	Sat Jun 04 06:30:33 2016 +0000
+++ b/light9/web/graph.coffee	Sat Jun 04 07:43:45 2016 +0000
@@ -65,9 +65,9 @@
 
   applyAndSendPatch: (patch, cb) ->
     @applyPatch(patch)
-    #console.log('patch to server:')
-    #console.log('  delete:', JSON.stringify(patch.delQuads))
-    #console.log('  add:', JSON.stringify(patch.addQuads))
+    console.log('patch to server:')
+    console.log('  delete:', JSON.stringify(patch.delQuads))
+    console.log('  add:', JSON.stringify(patch.addQuads))
     # post to server
 
   applyPatch: (patch) ->
--- a/light9/web/timeline-elements.html	Sat Jun 04 06:30:33 2016 +0000
+++ b/light9/web/timeline-elements.html	Sat Jun 04 07:43:45 2016 +0000
@@ -2,6 +2,42 @@
 <link rel="import" href="light9-timeline-audio.html">
 <link rel="import" href="/lib/iron-resizable-behavior/iron-resizable-behavior.html">
 
+<dom-module id="rdfdb-synced-graph">
+  <template>
+    <style>
+     :host { display: none; }
+    </style>
+  </template>
+  <script src="graph.js"></script>
+  <script>
+   Polymer({
+       is: "rdfdb-synced-graph",
+       properties: {
+           graph: {type: Object, notify: true}
+       },
+       ready: function() {
+           this.graph = new SyncedGraph('noServerYet', {
+               '': 'http://light9.bigasterisk.com/',
+               'xsd': 'http://www.w3.org/2001/XMLSchema#',
+           });
+           this.graph.loadTrig(
+'          @prefix : <http://light9.bigasterisk.com/> .'+
+'          @prefix dev: <http://light9.bigasterisk.com/device/> .'+
+'          <http://example.com/> {'+
+'            :demoResource0 :startTime 1; :endTime 120 .'+
+'            :demoResource1 :startTime 13; :endTime 16 .'+
+'            :demoResource2 :startTime 38; :endTime 60 .'+
+'            :demoResource3 :startTime 56; :endTime 60 .'+
+'            :demoResource4 :startTime 73; :endTime 74 .'+
+'            :demoResource5 :startTime 91; :endTime 105 .'+
+'            :demoResource6 :startTime 110; :endTime 120 .'+
+'            :demoResource7 :startTime 133; :endTime 140 .'+
+'          }');
+       }
+   });
+  </script>
+</dom-module>
+
 <!-- Whole editor- include this on your page.
      Most coordinates are relative to this element.
    -->
@@ -14,6 +50,7 @@
          flex-direction: column;
          position: relative;
          border: 1px solid black;
+         overflow: hidden;
      }
      light9-timeline-audio {
          width: 100%;
@@ -33,6 +70,9 @@
          }
     </style>
     <div>
+      <rdfdb-synced-graph graph="{{graph}}">
+       
+      </rdfdb-synced-graph>
       timeline editor: song [uri] <button>unlink</button>
       <label><input type="checkbox"> follow player song choice</label>
     </div>
@@ -251,16 +291,6 @@
       <light9-timeline-adjuster dia="{{dia}}" adj="{{item}}"></light9-timeline-adjuster>
     </template>
   </template>
-  <script>
-   Polymer({
-       is: "light9-timeline-adjusters",
-       properties: {
-           adjs: { type: Array },
-           dia: { type: Object }
-           
-       }
-   });
-  </script>
 </dom-module>
 
 <!-- Yellow dotted handle that you can adjust to edit something.
@@ -302,7 +332,7 @@
          -webkit-user-select: none;
      }
      span.empty {
-         width: 30px;
+         width: 30px; /* todo: supposed to fill the whole visible section*/
          height: 13px;
          display: inline-block;
          background: rgba(0,0,0,0);
@@ -337,6 +367,5 @@
 <script src="/lib/d3/build/d3.js"></script>
 <script src="/lib/N3.js/browser/n3-browser.js"></script>
 <script src="/lib/knockout/dist/knockout.js"></script>
-<script src="graph.js"></script>
 <script src="adjustable.js"></script>
 <script src="timeline.js"></script>
--- a/light9/web/timeline.coffee	Sat Jun 04 06:30:33 2016 +0000
+++ b/light9/web/timeline.coffee	Sat Jun 04 07:43:45 2016 +0000
@@ -1,26 +1,12 @@
 log = console.log
-window.graph = new SyncedGraph('noServerYet', {
-'': 'http://light9.bigasterisk.com/',
-'xsd', 'http://www.w3.org/2001/XMLSchema#',
-  })
-  
-window.graph.loadTrig("
-@prefix : <http://light9.bigasterisk.com/> .
-@prefix dev: <http://light9.bigasterisk.com/device/> .
 
-<http://example.com/> {
-  :demoResource :startTime 110; :endTime 120 .
-}
-    ")
-
-    
-      
 Polymer
   is: 'light9-timeline-editor'
   behaviors: [ Polymer.IronResizableBehavior ]
   properties:
     viewState: { type: Object }
     debug: {type: String}
+    graph: {type: Object, notify: true}
     
   attached: ->
     @dia = @$.dia
@@ -36,44 +22,50 @@
       @debug = ko.toJSON(@viewState)
 
     ko.computed =>
-      @fullZoomX = d3.scaleLinear().domain([0, @viewState.zoomSpec.duration()]).range([0, @offsetWidth]) # need to update this if width changes or if duration changes
-      @zoomInX = d3.scaleLinear().domain([@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2()]).range([0, @offsetWidth]) # need to update this if width changes or if duration changes
+      # todo: need to trigger this when @offsetWidth changes, too
+      @fullZoomX = d3.scaleLinear().domain([0, @viewState.zoomSpec.duration()]).range([0, @offsetWidth])
+      @zoomInX = d3.scaleLinear().domain([@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2()]).range([0, @offsetWidth])
+      @$.adjusters.updateAllCoords()
 
     animCursor = () => 
-      #@viewState.cursor.t = 130 + 20 * Math.sin(Date.now() / 2000)
+      @viewState.cursor.t = 130 + 20 * Math.sin(Date.now() / 2000)
       @$.dia.setCursor(@$.audio.offsetTop, @$.audio.offsetHeight,
                        @$.zoomed.$.time.offsetTop,
                        @$.zoomed.$.time.offsetHeight,
                        @fullZoomX, @zoomInX, @viewState.cursor)
 
-      @viewState.zoomSpec.t1(80 + 10 * Math.sin(Date.now() / 3000))
+      #@viewState.zoomSpec.t1(80 + 10 * Math.sin(Date.now() / 3000))
       
-    #setInterval(animCursor, 50)
+    setInterval(animCursor, 50)
 
     setTimeout(() =>
       @adjs = @makeZoomAdjs().concat(@persistDemo())
-    , 100)
+    , 500)
 
   persistDemo: ->
-    ctx = graph.Uri('http://example.com/')
-    return [
-      new AdjustableFloatObject({
-        graph: graph
-        subj: graph.Uri(':demoResource')
-        pred: graph.Uri(':startTime')
+    ctx = @graph.Uri('http://example.com/')
+    adjs = []
+    for n in [0..7]
+      subj = @graph.Uri(':demoResource'+n)
+      adjs.push(new AdjustableFloatObject({
+        graph: @graph
+        subj: subj
+        pred: @graph.Uri(':startTime')
         ctx: ctx
-        getTarget: () => $V([200, 300])
+        getTargetTransform: (value) => $V([@zoomInX(value), 300])
+        getValueForPos: (pos) => @zoomInX.invert(pos.e(1))
         getSuggestedTargetOffset: () => $V([-30, 80])
-      })
-      new AdjustableFloatObject({
-        graph: graph
-        subj: graph.Uri(':demoResource')
-        pred: graph.Uri(':endTime')
+      }))
+      adjs.push(new AdjustableFloatObject({
+        graph: @graph
+        subj: subj
+        pred: @graph.Uri(':endTime')
         ctx: ctx
-        getTarget: () => $V([300, 300])
+        getTargetTransform: (value) => $V([@zoomInX(value), 300])
+        getValueForPos: (pos) => @zoomInX.invert(pos.e(1))
         getSuggestedTargetOffset: () => $V([30, 100])
-      })
-      ]
+      }))
+    return adjs
 
   makeZoomAdjs: ->
     yMid = @$.audio.offsetTop + @$.audio.offsetHeight / 2
@@ -120,6 +112,17 @@
       
     return [left, right, pan]
 
+
+Polymer
+  is: "light9-timeline-adjusters"
+  properties:
+    adjs: { type: Array },
+    dia: { type: Object }
+  updateAllCoords: ->
+    for elem in @querySelectorAll('light9-timeline-adjuster')
+      elem.updateDisplay()
+    
+
 _adjusterSerial = 0
 
 Polymer
@@ -141,7 +144,9 @@
       value: ''
 
   onAdj: (adj) ->
-    @adj.subscribe () =>
+    @adj.subscribe(@updateDisplay.bind(this))
+
+  updateDisplay: () ->
       @spanClass = if @adj.config.emptyBox then 'empty' else ''
       @displayValue = @adj.getDisplayValue()
       center = @adj.getCenter()
@@ -180,20 +185,15 @@
   is: 'light9-timeline-diagram-layer'
   properties: {}
   ready: ->
+    @elemById = {}
     window.setNote = @setNote.bind(this)
     window.setMouse = @setMouse.bind(this)
-    @cursorPath =
-      top: @querySelector('#cursor1')
-      mid: @querySelector('#cursor2')
-      bot: @querySelector('#cursor3')
-    @elemById = {}
 
   setMouse: (pos) ->
     elem = @getOrCreateElem('mouse-x', 'mouse', 'path', {style: "fill:none;stroke:#333;stroke-width:0.5;"})
     elem.setAttribute('d', svgPathFromPoints([[-999, pos.e(2)], [999, pos.e(2)]]))
     elem = @getOrCreateElem('mouse-y', 'mouse', 'path', {style: "fill:none;stroke:#333;stroke-width:0.5;"})
-    elem.setAttribute('d', svgPathFromPoints([[pos.e(1), -999], [pos.e(1), 999]]))
-    
+    elem.setAttribute('d', svgPathFromPoints([[pos.e(1), -999], [pos.e(1), 999]]))   
 
   getOrCreateElem: (uri, groupId, tag, attrs) ->
     elem = @elemById[uri]
@@ -216,6 +216,12 @@
     elem.setAttribute('d', d)
 
   setCursor: (y1, h1, y2, h2, fullZoomX, zoomInX, cursor) ->
+    @cursorPath =
+      top: @querySelector('#cursor1')
+      mid: @querySelector('#cursor2')
+      bot: @querySelector('#cursor3')
+    return if !@cursorPath.top
+    
     xZoomedOut = fullZoomX(cursor.t)
     xZoomedIn = zoomInX(cursor.t)
     @cursorPath.top.setAttribute 'd', svgPathFromPoints([