Changeset - d6396679c121
[Not reviewed]
default
0 3 1
Drew Perttula - 9 years ago 2016-06-04 06:30:33
drewp@bigasterisk.com
move to adjustable.coffee and also simplify the getTarget code
Ignore-this: e7addcd75d8fcac10df92c64f8a77ecd
4 files changed with 117 insertions and 115 deletions:
0 comments (0 inline, 0 general)
light9/web/adjustable.coffee
Show inline comments
 
new file 100644
 
log = console.log
 

	
 
class Adjustable
 
  # Some value you can edit in the UI, probably by dragging stuff. May
 
  # have a <light9-timeline-adjuster> associated. This object does the
 
  # layout and positioning.
 
  #
 
  # The way dragging should work is that you start in the yellow *adj
 
  # widget*, wherever it is, but your drag is moving the *target*. The
 
  # adj will travel around too, but it may do extra moves to not bump
 
  # into stuff or to get out from under your finger.
 

	
 
  constructor: (@config) ->
 
    # config has:
 
    #   getTarget -> vec2 of current target position
 
    #   getSuggestedTargetOffset -> vec2 pixel offset from target
 
    #   emptyBox -> true if you want no value display
 

	
 
  getDisplayValue: () ->
 
    return '' if @config.emptyBox
 
    d3.format(".4g")(@_getValue())
 

	
 
  getCenter: () -> # vec2 of pixels
 
    @getTarget().add(@config.getSuggestedTargetOffset())
 

	
 
  getTarget: () -> # vec2 of pixels
 
    @config.getTarget()
 
            
 
  subscribe: (onChange) ->
 
    # change could be displayValue or center or target. This likely
 
    # calls onChange right away if there's any data yet.
 
    setInterval((() => onChange()), 100)
 

	
 
  startDrag: () ->
 
    # todo
 
    @dragStartValue = @_getValue()
 

	
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start
 
    
 
    # todo
 
    newValue = @dragStartValue + pos.e(0) * .1
 
    graph.patchObject(@_subj, @_pred, graph.Literal(newValue), @_ctx)
 

	
 
  endDrag: () ->
 
    0
 

	
 
class window.AdjustableFloatObservable extends Adjustable
 
  constructor: (@config) ->
 
    # config also has:
 
    #   observable -> ko.observable we will read and write
 
    #   getValueForPos(pos) -> what should we set to if the user
 
    #                          moves target to this coord?
 

	
 
  _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)
 

	
 
  subscribe: (onChange) ->
 
    ko.computed =>
 
      @config.observable()
 
      onChange()
 

	
 
class window.AdjustableFloatObject extends Adjustable
 
  constructor: (@config) ->
 
    # config has graph, subj, pred, ctx, getSuggestedTargetOffset
 
    super(@config)
 

	
 
  _getValue: () -> # for drag math
 
    @config.graph.floatValue(@config.subj, @config.pred)
 

	
 
  getCenter: () ->    
 
    $V([100 + 200 * @_getValue(), 200])
 

	
 
  subscribe: (onChange) ->
 
    @config.graph.subscribe @config.subj, @config.pred, null, (patch) =>
 
      onChange()
 
    
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start
 
    
 
    newValue = @dragStartValue + pos.e(1) / 200
 
    @config.graph.patchObject(@config.subj, @config.pred, @config.graph.Literal(newValue), @_ctx)
light9/web/timeline-elements.html
Show inline comments
 
@@ -335,7 +335,8 @@
 

	
 
<script src="/lib/sylvester/sylvester.js"></script>
 
<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>
light9/web/timeline.coffee
Show inline comments
 
@@ -11,114 +11,12 @@ window.graph.loadTrig("
 
<http://example.com/> {
 
  :demoResource :startTime 110; :endTime 120 .
 
}
 
    ")
 

	
 
    
 
class Adjustable
 
  # Some value you can edit in the UI, probably by dragging stuff. May
 
  # have a <light9-timeline-adjuster> associated. This object does the
 
  # layout and positioning.
 
  constructor: (@config) ->
 
    # config has getTarget, getSuggestedTargetOffset, getValue, emptyBox
 

	
 
  getDisplayValue: () ->
 
    return '' if @config.emptyBox
 
    d3.format(".4g")(@_getValue())
 

	
 
  getCenter: () -> # vec2 of pixels
 
    @getTarget().add(@config.getSuggestedTargetOffset())
 

	
 
  getTarget: () -> # vec2 of pixels
 
    @config.getTarget()
 
            
 
  subscribe: (onChange) ->
 
    # change could be displayValue or center or target. This likely
 
    # calls onChange right away if there's any data yet.
 
    setInterval((() => onChange()), 100)
 

	
 
  startDrag: () ->
 
    # todo
 
    @dragStartValue = @_getValue()
 

	
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start
 
    
 
    # todo
 
    newValue = @dragStartValue + pos.e(0) * .1
 
    graph.patchObject(@_subj, @_pred, graph.Literal(newValue), @_ctx)
 

	
 
  endDrag: () ->
 
    0
 

	
 
class AdjustableFloatObservable extends Adjustable
 
  constructor: (@config) ->
 
    # config has observable, getValueForPos, valueLow, targetLow, valueHigh, targetHigh, getSuggestedTargetOffset
 
    ko.computed =>
 
      @_normalizedValue = d3.scaleLinear().domain([
 
        ko.unwrap(@config.valueLow),
 
        ko.unwrap(@config.valueHigh)]).range([0, 1])
 

	
 
  _getValue: () ->
 
    @config.observable()
 

	
 
  getTarget: () ->
 
    f = @_normalizedValue(@_getValue())
 
    [lo, hi] = [ko.unwrap(@config.targetLow),
 
                ko.unwrap(@config.targetHigh)]
 
    return lo.add(hi.subtract(lo).multiply(f))
 

	
 
  _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)
 

	
 
  subscribe: (onChange) ->
 
    ko.computed =>
 
      @config.observable()
 
      onChange()
 

	
 
class AdjustableFloatObject extends Adjustable
 
  constructor: (@config) ->
 
    # config has graph, subj, pred, ctx, getSuggestedTargetOffset
 
    super(@config)
 

	
 
  _getValue: () -> # for drag math
 
    @config.graph.floatValue(@config.subj, @config.pred)
 

	
 
  getCenter: () ->    
 
    $V([100 + 200 * @_getValue(), 200])
 

	
 
  subscribe: (onChange) ->
 
    @config.graph.subscribe @config.subj, @config.pred, null, (patch) =>
 
      onChange()
 
    
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start
 
    
 
    newValue = @dragStartValue + pos.e(1) / 200
 
    @config.graph.patchObject(@config.subj, @config.pred, @config.graph.Literal(newValue), @_ctx)
 

	
 
      
 
Polymer
 
  is: 'light9-timeline-editor'
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  properties:
 
    viewState: { type: Object }
 
@@ -177,31 +75,28 @@ Polymer
 
      })
 
      ]
 

	
 
  makeZoomAdjs: ->
 
    yMid = @$.audio.offsetTop + @$.audio.offsetHeight / 2
 
    dur = @viewState.zoomSpec.duration
 
    
 
    valForPos = (pos) =>
 
        x = pos.e(1)
 
        t = @fullZoomX.invert(x)
 
    left = new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t1,
 
      valueLow: 0
 
      valueHigh: dur
 
      targetLow: $V([0, yMid])
 
      targetHigh: $V([@offsetWidth, yMid])
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t1()), yMid])
 
      getSuggestedTargetOffset: () => $V([-50, 0])
 
      getValueForPos: valForPos
 
    })
 

	
 
    right = new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t2,
 
      valueLow: 0
 
      valueHigh: dur
 
      targetLow: $V([0, yMid])
 
      targetHigh: $V([@offsetWidth, yMid])
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t2()), yMid])
 
      getSuggestedTargetOffset: () => $V([50, 0])
 
      getValueForPos: valForPos
 
    })
 

	
 
    panObs = ko.pureComputed({
 
        read: () =>
 
@@ -213,17 +108,15 @@ Polymer
 
          zs.t2(value + span / 2)
 
      })
 

	
 
    pan = new AdjustableFloatObservable({
 
      observable: panObs
 
      emptyBox: true
 
      valueLow: 0
 
      valueHigh: dur
 
      # not right- the sides shouldn't be able to go offscreen
 
      targetLow: $V([0, 30])  # y = @$.audio.offsetTop + @$.audio.offsetHeight / 2]
 
      targetHigh: $V([@offsetWidth, 30])
 
      # fullzoom is not right- the sides shouldn't be able to go
 
      # offscreen
 
      getTarget: () => $V([@fullZoomX(panObs()), yMid])
 
      getSuggestedTargetOffset: () => $V([0, 0])
 
      getValueForPos: valForPos
 
      })
 
      
 
    return [left, right, pan]
 

	
makefile
Show inline comments
 
@@ -82,6 +82,9 @@ darcs_show_checkpoint:
 

	
 
arduino_upload: /usr/share/arduino/Arduino.mk
 
	cd rgbled
 
	make upload
 

	
 
effect_node_setup: create_virtualenv packages binexec install_python_deps
 

	
 
coffee:
 
	coffee -cw light9/web/*.coffee
0 comments (0 inline, 0 general)