mirror of
https://github.com/penpot/penpot.git
synced 2025-04-15 16:31:25 -05:00
✨ Remove fill/auto when resizing
This commit is contained in:
parent
7f0054959f
commit
4ecc166055
13 changed files with 479 additions and 349 deletions
|
@ -138,20 +138,21 @@
|
|||
|
||||
(let [modifiers (get-in modif-tree [(:id parent) :modifiers])
|
||||
transformed-parent (gtr/transform-shape parent modifiers)
|
||||
|
||||
children (->> transformed-parent
|
||||
:shapes
|
||||
(map (comp apply-modifiers (d/getf objects))))
|
||||
|
||||
{auto-width :width auto-height :height}
|
||||
(when (and (d/not-empty? children) (or (ctl/auto-height? parent) (ctl/auto-width? parent)))
|
||||
(gcl/layout-content-bounds parent children))
|
||||
(when (and (d/not-empty? children) (or (ctl/auto-height? transformed-parent) (ctl/auto-width? transformed-parent)))
|
||||
(gcl/layout-content-bounds transformed-parent children))
|
||||
|
||||
modifiers
|
||||
(cond-> modifiers
|
||||
(and (some? auto-width) (ctl/auto-width? parent))
|
||||
(and (some? auto-width) (ctl/auto-width? transformed-parent))
|
||||
(set-parent-auto-width transformed-parent auto-width)
|
||||
|
||||
(and (some? auto-height) (ctl/auto-height? parent))
|
||||
(and (some? auto-height) (ctl/auto-height? transformed-parent))
|
||||
(set-parent-auto-height transformed-parent auto-height))]
|
||||
|
||||
(assoc-in modif-tree [(:id parent) :modifiers] modifiers))))
|
||||
|
|
|
@ -71,9 +71,12 @@
|
|||
|
||||
(defn get-children-ids
|
||||
[objects id]
|
||||
(if-let [shapes (-> (get objects id) :shapes (some-> vec))]
|
||||
(into shapes (mapcat #(get-children-ids objects %)) shapes)
|
||||
[]))
|
||||
(letfn [(get-children-ids-rec
|
||||
[id processed]
|
||||
(when (not (contains? processed id))
|
||||
(when-let [shapes (-> (get objects id) :shapes (some-> vec))]
|
||||
(into shapes (mapcat #(get-children-ids-rec % (conj processed id))) shapes))))]
|
||||
(get-children-ids-rec id #{})))
|
||||
|
||||
(defn get-children
|
||||
[objects id]
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
;; - structure-child: Structure recursive
|
||||
;; * scale-content
|
||||
;; * rotation
|
||||
;; * change-properties
|
||||
|
||||
(def conjv (fnil conj []))
|
||||
|
||||
|
@ -118,6 +119,13 @@
|
|||
(-> modifiers
|
||||
(update :structure-child conjv {:type :scale-content :value value})))
|
||||
|
||||
(defn set-change-property
|
||||
[modifiers property value]
|
||||
(-> modifiers
|
||||
(update :structure-child conjv {:type :change-property
|
||||
:property property
|
||||
:value value})))
|
||||
|
||||
(defn add-modifiers
|
||||
[modifiers new-modifiers]
|
||||
|
||||
|
@ -376,7 +384,7 @@
|
|||
(d/removev remove? shapes)))
|
||||
|
||||
apply-modifier
|
||||
(fn [shape {:keys [type value index rotation]}]
|
||||
(fn [shape {:keys [type property value index rotation]}]
|
||||
(cond-> shape
|
||||
(= type :rotation)
|
||||
(update :rotation #(mod (+ % rotation) 360))
|
||||
|
@ -395,7 +403,10 @@
|
|||
(update :shapes remove-children value)
|
||||
|
||||
(= type :scale-content)
|
||||
(apply-scale-content value)))]
|
||||
(apply-scale-content value)
|
||||
|
||||
(= type :change-property)
|
||||
(assoc property value)))]
|
||||
|
||||
(as-> shape $
|
||||
(reduce apply-modifier $ (:structure-parent modifiers))
|
||||
|
|
|
@ -97,8 +97,16 @@
|
|||
::layout-item-min-w
|
||||
::layout-item-align-self]))
|
||||
|
||||
(defn layout? [shape]
|
||||
(and (= :frame (:type shape)) (= :flex (:layout shape))))
|
||||
(defn layout?
|
||||
([objects id]
|
||||
(layout? (get objects id)))
|
||||
([shape]
|
||||
(and (= :frame (:type shape)) (= :flex (:layout shape)))))
|
||||
|
||||
(defn layout-child? [objects shape]
|
||||
(let [parent-id (:parent-id shape)
|
||||
parent (get objects parent-id)]
|
||||
(layout? parent)))
|
||||
|
||||
(defn wrap? [{:keys [layout-wrap-type]}]
|
||||
(= layout-wrap-type :wrap))
|
||||
|
|
284
frontend/src/app/main/data/workspace/modifiers.cljs
Normal file
284
frontend/src/app/main/data/workspace/modifiers.cljs
Normal file
|
@ -0,0 +1,284 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; 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) KALEIDOS INC
|
||||
|
||||
(ns app.main.data.workspace.modifiers
|
||||
"Events related with shapes transformations"
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.common :as cpc]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.comments :as-alias dwcm]
|
||||
[app.main.data.workspace.guides :as-alias dwg]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[beicon.core :as rx]
|
||||
[cljs.spec.alpha :as s]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
;; -- temporary modifiers -------------------------------------------
|
||||
|
||||
;; During an interactive transformation of shapes (e.g. when resizing or rotating
|
||||
;; a group with the mouse), there are a lot of objects that need to be modified
|
||||
;; (in this case, the group and all its children).
|
||||
;;
|
||||
;; To avoid updating the shapes theirselves, and forcing redraw of all components
|
||||
;; that depend on the "objects" global state, we set a "modifiers" structure, with
|
||||
;; the changes that need to be applied, and store it in :workspace-modifiers global
|
||||
;; variable. The viewport reads this and merges it into the objects list it uses to
|
||||
;; paint the viewport content, redrawing only the objects that have new modifiers.
|
||||
;;
|
||||
;; When the interaction is finished (e.g. user releases mouse button), the
|
||||
;; apply-modifiers event is done, that consolidates all modifiers into the base
|
||||
;; geometric attributes of the shapes.
|
||||
|
||||
|
||||
(defn- check-delta
|
||||
"If the shape is a component instance, check its relative position respect the
|
||||
root of the component, and see if it changes after applying a transformation."
|
||||
[shape root transformed-shape transformed-root objects modif-tree]
|
||||
(let [root
|
||||
(cond
|
||||
(:component-root? shape)
|
||||
shape
|
||||
|
||||
(nil? root)
|
||||
(cph/get-root-shape objects shape)
|
||||
|
||||
:else root)
|
||||
|
||||
transformed-root
|
||||
(cond
|
||||
(:component-root? transformed-shape)
|
||||
transformed-shape
|
||||
|
||||
(nil? transformed-root)
|
||||
(as-> (cph/get-root-shape objects transformed-shape) $
|
||||
(gsh/transform-shape (merge $ (get modif-tree (:id $)))))
|
||||
|
||||
:else transformed-root)
|
||||
|
||||
shape-delta
|
||||
(when root
|
||||
(gpt/point (- (gsh/left-bound shape) (gsh/left-bound root))
|
||||
(- (gsh/top-bound shape) (gsh/top-bound root))))
|
||||
|
||||
transformed-shape-delta
|
||||
(when transformed-root
|
||||
(gpt/point (- (gsh/left-bound transformed-shape) (gsh/left-bound transformed-root))
|
||||
(- (gsh/top-bound transformed-shape) (gsh/top-bound transformed-root))))
|
||||
|
||||
;; There are cases in that the coordinates change slightly (e.g. when
|
||||
;; rounding to pixel, or when recalculating text positions in different
|
||||
;; zoom levels). To take this into account, we ignore movements smaller
|
||||
;; than 1 pixel.
|
||||
distance (if (and shape-delta transformed-shape-delta)
|
||||
(gpt/distance-vector shape-delta transformed-shape-delta)
|
||||
(gpt/point 0 0))
|
||||
|
||||
ignore-geometry? (and (< (:x distance) 1) (< (:y distance) 1))]
|
||||
|
||||
[root transformed-root ignore-geometry?]))
|
||||
|
||||
(defn- get-ignore-tree
|
||||
"Retrieves a map with the flag `ignore-geometry?` given a tree of modifiers"
|
||||
([modif-tree objects shape]
|
||||
(get-ignore-tree modif-tree objects shape nil nil {}))
|
||||
|
||||
([modif-tree objects shape root transformed-root ignore-tree]
|
||||
(let [children (map (d/getf objects) (:shapes shape))
|
||||
|
||||
shape-id (:id shape)
|
||||
transformed-shape (gsh/transform-shape shape (get modif-tree shape-id))
|
||||
|
||||
[root transformed-root ignore-geometry?]
|
||||
(check-delta shape root transformed-shape transformed-root objects modif-tree)
|
||||
|
||||
ignore-tree (assoc ignore-tree shape-id ignore-geometry?)
|
||||
|
||||
set-child
|
||||
(fn [ignore-tree child]
|
||||
(get-ignore-tree modif-tree objects child root transformed-root ignore-tree))]
|
||||
|
||||
(reduce set-child ignore-tree children))))
|
||||
|
||||
(defn- update-grow-type
|
||||
[shape old-shape]
|
||||
(let [auto-width? (= :auto-width (:grow-type shape))
|
||||
auto-height? (= :auto-height (:grow-type shape))
|
||||
|
||||
changed-width? (not (mth/close? (:width shape) (:width old-shape)))
|
||||
changed-height? (not (mth/close? (:height shape) (:height old-shape)))
|
||||
|
||||
change-to-fixed? (or (and auto-width? (or changed-height? changed-width?))
|
||||
(and auto-height? changed-height?))]
|
||||
(cond-> shape
|
||||
change-to-fixed?
|
||||
(assoc :grow-type :fixed))))
|
||||
|
||||
(defn- clear-local-transform []
|
||||
(ptk/reify ::clear-local-transform
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(dissoc :workspace-modifiers)
|
||||
(dissoc ::current-move-selected)))))
|
||||
|
||||
(defn create-modif-tree
|
||||
[ids modifiers]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(into {} (map #(vector % {:modifiers modifiers})) ids))
|
||||
|
||||
(defn build-modif-tree
|
||||
[ids objects get-modifier]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(into {} (map #(vector % {:modifiers (get-modifier (get objects %))})) ids))
|
||||
|
||||
(defn build-change-frame-modifiers
|
||||
[modif-tree objects selected target-frame position]
|
||||
|
||||
(let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id])))
|
||||
layout? (get-in objects [target-frame :layout])
|
||||
child-set (set (get-in objects [target-frame :shapes]))
|
||||
drop-index (when layout? (gsl/get-drop-index target-frame objects position))
|
||||
|
||||
update-frame-modifiers
|
||||
(fn [modif-tree [original-frame shapes]]
|
||||
(let [shapes (->> shapes (d/removev #(= target-frame %)))
|
||||
shapes (cond->> shapes
|
||||
(and layout? (= original-frame target-frame))
|
||||
;; When movining inside a layout frame remove the shapes that are not immediate children
|
||||
(filterv #(contains? child-set %)))]
|
||||
(cond-> modif-tree
|
||||
(not= original-frame target-frame)
|
||||
(-> (update-in [original-frame :modifiers] ctm/set-remove-children shapes)
|
||||
(update-in [target-frame :modifiers] ctm/set-add-children shapes drop-index))
|
||||
|
||||
(and layout? (= original-frame target-frame))
|
||||
(update-in [target-frame :modifiers] ctm/set-add-children shapes drop-index))))]
|
||||
|
||||
(reduce update-frame-modifiers modif-tree origin-frame-ids)))
|
||||
|
||||
(defn modif->js
|
||||
[modif-tree objects]
|
||||
(clj->js (into {}
|
||||
(map (fn [[k v]]
|
||||
[(get-in objects [k :name]) v]))
|
||||
modif-tree)))
|
||||
|
||||
(defn set-modifiers
|
||||
([modif-tree]
|
||||
(set-modifiers modif-tree false))
|
||||
|
||||
([modif-tree ignore-constraints]
|
||||
(set-modifiers modif-tree ignore-constraints false))
|
||||
|
||||
([modif-tree ignore-constraints ignore-snap-pixel]
|
||||
(ptk/reify ::set-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects
|
||||
(wsh/lookup-page-objects state)
|
||||
|
||||
snap-pixel?
|
||||
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers modif-tree objects ignore-constraints snap-pixel?)]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree))))))
|
||||
|
||||
;; Rotation use different algorithm to calculate children modifiers (and do not use child constraints).
|
||||
(defn set-rotation-modifiers
|
||||
([angle shapes]
|
||||
(set-rotation-modifiers angle shapes (-> shapes gsh/selection-rect gsh/center-selrect)))
|
||||
|
||||
([angle shapes center]
|
||||
(ptk/reify ::set-rotation-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids
|
||||
(->> shapes
|
||||
(remove #(get % :blocked false))
|
||||
(filter #((cpc/editable-attrs (:type %)) :rotation))
|
||||
(map :id))
|
||||
|
||||
get-modifier
|
||||
(fn [shape]
|
||||
(ctm/rotation shape center angle))
|
||||
|
||||
modif-tree
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false false))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree))))))
|
||||
|
||||
|
||||
(defn apply-modifiers
|
||||
([]
|
||||
(apply-modifiers nil))
|
||||
|
||||
([{:keys [undo-transation?] :or {undo-transation? true}}]
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
object-modifiers (get state :workspace-modifiers)
|
||||
|
||||
ids (or (keys object-modifiers) [])
|
||||
ids-with-children (into (vec ids) (mapcat #(cph/get-children-ids objects %)) ids)
|
||||
|
||||
shapes (map (d/getf objects) ids)
|
||||
ignore-tree (->> (map #(get-ignore-tree object-modifiers objects %) shapes)
|
||||
(reduce merge {}))]
|
||||
|
||||
(rx/concat
|
||||
(if undo-transation?
|
||||
(rx/of (dwu/start-undo-transaction))
|
||||
(rx/empty))
|
||||
(rx/of (ptk/event ::dwg/move-frame-guides ids-with-children)
|
||||
(ptk/event ::dwcm/move-frame-comment-threads ids-with-children)
|
||||
(dch/update-shapes
|
||||
ids
|
||||
(fn [shape]
|
||||
(let [modif (get-in object-modifiers [(:id shape) :modifiers])
|
||||
text-shape? (cph/text-shape? shape)]
|
||||
(-> shape
|
||||
(gsh/transform-shape modif)
|
||||
(cond-> text-shape?
|
||||
(update-grow-type shape)))))
|
||||
{:reg-objects? true
|
||||
:ignore-tree ignore-tree
|
||||
;; 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
|
||||
:position-data
|
||||
:flip-x
|
||||
:flip-y
|
||||
:grow-type
|
||||
:layout-item-h-sizing
|
||||
:layout-item-v-sizing
|
||||
]})
|
||||
(clear-local-transform))
|
||||
(if undo-transation?
|
||||
(rx/of (dwu/commit-undo-transaction))
|
||||
(rx/empty))))))))
|
|
@ -21,6 +21,7 @@
|
|||
[app.main.data.modal :as md]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.collapse :as dwc]
|
||||
[app.main.data.workspace.shape-layout :as dwsl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.thumbnails :as dwt]
|
||||
[app.main.data.workspace.zoom :as dwz]
|
||||
|
@ -552,8 +553,11 @@
|
|||
(filter #(= :frame (get-in % [:obj :type])))
|
||||
(map #(vector (:old-id %) (get-in % [:obj :id]))))
|
||||
|
||||
id-duplicated (first new-selected)]
|
||||
id-duplicated (first new-selected)
|
||||
|
||||
frames (into #{}
|
||||
(map #(get-in objects [% :frame-id]))
|
||||
selected)]
|
||||
(rx/concat
|
||||
(->> (rx/from dup-frames)
|
||||
(rx/map (fn [[old-id new-id]] (dwt/duplicate-thumbnail old-id new-id))))
|
||||
|
@ -561,6 +565,7 @@
|
|||
;; Warning: This order is important for the focus mode.
|
||||
(rx/of (dch/commit-changes changes)
|
||||
(select-shapes new-selected)
|
||||
(dwsl/update-layout-positions frames)
|
||||
(memorize-duplicated id-original id-duplicated))))))))))
|
||||
|
||||
(defn change-hover-state
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.changes :as dwc]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
[beicon.core :as rx]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
|
@ -50,11 +50,11 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids (->> ids (filter #(get-in objects [% :layout])))]
|
||||
ids (->> ids (filter (partial ctl/layout? objects)))]
|
||||
(if (d/not-empty? ids)
|
||||
(let [modif-tree (dwt/create-modif-tree ids (ctm/reflow))]
|
||||
(rx/of (dwt/set-modifiers modif-tree)
|
||||
(dwt/apply-modifiers)))
|
||||
(let [modif-tree (dwm/create-modif-tree ids (ctm/reflow))]
|
||||
(rx/of (dwm/set-modifiers modif-tree)
|
||||
(dwm/apply-modifiers)))
|
||||
(rx/empty))))))
|
||||
|
||||
;; TODO LAYOUT: Remove constraints from children
|
||||
|
|
|
@ -14,15 +14,14 @@
|
|||
[app.common.geom.shapes.flex-layout :as gsl]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.common :as cpc]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.changes :as dch]
|
||||
[app.main.data.workspace.collapse :as dwc]
|
||||
[app.main.data.workspace.comments :as-alias dwcm]
|
||||
[app.main.data.workspace.guides :as-alias dwg]
|
||||
[app.main.data.workspace.modifiers :as dwm]
|
||||
[app.main.data.workspace.selection :as dws]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
|
@ -97,269 +96,12 @@
|
|||
(update state :workspace-local dissoc :transform))))
|
||||
|
||||
|
||||
;; -- Temporary modifiers -------------------------------------------
|
||||
|
||||
;; During an interactive transformation of shapes (e.g. when resizing or rotating
|
||||
;; a group with the mouse), there are a lot of objects that need to be modified
|
||||
;; (in this case, the group and all its children).
|
||||
;;
|
||||
;; To avoid updating the shapes theirselves, and forcing redraw of all components
|
||||
;; that depend on the "objects" global state, we set a "modifiers" structure, with
|
||||
;; the changes that need to be applied, and store it in :workspace-modifiers global
|
||||
;; variable. The viewport reads this and merges it into the objects list it uses to
|
||||
;; paint the viewport content, redrawing only the objects that have new modifiers.
|
||||
;;
|
||||
;; When the interaction is finished (e.g. user releases mouse button), the
|
||||
;; apply-modifiers event is done, that consolidates all modifiers into the base
|
||||
;; geometric attributes of the shapes.
|
||||
|
||||
(declare clear-local-transform)
|
||||
|
||||
(declare get-ignore-tree)
|
||||
|
||||
(defn create-modif-tree
|
||||
[ids modifiers]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(into {} (map #(vector % {:modifiers modifiers})) ids))
|
||||
|
||||
(defn build-modif-tree
|
||||
[ids objects get-modifier]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(into {} (map #(vector % {:modifiers (get-modifier (get objects %))})) ids))
|
||||
|
||||
(defn build-change-frame-modifiers
|
||||
[modif-tree objects selected target-frame position]
|
||||
|
||||
(let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id])))
|
||||
layout? (get-in objects [target-frame :layout])
|
||||
child-set (set (get-in objects [target-frame :shapes]))
|
||||
drop-index (when layout? (gsl/get-drop-index target-frame objects position))
|
||||
|
||||
update-frame-modifiers
|
||||
(fn [modif-tree [original-frame shapes]]
|
||||
(let [shapes (->> shapes (d/removev #(= target-frame %)))
|
||||
shapes (cond->> shapes
|
||||
(and layout? (= original-frame target-frame))
|
||||
;; When movining inside a layout frame remove the shapes that are not immediate children
|
||||
(filterv #(contains? child-set %)))]
|
||||
(cond-> modif-tree
|
||||
(not= original-frame target-frame)
|
||||
(-> (update-in [original-frame :modifiers] ctm/set-remove-children shapes)
|
||||
(update-in [target-frame :modifiers] ctm/set-add-children shapes drop-index))
|
||||
|
||||
(and layout? (= original-frame target-frame))
|
||||
(update-in [target-frame :modifiers] ctm/set-add-children shapes drop-index))))]
|
||||
|
||||
(reduce update-frame-modifiers modif-tree origin-frame-ids)))
|
||||
|
||||
(defn modif->js
|
||||
[modif-tree objects]
|
||||
(clj->js (into {}
|
||||
(map (fn [[k v]]
|
||||
[(get-in objects [k :name]) v]))
|
||||
modif-tree)))
|
||||
|
||||
(defn set-modifiers
|
||||
([modif-tree]
|
||||
(set-modifiers modif-tree false))
|
||||
|
||||
([modif-tree ignore-constraints]
|
||||
(set-modifiers modif-tree ignore-constraints false))
|
||||
|
||||
([modif-tree ignore-constraints ignore-snap-pixel]
|
||||
(ptk/reify ::set-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects
|
||||
(wsh/lookup-page-objects state)
|
||||
|
||||
snap-pixel?
|
||||
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
|
||||
|
||||
modif-tree
|
||||
(gsh/set-objects-modifiers modif-tree objects ignore-constraints snap-pixel?)]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree))))))
|
||||
|
||||
;; Rotation use different algorithm to calculate children modifiers (and do not use child constraints).
|
||||
(defn- set-rotation-modifiers
|
||||
([angle shapes]
|
||||
(set-rotation-modifiers angle shapes (-> shapes gsh/selection-rect gsh/center-selrect)))
|
||||
|
||||
([angle shapes center]
|
||||
(ptk/reify ::set-rotation-modifiers
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
ids
|
||||
(->> shapes
|
||||
(remove #(get % :blocked false))
|
||||
(filter #((cpc/editable-attrs (:type %)) :rotation))
|
||||
(map :id))
|
||||
|
||||
get-modifier
|
||||
(fn [shape]
|
||||
(ctm/rotation shape center angle))
|
||||
|
||||
modif-tree
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false false))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree))))))
|
||||
|
||||
(defn- update-grow-type
|
||||
[shape old-shape]
|
||||
(let [auto-width? (= :auto-width (:grow-type shape))
|
||||
auto-height? (= :auto-height (:grow-type shape))
|
||||
|
||||
changed-width? (not (mth/close? (:width shape) (:width old-shape)))
|
||||
changed-height? (not (mth/close? (:height shape) (:height old-shape)))
|
||||
|
||||
change-to-fixed? (or (and auto-width? (or changed-height? changed-width?))
|
||||
(and auto-height? changed-height?))]
|
||||
(cond-> shape
|
||||
change-to-fixed?
|
||||
(assoc :grow-type :fixed))))
|
||||
|
||||
(defn apply-modifiers
|
||||
([]
|
||||
(apply-modifiers nil))
|
||||
|
||||
([{:keys [undo-transation?] :or {undo-transation? true}}]
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
object-modifiers (get state :workspace-modifiers)
|
||||
|
||||
ids (or (keys object-modifiers) [])
|
||||
ids-with-children (into (vec ids) (mapcat #(cph/get-children-ids objects %)) ids)
|
||||
|
||||
shapes (map (d/getf objects) ids)
|
||||
ignore-tree (->> (map #(get-ignore-tree object-modifiers objects %) shapes)
|
||||
(reduce merge {}))]
|
||||
|
||||
(rx/concat
|
||||
(if undo-transation?
|
||||
(rx/of (dwu/start-undo-transaction))
|
||||
(rx/empty))
|
||||
(rx/of (ptk/event ::dwg/move-frame-guides ids-with-children)
|
||||
(ptk/event ::dwcm/move-frame-comment-threads ids-with-children)
|
||||
(dch/update-shapes
|
||||
ids
|
||||
(fn [shape]
|
||||
(let [modif (get-in object-modifiers [(:id shape) :modifiers])
|
||||
text-shape? (cph/text-shape? shape)]
|
||||
(-> shape
|
||||
(gsh/transform-shape modif)
|
||||
(cond-> text-shape?
|
||||
(update-grow-type shape)))))
|
||||
{:reg-objects? true
|
||||
:ignore-tree ignore-tree
|
||||
;; 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
|
||||
:position-data
|
||||
:flip-x
|
||||
:flip-y
|
||||
:grow-type]})
|
||||
(clear-local-transform))
|
||||
(if undo-transation?
|
||||
(rx/of (dwu/commit-undo-transaction))
|
||||
(rx/empty))))))))
|
||||
|
||||
(defn- check-delta
|
||||
"If the shape is a component instance, check its relative position respect the
|
||||
root of the component, and see if it changes after applying a transformation."
|
||||
[shape root transformed-shape transformed-root objects modif-tree]
|
||||
(let [root
|
||||
(cond
|
||||
(:component-root? shape)
|
||||
shape
|
||||
|
||||
(nil? root)
|
||||
(cph/get-root-shape objects shape)
|
||||
|
||||
:else root)
|
||||
|
||||
transformed-root
|
||||
(cond
|
||||
(:component-root? transformed-shape)
|
||||
transformed-shape
|
||||
|
||||
(nil? transformed-root)
|
||||
(as-> (cph/get-root-shape objects transformed-shape) $
|
||||
(gsh/transform-shape (merge $ (get modif-tree (:id $)))))
|
||||
|
||||
:else transformed-root)
|
||||
|
||||
shape-delta
|
||||
(when root
|
||||
(gpt/point (- (gsh/left-bound shape) (gsh/left-bound root))
|
||||
(- (gsh/top-bound shape) (gsh/top-bound root))))
|
||||
|
||||
transformed-shape-delta
|
||||
(when transformed-root
|
||||
(gpt/point (- (gsh/left-bound transformed-shape) (gsh/left-bound transformed-root))
|
||||
(- (gsh/top-bound transformed-shape) (gsh/top-bound transformed-root))))
|
||||
|
||||
;; There are cases in that the coordinates change slightly (e.g. when
|
||||
;; rounding to pixel, or when recalculating text positions in different
|
||||
;; zoom levels). To take this into account, we ignore movements smaller
|
||||
;; than 1 pixel.
|
||||
distance (if (and shape-delta transformed-shape-delta)
|
||||
(gpt/distance-vector shape-delta transformed-shape-delta)
|
||||
(gpt/point 0 0))
|
||||
|
||||
ignore-geometry? (and (< (:x distance) 1) (< (:y distance) 1))]
|
||||
|
||||
[root transformed-root ignore-geometry?]))
|
||||
|
||||
(defn- get-ignore-tree
|
||||
"Retrieves a map with the flag `ignore-geometry?` given a tree of modifiers"
|
||||
([modif-tree objects shape]
|
||||
(get-ignore-tree modif-tree objects shape nil nil {}))
|
||||
|
||||
([modif-tree objects shape root transformed-root ignore-tree]
|
||||
(let [children (map (d/getf objects) (:shapes shape))
|
||||
|
||||
shape-id (:id shape)
|
||||
transformed-shape (gsh/transform-shape shape (get modif-tree shape-id))
|
||||
|
||||
[root transformed-root ignore-geometry?]
|
||||
(check-delta shape root transformed-shape transformed-root objects modif-tree)
|
||||
|
||||
ignore-tree (assoc ignore-tree shape-id ignore-geometry?)
|
||||
|
||||
set-child
|
||||
(fn [ignore-tree child]
|
||||
(get-ignore-tree modif-tree objects child root transformed-root ignore-tree))]
|
||||
|
||||
(reduce set-child ignore-tree children))))
|
||||
|
||||
(defn- clear-local-transform []
|
||||
(ptk/reify ::clear-local-transform
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(dissoc :workspace-modifiers)
|
||||
(dissoc ::current-move-selected)))))
|
||||
|
||||
;; -- Resize --------------------------------------------------------
|
||||
|
||||
(defn start-resize
|
||||
"Enter mouse resize mode, until mouse button is released."
|
||||
[handler ids shape]
|
||||
(letfn [(resize [shape initial layout [point lock? center? point-snap]]
|
||||
(letfn [(resize [shape objects initial layout [point lock? center? point-snap]]
|
||||
(let [{:keys [width height]} (:selrect shape)
|
||||
{:keys [rotation]} shape
|
||||
|
||||
|
@ -423,18 +165,42 @@
|
|||
(some? displacement)
|
||||
(gpt/add displacement))
|
||||
|
||||
;; When the horizontal/vertical scale a flex children with auto/fill
|
||||
;; we change it too fixed
|
||||
layout? (ctl/layout? shape)
|
||||
layout-child? (ctl/layout-child? objects shape)
|
||||
auto-width? (ctl/auto-width? shape)
|
||||
fill-width? (ctl/fill-width? shape)
|
||||
auto-height? (ctl/auto-height? shape)
|
||||
fill-height? (ctl/fill-height? shape)
|
||||
|
||||
set-fix-width?
|
||||
(and (not (mth/close? (:x scalev) 1))
|
||||
(or (and (or layout? layout-child?) auto-width?)
|
||||
(and layout-child? fill-width?)))
|
||||
|
||||
set-fix-height?
|
||||
(and (not (mth/close? (:y scalev) 1))
|
||||
(or (and (or layout? layout-child?) auto-height?)
|
||||
(and layout-child? fill-height?)))
|
||||
|
||||
modifiers
|
||||
(-> (ctm/empty-modifiers)
|
||||
(cond-> displacement
|
||||
(ctm/set-move displacement))
|
||||
(ctm/set-resize scalev resize-origin shape-transform shape-transform-inverse)
|
||||
|
||||
(cond-> set-fix-width?
|
||||
(ctm/set-change-property :layout-item-h-sizing :fix))
|
||||
|
||||
(cond-> set-fix-height?
|
||||
(ctm/set-change-property :layout-item-v-sizing :fix))
|
||||
|
||||
(cond-> scale-text
|
||||
(ctm/set-scale-content (:x scalev))))
|
||||
|
||||
modif-tree (create-modif-tree ids modifiers)]
|
||||
|
||||
(rx/of (set-modifiers modif-tree))))
|
||||
modif-tree (dwm/create-modif-tree ids modifiers)]
|
||||
(rx/of (dwm/set-modifiers modif-tree))))
|
||||
|
||||
;; Unifies the instantaneous proportion lock modifier
|
||||
;; activated by Shift key and the shapes own proportion
|
||||
|
@ -458,6 +224,7 @@
|
|||
zoom (get-in state [:workspace-local :zoom] 1)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
resizing-shapes (map #(get objects %) ids)]
|
||||
|
||||
(rx/concat
|
||||
(->> ms/mouse-position
|
||||
(rx/with-latest-from ms/mouse-position-shift ms/mouse-position-alt)
|
||||
|
@ -465,9 +232,9 @@
|
|||
(rx/switch-map (fn [[point _ _ :as current]]
|
||||
(->> (snap/closest-snap-point page-id resizing-shapes objects layout zoom focus point)
|
||||
(rx/map #(conj current %)))))
|
||||
(rx/mapcat (partial resize shape initial-position layout))
|
||||
(rx/mapcat (partial resize shape objects initial-position layout))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (apply-modifiers)
|
||||
(rx/of (dwm/apply-modifiers)
|
||||
(finish-transform))))))))
|
||||
|
||||
(defn update-dimensions
|
||||
|
@ -487,14 +254,14 @@
|
|||
(fn [shape] (ctm/change-dimensions shape attr value))
|
||||
|
||||
modif-tree
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(-> (dwm/build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false snap-pixel?))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (apply-modifiers)))))
|
||||
(rx/of (dwm/apply-modifiers)))))
|
||||
|
||||
(defn change-orientation
|
||||
"Change orientation of shapes, from the sidebar options form.
|
||||
|
@ -512,14 +279,14 @@
|
|||
(fn [shape] (ctm/change-orientation-modifiers shape orientation))
|
||||
|
||||
modif-tree
|
||||
(-> (build-modif-tree ids objects get-modifier)
|
||||
(-> (dwm/build-modif-tree ids objects get-modifier)
|
||||
(gsh/set-objects-modifiers objects false snap-pixel?))]
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(rx/of (apply-modifiers)))))
|
||||
(rx/of (dwm/apply-modifiers)))))
|
||||
|
||||
;; -- Rotate --------------------------------------------------------
|
||||
|
||||
|
@ -560,9 +327,9 @@
|
|||
(rx/map
|
||||
(fn [[[pos mod?] shift?]]
|
||||
(let [delta-angle (calculate-angle pos mod? shift?)]
|
||||
(set-rotation-modifiers delta-angle shapes group-center))))
|
||||
(dwm/set-rotation-modifiers delta-angle shapes group-center))))
|
||||
(rx/take-until stoper))
|
||||
(rx/of (apply-modifiers)
|
||||
(rx/of (dwm/apply-modifiers)
|
||||
(finish-transform)))))))
|
||||
|
||||
(defn increase-rotation
|
||||
|
@ -576,10 +343,10 @@
|
|||
objects (wsh/lookup-page-objects state page-id)
|
||||
rotate-shape (fn [shape]
|
||||
(let [delta (- rotation (:rotation shape))]
|
||||
(set-rotation-modifiers delta [shape])))]
|
||||
(dwm/set-rotation-modifiers delta [shape])))]
|
||||
(rx/concat
|
||||
(rx/from (->> ids (map #(get objects %)) (map rotate-shape)))
|
||||
(rx/of (apply-modifiers)))))))
|
||||
(rx/of (dwm/apply-modifiers)))))))
|
||||
|
||||
|
||||
;; -- Move ----------------------------------------------------------
|
||||
|
@ -705,15 +472,15 @@
|
|||
(fn [move-vector]
|
||||
(let [position (gpt/add from-position move-vector)
|
||||
target-frame (ctst/top-nested-frame objects position)]
|
||||
(-> (create-modif-tree ids (ctm/move move-vector))
|
||||
(build-change-frame-modifiers objects selected target-frame position)
|
||||
(set-modifiers)))))
|
||||
(-> (dwm/create-modif-tree ids (ctm/move move-vector))
|
||||
(dwm/build-change-frame-modifiers objects selected target-frame position)
|
||||
(dwm/set-modifiers)))))
|
||||
|
||||
(rx/take-until stopper)))
|
||||
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(calculate-frame-for-move ids)
|
||||
(apply-modifiers {:undo-transation? false})
|
||||
(dwm/apply-modifiers {:undo-transation? false})
|
||||
(finish-transform)
|
||||
(dwu/commit-undo-transaction)))))))))
|
||||
|
||||
|
@ -756,12 +523,12 @@
|
|||
(rx/merge
|
||||
(->> move-events
|
||||
(rx/scan #(gpt/add %1 mov-vec) (gpt/point 0 0))
|
||||
(rx/map #(create-modif-tree selected (ctm/move %)))
|
||||
(rx/map (partial set-modifiers))
|
||||
(rx/map #(dwm/create-modif-tree selected (ctm/move %)))
|
||||
(rx/map (partial dwm/set-modifiers))
|
||||
(rx/take-until stopper))
|
||||
(rx/of (move-selected direction shift?)))
|
||||
|
||||
(rx/of (apply-modifiers)
|
||||
(rx/of (dwm/apply-modifiers)
|
||||
(finish-transform))))
|
||||
(rx/empty))))))
|
||||
|
||||
|
@ -789,10 +556,10 @@
|
|||
(or (:y position) (:y bbox)))
|
||||
delta (gpt/subtract pos cpos)
|
||||
|
||||
modif-tree (create-modif-tree [id] (ctm/move delta))]
|
||||
modif-tree (dwm/create-modif-tree [id] (ctm/move delta))]
|
||||
|
||||
(rx/of (set-modifiers modif-tree)
|
||||
(apply-modifiers))))))
|
||||
(rx/of (dwm/set-modifiers modif-tree)
|
||||
(dwm/apply-modifiers))))))
|
||||
|
||||
(defn- calculate-frame-for-move
|
||||
[ids]
|
||||
|
@ -851,14 +618,14 @@
|
|||
selrect (gsh/selection-rect shapes)
|
||||
origin (gpt/point (:x selrect) (+ (:y selrect) (/ (:height selrect) 2)))
|
||||
|
||||
modif-tree (create-modif-tree
|
||||
modif-tree (dwm/create-modif-tree
|
||||
selected
|
||||
(-> (ctm/empty-modifiers)
|
||||
(ctm/set-resize (gpt/point -1.0 1.0) origin)
|
||||
(ctm/move (gpt/point (:width selrect) 0))))]
|
||||
|
||||
(rx/of (set-modifiers modif-tree true)
|
||||
(apply-modifiers))))))
|
||||
(rx/of (dwm/set-modifiers modif-tree true)
|
||||
(dwm/apply-modifiers))))))
|
||||
|
||||
(defn flip-vertical-selected []
|
||||
(ptk/reify ::flip-vertical-selected
|
||||
|
@ -870,11 +637,11 @@
|
|||
selrect (gsh/selection-rect shapes)
|
||||
origin (gpt/point (+ (:x selrect) (/ (:width selrect) 2)) (:y selrect))
|
||||
|
||||
modif-tree (create-modif-tree
|
||||
modif-tree (dwm/create-modif-tree
|
||||
selected
|
||||
(-> (ctm/empty-modifiers)
|
||||
(ctm/set-resize (gpt/point 1.0 -1.0) origin)
|
||||
(ctm/move (gpt/point 0 (:height selrect)))))]
|
||||
|
||||
(rx/of (set-modifiers modif-tree true)
|
||||
(apply-modifiers))))))
|
||||
(rx/of (dwm/set-modifiers modif-tree true)
|
||||
(dwm/apply-modifiers))))))
|
||||
|
|
|
@ -443,7 +443,8 @@
|
|||
(l/derived
|
||||
(fn [objects]
|
||||
(->> ids
|
||||
(some #(-> (cph/get-parent objects %) ctl/layout?))))
|
||||
(map (d/getf objects))
|
||||
(some (partial ctl/layout-child? objects))))
|
||||
workspace-page-objects))
|
||||
|
||||
(defn get-flex-child-viewer?
|
||||
|
@ -452,8 +453,8 @@
|
|||
(fn [state]
|
||||
(let [objects (wsh/lookup-viewer-objects state page-id)]
|
||||
(into []
|
||||
(comp (filter #(= :flex (:layout (cph/get-parent objects %))))
|
||||
(map #(get objects %)))
|
||||
(comp (filter (partial ctl/layout-child? objects))
|
||||
(map (d/getf objects)))
|
||||
ids)))
|
||||
st/state =))
|
||||
|
||||
|
|
|
@ -87,6 +87,12 @@
|
|||
|
||||
flex-child? (->> selection-parents (some ctl/layout?))
|
||||
|
||||
flex-container? (ctl/layout? shape)
|
||||
flex-auto-width? (ctl/auto-width? shape)
|
||||
flex-fill-width? (ctl/fill-width? shape)
|
||||
flex-auto-height? (ctl/auto-height? shape)
|
||||
flex-fill-height? (ctl/fill-height? shape)
|
||||
|
||||
;; To show interactively the measures while the user is manipulating
|
||||
;; the shape with the mouse, generate a copy of the shapes applying
|
||||
;; the transient transformations.
|
||||
|
@ -306,6 +312,7 @@
|
|||
:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-change on-width-change
|
||||
:disabled (and (or flex-child? flex-container?) (or flex-auto-width? flex-fill-width?))
|
||||
:value (:width values)}]]
|
||||
|
||||
[:div.input-element.height {:title (tr "workspace.options.height")}
|
||||
|
@ -314,6 +321,7 @@
|
|||
:placeholder "--"
|
||||
:on-click select-all
|
||||
:on-change on-height-change
|
||||
:disabled (and (or flex-child? flex-container?) (or flex-auto-height? flex-fill-height?))
|
||||
:value (:height values)}]]
|
||||
|
||||
[:div.lock-size {:class (dom/classnames
|
||||
|
|
|
@ -286,7 +286,7 @@
|
|||
|
||||
(when show-frame-outline?
|
||||
[:& outline/shape-outlines
|
||||
{:objects base-objects
|
||||
{:objects objects-modified
|
||||
:hover #{(->> @hover-ids
|
||||
(filter #(cph/frame-shape? (get base-objects %)))
|
||||
(remove selected)
|
||||
|
|
|
@ -13,6 +13,44 @@
|
|||
[app.common.pages.helpers :as cph]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
;; Helper to debug the bounds when set the "hug" content property
|
||||
#_(mf/defc debug-bounds
|
||||
"Debug component to show the auto-layout drop areas"
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [objects (unchecked-get props "objects")
|
||||
selected-shapes (unchecked-get props "selected-shapes")
|
||||
hover-top-frame-id (unchecked-get props "hover-top-frame-id")
|
||||
|
||||
selected-frame
|
||||
(when (and (= (count selected-shapes) 1) (= :frame (-> selected-shapes first :type)))
|
||||
(first selected-shapes))
|
||||
|
||||
shape (or selected-frame (get objects hover-top-frame-id))]
|
||||
|
||||
(when (and shape (:layout shape))
|
||||
(let [children (cph/get-immediate-children objects (:id shape))
|
||||
layout-data (gsl/calc-layout-data shape children)
|
||||
|
||||
{pad-top :p1 pad-right :p2 pad-bottom :p3 pad-left :p4} (:layout-padding shape)
|
||||
pad-top (or pad-top 0)
|
||||
pad-right (or pad-right 0)
|
||||
pad-bottom (or pad-bottom 0)
|
||||
pad-left (or pad-left 0)
|
||||
|
||||
layout-bounds (gsl/layout-content-bounds shape children)]
|
||||
[:g.debug-layout {:pointer-events "none"
|
||||
:transform (gsh/transform-str shape)}
|
||||
|
||||
|
||||
[:rect {:x (:x layout-bounds)
|
||||
:y (:y layout-bounds)
|
||||
:width (:width layout-bounds)
|
||||
:height (:height layout-bounds)
|
||||
:style {:stroke "red"
|
||||
:fill "none"}}]]))))
|
||||
|
||||
(mf/defc debug-layout
|
||||
"Debug component to show the auto-layout drop areas"
|
||||
{::mf/wrap-props false}
|
||||
|
@ -27,7 +65,7 @@
|
|||
(first selected-shapes))
|
||||
|
||||
shape (or selected-frame (get objects hover-top-frame-id))]
|
||||
|
||||
|
||||
(when (and shape (:layout shape))
|
||||
(let [children (cph/get-immediate-children objects (:id shape))
|
||||
layout-data (gsl/calc-layout-data shape children)
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
[app.common.pages.diff :as diff]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.geom.grid :as gg]
|
||||
[app.util.geom.snap-points :as snap]
|
||||
|
@ -70,7 +71,7 @@
|
|||
(mapv grid->snap)))))
|
||||
|
||||
(defn- add-frame
|
||||
[page-data frame]
|
||||
[objects page-data frame]
|
||||
(let [frame-id (:id frame)
|
||||
parent-id (:parent-id frame)
|
||||
frame-data (->> (snap/shape-snap-points frame)
|
||||
|
@ -79,21 +80,24 @@
|
|||
:pt %)))
|
||||
grid-x-data (get-grids-snap-points frame :x)
|
||||
grid-y-data (get-grids-snap-points frame :y)]
|
||||
(-> page-data
|
||||
;; Update root frame information
|
||||
(assoc-in [uuid/zero :objects-data frame-id] frame-data)
|
||||
(update-in [parent-id :x] (make-insert-tree-data frame-data :x))
|
||||
(update-in [parent-id :y] (make-insert-tree-data frame-data :y))
|
||||
|
||||
;; Update frame information
|
||||
(assoc-in [frame-id :objects-data frame-id] (d/concat-vec frame-data grid-x-data grid-y-data))
|
||||
(update-in [frame-id :x] #(or % (rt/make-tree)))
|
||||
(update-in [frame-id :y] #(or % (rt/make-tree)))
|
||||
(update-in [frame-id :x] (make-insert-tree-data (d/concat-vec frame-data grid-x-data) :x))
|
||||
(update-in [frame-id :y] (make-insert-tree-data (d/concat-vec frame-data grid-y-data) :y)))))
|
||||
(cond-> page-data
|
||||
(not (ctl/layout-child? objects frame))
|
||||
|
||||
(-> ;; Update root frame information
|
||||
(assoc-in [uuid/zero :objects-data frame-id] frame-data)
|
||||
(update-in [parent-id :x] (make-insert-tree-data frame-data :x))
|
||||
(update-in [parent-id :y] (make-insert-tree-data frame-data :y))
|
||||
|
||||
;; Update frame information
|
||||
(assoc-in [frame-id :objects-data frame-id] (d/concat-vec frame-data grid-x-data grid-y-data))
|
||||
(update-in [frame-id :x] #(or % (rt/make-tree)))
|
||||
(update-in [frame-id :y] #(or % (rt/make-tree)))
|
||||
(update-in [frame-id :x] (make-insert-tree-data (d/concat-vec frame-data grid-x-data) :x))
|
||||
(update-in [frame-id :y] (make-insert-tree-data (d/concat-vec frame-data grid-y-data) :y))))))
|
||||
|
||||
(defn- add-shape
|
||||
[page-data shape]
|
||||
[objects page-data shape]
|
||||
(let [frame-id (:frame-id shape)
|
||||
snap-points (snap/shape-snap-points shape)
|
||||
shape-data (->> snap-points
|
||||
|
@ -101,11 +105,11 @@
|
|||
:type :shape
|
||||
:id (:id shape)
|
||||
:pt %)))]
|
||||
(-> page-data
|
||||
(assoc-in [frame-id :objects-data (:id shape)] shape-data)
|
||||
(update-in [frame-id :x] (make-insert-tree-data shape-data :x))
|
||||
(update-in [frame-id :y] (make-insert-tree-data shape-data :y)))))
|
||||
|
||||
(cond-> page-data
|
||||
(not (ctl/layout-child? objects shape))
|
||||
(-> (assoc-in [frame-id :objects-data (:id shape)] shape-data)
|
||||
(update-in [frame-id :x] (make-insert-tree-data shape-data :x))
|
||||
(update-in [frame-id :y] (make-insert-tree-data shape-data :y))))))
|
||||
|
||||
(defn- add-guide
|
||||
[objects page-data guide]
|
||||
|
@ -164,22 +168,22 @@
|
|||
(update-in [:guides (:axis guide)] (make-delete-tree-data guide-data (:axis guide)))))))
|
||||
|
||||
(defn- update-frame
|
||||
[page-data [_ new-frame]]
|
||||
[objects page-data [_ new-frame]]
|
||||
(let [frame-id (:id new-frame)
|
||||
root-data (get-in page-data [uuid/zero :objects-data frame-id])
|
||||
frame-data (get-in page-data [frame-id :objects-data frame-id])]
|
||||
(-> page-data
|
||||
(update-in [uuid/zero :x] (make-delete-tree-data root-data :x))
|
||||
(update-in [uuid/zero :y] (make-delete-tree-data root-data :y))
|
||||
(update-in [frame-id :x] (make-delete-tree-data frame-data :x))
|
||||
(update-in [frame-id :y] (make-delete-tree-data frame-data :y))
|
||||
(add-frame new-frame))))
|
||||
(as-> page-data $
|
||||
(update-in $ [uuid/zero :x] (make-delete-tree-data root-data :x))
|
||||
(update-in $ [uuid/zero :y] (make-delete-tree-data root-data :y))
|
||||
(update-in $ [frame-id :x] (make-delete-tree-data frame-data :x))
|
||||
(update-in $ [frame-id :y] (make-delete-tree-data frame-data :y))
|
||||
(add-frame objects $ new-frame))))
|
||||
|
||||
(defn- update-shape
|
||||
[page-data [old-shape new-shape]]
|
||||
(-> page-data
|
||||
(remove-shape old-shape)
|
||||
(add-shape new-shape)))
|
||||
[objects page-data [old-shape new-shape]]
|
||||
(as-> page-data $
|
||||
(remove-shape $ old-shape)
|
||||
(add-shape objects $ new-shape)))
|
||||
|
||||
(defn- update-guide
|
||||
[objects page-data [old-guide new-guide]]
|
||||
|
@ -205,8 +209,8 @@
|
|||
page-data
|
||||
(as-> {} $
|
||||
(add-root-frame $)
|
||||
(reduce add-frame $ frames)
|
||||
(reduce add-shape $ shapes)
|
||||
(reduce (partial add-frame objects) $ frames)
|
||||
(reduce (partial add-shape objects) $ shapes)
|
||||
(reduce (partial add-guide objects) $ guides))]
|
||||
(assoc snap-data (:id page) page-data)))
|
||||
|
||||
|
@ -233,16 +237,16 @@
|
|||
(diff/calculate-page-diff old-page page snap-attrs)]
|
||||
|
||||
(as-> page-data $
|
||||
(reduce update-shape $ change-frame-shapes)
|
||||
(reduce (partial update-shape objects) $ change-frame-shapes)
|
||||
(reduce remove-frame $ removed-frames)
|
||||
(reduce remove-shape $ removed-shapes)
|
||||
(reduce update-frame $ updated-frames)
|
||||
(reduce update-shape $ updated-shapes)
|
||||
(reduce add-frame $ new-frames)
|
||||
(reduce add-shape $ new-shapes)
|
||||
(reduce remove-guide $ removed-guides)
|
||||
(reduce (partial update-frame objects) $ updated-frames)
|
||||
(reduce (partial update-shape objects) $ updated-shapes)
|
||||
(reduce (partial add-frame objects) $ new-frames)
|
||||
(reduce (partial add-shape objects) $ new-shapes)
|
||||
|
||||
;; Guides functions. Need objects to get its frame data
|
||||
(reduce remove-guide $ removed-guides)
|
||||
(reduce (partial update-guide objects) $ change-frame-guides)
|
||||
(reduce (partial update-guide objects) $ updated-guides)
|
||||
(reduce (partial add-guide objects) $ new-guides)))))
|
||||
|
|
Loading…
Add table
Reference in a new issue