qmsk/dmx/web.py
changeset 83 136e210fce82
parent 82 b5878197d017
child 84 9ebf1a2cee3a
--- a/qmsk/dmx/web.py	Mon Apr 21 00:20:27 2014 +0300
+++ b/qmsk/dmx/web.py	Thu May 01 23:34:20 2014 +0300
@@ -3,6 +3,39 @@
 
 import logging; log = logging.getLogger('qmsk.dmx.web')
 
+def colorize (x, red, green, blue, alpha=1.0) :
+    return x(style='background-color: rgba({red}, {green}, {blue}, {alpha:0.2f})'.format(red=red, green=green, blue=blue, alpha=alpha))
+
+def input (head, name, value) :
+    return html.input(
+            type        = 'text',
+            name        = '-'.join([head, name]),
+
+            id          = '-'.join([head, name]),
+            class_      = 'form-control dmx-input dmx-input-{name}'.format(name=name),
+
+            placeholder = name,
+            value       = '{v:d}'.format(v=value) if value else None,
+    )
+
+def color_input (head, c, value) :
+    color = dict(red=0, green=0, blue=0, alpha=0)
+
+    color[c] = 255
+    if value :
+        color[alpha] = value / 255.0
+
+    return colorize(input(head, c, value), **color)
+
+def slider (head, name) :
+    return html.div(id='-'.join([head, name, 'slider']), class_='dmx-slider dmx-slider-{name}'.format(name=name))
+
+def color_slider (head, c) :
+    return slider(head, c)
+
+def head_color (head, value) :
+    return html.div(class_='dmx-color-background')(colorize(html.div(id='-'.join([head, 'color']), class_='dmx-color')(' '), **value))
+
 class Handler (pvl.web.Handler) :
     # Bootstrap
     DOCTYPE = 'html'
@@ -11,6 +44,8 @@
     CSS = (
             '//code.jquery.com/ui/1.10.4/themes/ui-darkness/jquery-ui.css',
             '//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css',
+
+            '/static/dmx.css',
     )
     JS = (
             '//code.jquery.com/jquery-2.1.0.js',
@@ -18,125 +53,71 @@
             '//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js',
             
             '/static/color-slider.js',
+            '/static/dmx.js',
     )
 
-    STYLE = """
-body {
-    padding-top: 2em;
-    text-align: center;
-}
-
-.container {
-    padding: 2em 1em;
-    text-align: left;
-}
-
-.panel {
-    width: 30em;
-    margin: 1em auto;
-}
-
-input.color-control {
-    width: 5em;
-}
-
-div#color {
-    width: 5em;
-    height: 5em;
-
-    margin: 1em auto;
-}
-
-div.color-slider {
-    margin: 1em;
-}
-
-div.color-slider#slider-r .ui-slider-range {
-    background: #ff0000;
-}
-
-div.color-slider#slider-g .ui-slider-range {
-    background: #00ff00;
-}
-
-div.color-slider#slider-b .ui-slider-range {
-    background: #0000ff;
-}
-    """
-
     # test
     TITLE = u"DMX Control"
 
     def process (self) :
         if self.request.method == 'POST' :
-            self.color = tuple((int(x, 16) if x else 0) for x in (
+            # XXX
+            r, g, b = tuple((int(x, 16) if x else 0) for x in (
                     self.request.form.get('r'),
                     self.request.form.get('g'),
                     self.request.form.get('b'),
             ))
 
-            r, g, b = self.color
-
             self.app.dmx_color(r, g, b, 255)
 
-        else :
-            self.color = None
-
-        log.info("%s", self.color)
-
-    def render (self) :
-        if self.color :
-            r, g, b = self.color
+    def render_head (self, name, head) :
+        if head.alpha() is None :
+            head_input = head_slider = None
         else :
-            r = g = b = None
-
-        def color_swatch () :
-            return html.div(id='color',
-                    style='background-color: rgb({r}, {g}, {b})'.format(r=r, g=g, b=b)
-            )(' '),
-
-        def color_input (name, value) :
-            color = dict(r=0, g=0, b=0)
-            bgcolor = dict(r=0, g=0, b=0)
-
-            if value :
-                color[name] = value
-                alpha = value / 255.0
-            else :
-                alpha = 0
-
-            bgcolor[name] = 255
+            head_input = input(name, 'alpha', head.alpha()['alpha'])
+            head_slider = slider(name, 'alpha')
 
-            return html.input(type='text', name=name,
-                    class_      = 'form-control color-control',
-                    placeholder = name,
-                    id          = name,
+        rowspan = 1
 
-                    value   = '{v:02x}'.format(v=value) if value else None,
-                    style   = 'background-color: rgba({r}, {g}, {b}, {a:0.2f})'.format(a=alpha, **bgcolor),
+        if head.color() is None :
+            colors = { }
+            color = None
+        else :
+            colors = head.color()
+            color = head_color(name, colors)
+            rowspan += 3
+
+        yield html.tr(
+            html.th(rowspan=rowspan)(name),
+            html.td(head_input),
+            html.td(head_slider),
+            html.td(rowspan=rowspan)(color),
+        )
+                
+        for c in colors :
+            yield html.tr(
+                html.td(
+                    color_input(name, c, colors[c]),
+                ),
+                html.td(
+                    color_slider(name, c),
+                ),
             )
-
+    
+    def render (self) :
         return html.div(class_='container')(
-            html.div(class_='panel')(
-                color_swatch(),
-                html.div(id='slider-r', class_='color-slider')(' '),
-                html.div(id='slider-g', class_='color-slider')(' '),
-                html.div(id='slider-b', class_='color-slider')(' '),
-                html.form(action='.', method='POST', class_='form-inline')(
-                       #html.label(for_='color', class_='control-label')("Color"),
-                    html.div(class_='form-group')(
-                       color_input('r', r),
+            html.form(action='.', method='POST')(
+                html.table(class_='dmx')(
+                    html.thead(
+                        html.th(class_='dmx-head')(u"Head"),
+                        html.th(class_='dmx-value')(u"DMX"),
+                        html.th(class_='dmx-control')(u"Control"),
+                        html.th(class_='dmx-head-control')(u"Head Control"),
                     ),
-                    html.div(class_='form-group')(
-                       color_input('g', g),
-                    ),
-                    html.div(class_='form-group')(
-                       color_input('b', b),
-                    ),
-                    html.div(class_='form-group')(
-                        html.button(type='submit', class_='btn btn-primary')("Go"),
-                    ),
-                )
+                    html.tbody(self.render_head(name, head) for name, head in sorted(self.app.heads.iteritems())),
+                ),
+
+                html.button(type='submit', class_='btn btn-primary')("Go"),
             )
         )
 
@@ -145,17 +126,8 @@
         urls.rule('/',          Handler),
     ))
 
-    def __init__ (self, dmx, **opts) :
+    def __init__ (self, dmx, heads, **opts) :
         super(DMXWebApplication, self).__init__(**opts)
 
         self.dmx = dmx
-
-    def dmx_color (self, r, g, b, a=255) :
-        # Stairville LED Par56
-        self.dmx[1] = (0, r, g, b, 0)
-
-        # 4ch dimmer
-        self.dmx[5] = (a, a, a, a)
-
-        # American DJ - Mega Tri 60 - Mode 2
-        self.dmx[10] = (r, g, b, 0, a)
+        self.heads = heads