diff --git a/light9/web/edit-choice.coffee b/light9/web/edit-choice.coffee --- a/light9/web/edit-choice.coffee +++ b/light9/web/edit-choice.coffee @@ -1,4 +1,44 @@ RDFS = 'http://www.w3.org/2000/01/rdf-schema#' + + + +window.setupDrop = (senseElem, highlightElem, coordinateOriginElem, onDrop) -> + + highlight = -> highlightElem.classList.add('dragging') + unhighlight = -> highlightElem.classList.remove('dragging') + + senseElem.addEventListener 'drag', (event) => + + senseElem.addEventListener 'dragstart', (event) => + + senseElem.addEventListener 'dragend', (event) => + + senseElem.addEventListener 'dragover', (event) => + event.preventDefault() + event.dataTransfer.dropEffect = 'copy' + highlight() + + senseElem.addEventListener 'dragenter', (event) => + highlight() + + senseElem.addEventListener 'dragleave', (event) => + unhighlight() + + senseElem.addEventListener 'drop', (event) -> + event.preventDefault() + uri = event.dataTransfer.getData('text/uri-list') + + pos = if coordinateOriginElem? + root = coordinateOriginElem.getBoundingClientRect() + $V([event.pageX - root.left, event.pageY - root.top]) + else + null + + onDrop(uri, pos) + unhighlight() + + + Polymer is: "edit-choice", properties: @@ -10,19 +50,10 @@ Polymer 'gotGraph(graph, uri)' ] - dragover: (event) -> - event.preventDefault() - event.dataTransfer.dropEffect = 'copy' - @$.box.classList.add('over') - - dragleave: (event) -> - @$.box.classList.remove('over') - - drop: (event) -> - event.preventDefault() - @uri = event.dataTransfer.getData('text/uri-list') - @updateLabel() - @$.box.classList.remove('over') + ready: -> + setupDrop @$.box, @$.box, null, (uri) => + @uri=uri + @updateLabel() gotGraph: -> @graph.runHandler(@updateLabel.bind(@)) diff --git a/light9/web/edit-choice.html b/light9/web/edit-choice.html --- a/light9/web/edit-choice.html +++ b/light9/web/edit-choice.html @@ -8,9 +8,9 @@ display: inline-block; background: #141448; } - #box.over { - background: red; - } + #box.dragging { + background: rgba(126, 52, 245, 0.0784313725490196); + } a { color: #5555e0; padding: 3px; @@ -18,12 +18,7 @@ } -
+
{{label}}
diff --git a/light9/web/timeline/timeline-elements.html b/light9/web/timeline/timeline-elements.html --- a/light9/web/timeline/timeline-elements.html +++ b/light9/web/timeline/timeline-elements.html @@ -82,6 +82,9 @@ flex-direction: column; height: 100%; } + #rows.dragging { +background: rgba(126, 52, 245, 0.0784313725490196); + } light9-timeline-audio { width: 100%; height: 100px; @@ -90,7 +93,7 @@ flex-grow: 1; } -
+
- +
+ +
diff --git a/light9/web/timeline/timeline.coffee b/light9/web/timeline/timeline.coffee --- a/light9/web/timeline/timeline.coffee +++ b/light9/web/timeline/timeline.coffee @@ -1,4 +1,5 @@ log = console.log +RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' Polymer is: 'light9-timeline-editor' @@ -197,6 +198,8 @@ Polymer return [left, right, pan] + + Polymer is: 'light9-timeline-time-zoomed' behaviors: [ Polymer.IronResizableBehavior ] @@ -212,6 +215,62 @@ Polymer updateZoomFlattened = -> @zoomFlattened = ko.toJS(@zoom) ko.computed(updateZoomFlattened.bind(@)) + ready: -> + + attached: -> + root = @closest('light9-timeline-editor') + setupDrop @, @$.rows, root, (effect, pos) => + + if not @graph.contains(effect, RDF + 'type', @graph.Uri(':Effect')) + log("drop #{effect} is not an effect") + return + + dropTime = @zoomInX.invert(pos.e(1)) + + U = (x) -> @graph.Uri(x) + + nextNumberedResources = (graph, base, howMany) -> + results = [] + # we could cache [base,lastSerial] + for serial in [0..1000] + uri = graph.Uri("#{base}#{serial}") + if not graph.contains(uri, null, null) + results.push(uri) + if results.length >= howMany + return results + throw new Error("can't make sequential uri with base #{base}") + + nextNumberedResource = (graph, base) -> + nextNumberedResources(graph, base, 1)[0] + + newNote = nextNumberedResource(graph, "#{@song}/n") + newCurve = nextNumberedResource(graph, "#{newNote}c") + points = nextNumberedResources(graph, "#{newCurve}p", 4) + + quad = (s, p, o) => {subject: s, predicate: p, object: o, graph: @song} + + curveQuads = [ + quad(@song, U(':note'), newNote) + quad(newNote, RDF + 'type', U(':Note')) + quad(newNote, U(':originTime'), @graph.LiteralRoundedFloat(dropTime)) + quad(newNote, U(':curve'), newCurve) + quad(newCurve, RDF + 'type', U(':Curve')) + quad(newCurve, U(':attr'), U(':strength')) + ] + pointQuads = [] + for i in [0...4] + pt = points[i] + pointQuads.push(quad(newCurve, U(':point'), pt)) + pointQuads.push(quad(pt, U(':time'), @graph.LiteralRoundedFloat(i))) + pointQuads.push(quad(pt, U(':value'), @graph.LiteralRoundedFloat(i == 1 or i == 2))) + + patch = { + delQuads: [] + addQuads: curveQuads.concat(pointQuads) + } + @graph.applyAndSendPatch(patch) + log('land', effect, dropTime, newNote) + Polymer is: "light9-timeline-time-axis", @@ -346,13 +405,14 @@ Polymer @adj.subscribe(@updateDisplay.bind(this)) updateDisplay: () -> - @spanClass = if @adj.config.emptyBox then 'empty' else '' - @displayValue = @adj.getDisplayValue() - center = @adj.getCenter() - target = @adj.getTarget() - return if isNaN(center.e(1)) - @centerStyle = {x: center.e(1), y: center.e(2)} - @dia?.setAdjusterConnector(@myId, center, target) + window.adjDragUpdates++ if window.adjDragUpdates? + @spanClass = if @adj.config.emptyBox then 'empty' else '' + @displayValue = @adj.getDisplayValue() + center = @adj.getCenter() + target = @adj.getTarget() + return if isNaN(center.e(1)) + @centerStyle = {x: center.e(1), y: center.e(2)} + @dia?.setAdjusterConnector(@myId, center, target) attached: -> @myId = 'adjuster-' + _adjusterSerial