0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-11 23:31:21 -05:00

🎉 Reimplement canvas as svg (instead of g+rect).

This commit is contained in:
Andrey Antukh 2020-02-18 17:11:17 +01:00
parent 63a339dd31
commit 86ba4fd083
12 changed files with 442 additions and 152 deletions

View file

@ -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?]

View file

@ -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 <niwi@niwi.nz>
;; 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 <niwi@niwi.nz>
(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)

View file

@ -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 <niwi@niwi.nz>
;; Copyright (c) 2015-2016 Juan de la Cruz <delacruzgarciajuan@gmail.com>
;; 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 <niwi@niwi.nz>
;; Copyright (c) 2015-2020 Juan de la Cruz <delacruzgarciajuan@gmail.com>
(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)}])]))

View file

@ -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]))

View file

@ -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

View file

@ -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)

View file

@ -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)"

View file

@ -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)"

View file

@ -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)"

View file

@ -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))

View file

@ -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

View file

@ -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