# HG changeset patch # User drewp@bigasterisk.com # Date 2023-06-02 16:42:18 # Node ID b09ff4b0094cf87e2b11fa9c14d9158ccc7cbbd2 # Parent e28a9b41ad875571e57f5ce21733b30158a5d58e faders in pages now diff --git a/light9/fade/Light9EffectFader.ts b/light9/fade/Light9EffectFader.ts --- a/light9/fade/Light9EffectFader.ts +++ b/light9/fade/Light9EffectFader.ts @@ -1,11 +1,74 @@ import { css, html, LitElement } from "lit"; import { customElement, property, state } from "lit/decorators.js"; -import { NamedNode } from "n3"; +import { NamedNode, Quad } from "n3"; import { getTopGraph } from "../web/RdfdbSyncedGraph"; import { showRoot } from "../web/show_specific"; import { SyncedGraph } from "../web/SyncedGraph"; +import { Patch } from "../web/patch"; +import { Literal } from "n3"; export { Light9Fader } from "./Light9Fader"; +////////////////////////////////////// +const RETURN_URI = new NamedNode(""); +const RETURN_FLOAT = 1; +function get2Step(returnWhat: T, graph: SyncedGraph, subj1: NamedNode, pred1: NamedNode, pred2: NamedNode): T | undefined { + // ?subj1 ?pred1 ?x . ?x ?pred2 ?returned . + let x: NamedNode; + try { + x = graph.uriValue(subj1, pred1); + } catch (e) { + return undefined; + } + try { + if (typeof returnWhat === "object" && (returnWhat as NamedNode).termType == "NamedNode") { + return graph.uriValue(x, pred2) as T; + } else if (typeof returnWhat === "number") { + return graph.floatValue(x, pred2) as T; + } + } catch (e) { + return undefined; + } +} +function set2Step( + graph: SyncedGraph, // + subj1: NamedNode, + pred1: NamedNode, + baseName: string, + pred2: NamedNode, + newObjLiteral: Literal +) {} + +function maybeUriValue(graph: SyncedGraph, s: NamedNode, p: NamedNode): NamedNode | undefined { + try { + return graph.uriValue(s, p); + } catch (e) { + return undefined; + } +} +function maybeStringValue(graph: SyncedGraph, s: NamedNode, p: NamedNode): string | undefined { + try { + return graph.stringValue(s, p); + } catch (e) { + return undefined; + } +} +function maybeFloatValue(graph: SyncedGraph, s: NamedNode, p: NamedNode): number | undefined { + try { + return graph.floatValue(s, p); + } catch (e) { + return undefined; + } +} + +////////////////////////////////////// +class EffectFader { + constructor(public uri: NamedNode) {} + column: string = "unset"; + effect?: NamedNode; + effectAttr?: NamedNode; // :strength + setting?: NamedNode; // we assume fader always has exactly one setting + value?: number; +} @customElement("light9-effect-fader") export class Light9EffectFader extends LitElement { @@ -23,81 +86,85 @@ export class Light9EffectFader extends L `, ]; render() { + if (this.conf === undefined || this.conf.value === undefined) { + return html`...`; + } return html` - -
${this.value.toPrecision(3)}
-
eff:
-
attr:
-
Slider ${this.column}
+ +
${this.conf.value.toPrecision(3)}
+
effect
+
attr
`; } graph?: SyncedGraph; ctx: NamedNode = new NamedNode(showRoot + "/fade"); @property() uri!: NamedNode; - @property() column!: string; - @property() effect?: NamedNode; - @property() effectAttr?: NamedNode; - @state() setting?: NamedNode; - - @property() value: number = 0.0; + @state() conf?: EffectFader; // compiled from graph constructor() { super(); getTopGraph().then((g) => { this.graph = g; - this.graph.runHandler(this.compile.bind(this, this.graph), `config ${this.uri.value}`); - this.graph.runHandler(this.compileValue.bind(this, this.graph), `valueSync ${this.uri.value}`); + this.graph.runHandler(this.compile.bind(this, this.graph), `fader config ${this.uri.value}`); }); } private compile(graph: SyncedGraph) { const U = graph.U(); + this.conf = undefined; + + const conf = new EffectFader(this.uri); + if (!graph.contains(this.uri, U("rdf:type"), U(":Fader"))) { // not loaded yet, perhaps - this.column = "unset"; - this.effect = undefined; - this.effectAttr = undefined; return; } - this.column = graph.stringValue(this.uri, U(":column")); - this.effect = graph.uriValue(this.uri, U(":effect")); - this.setting = graph.uriValue(this.uri, U(":setting")); - if (this.setting !== undefined) { - try { - this.effectAttr = graph.uriValue(this.setting, U(":effectAttr")); - } catch (e) { - this.effectAttr = undefined; - } - } + + conf.column = maybeStringValue(graph, this.uri, U(":column")) || "unset"; + conf.effect = maybeUriValue(graph, this.uri, U(":effect")); + conf.effectAttr = get2Step(RETURN_URI, graph, this.uri, U(":setting"), U(":effectAttr")); + + this.conf = conf; + graph.runHandler(this.compileValue.bind(this, graph, this.conf), `fader config.value ${this.uri.value}`); } - private compileValue(graph: SyncedGraph) { + private compileValue(graph: SyncedGraph, conf: EffectFader) { + // external graph change -> conf.value const U = graph.U(); - if (!graph.contains(this.uri, U("rdf:type"), U(":Fader"))) { - // not loaded yet - // console.timeEnd(`valueSync ${this.uri.value}`) - return; - } - const st = graph.uriValue(this.uri, U(":setting")); - this.value = graph.floatValue(st, graph.Uri(":value")); + conf.value = get2Step(RETURN_FLOAT, graph, this.uri, U(":setting"), U(":value")); } onSliderInput(ev: CustomEvent) { + // slider user input -> graph if (this.graph === undefined) { return; } const U = this.graph.U(); - const prev = this.value; - const v: number = ev.detail.value; - this.value = parseFloat(v.toPrecision(3)); // rewrite pls - if (this.value == prev) { + // const prev = this.value; + // const v: number = ev.detail.value; + // this.value = parseFloat(v.toPrecision(3)); // rewrite pls + // if (this.value == prev) { + // return; + // } + // if (!this.setting) { + // throw new Error("can't make new settings yet"); + // } + + if (this.conf === undefined) { return; } - if (!this.setting) { - throw new Error("can't make new settings yet"); + let patch = new Patch([], []); + let settingNode: NamedNode; + const valueTerm = this.graph.LiteralRoundedFloat(ev.detail.value); + try { + settingNode = this.graph.uriValue(this.uri, U(":setting")); + } catch (e) { + settingNode = this.graph.nextNumberedResource(U(":fadeset")); + patch = patch.update(new Patch([], [new Quad(this.conf.uri, U(":setting"), settingNode, this.ctx)])); } - this.graph.patchObject(this.setting, this.graph.Uri(":value"), this.graph.LiteralRoundedFloat(this.value), this.ctx); + patch = patch.update(this.graph.getObjectPatch(settingNode, this.graph.Uri(":value"), valueTerm, this.ctx)); + this.graph.applyAndSendPatch(patch); } onEffectChange(ev: CustomEvent) { @@ -112,11 +179,11 @@ export class Light9EffectFader extends L if (this.graph === undefined) { return; } - const { newValue } = ev.detail; - if (this.setting === undefined) { - this.setting = this.graph.nextNumberedResource(this.graph.Uri(":fade_set")); - this.graph.patchObject(this.uri, this.graph.Uri(":setting"), this.setting, this.ctx); - } - this.graph.patchObject(this.setting, this.graph.Uri(":effectAttr"), newValue, this.ctx); + // const { newValue } = ev.detail; + // if (this.setting === undefined) { + // this.setting = this.graph.nextNumberedResource(this.graph.Uri(":fade_set")); + // this.graph.patchObject(this.uri, this.graph.Uri(":setting"), this.setting, this.ctx); + // } + // this.graph.patchObject(this.setting, this.graph.Uri(":effectAttr"), newValue, this.ctx); } } diff --git a/light9/fade/Light9FadeUi.ts b/light9/fade/Light9FadeUi.ts --- a/light9/fade/Light9FadeUi.ts +++ b/light9/fade/Light9FadeUi.ts @@ -1,16 +1,26 @@ import debug from "debug"; -import { css, html, LitElement } from "lit"; +import { css, html, LitElement, TemplateResult } from "lit"; import { customElement, property } from "lit/decorators.js"; -import { NamedNode } from "n3"; +import * as N3 from "n3"; +import { NamedNode, Quad } from "n3"; +import { Patch } from "../web/patch"; import { getTopGraph } from "../web/RdfdbSyncedGraph"; -import { shortShow } from "../web/show_specific"; +import { showRoot } from "../web/show_specific"; import { SyncedGraph } from "../web/SyncedGraph"; export { EditChoice } from "../web/EditChoice"; export { Light9EffectFader } from "./Light9EffectFader"; -debug.enable("*"); +debug.enable("*,autodep"); const log = debug("fade"); +class FadePage { + constructor(public uri: NamedNode) {} + faders: NamedNode[] = []; +} +class FadePages { + pages: FadePage[] = []; +} + @customElement("light9-fade-ui") export class Light9FadeUi extends LitElement { static styles = [ @@ -27,35 +37,77 @@ export class Light9FadeUi extends LitEle

Fade

+ ${(this.fadePages?.pages || []).map(this.renderPage)} - ${this.faders.map((fd) => html` `)} +
`; } + private renderPage(page: FadePage): TemplateResult { + return html`
+
+ Page + ${page.faders.map((fd) => html` `)} +
+
`; + } graph!: SyncedGraph; + ctx: NamedNode = new NamedNode(showRoot + "/fade"); - @property() faders: NamedNode[] = []; + @property() fadePages?: FadePages; constructor() { super(); getTopGraph().then((g) => { this.graph = g; - // todo: start with a page, then find the faders on that page - this.faders = [ - g.Uri(`:show/${shortShow}/fadePage1f0`), - g.Uri(`:show/${shortShow}/fadePage1f1`), - g.Uri(`:show/${shortShow}/fadePage1f2`), - g.Uri(`:show/${shortShow}/fadePage1f3`), - g.Uri(`:show/${shortShow}/fadePage1f4`), - g.Uri(`:show/${shortShow}/fadePage1f5`), - g.Uri(`:show/${shortShow}/fadePage1f6`), - g.Uri(`:show/${shortShow}/fadePage1f7`), - ]; + this.graph.runHandler(this.compile.bind(this), `faders layout`); }); } connectedCallback(): void { super.connectedCallback(); } -} + compile() { + const U = this.graph.U(); + this.fadePages = undefined; + const fadePages = new FadePages(); + for (let page of this.graph.subjects(U("rdf:type"), U(":FadePage"))) { + const fp = new FadePage(page as NamedNode); + try { + for (let fader of this.graph.objects(page, U(":fader"))) { + fp.faders.push(fader as NamedNode); + } + fp.faders.sort((a, b) => { + // todo this is supposed to sort by :column so you can reorder + return a.value.localeCompare(b.value); + }); + fadePages.pages.push(fp); + } catch (e) {} + } + fadePages.pages.sort((a, b) => { + return a.uri.value.localeCompare(b.uri.value); + }); + this.fadePages = fadePages; + } + addPage() { + const U = this.graph.U(); + const uri = this.graph.nextNumberedResource(showRoot + "/fadePage"); + const adds = [ + // + new Quad(uri, U("rdf:type"), U(":FadePage"), this.ctx), + new Quad(uri, U("rdfs:label"), N3.DataFactory.literal("unnamed"), this.ctx), + ]; + for (let n = 1; n <= 8; n++) { + const f = this.graph.nextNumberedResource(showRoot + "/fader"); + const s = this.graph.nextNumberedResource(showRoot + "/faderset"); + adds.push(new Quad(uri, U(":fader"), f, this.ctx)); + adds.push(new Quad(f, U("rdf:type"), U(":Fader"), this.ctx)); + adds.push(new Quad(f, U(":column"), N3.DataFactory.literal("" + n), this.ctx)); + adds.push(new Quad(f, U(":setting"), s, this.ctx)); + adds.push(new Quad(s, U(":effectAttr"), U(":strength"), this.ctx)); + adds.push(new Quad(s, U(":value"), this.graph.LiteralRoundedFloat(0), this.ctx)); + } + this.graph.applyAndSendPatch(new Patch([], adds)); + } +} diff --git a/light9/fade/Light9Fader.ts b/light9/fade/Light9Fader.ts --- a/light9/fade/Light9Fader.ts +++ b/light9/fade/Light9Fader.ts @@ -17,7 +17,7 @@ export class Light9Fader extends LitElem display: inline-block; border: 2px gray inset; background: #000; - height: 250px; + height: 130px; } #handle { background: gray; @@ -33,7 +33,7 @@ export class Light9Fader extends LitElem @query("#handle") handleEl!: HTMLElement; - troughHeight = 250 - 2 - 2 - 5 - 5; + troughHeight = 130 - 2 - 2 - 5 - 5; handleHeight = 20; drag?: Drag; diff --git a/light9/web/EditChoice.ts b/light9/web/EditChoice.ts --- a/light9/web/EditChoice.ts +++ b/light9/web/EditChoice.ts @@ -17,11 +17,11 @@ function setupDrop( const highlight = () => highlightElem.classList.add("dragging"); const unhighlight = () => highlightElem.classList.remove("dragging"); - senseElem.addEventListener("drag", (event: DragEvent) => {}); + senseElem.addEventListener("drag", (event: DragEvent) => { }); - senseElem.addEventListener("dragstart", (event: DragEvent) => {}); + senseElem.addEventListener("dragstart", (event: DragEvent) => { }); - senseElem.addEventListener("dragend", (event: DragEvent) => {}); + senseElem.addEventListener("dragend", (event: DragEvent) => { }); senseElem.addEventListener("dragover", (event: DragEvent) => { event.preventDefault(); @@ -108,7 +108,7 @@ export class EditChoice extends LitEleme _setUri(u?: NamedNode) { this.uri = u; - this.dispatchEvent(new CustomEvent("edited", {detail: {newValue: u}})); + this.dispatchEvent(new CustomEvent("edited", { detail: { newValue: u } })); } unlink() {