Mercurial > code > home > repos > light9
diff web/fade/Light9EffectFader.ts @ 2376:4556eebe5d73
topdir reorgs; let pdm have its src/ dir; separate vite area from light9/
author | drewp@bigasterisk.com |
---|---|
date | Sun, 12 May 2024 19:02:10 -0700 |
parents | light9/web/fade/Light9EffectFader.ts@06bf6dae8e64 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/fade/Light9EffectFader.ts Sun May 12 19:02:10 2024 -0700 @@ -0,0 +1,190 @@ +import debug from "debug"; +import { css, html, LitElement } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import { NamedNode, Quad } from "n3"; +import { getTopGraph } from "../RdfdbSyncedGraph"; +import { showRoot } from "../show_specific"; +import { SyncedGraph } from "../SyncedGraph"; +import { Patch } from "../patch"; +import { Literal } from "n3"; +export { Light9Fader } from "./Light9Fader"; + +const log = debug("efffader") + +////////////////////////////////////// +const RETURN_URI = new NamedNode(""); +const RETURN_FLOAT = 1; +function get2Step<T extends NamedNode | number>(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 { + static styles = [ + css` + :host { + display: inline-block; + border: 2px gray outset; + background: #272727; + } + light9-fader { + margin: 0px; + width: 100%; + } + `, + ]; + render() { + if (this.conf === undefined || this.conf.value === undefined) { + return html`...`; + } + return html` + <div><resource-display .uri=${this.uri}></resource-display> + <light9-fader .value=${this.conf.value} @change=${this.onSliderInput}></light9-fader> + <div>${this.conf.value.toPrecision(3)}</div> + <div>effect <edit-choice nounlink .uri=${this.conf.effect} @edited=${this.onEffectChange}></edit-choice></div> + <div>attr <edit-choice nounlink .uri=${this.conf.effectAttr} @edited=${this.onEffectAttrChange}></edit-choice></div> + `; + } + + graph?: SyncedGraph; + ctx: NamedNode = new NamedNode(showRoot + "/fade"); + @property() uri!: NamedNode; + @state() conf?: EffectFader; // compiled from graph + + constructor() { + super(); + getTopGraph().then((g) => { + this.graph = g; + 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 + return; + } + + 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, conf: EffectFader) { + // external graph change -> conf.value + const U = graph.U(); + conf.value = get2Step(RETURN_FLOAT, graph, this.uri, U(":setting"), U(":value")); + // since conf attrs aren't watched as property: + this.requestUpdate() + } + + onSliderInput(ev: CustomEvent) { + // slider user input -> graph + if (this.conf === undefined) return; + this.conf.value = ev.detail.value + this.writeValueToGraph() + } + + writeValueToGraph() { + // this.value -> graph + if (this.graph === undefined) { + return; + } + const U = this.graph.U(); + if (this.conf === undefined) { + return; + } + if (this.conf.value === undefined) { + log(`value of ${this.uri} is undefined`) + return; + } + log('writeValueToGraph', this.conf.value) + const valueTerm = this.graph.LiteralRoundedFloat(this.conf.value); + const settingNode = this.graph.uriValue(this.uri, U(":setting")); + this.graph.patchObject(settingNode, this.graph.Uri(":value"), valueTerm, this.ctx); + + } + + onEffectChange(ev: CustomEvent) { + if (this.graph === undefined) { + return; + } + const { newValue } = ev.detail; + this.graph.patchObject(this.uri, this.graph.Uri(":effect"), newValue, this.ctx); + } + + onEffectAttrChange(ev: CustomEvent) { + 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); + } +}