Files @ b62c78f35380
Branch filter:

Location: light9/light9/web/live/Light9LiveControls.ts

drewp@bigasterisk.com
bin/live vitejs runner

<dom-module id="light9-live-controls">
<template>
  <style>
   :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 {

   }
  </style>
  <rdfdb-synced-graph graph="{{graph}}"></rdfdb-synced-graph>

  <h1>device control</h1>

  <div id="save">
    <div>
      <button on-click="newEffect">New effect</button>
      <edit-choice graph="{{graph}}" uri="{{effectChoice}}"></edit-choice>
      <button on-click="clearAll">clear settings in this effect</button>
    </div>
  </div>

  <div id="deviceControls">
    <template is="dom-repeat" items="{{devices}}" as="device">
      <light9-live-device-control
        graph="{{graph}}"
        uri="{{device.uri}}"
        effect="{{effect}}"
        graph-to-controls="{{graphToControls}}"
      ></light9-live-device-control>
    </template>
  </div>
  
</template>
</dom-module>

const coffeeElementSetupLight9LiveControls = (function() {
    class Light9LiveControls extends Polymer.Element {
      static is: string;
      static getter_properties: {
          graph: { type: any; notify: boolean; }; devices: { type: any; notify: boolean; value: {}; };
          // string uri of the effect being edited, or null. This is the
          // master value; GraphToControls follows.
          effectChoice: { type: any; notify: boolean; value: any; }; graphToControls: { type: any; };
      };
      static getter_observers: {};
      graphToControls: any;
      okToWriteUrl: boolean;
      currentSettings: {};
      graph: any;
      effectChoice: any;
      static initClass() {
        this.is = "light9-live-controls";
        this.getter_properties = {
          graph: { type: Object, notify: true },
          devices: { type: Array, notify: true, value: [] },
          // string uri of the effect being edited, or null. This is the
          // master value; GraphToControls follows.
          effectChoice: { type: String, notify: true, value: null },
          graphToControls: { type: Object }
        };
        this.getter_observers = [
          'onGraph(graph)',
          'onEffectChoice(effectChoice)'
          ];
      }
  
      constructor() {
        super();
        this.graphToControls = null;
        this.okToWriteUrl = false;
      }
  
      ready() {
        super.ready(...arguments).ready();
        return this.currentSettings = {};
      }
  
      onGraph() {
        this.graphToControls = new GraphToControls(this.graph);
        this.graph.runHandler(this.update.bind(this), 'Light9LiveControls update');
  
        // need graph to be loaded, so we don't make double settings? not sure.
        return setTimeout(this.setFromUrl.bind(this), 1);
      }
  
      setFromUrl() {
        // 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 url', effect);
          this.effectChoice = effect;
        }
        return this.okToWriteUrl = true;
      }
  
      writeToUrl(effectStr: any) {
        if (!this.okToWriteUrl) { return; }
        const u = new URL(window.location.href);
        if (u.searchParams.get('effect') === effectStr) {
          return;        
        }
        u.searchParams.set('effect', effectStr);
        window.history.replaceState({}, "", u.href);
        return log('wrote new url', u.href);
      }
  
      newEffect() {
        return this.effectChoice = this.graphToControls.newEffect().value;
      }
        
      onEffectChoice() {
        const U = (x: any) => this.graph.Uri(x);
        if ((this.effectChoice == null)) {
          // unlink
          if (this.graphToControls != null) { this.graphToControls.setEffect(null); }
        } else {
          log('load', this.effectChoice);
          if (this.graphToControls != null) { this.graphToControls.setEffect(this.graph.Uri(this.effectChoice)); }
        }
        return this.writeToUrl(this.effectChoice);
      }
   
      clearAll() {
        // clears the effect!
        return this.graphToControls.emptyEffect();
      }
      
      update() {
        const U = (x: string) => this.graph.Uri(x);
  
        const newDevs = [];
        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;
            }
            newDevs.push({uri: dev});
          }
        }
  
        //log("controls update now has #{newDevs.length} devices")
        syncArray(this, 'devices', newDevs, (a: { uri: { value: any; }; }, b: { uri: { value: any; }; }) => a.uri.value === b.uri.value);
  
        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);
      }
    }
    
    Light9LiveControls.initClass();
    return Light9LiveControls;
  })();