Added all the files that I THINK are needed.
This commit is contained in:
parent
445155a658
commit
2c46bb2be3
16 changed files with 530 additions and 0 deletions
1
src/clj/swinging_needle_meter/core.clj
Normal file
1
src/clj/swinging_needle_meter/core.clj
Normal file
|
|
@ -0,0 +1 @@
|
|||
(ns swinging-needle-meter.core)
|
||||
4
src/cljs/swinging_needle_meter/config.cljs
Normal file
4
src/cljs/swinging_needle_meter/config.cljs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(ns swinging-needle-meter.config)
|
||||
|
||||
(def debug?
|
||||
^boolean goog.DEBUG)
|
||||
23
src/cljs/swinging_needle_meter/core.cljs
Normal file
23
src/cljs/swinging_needle_meter/core.cljs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
(ns swinging-needle-meter.core
|
||||
(:require [reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[swinging-needle-meter.events]
|
||||
[swinging-needle-meter.subs]
|
||||
[swinging-needle-meter.views :as views]
|
||||
[swinging-needle-meter.config :as config]))
|
||||
|
||||
|
||||
(defn dev-setup []
|
||||
(when config/debug?
|
||||
(enable-console-print!)
|
||||
(println "dev mode")))
|
||||
|
||||
(defn mount-root []
|
||||
(re-frame/clear-subscription-cache!)
|
||||
(reagent/render [views/main-panel]
|
||||
(.getElementById js/document "app")))
|
||||
|
||||
(defn ^:export init []
|
||||
(re-frame/dispatch-sync [:initialize-db])
|
||||
(dev-setup)
|
||||
(mount-root))
|
||||
4
src/cljs/swinging_needle_meter/db.cljs
Normal file
4
src/cljs/swinging_needle_meter/db.cljs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
(ns swinging-needle-meter.db)
|
||||
|
||||
(def default-db
|
||||
{:name "re-frame"})
|
||||
8
src/cljs/swinging_needle_meter/events.cljs
Normal file
8
src/cljs/swinging_needle_meter/events.cljs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(ns swinging-needle-meter.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[swinging-needle-meter.db :as db]))
|
||||
|
||||
(re-frame/reg-event-db
|
||||
:initialize-db
|
||||
(fn [_ _]
|
||||
db/default-db))
|
||||
8
src/cljs/swinging_needle_meter/subs.cljs
Normal file
8
src/cljs/swinging_needle_meter/subs.cljs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
(ns swinging-needle-meter.subs
|
||||
(:require-macros [reagent.ratom :refer [reaction]])
|
||||
(:require [re-frame.core :as re-frame]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:name
|
||||
(fn [db]
|
||||
(:name db)))
|
||||
81
src/cljs/swinging_needle_meter/swinging_needle_meter.cljs
Normal file
81
src/cljs/swinging_needle_meter/swinging_needle_meter.cljs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
(ns swinging-needle-meter.swinging-needle-meter
|
||||
(:require [re-com.core :refer [h-box v-box box gap line label title slider checkbox p]]
|
||||
[re-com.box :refer [flex-child-style]]
|
||||
[re-com.util :refer [deref-or-value]]
|
||||
[re-com.validate :refer [number-or-string? css-style? html-attr? validate-args-macro]]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; ------------------------------------------------------------------------------------
|
||||
;; Component: swinging-needle
|
||||
;; ------------------------------------------------------------------------------------
|
||||
|
||||
(def swinging-needle-args-desc
|
||||
[{:name :model :required true :type "double | atom"
|
||||
:validate-fn number-or-string? :description "current value of the variable being watched. A number between 0 and 100"}
|
||||
{:name :setpoint :required false :type "double | atom"
|
||||
:validate-fn number-or-string? :description "current setpoint for the variable being watched, if any. A number between 0 and 100"}
|
||||
{:name :width :required false :type "string" :default "100%"
|
||||
:validate-fn string? :description "a CSS width"}
|
||||
{:name :height :required false :type "string" :default "100%"
|
||||
:validate-fn string? :description "a CSS height"}
|
||||
{:name :class :required false :type "string"
|
||||
:validate-fn string? :description "CSS class names, space separated"}
|
||||
;; {:name :cursor-class :required false :type "string" :default "snm-cursor"
|
||||
;; :validate-fn string? :description "CSS class names, space separated, for the cursor"}
|
||||
;; {:name :frame-class :required false :type "string" :default "snm-frame"
|
||||
;; :validate-fn string? :description "CSS class names, space separated, for the frame"}
|
||||
;; {:name :hub-class :required false :type "string" :default "snm-hub"
|
||||
;; :validate-fn string? :description "CSS class names, space separated, for the hub"}
|
||||
;; {:name :needle-class :required false :type "string" :default "snm-needle"
|
||||
;; :validate-fn string? :description "CSS class names, space separated, for the needle"}
|
||||
;; {:name :scale-class :required false :type "string" :default "snm-scale"
|
||||
;; :validate-fn string? :description "CSS class names, space separated, for the scale"}
|
||||
;; {:name :redzone-class :required false :type "string" :default "snm-redzone"
|
||||
;; :validate-fn string? :description "CSS class names, space separated, for the redzone"}
|
||||
{:name :style :required false :type "CSS style map"
|
||||
:validate-fn css-style? :description "CSS styles to add or override"}
|
||||
{:name :attr :required false :type "HTML attr map"
|
||||
:validate-fn html-attr? :description [:span "HTML attributes, like " [:code ":on-mouse-move"] [:br] "No " [:code ":class"] " or " [:code ":style"] "allowed"]}])
|
||||
|
||||
(defn swinging-needle-meter
|
||||
"Render an SVG swinging needle meter"
|
||||
[& {:keys [model setpoint width height class cursor-class frame-class hub-class needle-class scale-class redzone-class style attr]
|
||||
:or {width "100%" height "100%"}
|
||||
:as args}]
|
||||
{:pre [(validate-args-macro swinging-needle-args-desc args "swinging-needle")]}
|
||||
(let [model (deref-or-value model)
|
||||
setpoint (deref-or-value setpoint)]
|
||||
[box
|
||||
:align :start
|
||||
:child [:div
|
||||
(merge
|
||||
{:class (str "rc-swinging-needle " class)
|
||||
:style (merge (flex-child-style "none")
|
||||
{:width width :height height}
|
||||
style)}
|
||||
attr)
|
||||
[:div
|
||||
{:class (str "swinging-needle ")
|
||||
:role "swinging-needle"}
|
||||
[:svg {:xmlns:svg "http://www.w3.org/2000/svg"
|
||||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xml:space "preserve"
|
||||
:overflow "visible"
|
||||
:viewBox "0 0 180 120"
|
||||
:y "0px"
|
||||
:x "0px"
|
||||
:version "1.1"
|
||||
:class (str "snm-meter " class)}
|
||||
[:path {:class "snm-scale"
|
||||
:d "m 11.85914,76.864488 c 0,0 14.34545,-53.795412 68.140856,-53.795412 53.795424,0 68.140864,53.795412 68.140864,53.795412"}]
|
||||
[:path {:class "snm-redzone" :d "m 137.74738,54.878869 c 0,0 3.02675,3.620416 6.3911,11.14347 3.36435,7.523055 4.20612,11.198095 4.20612,11.198095"}]
|
||||
[:rect {:class "snm-frame" :x "5" :y "5" :height "100" :width "150"}]
|
||||
[:path {:class "snm-cursor"
|
||||
:d "M 80,20 80,100"
|
||||
:visibility (if (and (number? setpoint) (> setpoint 0)) "visible" "hidden")
|
||||
:transform (str "rotate( " (* (- setpoint 50) 1.4) ", 80, 100)")}]
|
||||
[:path {:class "snm-needle"
|
||||
:d "M 80,20 80,100"
|
||||
:transform (str "rotate( " (* (- model 50) 1.4) ", 80, 100)") }]
|
||||
[:circle {:class "snm-hub" :r "10" :cx "80" :cy "100"}]]
|
||||
(str model "%")]]]))
|
||||
115
src/cljs/swinging_needle_meter/utils.cljs
Normal file
115
src/cljs/swinging_needle_meter/utils.cljs
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
(ns swinging-needle-meter.utils
|
||||
(:require [re-com.core :refer [h-box v-box box gap title line label hyperlink-href align-style]]))
|
||||
|
||||
;;;; This file is just stolen wholesale from re-demo in the re-com package;
|
||||
;;;; I claim no credit for it.
|
||||
|
||||
(defn github-hyperlink
|
||||
"given a label and a relative path, return a component which hyperlinks to the GitHub URL in a new tab"
|
||||
[label src-path]
|
||||
(let [base-url (str "https://github.com/Day8/re-com/tree/master/")]
|
||||
[hyperlink-href
|
||||
:label label
|
||||
;:style {:font-size "13px"}
|
||||
:href (str base-url src-path)
|
||||
:target "_blank"]))
|
||||
|
||||
(defn panel-title
|
||||
"Shown across the top of each page"
|
||||
[panel-name src1 src2]
|
||||
[v-box
|
||||
:children [[h-box
|
||||
:margin "0px 0px 9px 0px"
|
||||
:height "54px"
|
||||
:align :end
|
||||
:children [[title
|
||||
:label panel-name
|
||||
:level :level1
|
||||
:margin-bottom "0px"
|
||||
:margin-top "2px"]
|
||||
[gap :size "25px"]
|
||||
(when src1 [h-box
|
||||
:class "all-small-caps"
|
||||
:gap "7px"
|
||||
:align :center
|
||||
:children [
|
||||
[label :label "source:" ]
|
||||
[github-hyperlink "component" src1]
|
||||
[label :label "|" :style {:font-size "12px"}]
|
||||
;[line]
|
||||
[github-hyperlink "page" src2]]])]]
|
||||
[line]]])
|
||||
|
||||
(defn title2
|
||||
"2nd level title"
|
||||
[text style]
|
||||
[title
|
||||
:label text
|
||||
:level :level2
|
||||
:style style])
|
||||
|
||||
(defn status-text
|
||||
"given some status text, return a component that displays that status"
|
||||
[status style]
|
||||
[:span
|
||||
[:span.bold "Status: "]
|
||||
[:span {:style style} status]])
|
||||
|
||||
(defn material-design-hyperlink
|
||||
[text]
|
||||
[hyperlink-href
|
||||
:label text
|
||||
:href "http://zavoloklom.github.io/material-design-iconic-font/icons.html"
|
||||
:target "_blank"])
|
||||
|
||||
|
||||
|
||||
(defn arg-row
|
||||
"I show one argument in an args table."
|
||||
[name-width arg odd-row?]
|
||||
(let [required (:required arg)
|
||||
default (:default arg)
|
||||
arg-type (:type arg)
|
||||
needed-vec (if (not required)
|
||||
(if (nil? default)
|
||||
[[:span.semibold.all-small-caps "optional"]]
|
||||
[[:span.semibold.all-small-caps "default:"] [:span.semibold (str default)]])
|
||||
[[:span.semibold.all-small-caps "required"]])]
|
||||
[h-box
|
||||
:style {:background (if odd-row? "#F4F4F4" "#FCFCFC")}
|
||||
:children [[:span {:class "semibold"
|
||||
:style (merge (align-style :align-self :center)
|
||||
{:width name-width
|
||||
:padding-left "15px"})}
|
||||
(str (:name arg))]
|
||||
[line :size "1px" :color "white"]
|
||||
[v-box
|
||||
:style {:padding "7px 15px 2px 15px"}
|
||||
:gap "4px"
|
||||
:width "310px"
|
||||
:children [[h-box
|
||||
:gap "4px"
|
||||
:children (concat [[:span.semibold arg-type]
|
||||
[gap :size "10px"]]
|
||||
needed-vec)]
|
||||
[:p
|
||||
{:font-size "smaller" :color "red"}
|
||||
(:description arg)]]]]]))
|
||||
|
||||
|
||||
(defn args-table
|
||||
"I display a component arguements in an easy to read format"
|
||||
[args]
|
||||
(let [name-width "130px"]
|
||||
(fn
|
||||
[]
|
||||
[v-box
|
||||
:children (concat
|
||||
[[title2 "Parameters"]
|
||||
[gap :size "10px"]]
|
||||
(map (partial arg-row name-width) args (cycle [true false])))])))
|
||||
|
||||
|
||||
(defn scroll-to-top
|
||||
[element]
|
||||
(set! (.-scrollTop element) 0))
|
||||
79
src/cljs/swinging_needle_meter/views.cljs
Normal file
79
src/cljs/swinging_needle_meter/views.cljs
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
(ns swinging-needle-meter.views
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[re-com.core :refer [h-box v-box box gap line label title progress-bar slider checkbox p]]
|
||||
[swinging-needle-meter.swinging-needle-meter :refer [swinging-needle-meter swinging-needle-args-desc]]
|
||||
[swinging-needle-meter.utils :refer [panel-title title2 args-table github-hyperlink status-text]]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; ------------------------------------------------------------------------------------
|
||||
;; Demo: swinging-needle
|
||||
;; ------------------------------------------------------------------------------------
|
||||
|
||||
(defn swinging-needle-demo
|
||||
[]
|
||||
(let [value (reagent/atom 75)
|
||||
setpoint (reagent/atom 75)
|
||||
striped? (reagent/atom false)]
|
||||
(fn
|
||||
[]
|
||||
[v-box
|
||||
:size "auto"
|
||||
:gap "10px"
|
||||
:children [[panel-title "Swinging needle meter"]
|
||||
[h-box
|
||||
:gap "100px"
|
||||
:children [[v-box
|
||||
:gap "10px"
|
||||
:width "450px"
|
||||
:children [[title2 "Notes"]
|
||||
[status-text "Wildly experimental"]
|
||||
[p "An SVG swinging needle meter. Note that the cursor will vanish if the setpoint is null or zero; this is intentional."]
|
||||
[p
|
||||
"TODO: You can't adjust the position of the start of the red-zone; "
|
||||
"you can't override the classes for the different elements of the meter; "
|
||||
"you can't override the maximum and minimum values."]
|
||||
[args-table swinging-needle-args-desc]]]
|
||||
[v-box
|
||||
:gap "10px"
|
||||
:children [[title2 "Demo"]
|
||||
[v-box
|
||||
:gap "20px"
|
||||
:children [[swinging-needle-meter
|
||||
:model value
|
||||
:setpoint setpoint
|
||||
:width "350px"]
|
||||
[title :level :level3 :label "Parameters"]
|
||||
[h-box
|
||||
:gap "10px"
|
||||
:children [[box :align :start :child [:code ":model"]]
|
||||
[slider
|
||||
:model value
|
||||
:min 0
|
||||
:max 100
|
||||
:width "200px"
|
||||
:on-change #(reset! value %)]
|
||||
[label :label @value]]]
|
||||
[h-box
|
||||
:gap "10px"
|
||||
:children [[box :align :start :child [:code ":setpoint"]]
|
||||
[slider
|
||||
:model setpoint
|
||||
:min 0
|
||||
:max 100
|
||||
:width "200px"
|
||||
:on-change #(reset! setpoint %)]
|
||||
[label :label @setpoint]]]
|
||||
]]]]]]]])))
|
||||
|
||||
|
||||
;; core holds a reference to panel, so need one level of indirection to get figwheel updates
|
||||
(defn panel
|
||||
[]
|
||||
[swinging-needle-demo])
|
||||
|
||||
|
||||
(defn main-panel []
|
||||
(fn []
|
||||
[v-box
|
||||
:height "100%"
|
||||
:children [[swinging-needle-demo]]]))
|
||||
Loading…
Add table
Add a link
Reference in a new issue