Lots of work on Web control interface
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Tue, 5 Apr 2016 09:31:36 +0000 (02:31 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Tue, 5 Apr 2016 09:31:36 +0000 (02:31 -0700)
bbctrl.py
src/jade/index.jade
src/jade/templates/axis-control.jade
src/jade/templates/control-view.jade [new file with mode: 0644]
src/jade/templates/estop.jade [new file with mode: 0644]
src/jade/templates/status-view.jade [deleted file]
src/js/app.js
src/js/control-view.js [new file with mode: 0644]
src/js/status-view.js [deleted file]
src/stylus/style.styl

index 38f095381677c58cb365a3ed1d8c27ea05f2465c..69bd1c47049ad2d0150950a11de3dab414c4d41e 100755 (executable)
--- a/bbctrl.py
+++ b/bbctrl.py
@@ -137,7 +137,7 @@ class SaveHandler(APIHandler):
         self.write_json('ok')
 
 
-class UploadHandler(APIHandler):
+class FileHandler(APIHandler):
     def prepare(self): pass
 
 
@@ -157,14 +157,19 @@ class UploadHandler(APIHandler):
 
 
     def get(self, path):
-        uploads = []
+        if path:
+            with open('upload/' + path, 'r') as f:
+                self.write_json(f.read())
+            return
+
+        files = []
 
         if os.path.exists('upload'):
             for path in os.listdir('upload'):
                 if os.path.isfile('upload/' + path):
-                    uploads.append(path)
+                    files.append(path)
 
-        self.write_json(uploads)
+        self.write_json(files)
 
 
     def post(self, path):
@@ -253,7 +258,7 @@ def checkQueue():
 handlers = [
     (r'/api/load', LoadHandler),
     (r'/api/save', SaveHandler),
-    (r'/api/upload(/.*)?', UploadHandler),
+    (r'/api/file(/.*)?', FileHandler),
     (r'/(.*)', web.StaticFileHandler,
      {'path': os.path.join(DIR, 'http/'),
       "default_filename": "index.html"}),
index 80ff0b3e3599985eea671d544c3164504ed0c40c..de88d52f239790e9301c98c2974110f8acd4efad 100644 (file)
@@ -35,7 +35,7 @@ html(lang="en")
         .pure-menu
           ul.pure-menu-list
             li.pure-menu-heading
-              a.pure-menu-link(href="#status") Status
+              a.pure-menu-link(href="#control") Control
 
             li.pure-menu-heading
               a.pure-menu-link(href="#motor:0") Motors
@@ -69,7 +69,7 @@ html(lang="en")
             span.right botics
           h2 Machine Controller
 
-        .content
+        .content(class="{{currentView}}-view")
           component(:is="currentView + '-view'", :index="index",
             :config="config", :template="template")
 
index a3ed1c44b99203fe63e61bcb11ce3ded77336922..a81c10baabc59606a1193d01c81fa913a90edd3c 100644 (file)
@@ -1,5 +1,6 @@
 script#axis-control-template(type="text/x-template")
-  svg(xmlns="http://www.w3.org/2000/svg", width="250", height="250",
+  svg(xmlns="http://www.w3.org/2000/svg",
+    width="200", height="200", transform="scale(0.8, 0.8)",
     xmlns:xlink="http://www.w3.org/1999/xlink")
     defs
       lineargradient#gold
@@ -21,296 +22,197 @@ script#axis-control-template(type="text/x-template")
 
       each color in 'gold blue green red'.split(' ')
         lineargradient(xlink:href="##{color}", id="#{color}-1",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="rotate(180 -85.912 21.235)",
-          x1="-204.843", y1="23.531", x2="-190.645", y2="-4.643")
+          gradientunits="userSpaceOnUse", gradienttransform="rotate(180 7 5)",
+          x1="0", y1="0", x2="15", y2="10")
 
         lineargradient(xlink:href="##{color}", id="#{color}-2",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="translate(265.971 167.066)",
-          x1="-236.439", y1="-42.033", x2="-221.978", y2="-31.237")
+          gradientunits="userSpaceOnUse", x1="10", y1="10", x2="40", y2="40")
+
+
+      filter#shadow-ring(x="-50%" y="-50%" width="200%" height="200%")
+        feOffset(in="SourceAlpha", dx="3", dy="3")
+        feComponentTransfer
+          feFuncR(type="discrete", tableValues="0.05")
+          feFuncG(type="discrete", tableValues="0.05")
+          feFuncB(type="discrete", tableValues="0.05")
+        feGaussianBlur(result="shadow", stdDeviation="5")
+        feBlend(in="SourceGraphic", in2="shadow", mode="normal")
+
+      filter#shadow(x="-50%" y="-50%" width="200%" height="200%")
+        feOffset(in="SourceAlpha", dx="3", dy="3")
+        feComponentTransfer
+          feFuncR(type="discrete", tableValues="0.3")
+          feFuncG(type="discrete", tableValues="0.3")
+          feFuncB(type="discrete", tableValues="0.3")
+        feGaussianBlur(result="shadow", stdDeviation="3")
+        feBlend(in="SourceGraphic", in2="shadow", mode="normal")
+
+      path#corner-button(d="M47,10 47,0 0,0 0,47 10,47C10,47 26,21 47,10Z",
+        enable-background="accumulate")
 
-        lineargradient(xlink:href="##{color}", id="#{color}-3",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="rotate(180 -8.636 44.528)",
-          x1="-236.439", y1="-42.033", x2="-221.978", y2="-31.237")
+      g.house#house
+        path(d="m15,26 0,-6 6,-5 6,5 0,6 -4,0 0,-4a4,8 0 0 0 -4,0l0,0 0,4z")
+        path(d="m27,17 0,-3", fill="none", stroke-width="1.5")
+        path(d="m13,19 8,-7 8,7", fill="none", stroke-width="1.5")
 
-        lineargradient(xlink:href="##{color}", id="#{color}-4",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="translate(377.241 36.636)",
-          x1="-142.626", y1="11.259", x2="-158.147", y2="-16.603")
+      path#arrow(d="M-16,9 0,9 0,17 17,0 0,-17 0,-9 -16,-9 -16,9Z")
 
-        lineargradient(xlink:href="##{color}", id="#{color}-5",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="rotate(180 -64.081 107.165)",
-          x1="-157.566", y1="-15.134", x2="-144.204", y2="8.297")
+      path#pie-1(d="M107,0 83,0 0,83 0,107A107,107 0 0 0 107,0Z")
+      path#pie-2(d="M83,0 59,0 0,59 0,83A83,83 0 0 0 83,0Z")
+      path#pie-3(d="M59,0 35,0 0,35 0,59A59,59 0 0 0 59,0Z")
+      path#pie-4(d="M35,0 0,0 0,35A35,35 0 0 0 35,0Z")
 
-        lineargradient(xlink:href="##{color}", id="#{color}-6",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="matrix(1 0 0 -1 377.241 214.33)",
-          x1="-168.279", y1="-18.947", x2="-140.843", y2="2.397")
 
-        lineargradient(xlink:href="##{color}", id="#{color}-7",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="rotate(180 .06 126.215)",
-          x1="-135.583", y1="44.109", x2="-115.921", y2="26.421")
+    // Home A
+    g.button(@click="home(0)", title="Home {{axes[0]}} axis",
+      filter="url(#shadow)")
+      use(xlink:href="#corner-button", fill="url(#{{colors[0]}}-2)",
+        transform="matrix(1 0 0 1 9 9)")
+      text(font-size="14", x="34", y="25") {{axes[0]}}
+      use(xlink:href="#house")
 
-        lineargradient(xlink:href="##{color}", id="#{color}-8",
-          gradientunits="userSpaceOnUse",
-          gradienttransform="translate(247.81 4.555)",
-          x1="-135.583", y1="44.109", x2="-115.921", y2="26.421")
 
+    // Home B
+    g.button(@click="home(1)", title="Home {{axes[1]}} axis",
+      filter="url(#shadow)")
+      use(xlink:href="#corner-button", fill="url(#{{colors[1]}}-2)",
+        transform="matrix(-1 0 0 1 241 9)")
+      text(font-size="14", x="205", y="25") {{axes[1]}}
+      use(xlink:href="#house", transform="translate(208 0)")
 
-      filter#shadow-1(color-interpolation-filters="sRGB",
-        x="-.108", y="-.108", width="1.216", height="1.216")
-        fegaussianblur(stddeviation="3.826")
 
-      filter#shadow-2(color-interpolation-filters="sRGB",
-        x="-.18", y="-.182", width="1.361", height="1.364")
-        fegaussianblur(stddeviation="3.539")
+    // Zero A
+    g.button(@click="zero(0)", title="Zero {{axes[0]}} axes",
+      filter="url(#shadow)")
+      use(xlink:href="#corner-button", fill="url(#{{colors[0]}}-2)",
+        transform="matrix(1 0 0 -1 9 231)")
+      text(font-size="20", x="12", y="227") &empty;
+      text(font-size="14", x="30", y="227") {{axes[0]}}
 
-      filter#shadow-3(color-interpolation-filters="sRGB")
-        fegaussianblur(stddeviation="2.863")
 
+    // Zero B
+    g.button(@click="zero(1)", title="Zero {{axes[1]}} axis",
+      filter="url(#shadow)")
+      use(xlink:href="#corner-button", fill="url(#{{colors[1]}}-2)",
+        transform="matrix(-1 0 0 -1 241 231)")
+      text(font-size="14", x="208", y="227") {{axes[1]}}
+      text(font-size="20", x="221", y="227") &empty;
 
-    // Home A
-    g(@click="home(0)", title="Home {{axes[0]}} axis", cursor="pointer")
-      // Shadow
-      path(
-        d="M51.267 352.962v-8.724H4.162v46.64h10.054s15.733-26 37.051-37.916z",
-        color="#000", fill-opacity=".599", overflow="visible",
-        filter="url(#shadow-2)", enable-background="accumulate",
-        transform="translate(4.799 -332.398)")
-
-      // Outline
-      path(d="M54.428 21.478v-8.724H7.323v46.64h10.054s15.733-26 37.05-37.916z",
-        color="#000", fill="url(#{{colors[0]}}-1)", stroke="#4c4c4c",
-        stroke-width="1.7", overflow="visible", enable-background="accumulate",
-        transform="translate(1.527 -2.914)")
-
-      // Letter
-      text(font-weight="bold", font-family="Sans", font-size="14",
-        x="31", y="28", fill="#2e3436") {{axes[0]}}
-
-      // House
-      g(stroke="#2e3436")
-        path(d="M14.974 20.11l5.82-4.7 6.1 4.7v6.505H23.64v-4.022c0-.828-.649-1.423-1.415-1.736-.819-.333-1.838-.343-2.653 0-.746.314-1.344.927-1.344 1.736v4.023h-3.254z",
-          fill="#2e3436", stroke-linejoin="round")
-        path(d="M25.915 16.773v-1.892h1.035v2.553", fill="#2e3436")
-        path(d="M12.493 19.325l8.288-6.692 8.686 6.692", fill="none",
-          stroke-width="1.5", stroke-linecap="round", stroke-linejoin="round")
 
+    // 100 ring
+    g.ring(fill="#9f9f9f", filter="url(#shadow-ring)")
+      use.button(xlink:href="#pie-1",
+        transform="translate(134 121) rotate(-45)",
+        @click="jog(0, 100)", title="Jog +100 {{axes[0]}}")
+
+      use.button(xlink:href="#pie-1",
+        transform="translate(115 121) rotate(135)",
+        @click="jog(0, -100)", title="Jog -100 {{axes[0]}}")
+
+      g.button(@click="jog(1, 100)", title="Jog +100 {{axes[1]}}")
+        use.button(xlink:href="#pie-1",
+          transform="translate(124 111) rotate(-135)")
+        text(x="125", y="24", transform="rotate(20 125 125)") 100
+        text(x="125", y="24", transform="rotate(-20 125 125)") 100
+        use.button(xlink:href="#pie-1", fill="transparent",
+          transform="translate(124 111) rotate(-135)")
+
+      use.button(xlink:href="#pie-1",
+        transform="translate(124 130) rotate(45)",
+        @click="jog(1, -100)", title="Jog -100 {{axes[1]}}")
 
-    // Home B
-    g(@click="home(1)", title="Home {{axes[1]}} axis", cursor="pointer")
-      // Shadow
-      path(transform="matrix(-1 0 0 1 437.856 12.746)",
-        d="M243.661 7.817V-.907h-47.105v46.64h10.054s15.733-26 37.051-37.916z",
-        color="#000", fill-opacity=".599", overflow="visible",
-        filter="url(#shadow-2)", enable-background="accumulate")
-
-      // Outline
-      path(d="M194.651 21.478v-8.724h47.106v46.64h-10.055s-15.732-26-37.05-37.916z",
-        color="#000", fill="url(#{{colors[1]}}-4)", stroke="#4c4c4c",
-        stroke-width="1.7", overflow="visible", enable-background="accumulate",
-        transform="translate(-1.862 -2.914)")
-
-      // Letter
-      text(font-weight="bold", font-family="Sans", font-size="14",
-        x="208", y="28", fill="#2e3436") {{axes[1]}}
-
-      // House
-      g(stroke="#2e3436")
-        path(d="M222.698 20.11l5.82-4.7 6.1 4.7v6.505h-3.254v-4.022c0-.828-.648-1.423-1.414-1.736-.82-.333-1.839-.343-2.654 0-.746.314-1.344.927-1.344 1.736v4.023h-3.254z",
-          fill="#2e3436", stroke-linejoin="round")
-        path(d="M233.64 16.773v-1.892h1.034v2.553", fill="#2e3436")
-        path(d="M220.218 19.325l8.287-6.692 8.687 6.692", fill="none",
-          stroke-width="1.5", stroke-linecap="round", stroke-linejoin="round")
+    // 10 ring
+    g.ring(fill="#c5c5c5", filter="url(#shadow-ring)")
+      use.button(xlink:href="#pie-2",
+        transform="translate(134 121) rotate(-45)",
+        @click="jog(0, 10)", title="Jog +10 {{axes[0]}}")
 
-    // Zero A
-    g(@click="zero(0)", title="Zero {{axes[0]}} axes", cursor="pointer")
-      // Shadow
-      path(
-        d="M243.661 7.817V-.907h-47.105v46.64h10.054s15.733-26 37.051-37.916z",
-        transform="matrix(1 0 0 -1 -187.595 233.179)", color="#000",
-        fill-opacity=".599", overflow="visible", filter="url(#shadow-1)",
-        enable-background="accumulate")
+      use.button(xlink:href="#pie-2",
+        transform="translate(115 121) rotate(135)",
+        @click="jog(0, -10)", title="Jog -10 {{axes[0]}}")
 
-      // Outline
-      path(
-        d="M54.428 229.488v8.724H7.323v-46.64h10.054s15.733 26 37.05 37.916z",
-        color="#000", fill="url(#{{colors[0]}}-5)", stroke="#4c4c4c",
-        stroke-width="1.7", overflow="visible", enable-background="accumulate",
-        transform="translate(1.527 -8.096)")
+      g.button(@click="jog(1, 10)", title="Jog +10 {{axes[1]}}")
+        use.button(xlink:href="#pie-2",
+          transform="translate(124 111) rotate(-135)")
+        text(x="125", y="50") 10
+        use.button(xlink:href="#pie-2", fill="transparent",
+          transform="translate(124 111) rotate(-135)")
 
-      // Letter
-      text(font-weight="bold", font-family="Sans", font-size="14",
-        x="16", y="227", fill="#2e3436") ∅ {{axes[0]}}
+      use.button(xlink:href="#pie-2",
+        transform="translate(124 130) rotate(45)",
+        @click="jog(1, -10)", title="Jog -10 {{axes[1]}}")
 
 
-    // Zero B
-    g(@click="zero(1)", title="Zero {{axes[1]}} axis", cursor="pointer")
-      // Shadow
-      path(
-        d="M243.661 7.817V-.907h-47.105v46.64h10.054s15.733-26 37.051-37.916z",
-        transform="rotate(180 218.928 116.59)", color="#000",
-        fill-opacity=".599", overflow="visible", filter="url(#shadow-2)",
-        enable-background="accumulate")
+    // 1 ring
+    g.ring(fill="#e2e2e2", filter="url(#shadow-ring)")
+      use.button(xlink:href="#pie-3",
+        transform="translate(134 121) rotate(-45)",
+        @click="jog(0, 1)", title="Jog +1 {{axes[0]}}")
 
-      // Outline
-      path(d="M194.651 229.488v8.724h47.106v-46.64h-10.055s-15.732 26-37.05 37.916z",
-        color="#000", fill="url(#{{colors[1]}}-6)", stroke="#4c4c4c",
-        stroke-width="1.7", overflow="visible", enable-background="accumulate",
-        transform="translate(-1.862 -8.096)")
+      use.button(xlink:href="#pie-3",
+        transform="translate(115 121) rotate(135)",
+        @click="jog(0, -1)", title="Jog -1 {{axes[0]}}")
 
-      // Letter
-      text(font-weight="bold", font-family="Sans", font-size="14",
-        x="206", y="227", fill="#2e3436") ∅ {{axes[1]}}
+      g.button(@click="jog(1, 1)", title="Jog +1 {{axes[1]}}")
+        use.button(xlink:href="#pie-3",
+          transform="translate(124 111) rotate(-135)")
+        text(x="125", y="75") 1
+        use.button(xlink:href="#pie-3", fill="transparent",
+          transform="translate(124 111) rotate(-135)")
 
+      use.button(xlink:href="#pie-3",
+        transform="translate(124 130) rotate(45)",
+        @click="jog(1, -1)", title="Jog -1 {{axes[1]}}")
 
-    // 100 shadow
-    path(d="M120.493 342.495c-29.034 0-55.484 10.944-75.5 28.938l15.281 15.28c16.085-14.095 37.151-22.624 60.219-22.624 23.07 0 44.164 8.527 60.25 22.625l15.281-15.281c-20.017-17.994-46.497-28.938-75.531-28.938zm-84.063 37.5c-17.993 20.017-28.937 46.466-28.937 75.5s10.944 55.515 28.937 75.531l15.281-15.28c-14.097-16.086-22.625-37.181-22.625-60.25 0-23.068 8.53-44.135 22.625-60.22l-15.28-15.28zm168.156 0l-15.312 15.313c14.088 16.083 22.656 37.126 22.656 60.187 0 23.063-8.566 44.135-22.656 60.219l15.312 15.312c17.988-20.015 28.938-46.502 28.938-75.53 0-29.03-10.95-55.486-28.938-75.5zM60.306 524.276L44.992 539.59c20.015 17.987 46.471 28.937 75.5 28.937 29.028 0 55.516-10.95 75.531-28.937l-15.313-15.313c-16.083 14.09-37.155 22.657-60.218 22.657-23.061 0-44.105-8.568-60.188-22.657z",
-      color="#000", fill-opacity=".725", fill-rule="evenodd",
-      overflow="visible", filter="url(#shadow-1)",
-      enable-background="accumulate", transform="translate(4.799 -332.398)")
 
-    // 100 shadow
-    path(d="M119.436 338.53c-29.443 0-56.275 11.115-76.562 29.375l1.062 1.063c20.017-17.994 46.466-28.938 75.5-28.938 29.035 0 55.515 10.944 75.532 28.938l1.062-1.063c-20.287-18.261-47.149-29.375-76.594-29.375zm-85.125 37.938C16.05 396.755 4.936 423.585 4.936 453.03s11.114 56.307 29.375 76.594l1.063-1.063c-17.994-20.016-28.938-46.497-28.938-75.53 0-29.035 10.944-55.484 28.938-75.5l-1.063-1.063zm170.282 0l-1.063 1.062c17.987 20.015 28.938 46.472 28.938 75.5 0 29.029-10.95 55.516-28.938 75.531l1.063 1.063c18.261-20.287 29.375-47.149 29.375-76.594 0-29.445-11.114-56.275-29.375-76.562zM43.936 537.124l-1.062 1.062c20.287 18.26 47.12 29.375 76.562 29.375 29.445 0 56.307-11.113 76.594-29.375l-1.062-1.062c-20.016 17.987-46.503 28.937-75.532 28.937-29.028 0-55.484-10.95-75.5-28.937z",
-      color="#000", fill-opacity=".553", fill-rule="evenodd",
-      overflow="visible", filter="url(#shadow-3)",
-      enable-background="accumulate", transform="translate(4.799 -332.39")
+    // 0.1 ring
+    g.ring(fill="#f7f7f7", filter="url(#shadow-ring)")
+      use.button(xlink:href="#pie-4",
+        transform="translate(134 121) rotate(-45)",
+        @click="jog(0, 0.1)", title="Jog +0.1 {{axes[0]}}")
 
-    // 100 ring
-    g(color="#000", fill="#9f9f9f", fill-rule="evenodd", stroke="#494949",
-      overflow="visible", enable-background="accumulate")
-      path(@click="jog(0, 100)", title="Jog +100 {{axes[0]}}", cursor="pointer",
-        d="M208.329,45.132 L193.017,60.445 C207.105,76.528 215.673,97.571 215.673,120.632 C215.673,143.695 207.107,164.767 193.017,180.851 L208.329,196.163 C226.316,176.148 237.267,149.661 237.267,120.633 C237.267,91.603 226.317,65.147 208.329,45.133 z")
-      path(@click="jog(0, -100)", title="Jog -100 {{axes[0]}}",
-        cursor="pointer",
-        d="M40.173,45.132 C22.179,65.149 11.235,91.598 11.235,120.632 S22.179,176.147 40.173,196.163 L55.454,180.883 C41.356,164.797 32.829,143.702 32.829,120.633 C32.829,97.565 41.359,76.498 55.454,60.413 L40.173,45.133 z")
-      path(@click="jog(1, 100)", title="Jog +100 {{axes[1]}}",
-        cursor="pointer",
-        d="M124.235,7.632 C95.201,7.632 68.752,18.576 48.735,36.57 L64.017,51.85 C80.102,37.754 101.167,29.225 124.235,29.225 C147.305,29.225 168.4,37.752 184.485,51.85 L199.767,36.569 C179.75,18.576 153.27,7.632 124.235,7.632 z")
-      path(@click="jog(1, -100)", title="Jog -100 {{axes[1]}}",
-        cursor="pointer",
-        d="M64.048,189.413 L48.735,204.726 C68.751,222.713 95.207,233.663 124.235,233.663 C153.264,233.663 179.751,222.713 199.767,204.726 L184.454,189.413 C168.371,203.504 147.298,212.07 124.235,212.07 C101.175,212.07 80.131,203.502 64.048,189.413 z")
-
-
-    // 10 shadow
-    path(d="M120.493 364.089c-23.068 0-44.134 8.53-60.219 22.625l17.344 17.344c11.623-9.702 26.551-15.532 42.875-15.532 16.323 0 31.283 5.83 42.906 15.532l17.344-17.344c-16.086-14.098-37.18-22.625-60.25-22.625zM51.71 395.276c-14.095 16.085-22.625 37.152-22.625 60.22 0 23.069 8.528 44.164 22.625 60.25L69.055 498.4c-9.702-11.622-15.531-26.582-15.531-42.906 0-16.324 5.83-31.252 15.531-42.875l-17.344-17.344zm137.563.032l-17.313 17.312c9.701 11.623 15.532 26.552 15.532 42.875s-5.83 31.284-15.532 42.906l17.313 17.313c14.09-16.084 22.656-37.156 22.656-60.219 0-23.06-8.568-44.104-22.656-60.187zM77.618 506.964l-17.313 17.312c16.083 14.089 37.127 22.657 60.188 22.657 23.063 0 44.135-8.566 60.218-22.657L163.4 506.964c-11.623 9.7-26.583 15.531-42.906 15.531s-31.253-5.83-42.875-15.531z",
-      color="#000", fill-opacity=".725", fill-rule="evenodd",
-      overflow="visible", filter="url(#shadow-1)",
-      enable-background="accumulate", transform="translate(4.799 -332.398)")
+      use.button(xlink:href="#pie-4",
+        transform="translate(115 121) rotate(135)",
+        @click="jog(0, -0.1)", title="Jog -0.1 {{axes[0]}}")
 
-    // 10 ring
-    g(color="#000", fill="#c5c5c5", fill-rule="evenodd", overflow="visible",
-      enable-background="accumulate")
-      path(@click="jog(0, 10)", title="Jog +10 {{axes[0]}}", cursor="pointer",
-        d="M193.017,60.445 L175.704,77.757 C185.405,89.38 191.235,104.309 191.235,120.632 S185.405,151.916 175.705,163.538 L193.017,180.851 C207.107,164.767 215.673,143.695 215.673,120.632 C215.673,97.572 207.105,76.528 193.017,60.445 z")
-      path(@click="jog(0, -10)", title="Jog -10 {{axes[0]}}", cursor="pointer",
-        d="M55.455,60.413 C41.359,76.498 32.829,97.565 32.829,120.633 C32.829,143.702 41.356,164.797 55.454,180.883 L72.798,163.538 C63.096,151.916 57.267,136.956 57.267,120.632 C57.267,104.309 63.097,89.38 72.797,77.757 L55.455,60.413 z")
-      path(@click="jog(1, 10)", title="Jog +10 {{axes[1]}}", cursor="pointer",
-        d="M124.235,29.226 C101.168,29.226 80.102,37.756 64.017,51.851 L81.36,69.195 C92.983,59.493 107.912,53.663 124.235,53.663 C140.559,53.663 155.519,59.493 167.142,69.195 L184.485,51.851 C168.4,37.753 147.305,29.226 124.235,29.226 z")
-      path(@click="jog(1, -10)", title="Jog -10 {{axes[1]}}", cursor="pointer",
-        d="M81.36,172.1 L64.048,189.412 C80.131,203.501 101.175,212.069 124.235,212.069 C147.298,212.069 168.371,203.503 184.455,189.412 L167.142,172.1 C155.519,181.8 140.558,187.631 124.235,187.631 C107.913,187.631 92.983,181.801 81.36,172.1 z")
-
-
-    // 1 shadow
-    path(d="M120.493 388.526c-16.324 0-31.252 5.83-42.875 15.532l17.406 17.406a42.303 42.303 0 0 1 25.469-8.469c9.556 0 18.399 3.147 25.5 8.469l17.406-17.406c-11.623-9.702-26.583-15.532-42.906-15.532zM69.055 412.62c-9.702 11.623-15.531 26.551-15.531 42.875s5.83 31.284 15.531 42.906l17.406-17.406c-5.321-7.1-8.468-15.943-8.468-25.5 0-9.565 3.138-18.396 8.468-25.5L69.055 412.62zm102.906 0l-17.406 17.406a42.304 42.304 0 0 1 8.469 25.47c0 9.556-3.147 18.398-8.469 25.5l17.406 17.405c9.701-11.622 15.532-26.583 15.532-42.906s-5.83-31.252-15.532-42.875zm-76.937 76.938l-17.406 17.406c11.622 9.7 26.552 15.531 42.875 15.531s31.283-5.83 42.906-15.531l-17.375-17.406c-7.104 5.33-15.966 8.468-25.531 8.468a42.304 42.304 0 0 1-25.469-8.468z",
-      color="#000", fill-opacity=".725", fill-rule="evenodd",
-      overflow="visible", filter="url(#shadow-1)",
-      enable-background="accumulate", transform="translate(4.799 -332.398)")
+      g.button(@click="jog(1, 0.1)", title="Jog +0.1 {{axes[1]}}")
+        use.button(xlink:href="#pie-4",
+          transform="translate(124 111) rotate(-135)")
+        text(x="125", y="95") 0.1
+        use.button(xlink:href="#pie-4", fill="transparent",
+          transform="translate(124 111) rotate(-135)")
 
-    // 1 ring
-    g(color="#000", fill="#e2e2e2", fill-rule="evenodd", overflow="visible",
-      enable-background="accumulate")
-      path(@click="jog(0, 1)", title="Jog +1 {{axes[0]}}", cursor="pointer",
-        d="M175.704,77.757 L158.298,95.163 A42.304,42.304 0 0,1 166.767,120.633 C166.767,130.189 163.62,139.031 158.297,146.133 L175.704,163.538 C185.405,151.916 191.235,136.955 191.235,120.632 S185.405,89.38 175.705,77.757 z")
-      path(@click="jog(0, -1)", title="Jog -1 {{axes[0]}}", cursor="pointer",
-        d="M72.798,77.757 C63.096,89.38 57.267,104.309 57.267,120.632 C57.267,136.956 63.097,151.916 72.797,163.538 L90.204,146.132 C84.882,139.032 81.735,130.189 81.735,120.632 C81.735,111.067 84.873,102.236 90.205,95.132 L72.797,77.757 z")
-      path(@click="jog(1, 1)", title="Jog +1 {{axes[1]}}", cursor="pointer",
-        d="M124.235,53.663 C107.912,53.663 92.983,59.493 81.36,69.195 L98.767,86.6 A42.303,42.303 0 0,1 124.235,78.131 C133.792,78.131 142.635,81.278 149.735,86.6 L167.142,69.194 C155.519,59.492 140.559,53.662 124.235,53.662 z")
-      path(@click="jog(1, -1)", title="Jog -1 {{axes[1]}}", cursor="pointer",
-        d="M98.767,154.695 L81.36,172.1 C92.983,181.8 107.913,187.631 124.235,187.631 C140.558,187.631 155.519,181.801 167.142,172.1 L149.767,154.694 C142.663,160.024 133.801,163.162 124.235,163.162 A42.304,42.304 0 0,1 98.767,154.694 z")
-
-
-    // 0.1 shadow
-    path(color="#000", fill-opacity=".725", fill-rule="evenodd",
-      overflow="visible", filter="url(#shadow-1)",
-      enable-background="accumulate", transform="translate(4.799 -332.398)",
-      d="M120.493 412.995a42.303 42.303 0 0 0-25.469 8.469l25.5 25.469 25.469-25.47c-7.101-5.321-15.944-8.468-25.5-8.468zm-34.032 17c-5.33 7.104-8.468 15.935-8.468 25.5 0 9.557 3.147 18.4 8.468 25.5l25.5-25.5-25.5-25.5zm68.094.031l-25.469 25.47 25.47 25.5c5.321-7.102 8.468-15.944 8.468-25.5a42.304 42.304 0 0 0-8.469-25.47zm-34.031 34.032l-25.5 25.5a42.304 42.304 0 0 0 25.469 8.468c9.565 0 18.427-3.138 25.531-8.468l-25.5-25.5z")
-
-    // 0.1 ring
-    g(color="#000", fill="#f7f7f7", fill-rule="evenodd", overflow="visible",
-      enable-background="accumulate")
-      path(@click="jog(0, 0.1)", title="Jog +0.1 {{axes[0]}}",
-        cursor="pointer",
-        d="M158.298,95.163 L132.829,120.633 L158.298,146.133 C163.62,139.031 166.767,130.189 166.767,120.633 A42.304,42.304 0 0,0 158.297,95.163 z")
-      path(@click="jog(0, -0.1)", title="Jog -0.1 {{axes[0]}}",
-        cursor="pointer",
-        d="M90.205,95.132 C84.873,102.236 81.735,111.067 81.735,120.632 C81.735,130.189 84.882,139.032 90.205,146.132 L115.705,120.632 L90.205,95.132 z")
-      path(@click="jog(1, 0.1)", title="Jog +0.1 {{axes[1]}}",
-        cursor="pointer",
-        d="M124.235,78.132 A42.303,42.303 0 0,0 98.767,86.601 L124.267,112.07 L149.735,86.6 C142.635,81.278 133.792,78.131 124.235,78.131 z")
-      path(@click="jog(1, -0.1)", title="Jog -0.1 {{axes[1]}}",
-        cursor="pointer",
-        d="M124.267,129.195 L98.767,154.695 A42.304,42.304 0 0,0 124.235,163.163 C133.801,163.163 142.663,160.025 149.767,154.695 L124.267,129.195 z")
-
-
-    // 100, 10, 1, 0.1
-    g(font-weight="bold", font-family="Sans", font-size="12", fill="#444",
-      text-anchor="middle", cursor="pointer")
-      text(@click="jog(1, 100)", title="Jog +100 {{axes[1]}}",
-        x="125", y="24", transform="rotate(20 125 125)") 100
-      text(@click="jog(1, 100)", title="Jog +100 {{axes[1]}}",
-        x="125", y="24", transform="rotate(-20 125 125)") 100
-      text(@click="jog(1, 10)", title="Jog +10 {{axes[1]}}",
-        x="125", y="50") 10
-      text(@click="jog(1, 1)", title="Jog +1 {{axes[1]}}",
-        x="125", y="75") 1
-      text(@click="jog(1, 0.1)", title="Jog +0.1 {{axes[1]}}",
-        x="125", y="95") 0.1
+      use.button(xlink:href="#pie-4",
+        transform="translate(124 130) rotate(45)",
+        @click="jog(1, -0.1)", title="Jog -0.1 {{axes[1]}}")
 
 
     // +A
-    g(@click="jog(0, 100)", title="Jog +100 {{axes[0]}}",
-      transform="translate(13, 0)", cursor="pointer")
-      path(d="M213.845 110.655l-.125 8.438h-16.062v17.937h16.062l.125 8.438c5.476-5.48 12.606-12.631 17.375-17.406-4.325-4.55-12.073-12.095-17.375-17.407z",
-        fill="url(#{{colors[0]}}-3)", stroke="#4c4c4c", stroke-width="1.7",
-        stroke-linejoin="round", transform="translate(.285 -7.414)")
-
-      text(font-weight="bold", font-family="Sans", font-size="14",
-        x="202", y="126", textLength="20") +{{axes[0]}}
+    g.button.arrow(@click="jog(0, 100)", title="Jog +100 {{axes[0]}}",
+      transform="translate(230 120)")
+      use(xlink:href="#arrow", fill="url(#{{colors[0]}}-1)")
+      text(x="-12", y="5", font-size="14", textLength="21") +{{axes[0]}}
 
 
     // -A
-    g(@click="jog(0, -100)", title="Jog -100 {{axes[0]}}",
-      transform="translate(-13, 0)", cursor="pointer")
-      path(d="M34.855 145.468l.125-8.438h16.062v-17.937H34.98l-.125-8.438c-5.475 5.48-12.606 12.632-17.375 17.407 4.325 4.549 12.073 12.094 17.375 17.406z",
-        fill="url(#{{colors[0]}}-2)", stroke="#4c4c4c", stroke-width="1.7",
-        stroke-linejoin="round", transform="translate(.285 -7.414)")
-
-      text(font-weight="bold", font-family="Sans", font-size="14",
-        x="26", y="126") -{{axes[0]}}
+    g.button.arrow(@click="jog(0, -100)", title="Jog -100 {{axes[0]}}",
+      transform="translate(20 120)")
+      use(xlink:href="#arrow", fill="url(#{{colors[0]}}-1)",
+        transform="rotate(180)")
+      text(x="-8", y="5", font-size="14", textLength="16") -{{axes[0]}}
 
 
     // +B
-    g(@click="jog(1, 100)", title="Jog +100 {{axes[1]}}",
-      transform="translate(0, -13)", cursor="pointer")
-      path(d="M106.56 38.086l8.437.125v16.062h17.937V38.211l8.438-.125c-5.48-5.476-12.631-12.606-17.406-17.375-4.55 4.325-12.095 12.073-17.407 17.375z",
-        fill="url(#{{colors[1]}}-8)", stroke="#4c4c4c", stroke-width="1.7",
-        stroke-linejoin="round", transform="translate(.285 -7.414)")
-
-      text(font-weight="bold", font-family="Sans", font-size="12",
-        x="115", y="33", textLength="18") +{{axes[1]}}
+    g.button.arrow(@click="jog(1, 100)", title="Jog +100 {{axes[1]}}",
+      transform="translate(125, 18)")
+      use(xlink:href="#arrow", fill="url(#{{colors[1]}}-1)",
+        transform="rotate(-90)")
+      text(x="-8", y="5", font-size="12", textLength="16") +{{axes[1]}}
 
 
     // -B
-    g(@click="jog(1, -100)", title="Jog -100 {{axes[1]}}",
-      transform="translate(0, 13)", cursor="pointer")
-      path(d="M141.372 218.899l-8.438-.125V202.71h-17.937v16.063l-8.438.125c5.48 5.475 12.632 12.605 17.407 17.375 4.549-4.326 12.094-12.073 17.406-17.375z",
-        fill="url(#{{colors[1]}}-7)", stroke="#4c4c4c", stroke-width="1.7",
-        stroke-linejoin="round", transform="translate(.285 -7.414)")
-
-      text(font-weight="bold", font-family="Sans", font-size="12",
-        x="115", y="218", textLength="16") -{{axes[1]}}
+    g.button.arrow(@click="jog(1, -100)", title="Jog -100 {{axes[1]}}",
+      transform="translate(125, 225)")
+      use(xlink:href="#arrow", fill="url(#{{colors[1]}}-1)",
+        transform="rotate(90)")
+      text(x="-7", y="5", font-size="12", textLength="14") -{{axes[1]}}
diff --git a/src/jade/templates/control-view.jade b/src/jade/templates/control-view.jade
new file mode 100644 (file)
index 0000000..ea58588
--- /dev/null
@@ -0,0 +1,100 @@
+script#control-view-template(type="text/x-template")
+  .jog
+    axis-control(axes="XY", :colors="['gold', 'blue']")
+    axis-control(axes="AZ", :colors="['red', 'green']")
+
+
+  .estop(:class="{active: state.es}")
+    estop(@click="estop")
+
+
+  table.info
+    tr
+      th Tool
+      td {{state.t || 0}}
+    tr
+      th Velocity
+      td {{state.v || 0}} mm/min
+    tr
+      th Feed
+      td {{state.f || 0}} mm/min
+    tr
+      th Speed
+      td {{state.s || 0}} RPM
+    tr
+      th Direction
+      td {{state.sd || 'Clockwise'}}
+    tr
+      th Mist
+      td {{state.mist || 'Off'}}
+    tr
+      th Coolant
+      td {{state.coolant || 'Off'}}
+
+
+  table.axes
+    tr
+      th Axis
+      th Position
+      th Offset
+      th Flags
+      th StallGuard
+
+    each axis in 'xyzabc'
+      tr.axis(class="axis-#{axis}")
+        th.name #{axis}
+        td.position {{state.#{axis}p || 0 | fixed 4}}
+        td.offset {{state.#{axis}o || 0 | fixed 4}}
+        td {{state.#{axis}sf}}
+        td {{state.#{axis}sgv}}
+
+
+  .overrides
+    | Override:
+    .override
+      label Feed
+      input(type="range", min="-1", max="1", step="0.01",
+        v-model="feed_override", @change="override_feed")
+      span.percent {{feed_override | percent 0}}
+
+    .override
+      label Spindle
+      input(type="range", min="-1", max="1", step="0.01",
+        v-model="speed_override", @change="override_speed")
+      span.percent {{speed_override | percent 0}}
+
+
+  .mdi.pure-form
+    fieldset
+      button.pure-button.pure-button-primary(
+        @click="submit_mdi", :disabled="running") MDI
+      input(v-model="mdi")
+
+
+  .toolbar
+    button.pure-button(@click="play_pause()", :disabled="!file")
+      .fa(:class="running ? 'fa-pause' : 'fa-play'")
+
+    button.pure-button(@click="stop", :disabled="!running")
+      .fa.fa-stop
+
+    button.pure-button(@click="step", :disabled="running || !file")
+      .fa.fa-step-forward
+
+    button.pure-button(@click="optional_stop", :disabled="!file")
+      .fa.fa-stop-circle-o
+
+    button.pure-button(@click="open")
+      .fa.fa-folder-open
+
+    input.gcode-file-input(type="file", @change="upload", style="display:none",
+      accept=".nc,.gcode,.gc,.ngc")
+
+    select(v-model="file", @change="load")
+      option(v-for="file in files", :value="file") {{file}}
+
+    button.pure-button(@click="delete", :disabled="!file")
+      .fa.fa-trash
+
+
+  .gcode {{gcode || 'GCode displays here.'}}
diff --git a/src/jade/templates/estop.jade b/src/jade/templates/estop.jade
new file mode 100644 (file)
index 0000000..8b2d120
--- /dev/null
@@ -0,0 +1,94 @@
+script#estop-template(type="text/x-template")
+  svg(version="1.1", xmlns:svg="http://www.w3.org/2000/svg",
+    xmlns="http://www.w3.org/2000/svg",
+    xmlns:xlink="http://www.w3.org/1999/xlink",
+    width="200", height="200", transform="scale(0.92, 0.92)")
+      defs
+        path#text-path-1(style="fill:none;stroke:none", d="m 73.735867,673.1299 c 0,55.10749 44.673453,99.78094 99.780973,99.78094 55.10748,0 99.78093,-44.67345 99.78093,-99.78094 0,-55.10749 -44.67345,-99.78094 -99.78093,-99.78094 -55.10752,0 -99.780973,44.67345 -99.780973,99.78094 z")
+
+        path#text-path-2(style="fill:none;stroke:none", d="m 258.7149,673.1299 c 0,47.0536 -38.14448,85.19809 -85.19809,85.19809 -47.0536,0 -85.198083,-38.14449 -85.198083,-85.19809 0,-47.05361 38.144483,-85.19809 85.198083,-85.19809 47.05361,0 85.19809,38.14448 85.19809,85.19809 z")
+
+        filter#filter5134(style="color-interpolation-filters:sRGB")
+          feflood(flood-opacity="0.431373", flood-color="rgb(0,0,0)")
+          fecomposite(in2="SourceGraphic", operator="in")
+          fegaussianblur(stddeviation="4", result="blur")
+          feoffset(dx="4", dy="4", result="offset")
+          fecomposite(in="SourceGraphic", in2="offset", operator="over",
+            result="fbSourceGraphic")
+          fecolormatrix(result="fbSourceGraphicAlpha", in="fbSourceGraphic",
+            values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0")
+          feflood(flood-opacity="0.431373", flood-color="rgb(0,0,0)",
+            in="fbSourceGraphic")
+          fecomposite(in2="fbSourceGraphic", operator="out")
+          fegaussianblur(stddeviation="4", result="blur")
+          feoffset(dx="-4", dy="-4", result="offset")
+          fecomposite(in2="fbSourceGraphic", in="offset", operator="atop",
+            result="fbSourceGraphic")
+          fecolormatrix(result="fbSourceGraphicAlpha", in="fbSourceGraphic",
+            values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0")
+          feflood(flood-opacity="0.431373", flood-color="rgb(0,0,0)",
+            in="fbSourceGraphic")
+          fecomposite(in2="fbSourceGraphic", operator="in")
+          fegaussianblur(stddeviation="4", result="blur")
+          feoffset(dx="4", dy="4", result="offset")
+          fecomposite(in2="offset", in="fbSourceGraphic", operator="over")
+
+        filter#filter5158(style="color-interpolation-filters:sRGB",)
+          feflood(flood-opacity="0.431373", flood-color="rgb(0,0,0)")
+          fecomposite(in2="SourceGraphic", operator="out")
+          fegaussianblur(stddeviation="7", result="blur")
+          feoffset(dx="4", dy="4")
+          fecomposite(in2="SourceGraphic", operator="atop")
+
+        filter#filter5266(style="color-interpolation-filters:sRGB")
+          feflood(flood-opacity="0.372549", flood-color="rgb(0,0,0)")
+          fecomposite(in2="SourceGraphic", operator="in")
+          fegaussianblur(stddeviation="2", result="blur")
+          feoffset(dx="1", dy="1", result="offset")
+          fecomposite(in="SourceGraphic", in2="offset", operator="over")
+
+        filter#filter5278(style="color-interpolation-filters:sRGB")
+          feflood(flood-opacity="0.372549", flood-color="rgb(0,0,0)")
+          fecomposite(in2="SourceGraphic", operator="out")
+          fegaussianblur(stddeviation="2", result="blur")
+          feoffset(dx="2", dy="2", result="offset")
+          fecomposite(in="offset", in2="SourceGraphic", operator="atop")
+
+
+      g(transform="translate(-65, -526)")
+        // Yellow ring
+        circle.ring(style="fill:#f5e138;filter:url(#filter5266)",
+          cx="173", cy="633", r="100")
+
+        // Text
+        text(style="font-weight:bold;font-size:20px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none",
+          transform="matrix(-0.73361478,-0.67956556,0.67956556,-0.73361478,-156.72624,1250.7027)",
+          x="-1350.5394", y="-1579.3965")
+          textpath(xlink:href="#text-path-2") EMERGENCY
+
+        text(style="font-weight:bold;font-size:20px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none",
+          transform="matrix(0.27634044,-0.96105981,0.96105981,0.27634044,-523.81801,609.02637)",
+          x="-754.20117", y="157.03941")
+          textpath(xlink:href="#text-path-1") STOP
+
+        g.button
+          circle(style="fill:#b72424;filter:url(#filter5134)",
+            cx="173", cy="633", r="74")
+
+          // Inner circle
+          circle(style="fill:#b72424;filter:url(#filter5158)",
+            cx="173", cy="633", r="37")
+
+          // Arrows
+          g(transform="matrix(0.32737901,0,0,0.32737901,50.806169,478.96619)", style="stroke:#fff;stroke-width:26;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;filter:url(#filter5278);fill:none")
+            g
+              path(transform="matrix(1.9461546,0,0,1.9461546,-359.98722,-383.37383)", style="stroke-width:13", d="m 411.6967,521.14701 c -10.57464,4.47269 -22.20085,6.94599 -34.40474,6.94599 -12.20389,0 -23.8301,-2.4733 -34.40474,-6.94599 -10.57463,-4.4727 -20.09769,-10.94478 -28.09526,-18.94236 -7.99757,-7.99757 -12.91355,-13.50409 -17.38625,-24.07872")
+              path(d="m 221.80189,582.65761 -2.99162,-35.52447 28.48213,14.16667 z")
+
+            g(transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,149.81163,1033.4478)")
+              path(transform="matrix(1.9461546,0,0,1.9461546,-359.98722,-383.37383)", style="stroke-width:13", d="m 411.6967,521.14701 c -10.57464,4.47269 -22.20085,6.94599 -34.40474,6.94599 -12.20389,0 -23.8301,-2.4733 -34.40474,-6.94599 -10.57463,-4.4727 -20.09769,-10.94478 -28.09526,-18.94236 -7.99757,-7.99757 -11.52544,-14.20559 -17.38625,-24.07872")
+              path(d="m 221.80189,582.65761 -2.99162,-35.52447 28.48213,14.16667 z")
+
+            g(transform="matrix(-0.5,0.8660254,-0.8660254,-0.5,971.43059,383.18517)")
+              path(transform="matrix(1.9461546,0,0,1.9461546,-359.98722,-383.37383)", style="stroke-width:13", d="m 411.6967,521.14701 c -10.57464,4.47269 -22.20085,6.94599 -34.40474,6.94599 -12.20389,0 -23.8301,-2.4733 -34.40474,-6.94599 -10.57463,-4.4727 -20.09769,-10.94478 -28.09526,-18.94236 -7.99757,-7.99757 -9.56206,-8.6246 -14.03476,-19.19923")
+              path(d="m 221.80189,582.65761 -2.99162,-35.52447 28.48213,14.16667 z")
diff --git a/src/jade/templates/status-view.jade b/src/jade/templates/status-view.jade
deleted file mode 100644 (file)
index 43f0654..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-script#status-view-template(type="text/x-template")
-  h2 Jog
-  axis-control(axes="XY", :colors="['gold', 'blue']")
-  axis-control(axes="AZ", :colors="['red', 'green']")
-
-  h2 MDI
-  form.pure-form.pure-form-aligned
-    .pure-control-group
-      textarea(v-model="mdi")
-    button(@click="submit_mdi") Submit
-
-  h2 GCode
-  table
-    tr(v-for="file in uploads")
-      td {{file}}
-      td
-        button(@click="delete(file)") Delete
-        button(@click="run(file)") Run
-
-  form
-    input(v-el="gcode", type="file", @change="upload", value="",
-      accept=".nc,.gcode,.gc,.ngc")
-
-  h2 Velocity {{state.v}}
-
-  table.axes
-    tr
-      th Axis
-      th Position
-      th Flags
-      th StallGuard
-
-    each axis in ['x', 'y', 'z']
-      tr.axis
-        th.name #{axis}
-        td {{state.#{axis}p}}
-        td {{state.#{axis}sf}}
-        td {{state.#{axis}sgv}}
index 9b4705c5b751575d08586a7e929f6d73b059eb0f..6becffcb870edb2d25d40670eebbeadd6787a504 100644 (file)
@@ -20,7 +20,7 @@ module.exports = new Vue({
 
   components: {
     'loading-view': {template: '<h1>Loading...</h1>'},
-    'status-view': require('./status-view'),
+    'control-view': require('./control-view'),
     'axis-view': require('./axis-view'),
     'motor-view': require('./motor-view'),
     'spindle-view': require('./spindle-view'),
@@ -54,7 +54,7 @@ module.exports = new Vue({
       var hash = location.hash.substr(1);
 
       if (!hash.trim().length) {
-        location.hash = 'status';
+        location.hash = 'control';
         return;
       }
 
diff --git a/src/js/control-view.js b/src/js/control-view.js
new file mode 100644 (file)
index 0000000..08329a4
--- /dev/null
@@ -0,0 +1,181 @@
+'use strict'
+
+var api = require('./api');
+
+
+function is_array(x) {
+  return Object.prototype.toString.call(x) === '[object Array]';
+}
+
+
+module.exports = {
+  template: '#control-view-template',
+
+
+  data: function () {
+    return {
+      mdi: '',
+      file: '',
+      last_file: '',
+      files: [],
+      axes: 'xyzabc',
+      state: {},
+      gcode: '',
+      speed_override: 0,
+      feed_override: 0
+    }
+  },
+
+
+  components: {
+    'axis-control': require('./axis-control'),
+    'estop': {template: '#estop-template'}
+  },
+
+
+  events: {
+    jog: function (axis, move) {
+      console.debug('jog(' + axis + ', ' + move + ')');
+      this.sock.send('g91 g0' + axis + move);
+    },
+
+
+    home: function (axis) {
+      console.debug('home(' + axis + ')');
+      this.sock.send('$home ' + axis);
+    },
+
+
+    zero: function (axis) {
+      console.debug('zero(' + axis + ')');
+      this.sock.send('$zero ' + axis);
+    }
+  },
+
+
+  ready: function () {
+    this.sock = new SockJS('//' + window.location.host + '/ws');
+
+    this.sock.onmessage = function (e) {
+      var data = e.data;
+      console.debug(data);
+
+      for (var key in data) {
+        this.$set('state.' + key, data[key]);
+
+        for (var axis of ['x', 'y', 'z', 'a'])
+          if (key == axis + 'pl' &&
+              typeof this.$get('current' + axis) == 'undefined')
+            this.$set('current' + axis, (32 * data[key]).toFixed());
+      }
+    }.bind(this);
+
+    this.update();
+  },
+
+
+  methods: {
+    estop: function () {
+      this.$set('state.es', !this.state.es);
+    },
+
+
+    update: function () {
+      api.get('file')
+        .done(function (files) {
+          var index = files.indexOf(this.file);
+          if (index == -1 && files.length) this.file = files[0];
+
+          this.files = files;
+
+          this.load()
+        }.bind(this))
+    },
+
+
+    submit_mdi: function () {
+      this.sock.send(this.mdi);
+    },
+
+
+    open: function (e) {
+      $('.gcode-file-input').click();
+    },
+
+
+    upload: function (e) {
+      var files = e.target.files || e.dataTransfer.files;
+      if (!files.length) return;
+
+      var file = files[0];
+      var fd = new FormData();
+
+      fd.append('gcode', file);
+
+      api.upload('file', fd)
+        .done(function () {
+          this.file = file.name;
+          if (file.name == this.last_file) this.last_file = '';
+          this.update();
+        }.bind(this));
+    },
+
+
+    load: function () {
+      var file = this.file;
+
+      if (!file || this.files.indexOf(file) == -1) {
+        this.file = '';
+        this.gcode = '';
+        return;
+      }
+
+      if (file == this.last_file) return;
+
+      api.get('file/' + file)
+        .done(function (data) {
+          this.gcode = data;
+          this.last_file = file;
+        }.bind(this));
+    },
+
+
+    delete: function () {
+      if (!this.file) return;
+      api.delete('file/' + this.file).done(this.update);
+    },
+
+
+    run: function (file) {
+      api.put('file/' + file).done(this.update);
+    },
+
+
+    send: function (data) {
+      this.sock.send(JSON.stringify(data));
+    },
+
+
+    current: function (axis, value) {
+      var x = value / 32.0;
+      if (this.state[axis + 'pl'] == x) return;
+
+      var data = {};
+      data[axis + 'pl'] = x;
+      this.send(data);
+    }
+  },
+
+
+  filters: {
+    percent: function (value, precision) {
+      if (typeof precision == 'undefined') precision = 2;
+      return (value * 100.0).toFixed(precision) + '%';
+    },
+
+
+    fixed: function (value, precision) {
+      return value.toFixed(precision);
+    }
+  }
+}
diff --git a/src/js/status-view.js b/src/js/status-view.js
deleted file mode 100644 (file)
index aa1355e..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-'use strict'
-
-var api = require('./api');
-
-
-function is_array(x) {
-  return Object.prototype.toString.call(x) === '[object Array]';
-}
-
-
-module.exports = {
-  template: '#status-view-template',
-
-
-  data: function () {
-    return {
-      mdi: '',
-      uploads: [],
-      axes: 'xyza',
-      state: {xpl: 1, ypl: 1, zpl: 1, apl: 1}
-    }
-  },
-
-
-  components: {
-    'axis-control': require('./axis-control')
-  },
-
-
-  events: {
-    jog: function (axis, move) {
-      console.debug('jog(' + axis + ', ' + move + ')');
-      this.sock.send('g91 g0' + axis + move);
-    },
-
-
-    home: function (axis) {
-      console.debug('home(' + axis + ')');
-      this.sock.send('$home ' + axis);
-    },
-
-
-    zero: function (axis) {
-      console.debug('zero(' + axis + ')');
-      this.sock.send('$zero ' + axis);
-    }
-  },
-
-
-  ready: function () {
-    this.sock = new SockJS('//' + window.location.host + '/ws');
-
-    this.sock.onmessage = function (e) {
-      var data = e.data;
-      console.debug(data);
-
-      for (var key in data) {
-        this.$set('state.' + key, data[key]);
-
-        for (var axis of ['x', 'y', 'z', 'a'])
-          if (key == axis + 'pl' &&
-              typeof this.$get('current' + axis) == 'undefined')
-            this.$set('current' + axis, (32 * data[key]).toFixed());
-      }
-    }.bind(this);
-
-    this.update();
-  },
-
-
-  methods: {
-    update: function () {
-      api.get('upload')
-        .done(function (uploads) {
-          this.uploads = uploads;
-        }.bind(this))
-    },
-
-
-    submit_mdi: function () {
-      this.sock.send(this.mdi);
-    },
-
-
-    upload: function (e) {
-      var files = e.target.files || e.dataTransfer.files;
-      if (!files.length) return;
-
-      var fd = new FormData();
-      fd.append('gcode', files[0]);
-
-      api.upload('upload', fd).done(this.update);
-    },
-
-
-    delete: function (file) {
-      api.delete('upload/' + file).done(this.update);
-    },
-
-
-    run: function (file) {
-      api.put('upload/' + file).done(this.update);
-    },
-
-
-    send: function (data) {
-      this.sock.send(JSON.stringify(data));
-    },
-
-
-    current: function (axis, value) {
-      var x = value / 32.0;
-      if (this.state[axis + 'pl'] == x) return;
-
-      var data = {};
-      data[axis + 'pl'] = x;
-      this.send(data);
-    }
-  },
-
-
-  filters: {
-    percent: function (value, precision) {
-      if (typeof precision == 'undefined') precision = 2;
-      return (value * 100.0).toFixed(precision) + '%';
-    }
-  }
-}
index 70d9fdfa4ed9d046e395596b402e6cc681fcd43f..1a96039c9ce0189bc2af16ceeadbfb5d913e2af7 100644 (file)
@@ -22,11 +22,6 @@ body
     color #e5aa3d
 
 
-.jog
-  button
-    width 3.5em
-    margin 0.25em
-
 #menu
   .save
     display block
@@ -62,29 +57,134 @@ body
         display inline-block
 
 
+.control-view
+  table
+    border-collapse collapse
+
+    td, th
+      border 1px solid #ddd
+
+
+.axes
+  .axis-x .name
+    color red
 
-table.axes
-  border-collapse collapse
+  .axis-y .name
+    color green
+
+  .axis-z .name
+    color blue
 
   td, th
-    border 1px solid black
     text-align center
+    padding 8px
 
   .axis
     .name
-      font-size 24pt
+      text-transform capitalize
+
+    .name, .position
+      font-size 36pt
+
+@keyframes blink
+  50%
+    fill #ff9d00
 
+.estop
+  width 130px
+  transition 250ms
+  display inline-block
 
-.gauge
-  position relative
+  &.active .ring
+    animation blink 2s step-start 0s infinite
 
-  span
+  svg
+    cursor pointer
+
+    .button:hover
+      filter brightness(120%)
+
+.jog
+  float right
+
+.jog svg
+  margin-left 2em
+
+  text
+    font-family Sans
     font-weight bold
-    color #000
-    text-shadow 0 0 2px #fff
-    font-size 20pt
-    text-align center
-    position absolute
-    left 0
-    right 0
-    top 75px
+    stroke transparent
+    fill #444
+
+  .button
+    cursor pointer
+    stroke #4c4c4c
+
+    &:hover
+      stroke #e55
+
+    path
+      overflow visible
+
+  .house
+    stroke #444
+    fill #444
+
+  .ring
+    cursor pointer
+    overflow visible
+
+    .button
+      stroke transparent
+
+      &:hover
+        stroke #e55
+
+      text
+        font-size 10pt
+        text-anchor middle
+
+.info
+  float right
+  clear right
+
+  th, td
+    padding 3px
+
+  th
+    text-align right
+
+.overrides .override
+  margin 0.5em
+  display inline-block
+
+  .percent
+    display inline-block
+    width 3em
+
+  input
+    border-radius 0
+    margin -0.4em 0.5em
+
+.mdi
+  clear both
+  white-space nowrap
+  margin 0.5em 0
+
+  input
+    width 90%
+
+.toolbar
+  margin 0.5em 0
+
+.gcode
+  clear both
+  border 2px inset #ccc
+  border-radius 5px
+  overflow auto
+  width 100%
+  max-width 100%
+  min-width 100%
+  height 200px
+  padding 2px
+  white-space pre