Mercurial > code > home > repos > light9
changeset 1317:4c6d88aa9e26
enough element and rdf support to drag one adjuster and see its value change
Ignore-this: 8aebc2ff62d5afee77845737737aab00
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Fri, 03 Jun 2016 11:35:09 +0000 |
parents | 2196532a6f0c |
children | 0bda9a9282c2 |
files | light9/web/graph.coffee light9/web/timeline-elements.html light9/web/timeline.coffee show/dance2016/timelinedemo.n3 |
diffstat | 3 files changed, 338 insertions(+), 217 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/light9/web/graph.coffee Fri Jun 03 11:35:09 2016 +0000 @@ -0,0 +1,148 @@ +# Patch is {addQuads: <quads>, delQuads: <quads>} +# <quads> is [{subject: s, ...}, ...] + +# partial port of autodepgraphapi.py +class GraphWatchers + constructor: -> + @handlersSp = {} # {s: {p: [handlers]}} + subscribe: (s, p, o, onChange) -> # return subscription handle + if o? then throw Error('not implemented') + if not @handlersSp[s] + @handlersSp[s] = {} + if not @handlersSp[s][p] + @handlersSp[s][p] = [] + @handlersSp[s][p].push(onChange) + + unsubscribe: (subscription) -> + throw Error('not implemented') + + graphChanged: (patch) -> + for quad in patch.delQuads + for cb in ((@handlersSp[quad.subject] || {})[quad.predicate] || []) + # currently calls multiple times, which is ok, but we might + # group things into fewer patches + cb({delQuads: [quad], addQuads: []}) + for quad in patch.addQuads + for cb in ((@handlersSp[quad.subject] || {})[quad.predicate] || []) + cb({delQuads: [], addQuads: [quad]}) + + +class window.SyncedGraph + # Note that applyPatch is the only method to write to the graph, so + # it can fire subscriptions. + + constructor: (patchSenderUrl, prefixes) -> + @graph = N3.Store() + @_addPrefixes(prefixes) + @_watchers = new GraphWatchers() + + _addPrefixes: (prefixes) -> + @graph.addPrefixes(prefixes) + + Uri: (curie) -> + N3.Util.expandPrefixedName(curie, @graph._prefixes) + + Literal: (jsValue) -> + N3.Util.createLiteral(jsValue) + + toJs: (literal) -> + # incomplete + parseFloat(N3.Util.getLiteralValue(literal)) + + loadTrig: (trig, cb) -> # for debugging + patch = {delQuads: [], addQuads: []} + parser = N3.Parser() + parser.parse trig, (error, quad, prefixes) => + if (quad) + patch.addQuads.push(quad) + else + @applyPatch(patch) + @_addPrefixes(prefixes) + cb() if cb + + quads: () -> # for debugging + [q.subject, q.predicate, q.object, q.graph] for q in @graph.find() + + applyAndSendPatch: (patch, cb) -> + @applyPatch(patch) + console.log('patch to server:', patch) + # post to server + + applyPatch: (patch) -> + # In most cases you want applyAndSendPatch. + # + # This is the only method that writes to the graph! + for quad in patch.delQuads + @graph.removeTriple(quad) + for quad in patch.addQuads + @graph.addTriple(quad) + @_watchers.graphChanged(patch) + + getObjectPatch: (s, p, newObject, g) -> + # send a patch which removes existing values for (s,p,*,c) and + # adds (s,p,newObject,c). Values in other graphs are not affected. + existing = @graph.findByIRI(s, p, null, g) + return { + delQuads: existing, + addQuads: [{subject: s, predicate: p, object: newObject, graph: g}] + } + + patchObject: (s, p, newObject, g) -> + @applyAndSendPatch(@getObjectPatch(s, p, newObject, g)) + + + subscribe: (s, p, o, onChange) -> # return subscription handle + # onChange is called with a patch that's limited to the quads + # that match your request. + # We call you immediately on existing triples. + @_watchers.subscribe(s, p, o, onChange) + immediatePatch = {delQuads: [], addQuads: @graph.findByIRI(s, p, o)} + if immediatePatch.addQuads.length + onChange(immediatePatch) + + unsubscribe: (subscription) -> + @_watchers.unsubscribe(subscription) + + floatValue: (s, p) -> + quads = @graph.findByIRI(s, p) + switch quads.length + when 0 then throw new Error("no value for "+s+" "+p) + when 1 + obj = quads[0].object + return parseFloat(N3.Util.getLiteralValue(obj)) + else + throw new Error("too many values: " + JSON.stringify(quads)) + + stringValue: (s, p) -> + + uriValue: (s, p) -> + + objects: (s, p) -> + + subjects: (p, o) -> + + items: (list) -> + + contains: (s, p, o) -> + +### +rdfstore.create((err, store) -> + window.store = store + store.setPrefix('l9', "http://light9.bigasterisk.com/") + store.setPrefix('xsd', "http://www.w3.org/2001/XMLSchema#") + store.load('text/turtle', " +@prefix : <http://light9.bigasterisk.com/> . +@prefix dev: <http://light9.bigasterisk.com/device/> . + +:demoResource :startTime 0.5 . + ", (err, n) -> + console.log('loaded', n) + store.graph (err, graph) -> + window.graph = graph + + ) + window.URI = (curie) -> store.rdf.createNamedNode(store.rdf.resolve(curie)) + window.Lit = (value, dtype) -> store.rdf.createLiteral(value, null, URI(dtype)) + + ) +### \ No newline at end of file
--- a/light9/web/timeline-elements.html Fri Jun 03 11:34:12 2016 +0000 +++ b/light9/web/timeline-elements.html Fri Jun 03 11:35:09 2016 +0000 @@ -2,7 +2,6 @@ <link rel="import" href="light9-timeline-audio.html"> <link rel="import" href="/lib/iron-resizable-behavior/iron-resizable-behavior.html"> - <!-- Whole editor- include this on your page. Most coordinates are relative to this element. --> @@ -25,17 +24,13 @@ } light9-timeline-diagram-layer, light9-timeline-adjusters { position: absolute; - left: 0; - top: 0; - right: 0; - bottom: 0; + left: 0; top: 0; right: 0; bottom: 0; } </style> <div> timeline editor: song [uri] <button>unlink</button> <label><input type="checkbox"> follow player song choice</label> </div> - <!-- Old zoom menu: See current time .. esc @@ -45,39 +40,9 @@ <light9-timeline-audio id="audio"></light9-timeline-audio> <!-- should have a zoom-out cursor on it, or zigzag the one cursor --> <light9-timeline-time-zoomed id="zoomed" zoom="{{viewState.zoomSpec}}"></light9-timeline-time-zoomed> <light9-timeline-diagram-layer id="dia"></light9-timeline-diagram-layer> - <light9-timeline-adjusters id="adjusters"></light9-timeline-adjusters> + <light9-timeline-adjusters id="adjusters" adjs="{{adjs}}"></light9-timeline-adjusters> </template> - <script> - Polymer({ - is: "light9-timeline-editor", - behaviors: [ - Polymer.IronResizableBehavior - ], - properties: { - viewState: {type: Object} - }, - ready: function() { - this.viewState = { // anything not persisted in the model - zoomSpec: { - duration: 190, - t1: 102, - t2: 161 - }, - cursor: { - t: 105, - } - }; - - setInterval(function() { - this.viewState.cursor.t = 130 + 20 * Math.sin(Date.now() / 2000); - this.$.dia.setCursor(this.$.audio.offsetTop, this.$.audio.offsetHeight, - this.$.zoomed.$.time.offsetTop, this.$.zoomed.$.time.offsetHeight, - this.viewState.zoomSpec, - this.viewState.cursor); - }.bind(this), 50); - } - }); - </script> + </dom-module> @@ -146,167 +111,48 @@ <dom-module id="light9-timeline-diagram-layer"> <template> <style> + :host { + pointer-events: none; + } svg { width: 100%; height: 100%; + pointer-events: none; } </style> -<svg - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://creativecommons.org/ns#" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - viewBox="0 0 1021 600" -> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <path - style="display:inline;fill:#758f8a;fill-opacity:0.32421055;fill-rule:evenodd;stroke:none;stroke-width:1px;" - d="m -559.27177,395.81 2.22362,-54.79762 C -204.84146,338.25666 -8.4912266,336.03416 0.40325327,297.52215 9.8280633,285.70343 40.880483,289.65152 49.016853,296.10794 c 20.15718,42.1653 270.720527,47.21149 589.526257,46.31865 l -4.2185,53.3834 z" - id="path4837" - sodipodi:nodetypes="ccccccc" /> - <path - style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.30736844" - d="M 0.75681338,294.44118 C -5.8919466,328.78953 -182.9094,341.3924 -555.73623,340.04956" - id="path4862" - sodipodi:nodetypes="cc" /> - <path - sodipodi:nodetypes="cc" - id="path4864" - d="m 48.622093,293.73407 c 6.6488,34.34835 183.666187,46.95123 556.493117,45.60839" - style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.30736844" /> - <path - style="display:inline;fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;" - d="m -570.58547,460.25772 1210.56688,0" - id="path5354"/> - <path - style="fill:#53774b;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.50000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" - d="m -393.10167,652.33195 70.00357,-68.30517 169.70563,0 161.5297134,68.30517" - id="note1" - sodipodi:nodetypes="cccc" /> - <rect - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.12637365;fill-rule:evenodd;stroke:none;stroke-width:1.10000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;" - id="note1Attrs" - width="108" - height="47" - x="-234.38405" - y="598.8988" - rx="0" - ry="0" /> - <path - id="path4246" - d="m -153.53195,562.60592 0,19.81802" - style="opacity:0.21600001;fill:none;fill-rule:evenodd;stroke:#d4d4d4;stroke-width:0.92825276;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.78475824, 2.78475824;stroke-dashoffset:0;stroke-opacity:1" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13px;line-height:125%;font-family:'Verana Sans';-inkscape-font-specification:'Verana Sans';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;" - x="-338.38403" - y="631.3988" - id="text4290" - sodipodi:linespacing="125%" ><tspan sodipodi:role="line" id="tspan4292" x="-338.38403" y="631.3988">spotchase</tspan></text> - <rect - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#1ed8ec;fill-opacity:0.53846154;fill-rule:evenodd;stroke:#f2ff0e;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;" - id="rect4294" - width="22.5" - height="17" - x="-224.88405" - y="603.8988" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13px;line-height:125%;font-family:'Verana Sans';-inkscape-font-specification:'Verana Sans';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;" - x="-192.88405" - y="615.8988" - id="text4296" - sodipodi:linespacing="125%" ><tspan sodipodi:role="line" id="tspan4298" x="-192.88405" y="615.8988">color</tspan></text> - <rect - y="620.97205" - x="-224.98763" - height="17" - width="22.5" - id="rect4304" - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#1ed8ec;fill-opacity:0;fill-rule:evenodd;stroke:#f2ff0e;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;" /> - <g - id="g4310" - transform="translate(-880.47502,196.64838)" > - <circle - r="6" - cy="432.78705" - cx="666.625" - id="path4306" - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#1ed8ec;fill-opacity:0;fill-rule:evenodd;stroke:#000000;stroke-width:1.10000014;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;" /> - <circle - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#1ed8ec;fill-opacity:0;fill-rule:evenodd;stroke:#000000;stroke-width:1.10000014;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;" - id="circle4308" - cx="666.625" - cy="432.78705" - r="3.6249998" /> - </g> - <path - style="opacity:0.21600001;fill:none;fill-rule:evenodd;stroke:#d4d4d4;stroke-width:0.92825276;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.78475822, 2.78475822;stroke-dashoffset:0;stroke-opacity:1" - d="m 7.2180534,637.60592 0,13.56802" - id="path4314"/> - <path - id="path4332" - d="m -393.38403,639.64882 0,12.75" - style="opacity:0.21600001;fill:none;fill-rule:evenodd;stroke:#d4d4d4;stroke-width:1.00000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:3.00000026, 3.00000026;stroke-dashoffset:0;stroke-opacity:1" /> - <path - style="opacity:1;fill:none;fill-rule:evenodd;stroke:#d4d4d4;stroke-width:0.9282527;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.78475821, 2.78475821;stroke-dashoffset:0;stroke-opacity:1" - d="m -22.190957,301.51493 22.56802038,0" - id="adjConnector"/> - <path - sodipodi:nodetypes="cccc" - id="path4893" - d="m -568.94472,458.6374 2.17576,-52.2338 1205.37474,0 1.5058,52.2338" - style="fill:#216ca1;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.50000012;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13px;line-height:125%;font-family:'Verana Sans';-inkscape-font-specification:'Verana Sans';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;" - x="-535.36261" - y="433.71609" - id="noteLabel" - sodipodi:linespacing="125%" ><tspan sodipodi:role="line" id="tspan4902" x="-535.36261" y="433.71609">song4</tspan></text> - <g - id="noteAttrs" - transform="translate(-930.38403,193.23677)" > - <rect - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#ffffff;fill-opacity:0.12637365;fill-rule:evenodd;stroke:none;stroke-width:1.10000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;" - id="rect4904" - width="108" - height="33" - x="454.5" - y="223.66205" - rx="0" - ry="0" /> - <rect - style="color:#000000;display:inline;overflow:visible;solid-color:#000000;solid-opacity:1;fill:#1ed8ec;fill-opacity:0.53846154;fill-rule:evenodd;stroke:#f2ff0e;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2, 2;stroke-dashoffset:0;stroke-opacity:1;" - id="rect4906" - width="22.5" - height="17" - x="467" - y="230.66205" /> - <text - xml:space="preserve" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:13px;line-height:125%;font-family:'Verana Sans';-inkscape-font-specification:'Verana Sans';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;" - x="499" - y="242.66205" - id="text4908" - sodipodi:linespacing="125%"><tspan sodipodi:role="line" id="tspan4910" x="499" y="242.66205">color</tspan></text> - </g> - - <g id="notes"> - </g> - <g id="cursor"> - <path id="cursor1" style="fill:none; stroke:#ff0303; stroke-width:1.5; stroke-linecap:butt;" /> - <path id="cursor2" style="fill:#9c0303;" /> - <path id="cursor3" style="fill:none; stroke:#ff0303; stroke-width:3; stroke-linecap:butt;" /> - </g> - </g> -</svg> + <svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + viewBox="0 0 1021 600" + > + <g id="layer1"> + + <path + style="fill:none;stroke:#d4d4d4;stroke-width:0.9282527;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:2.78475821, 2.78475821;stroke-dashoffset:0;" + d="m 202.190957,301.51493 22.56802038,0" + id="adjConnector"/> + <text + xml:space="preserve" + style="font-size:13px;line-height:125%;font-family:'Verana Sans';-inkscape-font-specification:'Verana Sans';text-align:start;text-anchor:start;fill:#000000;" + x="-338.38403" + y="631.3988" + id="text4290" + sodipodi:linespacing="125%" ><tspan sodipodi:role="line" id="tspan4292" x="-338.38403" y="631.3988">spotchase</tspan></text> + + <g id="notes"> + </g> + <g id="cursor"> + <path id="cursor1" style="fill:none; stroke:#ff0303; stroke-width:1.5; stroke-linecap:butt;" /> + <path id="cursor2" style="fill:#9c0303;" /> + <path id="cursor3" style="fill:none; stroke:#ff0303; stroke-width:3; stroke-linecap:butt;" /> + </g> + </g> + </svg> </template> <script> @@ -335,16 +181,19 @@ mid: this.querySelector("#cursor2"), bot: this.querySelector("#cursor3") }; - + + this.noteById = {}; }, setNote: function(uri, x1, x2, y1, y2) { - console.log('set', uri, x1, x2, y1, y2); - - var d = svgPathFromPoints([[x1, y2], [x1*.75 + x2*.25, y1], [x1*.25 + x2*.75, y1], [x2, y2]]); + var elem = this.noteById[uri]; + if (!elem) { + var s = '<path id="'+uri+'" style="fill:#53774b; stroke:#000000; stroke-width:1.5;"/>'; + this.$.notes.innerHTML += s; + elem = this.noteById[uri] = this.$.notes.lastChild; + } - var s = '<path style="fill:#53774b;fill-opacity:1;stroke:#000000;stroke-width:1.50000012;" d="' + d + '"/>'; - console.log(s); - this.$.notes.innerHTML += s; + var d = svgPathFromPoints([[x1, y2], [x1*.75 + x2*.25, y1], [x1*.25 + x2*.75, y1], [x2, y2]]); + elem.setAttribute('d', d); }, setCursor: function(y1, h1, y2, h2, zoom, cursor) { var xZoomedOut = this.offsetParent.offsetWidth * cursor.t / zoom.duration; @@ -481,17 +330,18 @@ <template> <style> :host { - pointer-events: none; - } + } </style> - <light9-timeline-adjuster center="{x: 50, y: 200}"></light9-timeline-adjuster> - <light9-timeline-adjuster center="{x: 90, y: 200}"></light9-timeline-adjuster> + <template is="dom-repeat" items="{{adjs}}"> + <light9-timeline-adjuster adj="{{item}}"></light9-timeline-adjuster> + </template> </template> <script> Polymer({ is: "light9-timeline-adjusters", properties: { + adjs: { type: Array } } }); </script> @@ -523,25 +373,18 @@ border: 3px yellow dotted; border-radius: 8px; padding: 5px; + + cursor: ew-resize; + -webkit-user-select: none; } </style> - <table style="left: {{center.x}}px; top: {{center.y}}px"> + <table id="top" style$="left: {{centerStyle.x}}px; top: {{centerStyle.y}}px"> <tr><td></td><td>↑</td><td></td></tr> - <tr><td>←</td><td><span>{{value}}</span></td><td>→</td></tr> + <tr><td>←</td><td><span id="label">{{value}}</span></td><td>→</td></tr> <tr><td></td><td>↓</td><td></td></tr> </table> </template> - <script> - Polymer({ - is: "light9-timeline-adjuster", - properties: { - center: {type: Object, notify: true}, - target: {type: Object, notify: true}, - value: {value: '0.26'} - } - }); - </script> </dom-module> <!-- sometimes we draw attrs within the shape of a note. --> @@ -557,3 +400,9 @@ }); </script> </dom-module> + +<script src="/lib/sylvester/sylvester.js"></script> +<script src="/lib/d3/d3.js"></script> +<script src="/lib/N3.js/browser/n3-browser.js"></script> +<script src="graph.js"></script> +<script src="timeline.js"></script>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/light9/web/timeline.coffee Fri Jun 03 11:35:09 2016 +0000 @@ -0,0 +1,124 @@ + +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 0.5 . +} + ") + + +class Adjustable + # + constructor: (@config) -> + @center = @config.getTarget().add(@config.getSuggestedTargetOffset()) + @getValue = @config.getValue + + +Polymer + is: 'light9-timeline-editor' + behaviors: [ Polymer.IronResizableBehavior ] + properties: + viewState: { type: Object } + ready: -> + @viewState = + zoomSpec: + duration: 190 + t1: 102 + t2: 161 + cursor: + t: 105 + + @fullZoomX = d3.scale.linear().domain([0, @viewState.zoomSpec.duration]).range([0, @offsetWidth]) + + animCursor = () => + @viewState.cursor.t = 130 + 20 * Math.sin(Date.now() / 2000) + @$.dia.setCursor(@$.audio.offsetTop, @$.audio.offsetHeight, + @$.zoomed.$.time.offsetTop, @$.zoomed.$.time.offsetHeight, + @viewState.zoomSpec, @viewState.cursor) + + @set('viewState.zoomSpec.t1', 80 + 10 * Math.sin(Date.now() / 3000)) + + setInterval(animCursor, 50) + + setTimeout(() => + @adjs = @persistDemo() #@makeZoomAdjs().concat(@persistDemo()) + , 3000) + + + persistDemo: -> + adj = new Adjustable({ + getValue: () => (graph.floatValue( + graph.Uri(':demoResource'), + graph.Uri(':startTime'))) + getTarget: () => $V([200, 300]) + getSuggestedTargetOffset: () => $V([-30, 0]) + }) + console.log(adj.config.getValue()) + + return [adj] + + makeZoomAdjs: -> + left = new Adjustable({ + getValue: () => (@viewState.zoomSpec.t1) + getTarget: () => $V([@fullZoomX(@viewState.zoomSpec.t1), @$.audio.offsetTop + @$.audio.offsetHeight / 2]) + getSuggestedTargetOffset: () => $V([-30, 0]) + }) + + right = new Adjustable({ + getValue: () => (@viewState.zoomSpec.t2) + getTarget: () => $V([@fullZoomX(@viewState.zoomSpec.t2), @$.audio.offsetTop + @$.audio.offsetHeight / 2]) + getSuggestedTargetOffset: () => $V([30, 0]) + }) + return [left, right] + + +Polymer + is: 'light9-timeline-adjuster' + properties: + adj: + type: Object + notify: true + target: + type: Object + notify: true + value: + type: String + computed: '_value(adj.value)' + centerStyle: + computed: '_centerStyle(adj.center)' + + _value: (adjValue) -> + d3.format(".4g")(adjValue) + + _centerStyle: (center) -> + { + x: center.e(1) + y: center.e(2) + } + + ready: -> + subj = graph.Uri(':demoResource') + pred = graph.Uri(':startTime') + ctx = graph.Uri('http://example.com/') + graph.subscribe subj, pred, null, (patch) => + for q in patch.addQuads + @set('adj.value', graph.toJs(q.object)) + + drag = d3.behavior.drag() + sel = d3.select(@$.label) + sel.call(drag) + drag.origin((d) -> {x: @offsetLeft, y: @offsetTop}) + drag.on 'dragstart', () => + drag._startValue = @adj.getValue() + + drag.on 'drag', () => + console.log('drag', d3.event) + newValue = drag._startValue + d3.event.x * .1 + graph.patchObject(subj, pred, graph.Literal(newValue), ctx)