Files @ d087499d7833
Branch filter:

Location: light9/web/live/Light9AttrControl.ts - annotation

drewp@bigasterisk.com
checkpoint show data
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
4556eebe5d73
import debug from "debug";
import { css, html, LitElement, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { Literal, NamedNode } from "n3";
import { SubEvent } from "sub-events";
import { getTopGraph } from "../RdfdbSyncedGraph";
import { SyncedGraph } from "../SyncedGraph";
import { ControlValue, Effect } from "./Effect";
import { DeviceAttrRow } from "./Light9DeviceControl";
export { Slider } from "@material/mwc-slider";
export { Light9ColorPicker } from "../light9-color-picker";
export { Light9Listbox } from "./Light9Listbox";
const log = debug("settings.dev.attr");

type DataTypeNames = "scalar" | "color" | "choice";
const makeType = (d: DataTypeNames) => new NamedNode(`http://light9.bigasterisk.com/${d}`);

// UI for one device attr (of any type).
@customElement("light9-attr-control")
export class Light9AttrControl extends LitElement {
  graph!: SyncedGraph;

  static styles = [
    css`
      #colorControls {
        display: flex;
        align-items: center;
      }
      #colorControls > * {
        margin: 0 3px;
      }
      :host {
      }
      mwc-slider {
        width: 250px;
      }
    `,
  ];

  @property() deviceAttrRow: DeviceAttrRow | null = null;
  @state() dataType: DataTypeNames = "scalar";
  @property() effect: Effect | null = null;
  @property() enableChange: boolean = false;
  @property() value: ControlValue | null = null; // e.g. color string

  constructor() {
    super();
    getTopGraph().then((g) => {
      this.graph = g;
      if (this.deviceAttrRow === null) throw new Error();
    });
  }

  connectedCallback(): void {
    super.connectedCallback();
    setTimeout(() => {
      // only needed once per page layout
      this.shadowRoot?.querySelector("mwc-slider")?.layout(/*skipUpdateUI=*/ false);
    }, 1);
  }

  render() {
    if (this.deviceAttrRow === null) throw new Error();
    if (this.dataType == "scalar") {
      const v = this.value || 0;
      return html`<mwc-slider .value=${v} step=${1 / 255} min="0" max="1" @input=${this.onValueInput}></mwc-slider> `;
    } else if ((this.dataType = "color")) {
      const v = this.value || "#000";
      return html`
        <div id="colorControls">
          <button @click=${this.goBlack}>0.0</button>
          <light9-color-picker .color=${v} @input=${this.onValueInput}></light9-color-picker>
        </div>
      `;
    } else if (this.dataType == "choice") {
      return html`<light9-listbox .choices=${this.deviceAttrRow.choices} .value=${this.value}> </light9-listbox> `;
    }
  }

  updated(changedProperties: PropertyValues<this>) {
    super.updated(changedProperties);

    if (changedProperties.has("deviceAttrRow")) {
      this.onDeviceAttrRowProperty();
    }
    if (changedProperties.has("effect")) {
      this.onEffectProperty();
    }
    if (changedProperties.has("value")) {
      this.onValueProperty();
    }
  }

  private onValueProperty() {
    if (this.deviceAttrRow === null) throw new Error();
    if (!this.graph) {
      log('ignoring value change- no graph yet')
      return;
    }
    if (this.effect === null) {
      this.value = null;
    } else {
      const p = this.effect.edit(
        //
        this.deviceAttrRow.device,
        this.deviceAttrRow.uri,
        this.value
      );
      if (!p.isEmpty()) {
        log("Effect told us to graph.patch this:\n", p.dump());
        this.graph.applyAndSendPatch(p);
      }
    }
  }

  private onEffectProperty() {
    if (this.effect === null) {
      log('no effect obj yet')
      return;
    }
    // effect will read graph changes on its own, but emit an event when it does
    this.effect.settingsChanged.subscribe(() => {
      this.effectSettingsChanged();
    });
    this.effectSettingsChanged();
  }

  private effectSettingsChanged() {
    // something in the settings graph is new
    if (this.deviceAttrRow === null) throw new Error();
    if (this.effect === null) throw new Error();
    // log("graph->ui on ", this.deviceAttrRow.device, this.deviceAttrRow.uri);
    const v = this.effect.currentValue(this.deviceAttrRow.device, this.deviceAttrRow.uri);
    this.onGraphValueChanged(v);
  }

  private onDeviceAttrRowProperty() {
    if (this.deviceAttrRow === null) throw new Error();
    const d = this.deviceAttrRow.dataType;
    if (d.equals(makeType("scalar"))) {
      this.dataType = "scalar";
    } else if (d.equals(makeType("color"))) {
      this.dataType = "color";
    } else if (d.equals(makeType("choice"))) {
      this.dataType = "choice";
    }
  }

  onValueInput(ev: CustomEvent) {
    if (ev.detail === undefined) {
      // not sure what this is, but it seems to be followed by good events
      return;
    }
    // log(ev.type, ev.detail.value);
    this.value = ev.detail.value;
    // this.graphToControls.controlChanged(this.device, this.deviceAttrRow.uri, ev.detail.value);
  }

  onGraphValueChanged(v: ControlValue | null) {
    if (this.deviceAttrRow === null) throw new Error();
    // log("change: control must display", v, "for", this.deviceAttrRow.device.value, this.deviceAttrRow.uri.value);
    // this.enableChange = false;
    if (this.dataType == "scalar") {
      if (v !== null) {
        this.value = v;
      } else {
        this.value = 0;
      }
    } else if (this.dataType == "color") {
      this.value = v;
    }
  }

  goBlack() {
    this.value = "#000000";
  }

  onChoice(value: any) {
    // if (value != null) {
    //   value = this.graph.Uri(value);
    // } else {
    //   value = null;
    // }
  }

  onChange(value: any) {
    // if (typeof value === "number" && isNaN(value)) {
    //   return;
    // } // let onChoice do it
    // //log('change: control tells graph', @deviceAttrRow.uri.value, value)
    // if (value === undefined) {
    //   value = null;
    // }
  }
}