changeset 1730:7d2d20f06d1d

cleanup viewstate change notifications. Use ko.computed more. Ignore-this: 3da1a8c7a09f05238ce3c640b05347b4
author Drew Perttula <drewp@bigasterisk.com>
date Sat, 12 May 2018 23:02:26 +0000
parents 338ea27aeb23
children e06c2c105035
files light9/web/timeline/cursor_canvas.coffee light9/web/timeline/timeline-elements.html light9/web/timeline/timeline.coffee
diffstat 3 files changed, 54 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/light9/web/timeline/cursor_canvas.coffee	Sat May 12 09:22:00 2018 +0000
+++ b/light9/web/timeline/cursor_canvas.coffee	Sat May 12 23:02:26 2018 +0000
@@ -3,41 +3,42 @@
   is: 'light9-cursor-canvas'
   behaviors: [ Polymer.IronResizableBehavior ]
   listeners: 'iron-resize': 'update'
-
+  properties:
+    viewState: { type: Object, notify: true, observer: "onViewState" }
   ready: ->
     @mouseX = 0
     @mouseY = 0
     @cursorPath = null
     @ctx = @$.canvas.getContext('2d')
 
+  onViewState: ->
+    ko.computed(@redrawCursor.bind(@))
+
   update: (ev) ->
     @$.canvas.width = ev.target.offsetWidth
     @$.canvas.height = ev.target.offsetHeight
     @redraw()
 
-  setMouse: (pos) ->
-    @mouseX = pos.e(1)
-    @mouseY = pos.e(2)
-    @redraw()
-
-  setCursor: (y1, h1, y2, h2, viewState) ->
-    
-    xZoomedOut = viewState.fullZoomX(viewState.latestMouseTime())
-    xZoomedIn = viewState.mouse.pos().e(1)
+  redrawCursor: ->
+    vs = @viewState
+    dependOn = [vs.zoomSpec.t1(), vs.zoomSpec.t2()]
+    xZoomedOut = vs.fullZoomX(vs.latestMouseTime())
+    xZoomedIn = vs.mouse.pos().e(1)
 
     @cursorPath = {
-      top0: $V([xZoomedOut, y1])
-      top1: $V([xZoomedOut, y1 + h1])
-      mid0: $V([xZoomedIn + 2, y2 + h2])
-      mid1: $V([xZoomedIn - 2, y2 + h2])
-      mid2: $V([xZoomedOut - 1, y1 + h1])
-      mid3: $V([xZoomedOut + 1, y1 + h1])
-      bot0: $V([xZoomedIn, y2 + h2])
+      top0: $V([xZoomedOut, vs.audioY()])
+      top1: $V([xZoomedOut, vs.audioY() + vs.audioH()])
+      mid0: $V([xZoomedIn + 2, vs.zoomedTimeY() + vs.zoomedTimeH()])
+      mid1: $V([xZoomedIn - 2, vs.zoomedTimeY() + vs.zoomedTimeH()])
+      mid2: $V([xZoomedOut - 1, vs.audioY() + vs.audioH()])
+      mid3: $V([xZoomedOut + 1, vs.audioY() + vs.audioH()])
+      bot0: $V([xZoomedIn, vs.zoomedTimeY() + vs.zoomedTimeH()])
       bot1: $V([xZoomedIn, @offsetParent.offsetHeight])
     }
     @redraw()
 
   redraw: ->
+    return unless @ctx
     @ctx.clearRect(0, 0, @$.canvas.width, @$.canvas.height)
 
     @ctx.strokeStyle = '#fff'
--- a/light9/web/timeline/timeline-elements.html	Sat May 12 09:22:00 2018 +0000
+++ b/light9/web/timeline/timeline-elements.html	Sat May 12 23:02:26 2018 +0000
@@ -76,7 +76,7 @@
       <light9-timeline-diagram-layer id="dia" selection="{{selection}}"></light9-timeline-diagram-layer>
       <light9-adjusters-canvas id="adjustersCanvas" set-adjuster="{{setAdjuster}}">
       </light9-adjusters-canvas>
-      <light9-cursor-canvas id="cursorCanvas"></light9-cursor-canvas>
+      <light9-cursor-canvas id="cursorCanvas" view-state="{{viewState}}"></light9-cursor-canvas>
     </div>
   </template>
   
--- a/light9/web/timeline/timeline.coffee	Sat May 12 09:22:00 2018 +0000
+++ b/light9/web/timeline/timeline.coffee	Sat May 12 23:02:26 2018 +0000
@@ -95,7 +95,6 @@
 class ViewState
   constructor: () ->
     # caller updates all these observables
-    @width = ko.observable(500)
     @zoomSpec =
       duration: ko.observable(100) # current song duration
       t1: ko.observable(0)
@@ -104,22 +103,27 @@
       t: ko.observable(20) # songTime
     @mouse =
       pos: ko.observable($V([0,0]))
+    @width = ko.observable(500)
+    @audioY = ko.observable(0)
+    @audioH = ko.observable(0)
+    @zoomedTimeY = ko.observable(0)
+    @zoomedTimeH = ko.observable(0)
       
     @fullZoomX = d3.scaleLinear()
     @zoomInX = d3.scaleLinear()
 
-    ko.computed(@zoomOrLayoutChanged.bind(@))    
+    @zoomAnimSec = .1
+
+    ko.computed(@maintainZoomLimitsAndScales.bind(@))    
  
   setWidth: (w) ->
     @width(w)
-    @zoomOrLayoutChanged() # before other handleers run
+    @maintainZoomLimitsAndScales() # before other handlers run
     
-  zoomOrLayoutChanged: () ->
-    log('zoomOrLayoutChanged')
+  maintainZoomLimitsAndScales: () ->
+    log('maintainZoomLimitsAndScales')
     # not for cursor updates
 
-    window.debug_zoomOrLayoutChangedCount++
-
     if @zoomSpec.t1() < 0
       @zoomSpec.t1(0)
     if @zoomSpec.duration() and @zoomSpec.t2() > @zoomSpec.duration()
@@ -130,7 +134,6 @@
 
     @zoomInX.domain([@zoomSpec.t1(), @zoomSpec.t2()])
     @zoomInX.range([0, @width()])
-    log('update zoomInX')
     
   latestMouseTime: ->
     @zoomInX.invert(@mouse.pos().e(1))
@@ -147,7 +150,19 @@
     zs.t2(center + right * scale)
     log('view to', ko.toJSON(@))
 
-    
+  frameCursor: ->
+    zs = @zoomSpec
+    visSeconds = zs.t2() - zs.t1()
+    margin = visSeconds * .4
+    # buggy: really needs t1/t2 to limit their ranges
+    if @cursor.t() < zs.t1() or @cursor.t() > zs.t2() - visSeconds * .6
+      newCenter = @cursor.t() + margin
+      @animatedZoom(newCenter - visSeconds / 2,
+                    newCenter + visSeconds / 2, @zoomAnimSec)
+  frameToEnd: ->
+    @animatedZoom(@cursor.t() - 2, @zoomSpec.duration(), @zoomAnimSec)
+  frameAll: ->
+    @animatedZoom(0, @zoomSpec.duration(), @zoomAnimSec)
   animatedZoom: (newT1, newT2, secs) ->
     fps = 30
     oldT1 = @zoomSpec.t1()
@@ -209,7 +224,6 @@
 
     ko.computed(@zoomOrLayoutChanged.bind(@))
     setTimeout =>
-      ko.computed(@songTimeChanged.bind(@))
 
       @trackMouse()
       @bindKeys()
@@ -228,7 +242,7 @@
     , 500
 
     @addEventListener('iron-resize', @_onIronResize.bind(@))
-    @_onIronResize()
+    setTimeout(@_onIronResize.bind(@), 1000) # when children are packed
     
     #if anchor == loadtest
     #  add note and delete it repeatedly
@@ -236,8 +250,12 @@
 
   _onIronResize: ->
     @viewState.setWidth(@offsetWidth)
-
-    log('changed width')
+    @viewState.audioY(@$.audio.offsetTop)
+    @viewState.audioH(@$.audio.offsetHeight)
+    @viewState.zoomedTimeY(@$.zoomed.$.time.offsetTop) if @$.zoomed?.$?.time?
+    @viewState.zoomedTimeH(30) #@$.zoomed.$.time.offsetHeight)
+      
+    log('editor resized')
   _onSongTime: (t) ->
     @viewState.cursor.t(t)
   _onSongDuration: (d) ->
@@ -260,9 +278,8 @@
     "
 
   zoomOrLayoutChanged: ->
-  
     vs = @viewState
-    
+    vs.width()
   
     # todo: these run a lot of work purely for a time change
     if @$.zoomed?.$?.audio?
@@ -270,17 +287,6 @@
       #@dia.setTimeAxis(vs.width(), @$.zoomed.$.audio.offsetTop, vs.zoomInX)
       @$.adjustersCanvas.updateAllCoords()
 
-    # cursor needs update when layout changes, but I don't want
-    # zoom/layout to depend on the playback time
-    setTimeout(@songTimeChanged.bind(@), 1)
-
-  songTimeChanged: ->
-    return unless @$.zoomed?.$?.time?
-    @$.cursorCanvas.setCursor(@$.audio.offsetTop, @$.audio.offsetHeight,
-                              @$.zoomed.$.time.offsetTop,
-                              30,#@$.zoomed.$.time.offsetHeight,
-                              @viewState)
-    
   trackMouse: ->
     # not just for show- we use the mouse pos sometimes
     for evName in ['mousemove', 'touchmove']
@@ -294,7 +300,6 @@
         root = @$.cursorCanvas.getBoundingClientRect()
         @viewState.mouse.pos($V([ev.pageX - root.left, ev.pageY - root.top]))
 
-        @$.cursorCanvas.setMouse(@viewState.mouse.pos())
         # should be controlled by a checkbox next to follow-player-song-choice
         @sendMouseToVidref() unless window.location.hash.match(/novidref/)
 
@@ -305,8 +310,6 @@
       @$.vidrefTime.generateRequest()
       @$.vidrefLastSent = now
 
-  
-
   bindWheelZoom: (elem) ->
     elem.addEventListener 'mousewheel', (ev) =>
       @viewState.onMouseWheel(ev.deltaY)
@@ -320,21 +323,9 @@
   bindKeys: ->
     shortcut.add "Ctrl+P", (ev) =>
       @$.music.seekPlayOrPause(@latestMouseTime())
-
-    zoomAnimSec = .1
-    shortcut.add "Ctrl+Escape", =>
-      @viewState.animatedZoom(0, @viewState.zoomSpec.duration(), zoomAnimSec)
-    shortcut.add "Shift+Escape", =>
-      @viewState.animatedZoom(@songTime - 2, @viewState.zoomSpec.duration(), zoomAnimSec)
-    shortcut.add "Escape", =>
-      zs = @viewState.zoomSpec
-      visSeconds = zs.t2() - zs.t1()
-      margin = visSeconds * .4
-      # buggy: really needs t1/t2 to limit their ranges
-      if @songTime < zs.t1() or @songTime > zs.t2() - visSeconds * .6
-        newCenter = @songTime + margin
-        @viewState.animatedZoom(newCenter - visSeconds / 2,
-                                newCenter + visSeconds / 2, zoomAnimSec)
+    shortcut.add "Ctrl+Escape", => @viewState.frameAll()
+    shortcut.add "Shift+Escape", => @viewState.frameToEnd()
+    shortcut.add "Escape", => @viewState.frameCursor()
     shortcut.add "L", =>
       @$.adjustersCanvas.updateAllCoords()
     shortcut.add 'Delete', =>
@@ -343,7 +334,6 @@
 
   makeZoomAdjs: ->
     yMid = => @$.audio.offsetTop + @$.audio.offsetHeight / 2
-    dur = @viewState.zoomSpec.duration
     
     valForPos = (pos) =>
         x = pos.e(1)