Changeset - 97e4f1b5ff19
[Not reviewed]
default
0 4 0
Drew Perttula - 8 years ago 2017-06-06 06:37:09
drewp@bigasterisk.com
choice UI support on live editor
Ignore-this: e9bb570f128b05a498d05b4c6b6bcf86
4 files changed with 83 insertions and 12 deletions:
0 comments (0 inline, 0 general)
light9/web/lib/bower.json
Show inline comments
 
{
 
  "name": "3rd-party libs",
 
  "dependencies": {
 
    "polymer": "~1.4.0",
 
    "paper-slider": "PolymerElements/paper-slider#~1.0.11",
 
    "iron-ajax": "PolymerElements/iron-ajax#~1.2.0",
 
    "jquery": "~2.2.4",
 
    "underscore": "~1.8.3",
 
    "jquery-ui": "~1.11.4",
 
    "QueryString": "http://unixpapa.com/js/QueryString.js",
 
    "knockout": "knockoutjs#^3.4.0",
 
    "sylvester": "~0.1.3",
 
    "d3": "https://github.com/d3/d3.git#e7194db33090a0afc06c77a959594361ffb949df",
 
    "rdflib.js": "https://github.com/linkeddata/rdflib.js.git#920e59fe37",
 
    "rdfstore": "https://github.com/antoniogarrote/rdfstore-js.git#b3f7c0c9c1da9b26261af0d4858722fa982411bb",
 
    "N3.js": "https://github.com/RubenVerborgh/N3.js.git#04f4e21f4ccb351587dc00a3f26340b28d4bb10f",
 
    "shortcut": "http://www.openjs.com/scripts/events/keyboard_shortcuts/shortcut.js",
 
    "async": "https://github.com/caolan/async.git#^1.5.2",
 
    "iron-resizable-behavior": "PolymerElements/iron-resizable-behavior#^1.0.3",
 
    "paper-radio-button": "PolymerElements/paper-radio-button#^1.2.2",
 
    "paper-button": "PolymerElements/paper-button#^1.0.12",
 
    "paper-dialog": "PolymerElements/paper-dialog#^1.0.4",
 
    "paper-radio-group": "PolymerElements/paper-radio-group#^1.2.2",
 
    "color": "https://github.com/One-com/one-color.git#^3.0.4"
 
    "color": "https://github.com/One-com/one-color.git#^3.0.4",
 
    "paper-listbox": "PolymerElements/paper-listbox#1.1.3",
 
    "paper-item": "PolymerElements/paper-item#1.2.2"
 
  },
 
  "resolutions": {
 
    "paper-styles": "^1.1.4",
 
    "rdflib.js": "920e59fe37",
 
    "d3": "e7194db33090a0afc06c77a959594361ffb949df",
 
    "webcomponentsjs": "^0.7.24",
 
    "polymer": "^1.2.1"
 
  }
 
}
light9/web/live/index.html
Show inline comments
 
<!doctype html>
 
<html>
 
  <head>
 
    <title>device control</title>
 
    <meta charset="utf-8" />
 
    <link rel="stylesheet" href="/style.css">
 
    <script src="/lib/webcomponentsjs/webcomponents-lite.min.js"></script>
 
    <link rel="import" href="/lib/polymer/polymer.html">
 
    <link rel="import" href="/lib/paper-slider/paper-slider.html">
 
    <link rel="import" href="/lib/paper-listbox/paper-listbox.html">
 
    <link rel="import" href="/lib/paper-item/paper-item.html">
 
    <link rel="import" href="/lib/iron-ajax/iron-ajax.html">
 
    <link rel="import" href="../light9-collector-client.html">
 

	
 
    <script src="/lib/d3/build/d3.min.js"></script>
 
    <script src="/lib/N3.js-pull61/browser/n3-browser.js"></script>
 
    <script src="/lib/async/dist/async.js"></script>
 
    <script src="/lib/underscore/underscore-min.js"></script>
 
    <link rel="import" href="../rdfdb-synced-graph.html">
 
    <link rel="import" href="/resource-display.html">
 
    <link rel="import" href="/light9-color-picker.html">
 
  </head>
 
  <body>
 

	
 
    <dom-module id="light9-listbox">
 
      <template>
 
        <style>
 
         paper-listbox {
 
             --paper-listbox-background-color: none;
 
             --paper-listbox-color: white;
 
             --paper-listbox: {
 
                 /* measure biggest item? use flex for columns? */
 
                 column-width: 9em;
 
             }
 
         }
 
         paper-item {
 
             --paper-item-min-height: 0;
 
             --paper-item: {
 
                 display: block;
 
                 border: 1px outset #0f440f;
 
                 margin: 0 1px 5px 0;
 
                 background: #0b1d0b;
 
             }
 
         }
 
        </style>
 
        <paper-listbox id="list"
 
                       selected="{{value}}"
 
                       attr-for-selected="uri"
 
                       on-focus-changed="selectOnFocus"
 
        >
 
          <paper-item on-focus="selectOnFocus">None</paper-item>
 
          <template is="dom-repeat" items="{{choices}}">
 
            <paper-item on-focus="selectOnFocus" uri="{{item.uri}}">{{item.label}}</paper-item>
 
          </template>
 
        </paper-listbox>
 

	
 
      </template>
 
      <script>
 
       HTMLImports.whenReady(function () {
 
           Polymer({
 
               is: "light9-listbox",
 
               properties: {
 
                   choices: { type: Array },
 
                   value: { type: String, notify: true },
 
               },
 
               observers: ['onValue(value)'],
 
               selectOnFocus: function(ev) {
 
                   if (ev.target.uri === undefined) {
 
                       // *don't* clear for this, or we can't cycle through all choices (including none) with up/down keys
 
                       //this.clear();
 
                       //return;
 
                   }
 
                   this.value = ev.target.uri;
 
                   
 
               },
 
               onValue: function(value) {
 
                   if (value === null) {
 
                       this.clear();
 
                   }
 
               },
 
               clear: function() {
 
                   this.async(function() {
 
                       this.querySelectorAll('paper-item').forEach(
 
                           function(item) { item.blur(); });
 
                       this.value = undefined;
 
                   }.bind(this));
 

	
 
               },
 
               
 
           });
 
       });
 
      </script>
 
    </dom-module>
 
    
 
    <dom-module id="light9-live-control">
 
      <template>
 
        <style>
 
         #colorControls {
 
             display: flex;
 
             align-items: center;
 
         }
 
         #colorControls > * {
 
             margin: 0 3px;
 
         }
 
         #colorControls paper-slider {
 

	
 
             }
 
         }
 
         paper-slider { width: 100%; height: 25px; }
 
        </style>
 

	
 
        <style is="custom-style">
 
         paper-slider {
 
             --paper-slider-knob-color: var(--paper-red-500);
 
             --paper-slider-active-color: var(--paper-red-500);
 

	
 
             --paper-slider-font-color: white;
 
             --paper-slider-input: {
 
                 width: 75px;
 

	
 
                 background: black;
 
             }
 
         }
 
         </style>
 
         
 
        </style>
 

	
 
        <template is="dom-if" if="{{deviceAttr.useSlider}}">
 
          <paper-slider min="0"
 
                        max="{{deviceAttr.max}}"
 
                        step=".001"
 
                        editable
 
                        content-type="application/json"
 
                        immediate-value="{{immediateSlider}}"></paper-slider>
 
        </template>
 
        <template is="dom-if" if="{{deviceAttr.useColor}}">
 
        <div id="colorControls">
 
          <button on-click="goBlack">0.0</button>
 
          <light9-color-picker color="{{value}}"></light9-color-picker>
 
         
 
        </div>
 
        </template>
 
        <template is="dom-if" if="{{deviceAttr.useChoice}}">
 
          <select size$="{{deviceAttr.choiceSize}}" value="{{pickedChoice::change}}">
 
            <option value="">None</option>
 
            <template is="dom-repeat" items="{{deviceAttr.choices}}">
 
              <option value="{{item.uri}}">{{item.label}}</option>
 
            </template>
 
          </select>
 
          <light9-listbox choices="{{deviceAttr.choices}}" value="{{value}}">
 
          </light9-listbox>
 
        </template>
 

	
 
      </template>
 
     
 
    </dom-module>
 

	
 
    <dom-module id="light9-live-device-control">
 
      <template>
 
        <style>
 
         .device {
 
             border: 2px solid #151e2d;
 
             margin: 4px;
 
             padding: 1px;
 
             background: #171717;  /* deviceClass gradient added later */
 
             break-inside: avoid-column;
 
             
 
         }
 
         .deviceAttr {
 
             border-top: 1px solid #272727;
 
             padding-bottom: 2px;
 
             display: flex;
 
         }
 
         .deviceAttr > span {
 

	
 
         }
 
         .deviceAttr > light9-live-control {
 
             flex-grow: 1;
 
         }
 
         h2 {
 
             font-size: 110%;
 
             padding: 4px;
 
         }
 
         .device, h2 {
 
         border-top-right-radius: 15px;
 
}
 

	
 
         #mainLabel {
 
             font-size: 120%; 
 
             color: #9ab8fd;
 
             text-decoration: initial;
 
         }
 
        </style>
 
        <div class="device">
 
          <h2 style$="[[bgStyle]]">
 
            <resource-display id="mainLabel" graph="{{graph}}" uri="{{uri}}"></resource-display>
 
            a <resource-display minor graph="{{graph}}" uri="{{deviceClass}}"></resource-display>
 
          </h2>
 
          <template is="dom-repeat" items="{{deviceAttrs}}" as="dattr">
light9/web/live/live.coffee
Show inline comments
 
@@ -56,97 +56,97 @@ Polymer
 
    @deviceAttrs = []
 
    for da in _.unique(_.sortBy(@graph.objects(@deviceClass, U(':deviceAttr'))))
 
      dataType = @graph.uriValue(da, U(':dataType'))
 
      daRow = {
 
        uri: da
 
        dataType: dataType
 
        showColorPicker: dataType == U(':color')
 
        }
 
      if dataType == 'http://light9.bigasterisk.com/color'
 
        daRow.useColor = true
 

	
 
      else if dataType == U(':choice')
 
        daRow.useChoice = true
 
        choiceUris = _.sortBy(@graph.objects(da, U(':choice')))
 
        daRow.choices = ({uri: x, label: @graph.labelOrTail(x)} for x in choiceUris)
 
        daRow.choiceSize = Math.min(choiceUris.length + 1, 10)
 
      else
 
        daRow.useSlider = true
 
        daRow.max = 1
 
        if dataType == U(':angle')
 
          # varies
 
          daRow.max = 1
 

	
 
      @push('deviceAttrs', daRow)
 

	
 
    
 
Polymer
 
  is: "light9-live-controls"
 
  properties:
 
    graph: { type: Object, notify: true }
 
    client: { type: Object, notify: true }
 
    devices: { type: Array, notify: true }
 
    currentSettings: { type: Object, notify: true } # dev+attr: [dev, attr, value]
 
    effectPreview: { type: String, notify: true }
 
    newEffectName: { type: String, notify: true }
 
  observers: [
 
    'onGraph(graph)'
 
    ]
 
  ready: ->
 
    @currentSettings = {}
 
    @effectPreview = JSON.stringify({})
 
    window.gather = (sent) =>
 
      [dev, devAttr, value] = sent[0]
 
      key = dev + " " + devAttr
 
      # this is a bug for zoom=0, since collector will default it to
 
      # stick at the last setting if we don't explicitly send the
 
      # 0. rx/ry similar though not the exact same deal because of
 
      # their remap.
 
      if value == 0 or value == '#000000'
 
      if value == 0 or value == '#000000' or value == null or value == undefined
 
        delete @currentSettings[key]
 
      else
 
        @currentSettings[key] = [dev, devAttr, value]
 
      @effectPreview = JSON.stringify(v for k,v of @currentSettings)
 

	
 
      @debounce('send', @sendAll.bind(@), 2)
 

	
 
  currentSettingsList: -> (v for k,v of @currentSettings)
 
      
 
  sendAll: ->
 
    @client.send(@currentSettingsList())
 
      
 
  saveNewEffect: ->
 
    uriName = @newEffectName.replace(/[^a-zA-Z0-9_]/g, '')
 
    return if not uriName.length
 

	
 
    U = (x) => @graph.Uri(x)
 

	
 
    effectUri = U(":effect") + "/#{uriName}"
 
    ctx = U("http://light9.bigasterisk.com/show/dance2017/effect/#{uriName}")
 
    quad = (s, p, o) => {subject: s, predicate: p, object: o, graph: ctx}
 

	
 
    addQuads = [
 
      quad(effectUri, U('rdf:type'), U(':Effect'))
 
      quad(effectUri, U('rdfs:label'), @graph.Literal(@newEffectName))
 
      quad(effectUri, U(':publishAttr'), U(':strength'))
 
      ]
 
    settings = @graph.nextNumberedResources(effectUri + '_set', @currentSettingsList().length)
 
    for row in @currentSettingsList()
 
      if row[2] == 0 or row[2] == '#000000'
 
        continue
 
      setting = settings.shift()
 
      addQuads.push(quad(effectUri, U(':setting'), setting))
 
      addQuads.push(quad(setting, U(':device'), row[0]))
 
      addQuads.push(quad(setting, U(':deviceAttr'), row[1]))
 
      scaledAttributeTypes = [U(':color'), U(':brightness'), U(':uv')]
 
      value = if typeof(row[2]) == 'number'
 
          @graph.LiteralRoundedFloat(row[2])
 
        else
 
          @graph.Literal(row[2])
 
      settingType = if row[1] in scaledAttributeTypes then U(':scaledValue') else U(':value')
 
      addQuads.push(quad(setting, settingType, value))
 
      
 
    patch = {addQuads: addQuads, delQuads: []}
 
    log('save', patch)
 
    @graph.applyAndSendPatch(patch)
 
    @newEffectName = ''
 

	
show/dance2017/deviceClass.n3
Show inline comments
 
@prefix : <http://light9.bigasterisk.com/> .
 
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
 

	
 
:color              a :DeviceAttr; rdfs:label "color"; :dataType :color .
 
:rx                 a :DeviceAttr; rdfs:label "rx"; :dataType :angle .
 
:ry                 a :DeviceAttr; rdfs:label "ry"; :dataType :angle .
 
:uv                 a :DeviceAttr; rdfs:label "uv"; :dataType :scalar .
 
:brightness         a :DeviceAttr; rdfs:label "brightness"; :dataType :scalar .
 
:zoom               a :DeviceAttr; rdfs:label "zoom"; :dataType :scalar ;
 
  rdfs:comment "maybe make this a separate 'wide to narrow' type" .
 
:focus              a :DeviceAttr; rdfs:label "focus"; :dataType :scalar .
 
:iris               a :DeviceAttr; rdfs:label "iris"; :dataType :scalar .
 
:prism              a :DeviceAttr; rdfs:label "prism"; :dataType :scalar .
 
:strobe             a :DeviceAttr; rdfs:label "strobe"; :dataType :scalar;
 
  rdfs:comment "0=none, 1=fastest" .
 
:goboSpeed          a :DeviceAttr; rdfs:label "goboSpeed"; :dataType :scalar ;
 
  rdfs:comment "0=stopped, 1=rotate the fastest".
 
:quantumGoboChoice  a :DeviceAttr; rdfs:label "quantumGoboChoice"; :dataType :choice;
 
:quantumGoboChoice  a :DeviceAttr; rdfs:label "gobo"; :dataType :choice;
 
  :choice :open, :spider, :windmill, :limbo, :brush, :whirlpool, :stars .
 
:mini15GoboChoice   a :DeviceAttr; rdfs:label "mini15GoboChoice"; :dataType :choice;
 
:mini15GoboChoice   a :DeviceAttr; rdfs:label "gobo"; :dataType :choice;
 
  :choice :mini15Gobo1, :mini15Gobo2, :mini15Gobo3, :mini15Gobo4, :mini15Gobo5, :mini15Gobo6, :mini15Gobo7, :mini15Gobo8, :mini15Gobo9, :mini15Gobo10 .
 

	
 
:goboShake          a :DeviceAttr; rdfs:label "goboShake"; :dataType :scalar .
 

	
 
:mini15Gobo1 :value 3 .
 
:mini15Gobo2 :value 10 .
 
:mini15Gobo3 :value 18 .
 
:mini15Gobo4 :value 26 .
 
:mini15Gobo5 :value 34 .
 
:mini15Gobo6 :value 42 .
 
:mini15Gobo7 :value 50 .
 
:mini15Gobo8 :value 58 .
 
:mini15Gobo9 :value 66 .
 
:mini15Gobo10 :value 74 .
 

	
 
:SimpleDimmer a :DeviceClass; rdfs:label "SimpleDimmer";
 
  :deviceAttr :brightness;
 
  :attr
 
    [ :outputAttr :level; :dmxOffset 0 ] .
 

	
 
:ChauvetColorStrip a :DeviceClass; rdfs:label "ChauvetColorStrip";
 
  :deviceAttr :color;
 
  :attr
 
    [ :outputAttr :mode;  :dmxOffset 0 ],
 
    [ :outputAttr :red;   :dmxOffset 1 ],
 
    [ :outputAttr :green; :dmxOffset 2 ],
 
    [ :outputAttr :blue;  :dmxOffset 3 ] .
 

	
 
:Mini15 a :DeviceClass; rdfs:label "Mini15";
 
  :deviceAttr :color, :rx, :ry, :mini15GoboChoice, :goboShake ;
 
  :attr
 
    [ :outputAttr :xRotation;     :dmxOffset 0 ],
 
    [ :outputAttr :xFine;         :dmxOffset 1 ],
 
    [ :outputAttr :yRotation;     :dmxOffset 2 ],
 
    [ :outputAttr :yFine;         :dmxOffset 3 ],
 
    [ :outputAttr :rotationSpeed; :dmxOffset 4 ],
 
    [ :outputAttr :dimmer;        :dmxOffset 5 ],
 
    [ :outputAttr :red;           :dmxOffset 6 ],
 
    [ :outputAttr :green;         :dmxOffset 7 ],
 
    [ :outputAttr :blue;          :dmxOffset 8 ],
 
    [ :outputAttr :colorChange;   :dmxOffset 9 ],
 
    [ :outputAttr :colorSpeed;    :dmxOffset 10 ],
 
    [ :outputAttr :goboShake;     :dmxOffset 11 ],
 
    [ :outputAttr :goboChoose;    :dmxOffset 12 ] .
 

	
 
:Source4LedSeries2 a :DeviceClass; rdfs:label "Source4LedSeries2";
 
  :docs <https://www.etcconnect.com/WorkArea/DownloadAsset.aspx?id=10737483869>;
 
  :deviceAttr :color;
0 comments (0 inline, 0 general)