Mercurial > code > home > repos > light9
view light9/live/Light9DeviceSettings.ts @ 2247:f5e4aa36985d
checkpoint show data
author | drewp@bigasterisk.com |
---|---|
date | Sat, 27 May 2023 01:15:29 -0700 |
parents | 5c269c03863d |
children | 75dfd7eb1e77 |
line wrap: on
line source
import debug from "debug"; import { css, html, LitElement, PropertyValues } from "lit"; import { customElement, property } from "lit/decorators.js"; import { NamedNode } from "n3"; import { sortBy, uniq } from "underscore"; import { Patch, patchContainsPreds } from "../web/patch"; import { getTopGraph } from "../web/RdfdbSyncedGraph"; import { SyncedGraph } from "../web/SyncedGraph"; import { GraphToControls } from "./GraphToControls"; import { Effect } from "./Effect"; export { EditChoice } from "../web/EditChoice"; export { Light9DeviceControl as Light9LiveDeviceControl } from "./Light9DeviceControl"; const log = debug("settings"); @customElement("light9-device-settings") export class Light9DeviceSettings extends LitElement { graph!: SyncedGraph; static styles = [ css` :host { display: flex; flex-direction: column; } #preview { width: 100%; } #deviceControls { flex-grow: 1; position: relative; width: 100%; overflow-y: auto; } light9-live-device-control > div { break-inside: avoid-column; } light9-live-device-control { } `, ]; render() { return html` <rdfdb-synced-graph></rdfdb-synced-graph> <h1>effect DeviceSettings</h1> <div id="save"> <div> <button @click=${this.newEffect}>New effect</button> <edit-choice .uri=${this.currentEffect ? this.currentEffect.uri : null} @edited=${this.onEffectChoice2}></edit-choice> <button @click=${this.clearAll}>clear settings in this effect</button> </div> </div> <div id="deviceControls"> ${this.devices.map( (device: NamedNode) => html` <light9-device-control .uri=${device} .effect=${this.currentEffect}> .graphToControls={this.graphToControls} </light9-device-control> ` )} </div> `; } devices: Array<NamedNode> = []; // uri of the effect being edited, or null. This is the // master value; GraphToControls follows. @property() currentEffect: Effect | null = null; // graphToControls!: GraphToControls; okToWriteUrl: boolean = false; constructor() { super(); getTopGraph().then((g) => { this.graph = g; this.graph.runHandler(this.findDevices.bind(this), "findDevices"); // this.graphToControls = new GraphToControls(this.graph); // this.graph.runHandler(this.update.bind(this), "Light9LiveControls update"); this.setEffectFromUrl(); }); } onEffectChoice2(ev: CustomEvent) { const uri = ev.detail.newValue as NamedNode; if (uri === null) { this.currentEffect = null; } else { this.currentEffect = new Effect(this.graph, uri); } } updated(changedProperties: PropertyValues<this>) { log("ctls udpated", changedProperties); if (changedProperties.has("currentEffect")) { log(`effectChoice to ${this.currentEffect?.uri?.value}`); this.onEffectChoice(); } // this.graphToControls?.debugDump(); } // Note that this doesn't fetch setting values, so it only should get rerun // upon (rarer) changes to the devices etc. findDevices(patch?: Patch) { const U = this.graph.U(); // if (patch && !patchContainsPreds(patch, [U("rdf:type")])) { // return; // } this.devices = []; let classes = this.graph.subjects(U("rdf:type"), U(":DeviceClass")); log(`found ${classes.length} device classes`); uniq(sortBy(classes, "value"), true).forEach((dc) => { sortBy(this.graph.subjects(U("rdf:type"), dc), "value").forEach((dev) => { log(`found dev ${dev.value}`); this.devices.push(dev as NamedNode); }); }); this.requestUpdate(); } setEffectFromUrl() { // not a continuous bidi link between url and effect; it only reads // the url when the page loads. const effect = new URL(window.location.href).searchParams.get("effect"); if (effect != null) { log(`found effect in url ${effect}`); this.currentEffect = new Effect(this.graph, this.graph.Uri(effect)); } this.okToWriteUrl = true; } writeToUrl(effect: NamedNode | undefined) { const effectStr = effect ? this.graph.shorten(effect) : ""; if (!this.okToWriteUrl) { return; } const u = new URL(window.location.href); if ((u.searchParams.get("effect") || "") === effectStr) { return; } u.searchParams.set("effect", effectStr); // this escapes : and / and i wish it didn't window.history.replaceState({}, "", u.href); log("wrote new url", u.href); } newEffect() { // this.effectChoice = this.graphToControls.newEffect(); } onEffectChoice() { const U = (x: any) => this.graph.Uri(x); // if (this.effectChoice == null) { // // unlink // log("onEffectChoice unlink"); // if (this.graphToControls != null) { // this.graphToControls.setEffect(null); // } // } else { // if (this.graphToControls != null) { // this.graphToControls.setEffect(this.effectChoice); // } else { // throw new Error("graphToControls not set"); // } // } this.writeToUrl(this.currentEffect?.uri); } clearAll() { // clears the effect! return; //this.graphToControls.emptyEffect(); } // configureFromGraph() { // const U = (x: string) => this.graph.Uri(x); // const newDevs: NamedNode[] = []; // for (let dc of Array.from(this.graph.sortedUris(this.graph.subjects(U("rdf:type"), U(":DeviceClass"))))) { // for (let dev of Array.from(this.graph.sortedUris(this.graph.subjects(U("rdf:type"), dc)))) { // if (this.graph.contains(dev, U(":hideInLiveUi"), null)) { // continue; // } // if (newDevs.length == 0) newDevs.push(dev); // } // } // log("is this called?"); // log(`controls update now has ${newDevs.length} devices`); // this.devices = newDevs; // this.requestUpdate(); // return; // // Tried css columns- big slowdown from relayout as I'm scrolling. // // Tried isotope- seems to only scroll to the right. // // Tried columnize- fails in jquery maybe from weird elements. // // not sure how to get this run after the children are created // return setTimeout( // () => // $("#deviceControls").isotope({ // // fitColumns would be nice, but it doesn't scroll vertically // layoutMode: "masonry", // containerStyle: null, // }), // 2000 // ); // } }