mirror of
https://github.com/penpot/penpot.git
synced 2026-03-19 08:53:39 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
@@ -52,7 +52,7 @@
|
||||
(t/testing "Shape without modifiers should stay the same"
|
||||
(t/are [type]
|
||||
(let [shape-before (create-test-shape type)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(= shape-before shape-after))
|
||||
|
||||
:rect :path))
|
||||
@@ -61,7 +61,7 @@
|
||||
(t/are [type]
|
||||
(let [modifiers {:displacement (gmt/translate-matrix (gpt/point 10 -10))}]
|
||||
(let [shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(t/is (not= shape-before shape-after))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
@@ -82,7 +82,7 @@
|
||||
(t/are [type]
|
||||
(let [modifiers {:displacement (gmt/matrix)}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
@@ -95,7 +95,7 @@
|
||||
:resize-vector (gpt/point 2 2)
|
||||
:resize-transform (gmt/matrix)}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(t/is (not= shape-before shape-after))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
@@ -117,7 +117,7 @@
|
||||
:resize-vector (gpt/point 1 1)
|
||||
:resize-transform (gmt/matrix)}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
@@ -130,7 +130,7 @@
|
||||
:resize-vector (gpt/point 0 0)
|
||||
:resize-transform (gmt/matrix)}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(t/is (> (get-in shape-before [:selrect :width])
|
||||
(get-in shape-after [:selrect :width])))
|
||||
(t/is (> (get-in shape-after [:selrect :width]) 0))
|
||||
@@ -144,7 +144,7 @@
|
||||
(t/are [type]
|
||||
(let [modifiers {:rotation 30}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
|
||||
(t/is (not= shape-before shape-after))
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
(t/are [type]
|
||||
(let [modifiers {:rotation 0}
|
||||
shape-before (create-test-shape type {:modifiers modifiers})
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(t/are [prop]
|
||||
(t/is (close? (get-in shape-before [:selrect prop])
|
||||
(get-in shape-after [:selrect prop])))
|
||||
@@ -180,7 +180,7 @@
|
||||
(let [modifiers {:displacement (gmt/matrix)}
|
||||
shape-before (-> (create-test-shape type {:modifiers modifiers})
|
||||
(assoc :selrect selrect))
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
shape-after (gsh/transform-shape shape-before {:round-coords? false})]
|
||||
(= (:selrect shape-before) (:selrect shape-after)))
|
||||
|
||||
:rect {:x 0 :y 0 :width ##Inf :height ##Inf}
|
||||
|
||||
@@ -174,9 +174,17 @@
|
||||
"Checks if the given rect overlaps with the path in any point"
|
||||
[shape rect]
|
||||
|
||||
(let [rect-points (gpr/rect->points rect)
|
||||
(let [;; If paths are too complex the intersection is too expensive
|
||||
;; we fallback to check its bounding box otherwise the performance penalty
|
||||
;; is too big
|
||||
;; TODO: Look for ways to optimize this operation
|
||||
simple? (> (count (:content shape)) 100)
|
||||
|
||||
rect-points (gpr/rect->points rect)
|
||||
rect-lines (points->lines rect-points)
|
||||
path-lines (gpp/path->lines shape)
|
||||
path-lines (if simple?
|
||||
(points->lines (:points shape))
|
||||
(gpp/path->lines shape))
|
||||
start-point (-> shape :content (first) :params (gpt/point))]
|
||||
|
||||
(or (is-point-inside-nonzero? (first rect-points) path-lines)
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
(defn apply-transform
|
||||
"Given a new set of points transformed, set up the rectangle so it keeps
|
||||
its properties. We adjust de x,y,width,height and create a custom transform"
|
||||
[shape transform]
|
||||
[shape transform round-coords?]
|
||||
;;
|
||||
(let [points (-> shape :points (transform-points transform))
|
||||
center (gco/center-points points)
|
||||
@@ -283,6 +283,11 @@
|
||||
center
|
||||
(:width points-temp-dim)
|
||||
(:height points-temp-dim))
|
||||
(cond-> round-coords?
|
||||
(-> (update :x #(mth/precision % 0))
|
||||
(update :y #(mth/precision % 0))
|
||||
(update :width #(mth/precision % 0))
|
||||
(update :height #(mth/precision % 0))))
|
||||
(update :width max 1)
|
||||
(update :height max 1))
|
||||
|
||||
@@ -297,11 +302,7 @@
|
||||
|
||||
:else
|
||||
(-> shape
|
||||
(merge rect-shape)
|
||||
(update :x #(mth/precision % 0))
|
||||
(update :y #(mth/precision % 0))
|
||||
(update :width #(mth/precision % 0))
|
||||
(update :height #(mth/precision % 0))))]
|
||||
(merge rect-shape)))]
|
||||
(as-> shape $
|
||||
(update $ :transform #(gmt/multiply (or % (gmt/matrix)) matrix))
|
||||
(update $ :transform-inverse #(gmt/multiply matrix-inverse (or % (gmt/matrix))))
|
||||
@@ -347,18 +348,23 @@
|
||||
%)))
|
||||
shape))
|
||||
|
||||
(defn transform-shape [shape]
|
||||
(let [shape (apply-displacement shape)
|
||||
center (gco/center-shape shape)
|
||||
modifiers (:modifiers shape)]
|
||||
(if (and modifiers center)
|
||||
(let [transform (modifiers->transform center modifiers)]
|
||||
(-> shape
|
||||
(set-flip modifiers)
|
||||
(apply-transform transform)
|
||||
(apply-text-resize shape modifiers)
|
||||
(dissoc :modifiers)))
|
||||
shape)))
|
||||
(defn transform-shape
|
||||
([shape]
|
||||
(transform-shape shape nil))
|
||||
|
||||
([shape {:keys [round-coords?]
|
||||
:or {round-coords? true}}]
|
||||
(let [shape (apply-displacement shape)
|
||||
center (gco/center-shape shape)
|
||||
modifiers (:modifiers shape)]
|
||||
(if (and modifiers center)
|
||||
(let [transform (modifiers->transform center modifiers)]
|
||||
(-> shape
|
||||
(set-flip modifiers)
|
||||
(apply-transform transform round-coords?)
|
||||
(apply-text-resize shape modifiers)
|
||||
(dissoc :modifiers)))
|
||||
shape))))
|
||||
|
||||
(defn update-group-viewbox
|
||||
"Updates the viewbox for groups imported from SVG's"
|
||||
@@ -407,5 +413,5 @@
|
||||
;; need to remove the flip flags
|
||||
(assoc :flip-x false)
|
||||
(assoc :flip-y false)
|
||||
(apply-transform (gmt/matrix)))))
|
||||
(apply-transform (gmt/matrix) true))))
|
||||
|
||||
|
||||
@@ -461,8 +461,9 @@
|
||||
(defn merge-modifiers
|
||||
[objects modifiers]
|
||||
|
||||
(let [set-modifier (fn [objects [id modifiers]]
|
||||
(-> objects
|
||||
(d/update-when id assoc :modifiers modifiers)))]
|
||||
(let [set-modifier
|
||||
(fn [objects [id modifiers]]
|
||||
(-> objects
|
||||
(d/update-when id merge modifiers)))]
|
||||
(->> modifiers
|
||||
(reduce set-modifier objects))))
|
||||
|
||||
@@ -46,7 +46,7 @@ http {
|
||||
listen 3449 default_server;
|
||||
server_name _;
|
||||
|
||||
client_max_body_size 5M;
|
||||
client_max_body_size 20M;
|
||||
charset utf-8;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
|
||||
@@ -1164,11 +1164,15 @@
|
||||
(ptk/reify ::update-shape-flags
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(letfn [(update-fn [obj]
|
||||
(cond-> obj
|
||||
(boolean? blocked) (assoc :blocked blocked)
|
||||
(boolean? hidden) (assoc :hidden hidden)))]
|
||||
(rx/of (dch/update-shapes-recursive [id] update-fn))))))
|
||||
(let [update-fn
|
||||
(fn [obj]
|
||||
(cond-> obj
|
||||
(boolean? blocked) (assoc :blocked blocked)
|
||||
(boolean? hidden) (assoc :hidden hidden)))
|
||||
|
||||
objects (wsh/lookup-page-objects state)
|
||||
ids (d/concat [id] (cp/get-children id objects))]
|
||||
(rx/of (dch/update-shapes ids update-fn))))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.common.pages.spec :as spec]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.worker :as uw]
|
||||
[app.main.store :as st]
|
||||
[app.util.logging :as log]
|
||||
@@ -31,127 +32,75 @@
|
||||
|
||||
(def commit-changes? (ptk/type? ::commit-changes))
|
||||
|
||||
(defn- generate-operations
|
||||
([ma mb] (generate-operations ma mb false))
|
||||
([ma mb undo?]
|
||||
(let [ops (let [ma-keys (set (keys ma))
|
||||
mb-keys (set (keys mb))
|
||||
added (set/difference mb-keys ma-keys)
|
||||
removed (set/difference ma-keys mb-keys)
|
||||
both (set/intersection ma-keys mb-keys)]
|
||||
(d/concat
|
||||
(mapv #(array-map :type :set :attr % :val (get mb %)) added)
|
||||
(mapv #(array-map :type :set :attr % :val nil) removed)
|
||||
(loop [items (seq both)
|
||||
result []]
|
||||
(if items
|
||||
(let [k (first items)
|
||||
vma (get ma k)
|
||||
vmb (get mb k)]
|
||||
(if (= vma vmb)
|
||||
(recur (next items) result)
|
||||
(recur (next items)
|
||||
(conj result {:type :set
|
||||
:attr k
|
||||
:val vmb
|
||||
:ignore-touched undo?}))))
|
||||
result))))]
|
||||
(if undo?
|
||||
(conj ops {:type :set-touched :touched (:touched mb)})
|
||||
ops))))
|
||||
(defn- generate-operation
|
||||
"Given an object old and new versions and an attribute will append into changes
|
||||
the set and undo operations"
|
||||
[changes attr old new]
|
||||
(let [old-val (get old attr)
|
||||
new-val (get new attr)]
|
||||
(if (= old-val new-val)
|
||||
changes
|
||||
(-> changes
|
||||
(update :rops conj {:type :set :attr attr :val new-val})
|
||||
(update :uops conj {:type :set :attr attr :val old-val :ignore-touched true})))))
|
||||
|
||||
(defn- update-shape-changes
|
||||
"Calculate the changes and undos to be done when a function is applied to a
|
||||
single object"
|
||||
[changes page-id objects update-fn attrs id]
|
||||
(let [old-obj (get objects id)
|
||||
new-obj (update-fn old-obj)
|
||||
|
||||
attrs (or attrs (d/concat #{} (keys old-obj) (keys new-obj)))
|
||||
|
||||
{rops :rops uops :uops}
|
||||
(reduce #(generate-operation %1 %2 old-obj new-obj)
|
||||
{:rops [] :uops []}
|
||||
attrs)
|
||||
|
||||
uops (cond-> uops
|
||||
(not (empty? uops))
|
||||
(conj {:type :set-touched :touched (:touched old-obj)}))
|
||||
|
||||
change {:type :mod-obj :page-id page-id :id id}]
|
||||
|
||||
(cond-> changes
|
||||
(not (empty? rops))
|
||||
(update :rch conj (assoc change :operations rops))
|
||||
|
||||
(not (empty? uops))
|
||||
(update :uch conj (assoc change :operations uops)))))
|
||||
|
||||
(defn update-shapes
|
||||
([ids f] (update-shapes ids f nil))
|
||||
([ids f {:keys [reg-objects? save-undo?]
|
||||
:or {reg-objects? false save-undo? true}}]
|
||||
([ids f {:keys [reg-objects? save-undo? keys]
|
||||
:or {reg-objects? false save-undo? true attrs nil}}]
|
||||
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
|
||||
(ptk/reify ::update-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}]
|
||||
(loop [ids (seq ids)
|
||||
rch []
|
||||
uch []]
|
||||
(if (nil? ids)
|
||||
(rx/of (let [has-rch? (not (empty? rch))
|
||||
has-uch? (not (empty? uch))
|
||||
rch (cond-> rch (and has-rch? reg-objects?) (conj reg-objects))
|
||||
uch (cond-> uch (and has-rch? reg-objects?) (conj reg-objects))]
|
||||
(when (and has-rch? has-uch?)
|
||||
(commit-changes {:redo-changes rch
|
||||
:undo-changes uch
|
||||
:origin it
|
||||
:save-undo? save-undo?}))))
|
||||
objects (wsh/lookup-page-objects state)
|
||||
reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}
|
||||
|
||||
(let [id (first ids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rch-operations (generate-operations obj1 obj2)
|
||||
uch-operations (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rch-operations
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uch-operations
|
||||
:id id}]
|
||||
(recur (next ids)
|
||||
(if (empty? rch-operations) rch (conj rch rchg))
|
||||
(if (empty? uch-operations) uch (conj uch uchg)))))))))))
|
||||
{redo-changes :rch undo-changes :uch}
|
||||
(reduce #(update-shape-changes %1 page-id objects f keys %2)
|
||||
{:rch [] :uch []} ids)]
|
||||
|
||||
(defn update-shapes-recursive
|
||||
[ids f]
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
(letfn [(impl-get-children [objects id]
|
||||
(cons id (cp/get-children id objects)))
|
||||
(when-not (empty? redo-changes)
|
||||
(let [redo-changes (cond-> redo-changes
|
||||
reg-objects? (conj reg-objects))
|
||||
|
||||
(impl-gen-changes [objects page-id ids]
|
||||
(loop [sids (seq ids)
|
||||
cids (seq (impl-get-children objects (first sids)))
|
||||
rchanges []
|
||||
uchanges []]
|
||||
(cond
|
||||
(nil? sids)
|
||||
[rchanges uchanges]
|
||||
undo-changes (cond-> undo-changes
|
||||
reg-objects? (conj reg-objects))]
|
||||
|
||||
(nil? cids)
|
||||
(recur (next sids)
|
||||
(seq (impl-get-children objects (first (next sids))))
|
||||
rchanges
|
||||
uchanges)
|
||||
|
||||
:else
|
||||
(let [id (first cids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rops (generate-operations obj1 obj2)
|
||||
uops (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rops
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uops
|
||||
:id id}]
|
||||
(recur sids
|
||||
(next cids)
|
||||
(conj rchanges rchg)
|
||||
(conj uchanges uchg))))))]
|
||||
(ptk/reify ::update-shapes-recursive
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
[rchanges uchanges] (impl-gen-changes objects page-id (seq ids))]
|
||||
(rx/of (commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})))))))
|
||||
(rx/of (commit-changes {:redo-changes redo-changes
|
||||
:undo-changes undo-changes
|
||||
:origin it
|
||||
:save-undo? save-undo?})))))))))
|
||||
|
||||
(defn update-indices
|
||||
[page-id changes]
|
||||
@@ -222,4 +171,4 @@
|
||||
(when (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes undo-changes
|
||||
:redo-changes redo-changes}]
|
||||
(rx/of (dwu/append-undo entry)))))))))))
|
||||
(rx/of (dwu/append-undo entry)))))))))))
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
(watch [_ state stream]
|
||||
(let [shape (get-in state [:workspace-drawing :object])]
|
||||
(rx/concat
|
||||
(rx/of clear-drawing)
|
||||
(when (:initialized? shape)
|
||||
(let [page-id (:current-page-id state)
|
||||
shape-click-width (case (:type shape)
|
||||
@@ -65,4 +64,8 @@
|
||||
:page-id page-id
|
||||
:rect (:selrect shape)})
|
||||
(rx/map #(dwc/move-shapes-into-frame (:id shape) %)))
|
||||
(rx/empty))))))))))
|
||||
(rx/empty)))))
|
||||
|
||||
;; Delay so the mouse event can read the drawing state
|
||||
(->> (rx/of clear-drawing)
|
||||
(rx/delay 0)))))))
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
|
||||
(ns app.main.data.workspace.state-helpers
|
||||
(:require
|
||||
[app.common.data :as d]))
|
||||
[app.common.data :as d]
|
||||
[app.common.pages :as cp]))
|
||||
|
||||
(defn lookup-page-objects
|
||||
([state]
|
||||
@@ -26,8 +27,9 @@
|
||||
|
||||
(defn lookup-selected
|
||||
[state]
|
||||
(let [selected (get-in state [:workspace-local :selected])
|
||||
objects (lookup-page-objects state)
|
||||
(let [objects (lookup-page-objects state)
|
||||
selected (->> (get-in state [:workspace-local :selected])
|
||||
(cp/clean-loops objects))
|
||||
is-present? (fn [id] (contains? objects id))]
|
||||
(into (d/ordered-set)
|
||||
(filter is-present?)
|
||||
|
||||
@@ -72,6 +72,27 @@
|
||||
:bottom-left [ex sy])]
|
||||
(gpt/point x y)))
|
||||
|
||||
(defn- fix-init-point
|
||||
"Fix the initial point so the resizes are accurate"
|
||||
[initial handler shape]
|
||||
(let [{:keys [x y width height]} (:selrect shape)
|
||||
{:keys [rotation]} shape
|
||||
rotation (or rotation 0)]
|
||||
(if (= rotation 0)
|
||||
(cond-> initial
|
||||
(contains? #{:left :top-left :bottom-left} handler)
|
||||
(assoc :x x)
|
||||
|
||||
(contains? #{:right :top-right :bottom-right} handler)
|
||||
(assoc :x (+ x width))
|
||||
|
||||
(contains? #{:top :top-right :top-left} handler)
|
||||
(assoc :y y)
|
||||
|
||||
(contains? #{:bottom :bottom-right :bottom-left} handler)
|
||||
(assoc :y (+ y height)))
|
||||
initial)))
|
||||
|
||||
(defn finish-transform []
|
||||
(ptk/reify ::finish-transform
|
||||
ptk/UpdateEvent
|
||||
@@ -84,6 +105,10 @@
|
||||
(letfn [(resize [shape initial resizing-shapes layout [point lock? point-snap]]
|
||||
(let [{:keys [width height]} (:selrect shape)
|
||||
{:keys [rotation]} shape
|
||||
rotation (or rotation 0)
|
||||
|
||||
initial (fix-init-point initial handler shape)
|
||||
|
||||
shapev (-> (gpt/point width height))
|
||||
|
||||
scale-text (:scale-text layout)
|
||||
@@ -253,6 +278,7 @@
|
||||
frame-id (cp/frame-id-by-position objects position)
|
||||
|
||||
moving-shapes (->> ids
|
||||
(cp/clean-loops objects)
|
||||
(map #(get objects %))
|
||||
(remove #(= (:frame-id %) frame-id)))
|
||||
|
||||
@@ -320,8 +346,7 @@
|
||||
(rx/map snap/correct-snap-point)
|
||||
(rx/map start-local-displacement))
|
||||
|
||||
(rx/of (set-modifiers ids)
|
||||
(apply-modifiers ids)
|
||||
(rx/of (apply-modifiers ids {:set-modifiers? true})
|
||||
(calculate-frame-for-move ids)
|
||||
(finish-transform)))))))))
|
||||
|
||||
@@ -390,8 +415,7 @@
|
||||
(rx/map start-local-displacement))
|
||||
(rx/of (move-selected direction shift?)))
|
||||
|
||||
(rx/of (set-modifiers selected)
|
||||
(apply-modifiers selected)
|
||||
(rx/of (apply-modifiers selected {:set-modifiers? true})
|
||||
(finish-transform))))
|
||||
(rx/empty))))))
|
||||
|
||||
@@ -469,22 +493,46 @@
|
||||
(rx/of (apply-modifiers ids)))))))
|
||||
|
||||
(defn apply-modifiers
|
||||
[ids]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
children-ids (->> ids (mapcat #(cp/get-children % objects)))
|
||||
ids-with-children (d/concat [] children-ids ids)
|
||||
object-modifiers (get state :workspace-modifiers)]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/update-shapes ids-with-children (fn [shape]
|
||||
(-> shape
|
||||
(merge (get object-modifiers (:id shape)))
|
||||
(gsh/transform-shape))) {:reg-objects? true})
|
||||
(clear-local-transform)
|
||||
(dwu/commit-undo-transaction))))))
|
||||
([ids]
|
||||
(apply-modifiers ids nil))
|
||||
|
||||
([ids {:keys [set-modifiers?]
|
||||
:or {set-modifiers? false}}]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
children-ids (->> ids (mapcat #(cp/get-children % objects)))
|
||||
ids-with-children (d/concat [] children-ids ids)
|
||||
|
||||
state (if set-modifiers?
|
||||
(ptk/update (set-modifiers ids) state)
|
||||
state)
|
||||
object-modifiers (get state :workspace-modifiers)]
|
||||
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/update-shapes
|
||||
ids-with-children
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(merge (get object-modifiers (:id shape)))
|
||||
(gsh/transform-shape)))
|
||||
{:reg-objects? true
|
||||
;; Attributes that can change in the transform. This way we don't have to check
|
||||
;; all the attributes
|
||||
:attrs [:selrect :points
|
||||
:x :y
|
||||
:width :height
|
||||
:content
|
||||
:transform
|
||||
:transform-inverse
|
||||
:rotation
|
||||
:flip-x
|
||||
:flip-y]
|
||||
})
|
||||
(clear-local-transform)
|
||||
(dwu/commit-undo-transaction)))))))
|
||||
|
||||
;; --- Update Dimensions
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
[props]
|
||||
(let [shape (obj/get props "shape")
|
||||
frame (obj/get props "frame")
|
||||
shape (-> (geom/transform-shape shape)
|
||||
shape (-> (geom/transform-shape shape {:round-coords? false})
|
||||
(geom/translate-to-frame frame))
|
||||
opts #js {:shape shape
|
||||
:frame frame}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
(ns app.main.ui.workspace.viewport
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.context :as ctx]
|
||||
@@ -61,7 +62,9 @@
|
||||
options (mf/deref refs/workspace-page-options)
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
object-modifiers (mf/deref refs/workspace-modifiers)
|
||||
objects (d/deep-merge objects object-modifiers)
|
||||
objects (mf/use-memo
|
||||
(mf/deps objects object-modifiers)
|
||||
#(cp/merge-modifiers objects object-modifiers))
|
||||
|
||||
;; STATE
|
||||
alt? (mf/use-state false)
|
||||
@@ -135,7 +138,9 @@
|
||||
show-prototypes? (= options-mode :prototype)
|
||||
show-selection-handlers? (seq selected)
|
||||
show-snap-distance? (and (contains? layout :dynamic-alignment) (= transform :move) (not (empty? selected)))
|
||||
show-snap-points? (and (contains? layout :dynamic-alignment) (or drawing-obj transform))
|
||||
show-snap-points? (and (or (contains? layout :dynamic-alignment)
|
||||
(contains? layout :snap-grid))
|
||||
(or drawing-obj transform))
|
||||
show-selrect? (and selrect (empty? drawing))
|
||||
show-measures? (and (not transform) (not path-editing?) show-distances?)]
|
||||
|
||||
@@ -283,6 +288,7 @@
|
||||
:zoom zoom
|
||||
:page-id page-id
|
||||
:selected selected
|
||||
:objects objects
|
||||
:modifiers modifiers}])
|
||||
|
||||
(when show-snap-distance?
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
(not selected?)
|
||||
(not edition)
|
||||
(not drawing-path?)
|
||||
(not (#{:comments :path} drawing-tool)))
|
||||
(not drawing-tool))
|
||||
(st/emit! (dw/select-shape (:id @hover)))))))))
|
||||
|
||||
(defn on-double-click
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
(mf/deps shape)
|
||||
#(when path? (upf/format-path (:content shape))))
|
||||
|
||||
{:keys [id x y width height]} shape
|
||||
{:keys [id x y width height selrect]} shape
|
||||
|
||||
outline-type (case (:type shape)
|
||||
:circle "ellipse"
|
||||
@@ -53,10 +53,10 @@
|
||||
{:d path-data
|
||||
:transform nil}
|
||||
|
||||
{:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height})]
|
||||
{:x (:x selrect)
|
||||
:y (:y selrect)
|
||||
:width (:width selrect)
|
||||
:height (:height selrect)})]
|
||||
|
||||
[:> outline-type (map->obj (merge common props))]))
|
||||
|
||||
|
||||
@@ -241,8 +241,7 @@
|
||||
disable-handlers (obj/get props "disable-handlers")
|
||||
current-transform (mf/deref refs/current-transform)
|
||||
|
||||
selrect (-> (:selrect shape)
|
||||
minimum-selrect)
|
||||
selrect (:selrect shape)
|
||||
transform (geom/transform-matrix shape {:no-flip true})]
|
||||
|
||||
(when (not (#{:move :rotate} current-transform))
|
||||
@@ -327,7 +326,7 @@
|
||||
(mf/defc single-selection-handlers
|
||||
[{:keys [shape zoom color disable-handlers on-move-selected] :as props}]
|
||||
(let [shape-id (:id shape)
|
||||
shape (geom/transform-shape shape)
|
||||
shape (geom/transform-shape shape {:round-coords? false})
|
||||
|
||||
frame (mf/deref (refs/object-by-id (:frame-id shape)))
|
||||
frame (when-not (= (:id frame) uuid/zero) frame)
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
(ns app.main.ui.workspace.viewport.snap-points
|
||||
(:require
|
||||
[app.common.pages :as cp]
|
||||
[app.common.math :as mth]
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
@@ -151,15 +152,25 @@
|
||||
|
||||
(mf/defc snap-points
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [layout zoom selected page-id drawing transform modifiers] :as props}]
|
||||
(let [shapes (mf/deref (refs/objects-by-id selected))
|
||||
filter-shapes (mf/deref refs/selected-shapes-with-children)
|
||||
[{:keys [layout zoom objects selected page-id drawing transform modifiers] :as props}]
|
||||
|
||||
(let [;; shapes (mf/deref (refs/objects-by-id selected))
|
||||
;; filter-shapes (mf/deref refs/selected-shapes-with-children)
|
||||
|
||||
shapes (->> selected
|
||||
(map #(get objects %))
|
||||
(filterv (comp not nil?)))
|
||||
filter-shapes (into #{}
|
||||
(mapcat #(cp/get-object-with-children % objects))
|
||||
selected)
|
||||
|
||||
filter-shapes (fn [id]
|
||||
(if (= id :layout)
|
||||
(or (not (contains? layout :display-grid))
|
||||
(not (contains? layout :snap-grid)))
|
||||
(or (filter-shapes id)
|
||||
(not (contains? layout :dynamic-alignment)))))
|
||||
|
||||
shapes (if drawing [drawing] shapes)]
|
||||
(when (or drawing transform)
|
||||
[:& snap-feedback {:shapes shapes
|
||||
|
||||
@@ -99,7 +99,8 @@
|
||||
(timers/schedule
|
||||
(fn []
|
||||
(st/emit! (dwc/update-shapes [@shape-id]
|
||||
#(assoc % :thumbnail data)))
|
||||
#(assoc % :thumbnail data)
|
||||
{:save-undo? false}))
|
||||
(rx/push! next :next)))))
|
||||
|
||||
on-frame-not-found
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
(.-parentNode shape-node)
|
||||
|
||||
(and (some? thumb-node) (= :frame type))
|
||||
thumb-node
|
||||
(.-parentNode thumb-node)
|
||||
|
||||
:else
|
||||
shape-node)]
|
||||
|
||||
@@ -88,7 +88,9 @@
|
||||
|
||||
(defn grid-snap-points
|
||||
"Returns the snap points for a given grid"
|
||||
([shape coord] (mapcat #(grid-snap-points shape % coord) (:grids shape)))
|
||||
([shape coord]
|
||||
(mapcat #(grid-snap-points shape % coord) (:grids shape)))
|
||||
|
||||
([shape {:keys [type display params] :as grid} coord]
|
||||
(when (:display grid)
|
||||
(case type
|
||||
|
||||
@@ -122,9 +122,9 @@
|
||||
(into []
|
||||
(comp (map #(unchecked-get % "data"))
|
||||
(filter match-criteria?)
|
||||
(filter overlaps?)
|
||||
(filter (comp overlaps? :frame))
|
||||
(filter (comp overlaps-masks? :masks))
|
||||
(filter overlaps?)
|
||||
(map add-z-index))
|
||||
result)
|
||||
|
||||
|
||||
@@ -71,13 +71,23 @@
|
||||
(fn [frame-id shapes]
|
||||
{:x (-> (rt/make-tree) (add-coord-data frame-id shapes :x))
|
||||
:y (-> (rt/make-tree) (add-coord-data frame-id shapes :y))})]
|
||||
|
||||
(d/mapm create-index shapes-data)))
|
||||
|
||||
;; Attributes that will change the values of their snap
|
||||
(def snap-attrs [:x :y :width :height :selrect :grids])
|
||||
|
||||
(defn- update-snap-data
|
||||
[snap-data old-objects new-objects]
|
||||
|
||||
(let [changed? #(not= (get old-objects %) (get new-objects %))
|
||||
(let [changed? (fn [id]
|
||||
(let [oldv (get old-objects id)
|
||||
newv (get new-objects id)]
|
||||
;; Check first without select-keys because is faster if they are
|
||||
;; the same reference
|
||||
(and (not= oldv newv)
|
||||
(not= (select-keys oldv snap-attrs)
|
||||
(select-keys newv snap-attrs)))))
|
||||
|
||||
is-deleted-frame? #(and (not= uuid/zero %)
|
||||
(contains? old-objects %)
|
||||
(not (contains? new-objects %))
|
||||
@@ -119,9 +129,9 @@
|
||||
:y (rt/make-tree)}))]
|
||||
|
||||
(as-> snap-data $
|
||||
(reduce delete-data $ to-delete)
|
||||
(reduce add-frames $ frames-to-add)
|
||||
(reduce add-data $ to-add)
|
||||
(reduce delete-data $ to-delete)
|
||||
(reduce delete-frames $ frames-to-delete))))
|
||||
|
||||
(defn- log-state
|
||||
@@ -160,8 +170,10 @@
|
||||
|
||||
(defmethod impl/handler :snaps/update-index
|
||||
[{:keys [page-id old-objects new-objects] :as message}]
|
||||
;; TODO: Check the difference and update the index acordingly
|
||||
(swap! state update-page page-id old-objects new-objects)
|
||||
|
||||
;; Uncomment this to regenerate the index everytime
|
||||
#_(swap! state index-page page-id new-objects)
|
||||
;; (log-state)
|
||||
nil)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user