diff --git a/frontend/src/uxbox/main/data/workspace.cljs b/frontend/src/uxbox/main/data/workspace.cljs index f9f6270bf..1ac994329 100644 --- a/frontend/src/uxbox/main/data/workspace.cljs +++ b/frontend/src/uxbox/main/data/workspace.cljs @@ -960,28 +960,107 @@ (let [shape (get-in state [:workspace-data :shapes-by-id id])] (assoc shape :id (uuid/next)))) +;; (defn duplicate-shapes +;; [ids] +;; (us/verify (s/every ::us/uuid) ids) +;; (ptk/reify ::duplicate-selected +;; ptk/UpdateEvent +;; (update [_ state] +;; (let [duplicate #(-> (get-in state [:workspace-data :shapes-by-id %]) +;; (assoc :id (uuid/next)))] +;; (reduce + +;; shapes (map duplicate selected) +;; sid (:session-id state) +;; changes (mapv (fn [shape] +;; {:type :add-shape +;; :id (:id shape) +;; :shape shape +;; :session-id sid}) +;; shapes) +;; uchanges (mapv (fn [shape] +;; {:type :del-shape +;; :id (:id shape) +;; :session-id sid}) +;; shapes)] +;; (rx/merge + +(defn duplicate-shapes + [shapes] + (ptk/reify ::duplicate-shapes + ptk/UpdateEvent + (update [_ state] + (reduce (fn [state {:keys [id] :as shape}] + (-> state + (assoc-in [:workspace-data :shapes-by-id id] shape) + (update-in [:workspace-data :shapes] (fnil conj []) id))) + state + shapes)) + + ptk/WatchEvent + (watch [_ state stream] + (let [rchanges (mapv (fn [shape] + {:type :add-shape + :id (:id shape) + :shape shape + :session-id (:session-id state)}) + shapes) + uchanges (mapv (fn [shape] + {:type :del-shape + :id (:id shape) + :session-id (:session-id state)}) + shapes)] + (rx/of (commit-changes rchanges uchanges)))))) + +(defn duplicate-canvas + [{:keys [id] :as canvas} prev-id] + (ptk/reify ::duplicate-canvas + ptk/UpdateEvent + (update [_ state] + (-> state + (assoc-in [:workspace-data :shapes-by-id id] canvas) + (update-in [:workspace-data :canvas] (fnil conj []) id))) + + ptk/WatchEvent + (watch [_ state stream] + (let [shapes (->> (vals (get-in state [:workspace-data :shapes-by-id])) + (filter #(= (:canvas %) prev-id)) + (map #(assoc % :id (uuid/next))) + (map #(assoc % :canvas id))) + + rchange {:type :add-canvas + :id id + :shape canvas + :session-id (:session-id state)} + uchange {:type :del-canvas + :id id + :session-id (:session-id state)}] + (rx/of (duplicate-shapes shapes) + (commit-changes [rchange] [uchange])))))) + + (def duplicate-selected (ptk/reify ::duplicate-selected ptk/WatchEvent (watch [_ state stream] - (let [selected (get-in state [:workspace-local :selected]) - duplicate (partial impl-duplicate-shape state) - shapes (map duplicate selected) - sid (:session-id state) - changes (mapv (fn [shape] - {:type :add-shape - :id (:id shape) - :shape shape - :session-id sid}) - shapes) - uchanges (mapv (fn [shape] - {:type :del-shape - :id (:id shape) - :session-id sid}) - shapes)] - (rx/merge - (rx/from (map (fn [s] #(impl-assoc-shape % s)) shapes)) - (rx/of (commit-changes changes uchanges))))))) + (let [selected (get-in state [:workspace-local :selected]) + dup #(-> (get-in state [:workspace-data :shapes-by-id %]) + (assoc :id (uuid/next))) + shapes (map dup selected) + shape? #(not= (:type %) :canvas)] + (cond + (and (= (count shapes) 1) + (= (:type (first shapes)) :canvas)) + (rx/of (duplicate-canvas (first shapes) (first selected))) + + (and (pos? (count shapes)) + (every? shape? shapes)) + (rx/of (duplicate-shapes shapes)) + + :else + (rx/empty)))))) + + ;; --- Toggle shape's selection status (selected or deselected) @@ -1080,8 +1159,6 @@ ;; --- Shape Movement (using keyboard shorcuts) (declare initial-selection-align) -(declare apply-temporal-displacement-in-bulk) -(declare materialize-temporal-modifier-in-bulk) (defn- get-displacement-with-grid "Retrieve the correct displacement delta point for the @@ -1109,6 +1186,9 @@ (s/def ::direction #{:up :down :right :left}) +(declare apply-displacement-in-bulk) +(declare materialize-displacement-in-bulk) + (defn move-selected [direction align?] (us/verify ::direction direction) @@ -1124,8 +1204,8 @@ displacement (if align? (get-displacement-with-grid shape direction options) (get-displacement shape direction))] - (rx/of (apply-temporal-displacement-in-bulk selected displacement) - (materialize-temporal-modifier-in-bulk selected)))))) + (rx/of (apply-displacement-in-bulk selected displacement) + (materialize-displacement-in-bulk selected)))))) ;; --- Delete Selected @@ -1289,34 +1369,10 @@ (:y1 sshape))] (->> (uwrk/align-point point) (rx/map (fn [{:keys [x y] :as pt}] - (apply-temporal-displacement-in-bulk ids (gpt/subtract pt point))))))))) + (apply-displacement-in-bulk ids (gpt/subtract pt point))))))))) ;; --- Temportal displacement for Shape / Selection -(defn assoc-temporal-modifier-in-bulk - [ids xfmt] - (us/verify ::set-of-uuid ids) - (us/verify gmt/matrix? xfmt) - (ptk/reify ::assoc-temporal-modifier-in-bulk - ptk/UpdateEvent - (update [_ state] - (reduce #(assoc-in %1 [:workspace-data :shapes-by-id %2 :modifier-mtx] xfmt) state ids)))) - -(defn apply-temporal-displacement-in-bulk - "Apply the same displacement delta to all shapes identified by the - set if ids." - [ids delta] - (us/verify ::set-of-uuid ids) - (us/verify gpt/point? delta) - (letfn [(process-shape [state id] - (let [prev (get-in state [:workspace-data :shapes-by-id id :modifier-mtx] (gmt/matrix)) - xfmt (gmt/translate prev delta)] - (assoc-in state [:workspace-data :shapes-by-id id :modifier-mtx] xfmt)))] - (ptk/reify ::apply-temporal-displacement-in-bulk - ptk/UpdateEvent - (update [_ state] - (reduce process-shape state ids))))) - (defn- recalculate-shape-canvas-relation [state shape] (let [shape' (geom/shape->rect-shape shape) @@ -1330,21 +1386,109 @@ (first))] (assoc shape :canvas id))) -(defn materialize-temporal-modifier-in-bulk +(defn assoc-resize-modifier-in-bulk + [ids xfmt] + (us/verify ::set-of-uuid ids) + (us/verify gmt/matrix? xfmt) + (ptk/reify ::assoc-resize-modifier-in-bulk + ptk/UpdateEvent + (update [_ state] + (reduce #(assoc-in %1 [:workspace-data :shapes-by-id %2 :resize-modifier] xfmt) state ids)))) + +(defn materialize-resize-modifier-in-bulk [ids] (letfn [(process-shape [state id] (let [shape (get-in state [:workspace-data :shapes-by-id id]) - xfmt (or (:modifier-mtx shape) (gmt/matrix)) - shape-old (dissoc shape :modifier-mtx) - shape-new (geom/transform shape-old xfmt) - shape-new (recalculate-shape-canvas-relation state shape-new)] - (assoc-in state [:workspace-data :shapes-by-id id] shape-new)))] - (ptk/reify ::materialize-temporal-modifier-in-bulk + modifier (:resize-modifier shape (gmt/matrix)) + + shape (-> (dissoc shape :resize-modifier) + (geom/transform modifier)) + shape (recalculate-shape-canvas-relation state shape)] + (assoc-in state [:workspace-data :shapes-by-id id] shape)))] + (ptk/reify ::materialize-resize-modifier-in-bulk IBatchedChange ptk/UpdateEvent (update [_ state] (reduce process-shape state ids))))) +(defn apply-displacement-in-bulk + "Apply the same displacement delta to all shapes identified by the + set if ids." + [ids delta] + (us/verify ::set-of-uuid ids) + (us/verify gpt/point? delta) + (letfn [(process-shape [state id] + (let [shape (get-in state [:workspace-data :shapes-by-id id]) + prev (:displacement-modifier shape (gmt/matrix)) + curr (gmt/translate prev delta)] + (->> (assoc shape :displacement-modifier curr) + (assoc-in state [:workspace-data :shapes-by-id id]))))] + (ptk/reify ::apply-displacement-in-bulk + ptk/UpdateEvent + (update [_ state] + (reduce process-shape state ids))))) + +(defn materialize-displacement-in-bulk + [ids] + (letfn [(process-shape [state id] + (let [shape (get-in state [:workspace-data :shapes-by-id id]) + modifier (:displacement-modifier shape (gmt/matrix)) + + shape (-> (dissoc shape :displacement-modifier) + (geom/transform modifier)) + shape (recalculate-shape-canvas-relation state shape)] + (assoc-in state [:workspace-data :shapes-by-id id] shape)))] + (ptk/reify ::materialize-displacement-in-bulk + IBatchedChange + ptk/UpdateEvent + (update [_ state] + (reduce process-shape state ids))))) + + +(defn apply-canvas-displacement + "Apply the same displacement delta to all shapes identified by the + set if ids." + [id delta] + (us/verify ::us/uuid id) + (us/verify gpt/point? delta) + (ptk/reify ::apply-canvas-displacement + ptk/UpdateEvent + (update [_ state] + (let [shape (get-in state [:workspace-data :shapes-by-id id]) + prev-xfmt (:displacement-modifier shape (gmt/matrix)) + xfmt (gmt/translate prev-xfmt delta)] + (->> (assoc shape :displacement-modifier xfmt) + (assoc-in state [:workspace-data :shapes-by-id id])))))) + +(defn materialize-canvas-displacement + [id] + (us/verify ::us/uuid id) + (ptk/reify ::materialize-canvas-displacement + IBatchedChange + ptk/UpdateEvent + (update [_ state] + (let [data (:workspace-data state) + shapes-map (:shapes-by-id data) + + canvas (get shapes-map id) + + xfmt (or (:displacement-modifier canvas) (gmt/matrix)) + + canvas (-> canvas + (dissoc :displacement-modifier) + (geom/transform xfmt)) + + shapes (->> (:shapes data []) + (map #(get shapes-map %)) + (filter #(= (:canvas %) id)) + (map #(geom/transform % xfmt))) + + shapes (d/index-by :id shapes) + shapes (assoc shapes (:id canvas) canvas)] + + (update-in state [:workspace-data :shapes-by-id] merge shapes))))) + + (defn commit-changes ([changes undo-changes] (commit-changes changes undo-changes true)) ([changes undo-changes save-undo?] diff --git a/frontend/src/uxbox/main/ui/shapes.cljs b/frontend/src/uxbox/main/ui/shapes.cljs index 666acc9e3..8df0648c6 100644 --- a/frontend/src/uxbox/main/ui/shapes.cljs +++ b/frontend/src/uxbox/main/ui/shapes.cljs @@ -2,7 +2,10 @@ ;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; -;; Copyright (c) 2016-2019 Andrey Antukh +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2016-2020 Andrey Antukh (ns uxbox.main.ui.shapes (:require @@ -10,25 +13,7 @@ [rumext.alpha :as mf] [uxbox.main.refs :as refs] [uxbox.main.store :as st] - [uxbox.main.ui.shapes.circle :as circle] - [uxbox.main.ui.shapes.icon :as icon] - [uxbox.main.ui.shapes.image :as image] - [uxbox.main.ui.shapes.path :as path] - [uxbox.main.ui.shapes.rect :as rect] - [uxbox.main.ui.shapes.canvas :as canvas] - [uxbox.main.ui.shapes.text :as text])) - -(mf/defc shape-wrapper - {:wrap [mf/wrap-memo]} - [{:keys [shape] :as props}] - (when (and shape (not (:hidden shape))) - (case (:type shape) - :canvas [:& canvas/canvas-wrapper {:shape shape}] - :curve [:& path/path-wrapper {:shape shape}] - :text [:& text/text-wrapper {:shape shape}] - :icon [:& icon/icon-wrapper {:shape shape}] - :rect [:& rect/rect-wrapper {:shape shape}] - :path [:& path/path-wrapper {:shape shape}] - :image [:& image/image-wrapper {:shape shape}] - :circle [:& circle/circle-wrapper {:shape shape}]))) + [uxbox.main.ui.shapes.canvas :as canvas])) +(def shape-wrapper canvas/shape-wrapper) +(def canvas-wrapper canvas/canvas-wrapper) diff --git a/frontend/src/uxbox/main/ui/shapes/canvas.cljs b/frontend/src/uxbox/main/ui/shapes/canvas.cljs index ea61005d4..1b5198259 100644 --- a/frontend/src/uxbox/main/ui/shapes/canvas.cljs +++ b/frontend/src/uxbox/main/ui/shapes/canvas.cljs @@ -2,8 +2,11 @@ ;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; -;; Copyright (c) 2015-2016 Andrey Antukh -;; Copyright (c) 2015-2016 Juan de la Cruz +;; This Source Code Form is "Incompatible With Secondary Licenses", as +;; defined by the Mozilla Public License, v. 2.0. +;; +;; Copyright (c) 2015-2020 Andrey Antukh +;; Copyright (c) 2015-2020 Juan de la Cruz (ns uxbox.main.ui.shapes.canvas (:require @@ -13,29 +16,97 @@ [uxbox.main.data.workspace :as dw] [uxbox.main.geom :as geom] [uxbox.main.refs :as refs] - [uxbox.main.ui.shapes.common :as common] [uxbox.main.store :as st] - [uxbox.main.ui.shapes.rect :refer [rect-shape]] + [uxbox.main.ui.shapes.attrs :as attrs] + [uxbox.main.ui.shapes.circle :as circle] + [uxbox.main.ui.shapes.common :as common] + [uxbox.main.ui.shapes.icon :as icon] + [uxbox.main.ui.shapes.image :as image] + [uxbox.main.ui.shapes.path :as path] + [uxbox.main.ui.shapes.rect :as rect] + [uxbox.main.ui.shapes.text :as text] [uxbox.util.data :refer [parse-int]] [uxbox.util.dom :as dom] + [uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.point :as gpt])) +(declare canvas-wrapper) + +(mf/defc shape-wrapper + {:wrap [mf/wrap-memo]} + [{:keys [shape] :as props}] + (when (and shape (not (:hidden shape))) + (case (:type shape) + :canvas [:& canvas-wrapper {:shape shape :childs []}] + :curve [:& path/path-wrapper {:shape shape}] + :text [:& text/text-wrapper {:shape shape}] + :icon [:& icon/icon-wrapper {:shape shape}] + :rect [:& rect/rect-wrapper {:shape shape}] + :path [:& path/path-wrapper {:shape shape}] + :image [:& image/image-wrapper {:shape shape}] + :circle [:& circle/circle-wrapper {:shape shape}]))) + (def canvas-default-props {:fill-color "#ffffff"}) +(declare canvas-shape) + (mf/defc canvas-wrapper - [{:keys [shape] :as props}] - (let [selected (mf/deref refs/selected-shapes) - selected? (contains? selected (:id shape)) - on-mouse-down #(common/on-mouse-down % shape selected) - shape (merge canvas-default-props shape)] - (letfn [(on-double-click [event] - (dom/prevent-default event) - (st/emit! dw/deselect-all - (dw/select-shape (:id shape))))] - [:g.shape {:class (when selected? "selected") - :on-double-click on-double-click - :on-mouse-down on-mouse-down} - [:& rect-shape {:shape shape}]]))) + [{:keys [shape childs] :as props}] + (when (and shape (not (:hidden shape))) + (let [selected (mf/deref refs/selected-shapes) + selected? (contains? selected (:id shape)) + on-mouse-down #(common/on-mouse-down % shape selected) + shape (merge canvas-default-props shape) + + on-double-click + (fn [event] + (dom/prevent-default event) + (st/emit! dw/deselect-all + (dw/select-shape (:id shape))))] + [:g {:class (when selected? "selected") + :on-double-click on-double-click + :on-mouse-down on-mouse-down} + [:& canvas-shape {:shape shape :childs childs}]]))) + +(defn- translate-to-canvas + [shape canvas-ds-modifier pt] + (let [rz-modifier (:resize-modifier shape) + shape (cond-> shape + (gmt/matrix? canvas-ds-modifier) + (geom/transform canvas-ds-modifier) + + (gmt/matrix? rz-modifier) + (-> (geom/transform rz-modifier) + (dissoc :resize-modifier)))] + (geom/move shape pt))) + +(mf/defc canvas-shape + [{:keys [shape childs] :as props}] + (let [rotation (:rotation shape) + ds-modifier (:displacement-modifier shape) + rz-modifier (:modifier-mtx shape) + + shape (cond-> shape + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier)) + + {:keys [id x y width height]} shape + + props (-> (attrs/extract-style-attrs shape) + (assoc :x 0 + :y 0 + :id (str "shape-" id) + :width width + :height height + )) + + translate #(translate-to-canvas % ds-modifier (gpt/point (- x) (- y)))] + + [:svg {:x x :y y :width width :height height} + [:& "rect" props] + (for [item (map translate childs)] + [:& shape-wrapper {:shape item :key (:id item)}])])) + diff --git a/frontend/src/uxbox/main/ui/shapes/circle.cljs b/frontend/src/uxbox/main/ui/shapes/circle.cljs index 694fdcdae..fa2299890 100644 --- a/frontend/src/uxbox/main/ui/shapes/circle.cljs +++ b/frontend/src/uxbox/main/ui/shapes/circle.cljs @@ -32,28 +32,28 @@ (mf/defc circle-shape [{:keys [shape] :as props}] - (let [{:keys [id rotation cx cy modifier-mtx]} shape - shape (cond - (gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx) - :else shape) + (let [ds-modifier (:displacement-modifier shape) + rz-modifier (:resize-modifier shape) - center (gpt/point (:cx shape) - (:cy shape)) + shape (cond-> shape + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier)) - rotation (or rotation 0) - - moving? (boolean modifier-mtx) + {:keys [id cx cy rx ry rotation]} shape + center (gpt/point cx cy) + rotation (or rotation 0) transform (when (pos? rotation) (str (-> (gmt/matrix) (gmt/rotate rotation center)))) - props {:id (str "shape-" id) - :class (classnames :move-cursor moving?) - :transform transform} - - attrs (merge props - (attrs/extract-style-attrs shape) - (select-keys shape [:cx :cy :rx :ry]))] - [:> :ellipse (normalize-props attrs)])) + props (-> (attrs/extract-style-attrs shape) + (assoc :cx cx + :cy cy + :rx rx + :ry ry + :transform transform + :id (str "shape-" id) + ))] + [:& "elipse" props])) diff --git a/frontend/src/uxbox/main/ui/shapes/common.cljs b/frontend/src/uxbox/main/ui/shapes/common.cljs index 2cfc9e89d..e23191995 100644 --- a/frontend/src/uxbox/main/ui/shapes/common.cljs +++ b/frontend/src/uxbox/main/ui/shapes/common.cljs @@ -13,12 +13,15 @@ (:require [potok.core :as ptk] [beicon.core :as rx] + [uxbox.common.data :as d] + [uxbox.common.spec :as us] [uxbox.main.data.workspace :as dw] [uxbox.main.refs :as refs] [uxbox.main.store :as st] [uxbox.main.ui.keyboard :as kbd] [uxbox.main.streams :as uws] [uxbox.main.workers :as uwrk] + [uxbox.main.geom :as geom] [uxbox.util.geom.matrix :as gmt] [uxbox.util.geom.point :as gpt] [uxbox.util.dom :as dom])) @@ -34,14 +37,93 @@ stoper (rx/filter uws/mouse-up? stream) position @uws/mouse-position] (rx/concat - ;; (when (refs/alignment-activated? flags) - ;; (rx/of (dw/initial-selection-align selected))) (->> (uws/mouse-position-deltas position) - (rx/map #(dw/apply-temporal-displacement-in-bulk selected %)) + (rx/map #(dw/apply-displacement-in-bulk selected %)) (rx/take-until stoper)) - (rx/of (dw/materialize-temporal-modifier-in-bulk selected) + (rx/of (dw/materialize-displacement-in-bulk selected) ::dw/page-data-update)))))) +;; (defn apply-canvas-displacement +;; "Apply the same displacement delta to all shapes identified by the +;; set if ids." +;; [id delta] +;; (us/verify ::us/uuid id) +;; (us/verify gpt/point? delta) +;; (ptk/reify ::apply-temporal-displacement-in-bulk +;; ptk/UpdateEvent +;; (update [_ state] +;; (let [shape (get-in state [:workspace-data :shapes-by-id id]) +;; prev-xfmt (:displacement-modifier shape (gmt/matrix)) +;; xfmt (gmt/translate prev-xfmt delta)] +;; (->> (assoc shape :displacement-modifier xfmt) +;; (assoc-in state [:workspace-data :shapes-by-id id])))))) + +;; (defn materialize-canvas-displacement +;; [id] +;; (us/verify ::us/uuid id) +;; (ptk/reify ::materialize-temporal-modifier +;; dw/IBatchedChange +;; ptk/UpdateEvent +;; (update [_ state] +;; (let [data (:workspace-data state) +;; shapes-map (:shapes-by-id data) + +;; canvas (get shapes-map id) + +;; xfmt (or (:displacement-modifier canvas) (gmt/matrix)) + +;; canvas (-> canvas +;; (dissoc :displacement-modifier) +;; (geom/transform xfmt)) + +;; shapes (->> (:shapes data []) +;; (map #(get shapes-map %)) +;; (filter #(= (:canvas %) id)) +;; (map #(geom/transform % xfmt))) + +;; shapes (d/index-by :id shapes) +;; shapes (assoc shapes (:id canvas) canvas)] + +;; (update-in state [:workspace-data :shapes-by-id] merge shapes))))) + +;; (defn- move-canvas +;; [id delta] +;; (ptk/reify ::move-canvas +;; ptk/UpdateEvent +;; (update [_ state] +;; (let [data (:workspace-data state) +;; shapes-map (:shapes-by-id data) + +;; canvas (-> (get shapes-map id) +;; (geom/move delta)) + +;; shapes (->> (:shapes data []) +;; (map #(get shapes-map %)) +;; (filter #(= (:canvas %) id)) +;; (map #(geom/move % delta))) + +;; shapes (d/index-by :id shapes) +;; shapes (assoc shapes (:id canvas) canvas)] + +;; (update-in state [:workspace-data :shapes-by-id] merge shapes))))) + + +(def start-move-canvas + (ptk/reify ::start-move-selected + ptk/WatchEvent + (watch [_ state stream] + (let [flags (get-in state [:workspace-local :flags]) + selected (get-in state [:workspace-local :selected]) + stoper (rx/filter uws/mouse-up? stream) + canvas-id (first selected) + position @uws/mouse-position] + + (rx/concat + (->> (uws/mouse-position-deltas position) + (rx/map #(dw/apply-canvas-displacement canvas-id %)) + (rx/take-until stoper)) + (rx/of (dw/materialize-canvas-displacement canvas-id))))))) + (defn on-mouse-down [event {:keys [id type] :as shape} selected] (let [selected? (contains? selected id) @@ -54,7 +136,7 @@ (= type :canvas) (when selected? (dom/stop-propagation event) - (st/emit! start-move-selected)) + (st/emit! start-move-canvas)) (and (not selected?) (empty? selected)) (do diff --git a/frontend/src/uxbox/main/ui/shapes/icon.cljs b/frontend/src/uxbox/main/ui/shapes/icon.cljs index cb46e0a23..0f3fef643 100644 --- a/frontend/src/uxbox/main/ui/shapes/icon.cljs +++ b/frontend/src/uxbox/main/ui/shapes/icon.cljs @@ -34,13 +34,14 @@ (mf/defc icon-shape [{:keys [shape] :as props}] - (let [{:keys [id content metadata rotation modifier-mtx]} shape + (let [ds-modifier (:displacement-modifier shape) + rz-modifier (:resize-modifier shape) - shape (cond - (gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx) - :else shape) + shape (cond-> shape + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier)) - {:keys [x y width height] :as shape} shape + {:keys [id x y width height metadata rotation content] :as shape} shape transform (when (and rotation (pos? rotation)) (str/format "rotate(%s %s %s)" @@ -48,7 +49,6 @@ (+ x (/ width 2)) (+ y (/ height 2)))) - view-box (apply str (interpose " " (:view-box metadata))) props (-> (attrs/extract-style-attrs shape) diff --git a/frontend/src/uxbox/main/ui/shapes/image.cljs b/frontend/src/uxbox/main/ui/shapes/image.cljs index 1bc3a7524..024f26792 100644 --- a/frontend/src/uxbox/main/ui/shapes/image.cljs +++ b/frontend/src/uxbox/main/ui/shapes/image.cljs @@ -33,13 +33,14 @@ (mf/defc image-shape [{:keys [shape] :as props}] - (let [{:keys [id rotation modifier-mtx metadata]} shape + (let [ds-modifier (:displacement-modifier shape) + rz-modifier (:resize-modifier shape) - shape (cond - (gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx) - :else shape) + shape (cond-> shape + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier)) - {:keys [x y width height]} shape + {:keys [id x y width height rotation metadata]} shape transform (when (and rotation (pos? rotation)) (str/format "rotate(%s %s %s)" diff --git a/frontend/src/uxbox/main/ui/shapes/path.cljs b/frontend/src/uxbox/main/ui/shapes/path.cljs index 70ab92544..edad7ce68 100644 --- a/frontend/src/uxbox/main/ui/shapes/path.cljs +++ b/frontend/src/uxbox/main/ui/shapes/path.cljs @@ -61,14 +61,14 @@ (mf/defc path-shape [{:keys [shape background?] :as props}] - (let [modifier-mtx (:modifier-mtx shape) - rotation (:rotation shape) + (let [ds-modifier (:displacement-modifier shape) + rz-modifier (:resize-modifier shape) - shape (cond - (gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx) - :else shape) + shape (cond-> shape + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier)) - {:keys [id x y width height]} (geom/shape->rect-shape shape) + {:keys [id x y width height rotation]} (geom/shape->rect-shape shape) transform (when (and rotation (pos? rotation)) (str/format "rotate(%s %s %s)" diff --git a/frontend/src/uxbox/main/ui/shapes/rect.cljs b/frontend/src/uxbox/main/ui/shapes/rect.cljs index f1cfa5d75..9e379bbfa 100644 --- a/frontend/src/uxbox/main/ui/shapes/rect.cljs +++ b/frontend/src/uxbox/main/ui/shapes/rect.cljs @@ -34,13 +34,14 @@ (mf/defc rect-shape [{:keys [shape] :as props}] - (let [{:keys [id rotation modifier-mtx]} shape + (let [ds-modifier (:displacement-modifier shape) + rz-modifier (:resize-modifier shape) - shape (cond - (gmt/matrix? modifier-mtx) (geom/transform shape modifier-mtx) - :else shape) + shape (cond-> shape + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier)) - {:keys [x y width height]} shape + {:keys [id x y width height rotation]} shape transform (when (and rotation (pos? rotation)) (str/format "rotate(%s %s %s)" diff --git a/frontend/src/uxbox/main/ui/workspace/drawarea.cljs b/frontend/src/uxbox/main/ui/workspace/drawarea.cljs index d776405e0..999dc5175 100644 --- a/frontend/src/uxbox/main/ui/workspace/drawarea.cljs +++ b/frontend/src/uxbox/main/ui/workspace/drawarea.cljs @@ -120,7 +120,7 @@ result (geom/resize-shape :bottom-right shape' point lock?) scale (geom/calculate-scale-ratio shape' result) mtx (geom/generate-resize-matrix :bottom-right shape' scale)] - (assoc shape :modifier-mtx mtx))) + (assoc shape :resize-modifier mtx))) (update-drawing [state point lock?] (update-in state [:workspace-local :drawing] resize-shape point lock?))] @@ -273,11 +273,11 @@ (rx/concat (rx/of dw/clear-drawing) (when (::initialized? shape) - (let [modifier-mtx (:modifier-mtx shape) - shape (if (gmt/matrix? modifier-mtx) - (geom/transform shape modifier-mtx) + (let [modifier (:resize-modifier shape) + shape (if (gmt/matrix? modifier) + (geom/transform shape modifier) shape) - shape (dissoc shape ::initialized? :modifier-mtx)] + shape (dissoc shape ::initialized? :resize-modifier)] ;; Add & select the created shape to the workspace (rx/of dw/deselect-all (if (= :canvas (:type shape)) diff --git a/frontend/src/uxbox/main/ui/workspace/selection.cljs b/frontend/src/uxbox/main/ui/workspace/selection.cljs index 36584604c..06ed474f7 100644 --- a/frontend/src/uxbox/main/ui/workspace/selection.cljs +++ b/frontend/src/uxbox/main/ui/workspace/selection.cljs @@ -35,7 +35,7 @@ (let [result (geom/resize-shape vid shape point lock?) scale (geom/calculate-scale-ratio shape result) mtx (geom/generate-resize-matrix vid shape scale)] - (rx/of (dw/assoc-temporal-modifier-in-bulk ids mtx)))) + (rx/of (dw/assoc-resize-modifier-in-bulk ids mtx)))) ;; Unifies the instantaneous proportion lock modifier ;; activated by Ctrl key and the shapes own proportion @@ -64,8 +64,7 @@ (rx/map normalize-proportion-lock) (rx/mapcat (partial resize shape)) (rx/take-until stoper)) - (rx/of (dw/materialize-temporal-modifier-in-bulk ids) - ::dw/page-data-update))))))) + (rx/of (dw/materialize-resize-modifier-in-bulk ids)))))))) (defn start-rotate [shape] @@ -261,9 +260,13 @@ (st/emit! (start-resize %1 #{(:id shape)} shape))) on-rotate #(do (dom/stop-propagation %) (st/emit! (start-rotate shape))) - modifier (:modifier-mtx shape) - shape (-> (geom/shape->rect-shape shape) - (geom/transform (or modifier (gmt/matrix))))] + + ds-modifier (:displacement-modifier shape) + rz-modifier (:resize-modifier shape) + shape (cond-> (geom/shape->rect-shape shape) + (gmt/matrix? rz-modifier) (geom/transform rz-modifier) + (gmt/matrix? ds-modifier) (geom/transform ds-modifier))] + [:& controls {:shape shape :zoom zoom :on-rotate on-rotate diff --git a/frontend/src/uxbox/main/ui/workspace/viewport.cljs b/frontend/src/uxbox/main/ui/workspace/viewport.cljs index fbec6a65a..e3426fb7c 100644 --- a/frontend/src/uxbox/main/ui/workspace/viewport.cljs +++ b/frontend/src/uxbox/main/ui/workspace/viewport.cljs @@ -23,7 +23,7 @@ [uxbox.main.ui.workspace.ruler :refer [ruler]] [uxbox.main.ui.workspace.drawarea :refer [start-drawing]] - [uxbox.main.ui.shapes :refer [shape-wrapper]] + [uxbox.main.ui.shapes :refer [shape-wrapper canvas-wrapper]] [uxbox.main.ui.workspace.drawarea :refer [draw-area]] [uxbox.main.ui.workspace.selection :refer [selection-handlers]] @@ -149,11 +149,14 @@ (let [data (mf/deref refs/workspace-data) shapes-by-id (:shapes-by-id data) shapes (map #(get shapes-by-id %) (:shapes data [])) - canvas (map #(get shapes-by-id %) (:canvas data []))] + canvas (map #(get shapes-by-id %) (:canvas data [])) + unassinged (filter #(nil? (:canvas %)) shapes)] [:g.shapes (for [item canvas] - [:& shape-wrapper {:shape item :key (:id item)}]) - (for [item shapes] + (let [shapes (filter #(= (:canvas %) (:id item)) shapes)] + [:& canvas-wrapper {:shape item :key (:id item) + :childs shapes}])) + (for [item unassinged] [:& shape-wrapper {:shape item :key (:id item)}])])) (mf/defc viewport