Changeset - c4e990d1dacf
[Not reviewed]
default
0 2 0
Drew Perttula - 8 years ago 2017-06-09 08:48:29
drewp@bigasterisk.com
delete key deletes selected notes. Try to fix mem leak in timeline.
Ignore-this: c122fe14883cfda925c1bd66c13773b2
2 files changed with 37 insertions and 20 deletions:
0 comments (0 inline, 0 general)
light9/web/timeline/adjustable.coffee
Show inline comments
 
@@ -79,24 +79,25 @@ class window.AdjustableFloatObservable e
 

	
 
  _getValue: () ->
 
    @config.observable()
 
    
 
  continueDrag: (pos) ->
 
    # pos is vec2 of pixels relative to the drag start.
 
    super(pos)
 
    epos = @_editorCoordinates()
 
    newValue = @config.getValueForPos(epos)
 
    @config.observable(newValue)
 

	
 
  subscribe: (onChange) ->
 
    log('AdjustableFloatObservable subscribe', @config)
 
    ko.computed =>
 
      @config.observable()
 
      onChange()
 

	
 
class window.AdjustableFloatObject extends Adjustable
 
  constructor: (@config) ->
 
    # config also has:
 
    #   graph
 
    #   subj
 
    #   pred
 
    #   ctx
 
    #   getTargetPosForValue(value) -> getTarget result for value
light9/web/timeline/timeline.coffee
Show inline comments
 
@@ -8,25 +8,25 @@ ROW_COUNT = 7
 
# side effects if your attributes are changing before the detach
 
# call. This alternative to dom-repeat never reassigns
 
# attributes. But, it can't set up property bindings.
 
updateChildren = (parent, newUris, makeChild) ->
 
  childUris = []
 
  childByUri = {}
 
  for e in parent.children
 
    childUris.push(e.uri)
 
    childByUri[e.uri] = e
 

	
 
  for uri in _.difference(childUris, newUris)
 
    childByUri[uri].detached()
 
    childByUri[uri].remove()
 
    ko.removeNode(childByUri[uri])
 
  for uri in _.difference(newUris, childUris)
 
    parent.appendChild(makeChild(uri))
 

	
 

	
 
Polymer
 
  is: 'light9-timeline-editor'
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  properties:
 
    viewState: { type: Object }
 
    debug: {type: String}
 
    graph: {type: Object, notify: true}
 
    setAdjuster: {type: Function, notify: true}
 
@@ -100,37 +100,38 @@ Polymer
 
    @trackMouse()
 
    @bindKeys()
 
    @bindWheelZoom(@dia.querySelector('svg'))
 
    @forwardMouseEventsToAdjustersCanvas()
 

	
 
    @makeZoomAdjs()
 

	
 
    zoomed = @$.zoomed
 
    setupDrop(@$.dia.querySelector('svg'), zoomed.$.rows, @, zoomed.onDrop.bind(zoomed))
 

	
 

	
 
  zoomOrLayoutChanged: ->
 
    log('zoomOrLayoutChanged')
 
    # not for cursor updates
 

	
 
    window.debug_zoomOrLayoutChangedCount++
 
    @fullZoomX.domain([0, @viewState.zoomSpec.duration()])
 
    @fullZoomX.range([0, @width()])
 

	
 
    # had trouble making notes update when this changes
 
    zoomInX = d3.scaleLinear()
 
    zoomInX.domain([@viewState.zoomSpec.t1(), @viewState.zoomSpec.t2()])
 
    zoomInX.range([0, @width()])
 
    @zoomInX = zoomInX
 

	
 
    # todo: these run a lot of work purely for a time change    
 
    # todo: these run a lot of work purely for a time change
 
    @dia.setTimeAxis(@width(), @$.zoomed.$.audio.offsetTop, @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: ->
 
    @$.cursorCanvas.setCursor(@$.audio.offsetTop, @$.audio.offsetHeight,
 
                              @$.zoomed.$.time.offsetTop,
 
                              @$.zoomed.$.time.offsetHeight,
 
                              @fullZoomX, @zoomInX, @viewState.cursor)
 
@@ -210,24 +211,28 @@ Polymer
 
      @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
 
        @animatedZoom(newCenter - visSeconds / 2,
 
                      newCenter + visSeconds / 2, zoomAnimSec)
 
    shortcut.add "L", =>
 
      @$.adjustersCanvas.updateAllCoords()
 
    shortcut.add 'Delete', =>
 
      for note in @selection.selected()
 
        deleteNote(@graph, @song, note, @selection)
 

	
 

	
 
  makeZoomAdjs: ->
 
    yMid = => @$.audio.offsetTop + @$.audio.offsetHeight / 2
 
    dur = @viewState.zoomSpec.duration
 
    
 
    valForPos = (pos) =>
 
        x = pos.e(1)
 
        t = @fullZoomX.invert(x)
 
    @setAdjuster('zoom-left', => new AdjustableFloatObservable({
 
      observable: @viewState.zoomSpec.t1,
 
      getTarget: () =>
 
        $V([@fullZoomX(@viewState.zoomSpec.t1()), yMid()])
 
@@ -269,24 +274,25 @@ Polymer
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  properties:
 
    graph: { type: Object, notify: true }
 
    selection: { type: Object, notify: true }
 
    dia: { type: Object, notify: true }
 
    song: { type: String, notify: true }
 
    zoomInX: { type: Object, notify: true }
 
    rows: { value: [0...ROW_COUNT] }
 
    zoom: { type: Object, notify: true, observer: 'onZoom' }
 
    zoomFlattened: { type: Object, notify: true }
 
  onZoom: ->
 
    updateZoomFlattened = ->
 
      log('updateZoomFlattened')
 
      @zoomFlattened = ko.toJS(@zoom)
 
    ko.computed(updateZoomFlattened.bind(@))
 
  ready: ->
 

	
 
  attached: ->
 
    root = @closest('light9-timeline-editor')
 

	
 
  onDrop: (effect, pos) ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    # we could probably accept some initial overrides right on the
 
    # effect uri, maybe as query params
 
@@ -513,25 +519,25 @@ Polymer
 
      rightX = leftX + 120
 
    w = 430
 
    h = 80
 
    @inlineRect = {
 
      left: leftX,
 
      top: @offsetTop + @offsetHeight - h - 5,
 
      width: w,
 
      height: h,
 
      display: if rightX - leftX > w then 'block' else 'none'
 
      }
 
    if @inlineRect.display != 'none'
 
      @async =>
 
        @querySelector('light9-timeline-note-inline-attrs').displayed()
 
        @querySelector('light9-timeline-note-inline-attrs')?.displayed()
 

	
 
    if screenPts[screenPts.length - 1].e(1) - screenPts[0].e(1) < 100
 
      @clearAdjusters()
 
      # also kill their connectors
 
      return
 

	
 
    @makeCurveAdjusters(curveWidth, yForV, @worldPts)
 
    
 
  makeCurveAdjusters: (curveWidth, yForV, worldPts) ->
 
    U = (x) => @graph.Uri(x)
 

	
 
    if true
 
@@ -591,70 +597,80 @@ Polymer
 
    noteLabel: { type: String, notify: true }
 
    selection: { type: Object, notify: true }
 
  observers: [
 
    'addHandler(graph, uri)'
 
    'onColorScale(graph, uri, colorScale)'
 
    ]
 
  displayed: ->
 
    @querySelector('light9-color-picker').displayed()
 
  onColorScale: ->
 
    U = (x) => @graph.Uri(x)
 
    if @colorScale == @colorScaleFromGraph
 
      return
 
      
 
    quad = (s, p, o) => {subject: s, predicate: p, object: o, graph: @song}
 
    log('ch', ko.toJS(@selection))
 
    settingValue = @graph.Literal(@colorScale)
 
    if @existingColorScaleSetting
 
      @graph.patchObject(@existingColorScaleSetting, U(':value'), settingValue, @song)
 
    @editAttr(@song, @uri, U(':colorScale'), @graph.Literal(@colorScale))
 

	
 
  editAttr: (song, note, attr, value) ->
 
    U = (x) => @graph.Uri(x)
 
    quad = (s, p, o) => {subject: s, predicate: p, object: o, graph: song}
 

	
 
    existingColorScaleSetting = null
 
    for setting in @graph.objects(note, U(':setting'))
 
      ea = @graph.uriValue(setting, U(':effectAttr'))
 
      if ea == attr
 
        existingColorScaleSetting = setting
 
        
 
    if existingColorScaleSetting
 
      @graph.patchObject(existingColorScaleSetting, U(':value'), value, song)
 
    else
 
      setting = @graph.nextNumberedResource(@uri + 'set')
 
      setting = @graph.nextNumberedResource(note + 'set')
 
      patch = {delQuads: [], addQuads: [
 
        quad(@uri, U(':setting'), setting)
 
        quad(setting, U(':effectAttr'), U(':colorScale'))
 
        quad(setting, U(':value'), settingValue)
 
        quad(note, U(':setting'), setting)
 
        quad(setting, U(':effectAttr'), attr)
 
        quad(setting, U(':value'), value)
 
        ]}
 
      @graph.applyAndSendPatch(patch)
 
    
 
  addHandler: ->
 
    @graph.runHandler(@update.bind(@))
 
    
 
  update: ->
 
    console.time('attrs update')
 
    U = (x) => @graph.Uri(x)
 
    @effect = @graph.uriValue(@uri, U(':effectClass'))
 
    @effectLabel = @graph.stringValue(@effect, U('rdfs:label')) or (@effect.replace(/.*\//, ''))
 
    @noteLabel = @uri.replace(/.*\//, '')
 

	
 
    @existingColorScaleSetting = null
 
    existingColorScaleSetting = null
 
    for setting in @graph.objects(@uri, U(':setting'))
 
      ea = @graph.uriValue(setting, U(':effectAttr'))
 
      value = @graph.stringValue(setting, U(':value'))
 
      if ea == U(':colorScale')
 
        @colorScaleFromGraph = value
 
        @colorScale = value
 
        @existingColorScaleSetting = setting
 
    if @existingColorScaleSetting == null
 
        existingColorScaleSetting = setting
 
    if existingColorScaleSetting == null
 
      @colorScaleFromGraph = '#ffffff'
 
      @colorScale = '#ffffff'
 
    console.timeEnd('attrs update')
 

	
 

	
 
  onDel: ->
 
    deleteNote(@graph, @song, @uri)
 
    deleteNote(@graph, @song, @uri, @selection)
 

	
 

	
 
deleteNote = (graph, song, note) ->
 
deleteNote = (graph, song, note, selection) ->
 
  patch = {delQuads: [{subject: song, predicate: graph.Uri(':note'), object: note, graph: song}], addQuads: []}
 
  graph.applyAndSendPatch(patch)
 
  if note in selection.selected()
 
    selection.selected(_.without(selection.selected(), note))
 
  
 

	
 
Polymer
 
  is: 'light9-cursor-canvas'
 
  behaviors: [ Polymer.IronResizableBehavior ]
 
  listeners: 'iron-resize': 'update'
 

	
 
  ready: ->
 
    @mouseX = 0
 
    @mouseY = 0
 
    @cursorPath = null
 
    @ctx = @$.canvas.getContext('2d')
 
@@ -862,25 +878,25 @@ Polymer
 
    @ctx.font = "12px sans"
 
    @ctx.fillStyle = '#000'
 
    @ctx.fillText(label, x1 + 5, y2 - 5, x2 - x1 - 10)
 

	
 
    # coords from a center that's passed in
 
    # # special layout for the thaeter ones with middinh 
 
    # l/r arrows
 
    # mouse arrow cursor upon hover, and accent the hovered adjuster
 
    # connector
 

	
 
  
 
Polymer
 
  # note boxes. Page selection.
 
  # note boxes. 
 
  is: 'light9-timeline-diagram-layer'
 
  properties: {
 
    selection: {type: Object, notify: true}
 
  }
 
  ready: ->
 
    @elemById = {}
 

	
 
  attached: ->
 
    
 

	
 
  setTimeAxis: (width, yTop, scale) ->
 
    pxPerTick = 50
 
@@ -894,25 +910,25 @@ Polymer
 
      @$[groupId].appendChild(elem)
 
      elem.setAttribute('id', uri)
 
      for k,v of attrs
 
        elem.setAttribute(k, v)
 
      if moreBuild
 
        moreBuild(elem)
 
    return elem
 

	
 
  clearElem: (uri, suffixes) -> # todo: caller shouldn't have to know suffixes!
 
    for suff in suffixes
 
      elem = @elemById[uri+suff]
 
      if elem
 
        elem.remove()
 
        ko.removeNode(elem)
 
        delete @elemById[uri+suff]
 

	
 
  anyPointsInView: (pts) ->
 
    for pt in pts
 
      # wrong:
 
      if pt.e(1) > -100 && pt.e(1) < 2500
 
        return true
 
    return false
 
    
 
  setNote: (uri, curvePts, effect, classes) ->
 
    areaId = uri + '/area'
 
    labelId = uri + '/label'
0 comments (0 inline, 0 general)