diff --git a/src/uxbox/data/workspace.cljs b/src/uxbox/data/workspace.cljs index bc4064e713..c7dd0b8dab 100644 --- a/src/uxbox/data/workspace.cljs +++ b/src/uxbox/data/workspace.cljs @@ -15,30 +15,40 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (def ^:static +shape-schema+ - {:x [v/integer] - :y [v/integer] - :width [v/integer] - :height [v/integer] - :type [v/required sc/shape-type]}) + {:x [sc/integer] + :y [sc/integer] + :width [sc/integer] + :height [sc/integer] + :type [sc/required sc/shape-type]}) -(def ^:static +shape-update-size-schema+ - {:width [v/integer] - :height [v/integer] - :lock [v/boolean]}) +(def ^:static +shape-size-schema+ + {:width [sc/integer] + :height [sc/integer] + :lock [sc/boolean]}) -(def ^:static +shape-update-fill-schema+ +(def ^:static +shape-fill-attrs-schema+ {:color [sc/color] - :opacity [v/number]}) + :opacity [sc/number]}) -(def ^:static +shape-update-stroke-schema+ +(def ^:static +shape-stroke-attrs-schema+ {:color [sc/color] - :opacity [v/number]}) + :width [sc/integer] + :type [sc/keyword] + :opacity [sc/number]}) -(def ^:static +shape-update-position-schema+ - {:x1 [v/integer] - :y1 [v/integer] - :x2 [v/integer] - :y2 [v/integer]}) +(def ^:static +shape-line-attrs-schema+ + {:x1 [sc/integer] + :y1 [sc/integer] + :x2 [sc/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) @@ -194,13 +204,14 @@ (let [shape (get-in state [:shapes-by-id sid])] (update-in state [:shapes-by-id sid] sh/-move delta))))) -(defn update-line - [sid props] +(defn update-line-attrs + [sid {:keys [x1 y1 x2 y2] :as opts}] + (sc/validate! +shape-line-attrs-schema+ opts) (reify rs/UpdateEvent (-apply-update [_ state] (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])] (update-in state [:shapes-by-id sid] sh/-initialize (merge props' props)))))) @@ -224,7 +235,7 @@ WARN: only works with shapes that works with height and width such are" [sid {:keys [width height] :as opts}] - (sc/validate! +shape-update-size-schema+ opts) + (sc/validate! +shape-size-schema+ opts) (reify rs/UpdateEvent (-apply-update [_ state] @@ -234,17 +245,15 @@ (defn update-position "Update the start position coordenate of the shape." [sid {:keys [x y] :as opts}] - (sc/validate! +shape-update-position-schema+ opts) + (sc/validate! +shape-position-schema+ opts) (reify rs/UpdateEvent (-apply-update [_ state] (update-in state [:shapes-by-id sid] sh/-move' [x y])))) -;; TODO: rename fill to "color" for consistency. - (defn update-fill-attrs [sid {:keys [color opacity] :as opts}] - (sc/validate! +shape-update-fill-schema+ opts) + (sc/validate! +shape-fill-attrs-schema+ opts) (reify rs/UpdateEvent (-apply-update [_ state] @@ -254,8 +263,8 @@ (when opacity {:opacity opacity}))))) (defn update-stroke-attrs - [sid {:keys [color opacity width type] :as opts}] - (sc/validate! +shape-update-stroke-schema+ opts) + [sid {:keys [color opacity type width] :as opts}] + (sc/validate! +shape-stroke-attrs-schema+ opts) (reify rs/UpdateEvent (-apply-update [_ state] @@ -266,6 +275,17 @@ (when color {:stroke color}) (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 [sid] (reify @@ -455,7 +475,7 @@ "Update the fill related attributed on selected shapes." [opts] - (sc/validate! +shape-update-fill-schema+ opts) + (sc/validate! +shape-fill-attrs-schema+ opts) (reify rs/WatchEvent (-apply-watch [_ state] diff --git a/src/uxbox/schema.cljs b/src/uxbox/schema.cljs index eec520f477..ca3bb03c04 100644 --- a/src/uxbox/schema.cljs +++ b/src/uxbox/schema.cljs @@ -1,5 +1,5 @@ (ns uxbox.schema - (:refer-clojure :exclude [keyword uuid vector]) + (:refer-clojure :exclude [keyword uuid vector boolean]) (:require [bouncer.core :as b] [bouncer.validators :as v] [cuerdas.core :as str] @@ -49,6 +49,8 @@ (def required v/required) (def number v/number) +(def integer v/integer) +(def boolean v/boolean) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Public Api diff --git a/src/uxbox/shapes.cljs b/src/uxbox/shapes.cljs index 1e3d6f54eb..98c2a80454 100644 --- a/src/uxbox/shapes.cljs +++ b/src/uxbox/shapes.cljs @@ -196,11 +196,8 @@ (defmethod -move' :builtin/circle [shape [x y]] - (let [{:keys [cx cy rx ry]} shape - x1 (- cx rx) - y1 (- cy ry) - dx (if x (- (:x1 shape) x) 0) - dy (if y (- (:y1 shape) y) 0)] + (let [dx (if x (- (:cx shape) x) 0) + dy (if y (- (:cy shape) y) 0)] (-move shape [dx dy]))) (defmethod -move' :default diff --git a/src/uxbox/ui/shapes.cljs b/src/uxbox/ui/shapes.cljs index b9449b65e8..2d5e8db680 100644 --- a/src/uxbox/ui/shapes.cljs +++ b/src/uxbox/ui/shapes.cljs @@ -16,7 +16,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (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 [attrs] diff --git a/src/uxbox/ui/workspace/options.cljs b/src/uxbox/ui/workspace/options.cljs index 1eca7f866e..2bed8cad67 100644 --- a/src/uxbox/ui/workspace/options.cljs +++ b/src/uxbox/ui/workspace/options.cljs @@ -18,14 +18,18 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (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/line [:menu/line-measures :menu/stroke] :builtin/circle [:menu/circle-measures :menu/fill :menu/stroke] :builtin/group []}) (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" :icon i/infocard} @@ -192,7 +196,12 @@ sid (:id shape) props {attr value}] (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 [:div.element-set {:key (str (:id 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 [menu own shape] (letfn [(on-size-change [attr event] @@ -270,18 +356,18 @@ value (parse-int value 0) sid (:id shape) props {attr value}] - #_(rs/emit! (dw/update-size sid props)))) + (rs/emit! (dw/update-radius-attrs 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)))) + (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))))] + (rs/emit! (dw/update-position sid props))))] (html [:div.element-set {:key (str (:id menu))} [:div.element-set-title (:name menu)] @@ -309,12 +395,12 @@ {:placeholder "cx" :type "number" :value (:cx shape "") - :on-change (partial on-pos-change :cx)}] + :on-change (partial on-pos-change :x)}] [:input#width.input-text {:placeholder "cy" :type "number" :value (:cy shape "") - :on-change (partial on-pos-change :cy)}]] + :on-change (partial on-pos-change :y)}]] [:span "Rotation"] [:div.row-flex @@ -351,7 +437,7 @@ value (parse-int value nil) sid (:id shape) props {attr value}] - (rs/emit! (dw/update-line sid props))))] + (rs/emit! (dw/update-line-attrs sid props))))] (html [:div.element-set {:key (str (:id menu))} [:div.element-set-title (:name menu)]