More work on element options.

This commit is contained in:
Andrey Antukh 2016-01-30 12:02:21 +02:00
parent 43b6056c1e
commit e1a15aed9a
5 changed files with 150 additions and 45 deletions

View file

@ -15,30 +15,40 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ^:static +shape-schema+ (def ^:static +shape-schema+
{:x [v/integer] {:x [sc/integer]
:y [v/integer] :y [sc/integer]
:width [v/integer] :width [sc/integer]
:height [v/integer] :height [sc/integer]
:type [v/required sc/shape-type]}) :type [sc/required sc/shape-type]})
(def ^:static +shape-update-size-schema+ (def ^:static +shape-size-schema+
{:width [v/integer] {:width [sc/integer]
:height [v/integer] :height [sc/integer]
:lock [v/boolean]}) :lock [sc/boolean]})
(def ^:static +shape-update-fill-schema+ (def ^:static +shape-fill-attrs-schema+
{:color [sc/color] {:color [sc/color]
:opacity [v/number]}) :opacity [sc/number]})
(def ^:static +shape-update-stroke-schema+ (def ^:static +shape-stroke-attrs-schema+
{:color [sc/color] {:color [sc/color]
:opacity [v/number]}) :width [sc/integer]
:type [sc/keyword]
:opacity [sc/number]})
(def ^:static +shape-update-position-schema+ (def ^:static +shape-line-attrs-schema+
{:x1 [v/integer] {:x1 [sc/integer]
:y1 [v/integer] :y1 [sc/integer]
:x2 [v/integer] :x2 [sc/integer]
:y2 [v/integer]}) :y2 [sc/integer]})
(def ^:static +shape-radius-attrs-schema+
{:rx [sc/integer]
:ry [sc/integer]})
(def ^:static +shape-position-schema+
{:x [sc/integer]
:y [sc/integer]})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Events (explicit) ;; Events (explicit)
@ -194,13 +204,14 @@
(let [shape (get-in state [:shapes-by-id sid])] (let [shape (get-in state [:shapes-by-id sid])]
(update-in state [:shapes-by-id sid] sh/-move delta))))) (update-in state [:shapes-by-id sid] sh/-move delta)))))
(defn update-line (defn update-line-attrs
[sid props] [sid {:keys [x1 y1 x2 y2] :as opts}]
(sc/validate! +shape-line-attrs-schema+ opts)
(reify (reify
rs/UpdateEvent rs/UpdateEvent
(-apply-update [_ state] (-apply-update [_ state]
(let [shape (get-in state [:shapes-by-id sid]) (let [shape (get-in state [:shapes-by-id sid])
props (select-keys props [:x1 :y1 :x2 :y2]) props (select-keys opts [:x1 :y1 :x2 :y2])
props' (select-keys shape [:x1 :y1 :x2 :y2])] props' (select-keys shape [:x1 :y1 :x2 :y2])]
(update-in state [:shapes-by-id sid] sh/-initialize (update-in state [:shapes-by-id sid] sh/-initialize
(merge props' props)))))) (merge props' props))))))
@ -224,7 +235,7 @@
WARN: only works with shapes that works WARN: only works with shapes that works
with height and width such are" with height and width such are"
[sid {:keys [width height] :as opts}] [sid {:keys [width height] :as opts}]
(sc/validate! +shape-update-size-schema+ opts) (sc/validate! +shape-size-schema+ opts)
(reify (reify
rs/UpdateEvent rs/UpdateEvent
(-apply-update [_ state] (-apply-update [_ state]
@ -234,17 +245,15 @@
(defn update-position (defn update-position
"Update the start position coordenate of the shape." "Update the start position coordenate of the shape."
[sid {:keys [x y] :as opts}] [sid {:keys [x y] :as opts}]
(sc/validate! +shape-update-position-schema+ opts) (sc/validate! +shape-position-schema+ opts)
(reify (reify
rs/UpdateEvent rs/UpdateEvent
(-apply-update [_ state] (-apply-update [_ state]
(update-in state [:shapes-by-id sid] sh/-move' [x y])))) (update-in state [:shapes-by-id sid] sh/-move' [x y]))))
;; TODO: rename fill to "color" for consistency.
(defn update-fill-attrs (defn update-fill-attrs
[sid {:keys [color opacity] :as opts}] [sid {:keys [color opacity] :as opts}]
(sc/validate! +shape-update-fill-schema+ opts) (sc/validate! +shape-fill-attrs-schema+ opts)
(reify (reify
rs/UpdateEvent rs/UpdateEvent
(-apply-update [_ state] (-apply-update [_ state]
@ -254,8 +263,8 @@
(when opacity {:opacity opacity}))))) (when opacity {:opacity opacity})))))
(defn update-stroke-attrs (defn update-stroke-attrs
[sid {:keys [color opacity width type] :as opts}] [sid {:keys [color opacity type width] :as opts}]
(sc/validate! +shape-update-stroke-schema+ opts) (sc/validate! +shape-stroke-attrs-schema+ opts)
(reify (reify
rs/UpdateEvent rs/UpdateEvent
(-apply-update [_ state] (-apply-update [_ state]
@ -266,6 +275,17 @@
(when color {:stroke color}) (when color {:stroke color})
(when opacity {:stroke-opacity opacity}))))) (when opacity {:stroke-opacity opacity})))))
(defn update-radius-attrs
[sid {:keys [rx ry] :as opts}]
(sc/validate! +shape-radius-attrs-schema+ opts)
(reify
rs/UpdateEvent
(-apply-update [_ state]
(update-in state [:shapes-by-id sid]
merge
(when rx {:rx rx})
(when ry {:ry ry})))))
(defn hide-shape (defn hide-shape
[sid] [sid]
(reify (reify
@ -455,7 +475,7 @@
"Update the fill related attributed on "Update the fill related attributed on
selected shapes." selected shapes."
[opts] [opts]
(sc/validate! +shape-update-fill-schema+ opts) (sc/validate! +shape-fill-attrs-schema+ opts)
(reify (reify
rs/WatchEvent rs/WatchEvent
(-apply-watch [_ state] (-apply-watch [_ state]

View file

@ -1,5 +1,5 @@
(ns uxbox.schema (ns uxbox.schema
(:refer-clojure :exclude [keyword uuid vector]) (:refer-clojure :exclude [keyword uuid vector boolean])
(:require [bouncer.core :as b] (:require [bouncer.core :as b]
[bouncer.validators :as v] [bouncer.validators :as v]
[cuerdas.core :as str] [cuerdas.core :as str]
@ -49,6 +49,8 @@
(def required v/required) (def required v/required)
(def number v/number) (def number v/number)
(def integer v/integer)
(def boolean v/boolean)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Public Api ;; Public Api

View file

@ -196,11 +196,8 @@
(defmethod -move' :builtin/circle (defmethod -move' :builtin/circle
[shape [x y]] [shape [x y]]
(let [{:keys [cx cy rx ry]} shape (let [dx (if x (- (:cx shape) x) 0)
x1 (- cx rx) dy (if y (- (:cy shape) y) 0)]
y1 (- cy ry)
dx (if x (- (:x1 shape) x) 0)
dy (if y (- (:y1 shape) y) 0)]
(-move shape [dx dy]))) (-move shape [dx dy])))
(defmethod -move' :default (defmethod -move' :default

View file

@ -16,7 +16,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ^:static ^:private +style-attrs+ (def ^:static ^:private +style-attrs+
#{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type}) #{:fill :opacity :stroke :stroke-opacity :stroke-width :stroke-type :rx :ry})
(defn- transform-stroke-type (defn- transform-stroke-type
[attrs] [attrs]

View file

@ -18,14 +18,18 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def ^:static ^:private +menus-map+ (def ^:static ^:private +menus-map+
{:builtin/icon [:menu/rect-measures :menu/fill :menu/stroke] {:builtin/icon [:menu/icon-measures :menu/fill :menu/stroke]
:builtin/rect [:menu/rect-measures :menu/fill :menu/stroke] :builtin/rect [:menu/rect-measures :menu/fill :menu/stroke]
:builtin/line [:menu/line-measures :menu/stroke] :builtin/line [:menu/line-measures :menu/stroke]
:builtin/circle [:menu/circle-measures :menu/fill :menu/stroke] :builtin/circle [:menu/circle-measures :menu/fill :menu/stroke]
:builtin/group []}) :builtin/group []})
(def ^:static ^:private +menus-by-id+ (def ^:static ^:private +menus-by-id+
{:menu/rect-measures {:menu/icon-measures
{:name "Size, position & rotation"
:icon i/infocard}
:menu/rect-measures
{:name "Size, position & rotation" {:name "Size, position & rotation"
:icon i/infocard} :icon i/infocard}
@ -192,7 +196,12 @@
sid (:id shape) sid (:id shape)
props {attr value}] props {attr value}]
(rs/emit! (dw/update-position sid props)))) (rs/emit! (dw/update-position sid props))))
(on-border-change [attr event])] (on-border-change [attr event]
(let [value (dom/event->value event)
value (parse-int value nil)
sid (:id shape)
props {attr value}]
(rs/emit! (dw/update-radius-attrs sid props))))]
(html (html
[:div.element-set {:key (str (:id menu))} [:div.element-set {:key (str (:id menu))}
[:div.element-set-title (:name menu)] [:div.element-set-title (:name menu)]
@ -263,6 +272,83 @@
]]] ]]]
))) )))
(defmethod -render-menu :menu/icon-measures
[menu own shape]
(letfn [(on-size-change [attr event]
(let [value (dom/event->value event)
value (parse-int value 0)
sid (:id shape)
props {attr value}]
(rs/emit! (dw/update-size sid props))))
(on-rotation-change [event]
(let [value (dom/event->value event)
value (parse-int value 0)
sid (:id shape)]
(rs/emit! (dw/update-rotation sid value))))
(on-pos-change [attr event]
(let [value (dom/event->value event)
value (parse-int value nil)
sid (:id shape)
props {attr value}]
(rs/emit! (dw/update-position sid props))))]
(html
[:div.element-set {:key (str (:id menu))}
[:div.element-set-title (:name menu)]
[:div.element-set-content
;; SLIDEBAR FOR ROTATION AND OPACITY
[:span "Size"]
[:div.row-flex
[:input#width.input-text
{:placeholder "Width"
:type "number"
:min "0"
:value (:width shape)
:on-change (partial on-size-change :width)}]
[:div.lock-size i/lock]
[:input#width.input-text
{:placeholder "Height"
:type "number"
:min "0"
:value (:height shape)
:on-change (partial on-size-change :height)}]]
[:span "Position"]
[:div.row-flex
[:input#width.input-text
{:placeholder "x"
:type "number"
:value (:x shape "")
:on-change (partial on-pos-change :x)}]
[:input#width.input-text
{:placeholder "y"
:type "number"
:value (:y shape "")
:on-change (partial on-pos-change :y)}]]
[:span "Rotation"]
[:div.row-flex
[:input.slidebar
{:type "range"
:min 0
:max 360
:value (:rotation shape 0)
:on-change on-rotation-change}]]
[:div.row-flex
[:input#width.input-text
{:placeholder ""
:type "number"
:min 0
:max 360
:value (:rotation shape "0")
:on-change on-rotation-change
}]
[:input.input-text
{:style {:visibility "hidden"}}]
]]]
)))
(defmethod -render-menu :menu/circle-measures (defmethod -render-menu :menu/circle-measures
[menu own shape] [menu own shape]
(letfn [(on-size-change [attr event] (letfn [(on-size-change [attr event]
@ -270,18 +356,18 @@
value (parse-int value 0) value (parse-int value 0)
sid (:id shape) sid (:id shape)
props {attr value}] props {attr value}]
#_(rs/emit! (dw/update-size sid props)))) (rs/emit! (dw/update-radius-attrs sid props))))
(on-rotation-change [event] (on-rotation-change [event]
(let [value (dom/event->value event) (let [value (dom/event->value event)
value (parse-int value 0) value (parse-int value 0)
sid (:id shape)] sid (:id shape)]
#_(rs/emit! (dw/update-rotation sid value)))) (rs/emit! (dw/update-rotation sid value))))
(on-pos-change [attr event] (on-pos-change [attr event]
(let [value (dom/event->value event) (let [value (dom/event->value event)
value (parse-int value nil) value (parse-int value nil)
sid (:id shape) sid (:id shape)
props {attr value}] props {attr value}]
#_(rs/emit! (dw/update-position sid props))))] (rs/emit! (dw/update-position sid props))))]
(html (html
[:div.element-set {:key (str (:id menu))} [:div.element-set {:key (str (:id menu))}
[:div.element-set-title (:name menu)] [:div.element-set-title (:name menu)]
@ -309,12 +395,12 @@
{:placeholder "cx" {:placeholder "cx"
:type "number" :type "number"
:value (:cx shape "") :value (:cx shape "")
:on-change (partial on-pos-change :cx)}] :on-change (partial on-pos-change :x)}]
[:input#width.input-text [:input#width.input-text
{:placeholder "cy" {:placeholder "cy"
:type "number" :type "number"
:value (:cy shape "") :value (:cy shape "")
:on-change (partial on-pos-change :cy)}]] :on-change (partial on-pos-change :y)}]]
[:span "Rotation"] [:span "Rotation"]
[:div.row-flex [:div.row-flex
@ -351,7 +437,7 @@
value (parse-int value nil) value (parse-int value nil)
sid (:id shape) sid (:id shape)
props {attr value}] props {attr value}]
(rs/emit! (dw/update-line sid props))))] (rs/emit! (dw/update-line-attrs sid props))))]
(html (html
[:div.element-set {:key (str (:id menu))} [:div.element-set {:key (str (:id menu))}
[:div.element-set-title (:name menu)] [:div.element-set-title (:name menu)]