mirror of
https://github.com/penpot/penpot.git
synced 2025-03-20 11:41:47 -05:00
✨ Redone the calculus of sizing auto
This commit is contained in:
parent
efc1b87ab0
commit
32756db1c1
3 changed files with 124 additions and 100 deletions
common/src/app/common
|
@ -135,10 +135,10 @@
|
|||
(letfn [(apply-modifiers [modif-tree child]
|
||||
(let [modifiers (dm/get-in modif-tree [(:id child) :modifiers])]
|
||||
(cond-> child
|
||||
(some? modifiers)
|
||||
(and (not (cph/group-shape? child)) (some? modifiers))
|
||||
(gtr/transform-shape modifiers)
|
||||
|
||||
(cph/group-like-shape? child)
|
||||
(cph/group-shape? child)
|
||||
(gtr/apply-group-modifiers objects modif-tree))))
|
||||
|
||||
(set-child-modifiers [parent [layout-line modif-tree] child]
|
||||
|
@ -152,7 +152,7 @@
|
|||
|
||||
[layout-line modif-tree]))]
|
||||
|
||||
(let [children (map (d/getf objects) (:shapes parent))
|
||||
(let [children (map (d/getf objects) (:shapes parent))
|
||||
children (->> children (map (partial apply-modifiers modif-tree)))
|
||||
layout-data (gcl/calc-layout-data parent children)
|
||||
children (into [] (cond-> children (:reverse? layout-data) reverse))
|
||||
|
@ -173,119 +173,136 @@
|
|||
|
||||
modif-tree)))))
|
||||
|
||||
(defn- set-auto-modifiers
|
||||
(defn- calc-auto-modifiers
|
||||
"Calculates the modifiers to adjust the bounds for auto-width/auto-height shapes"
|
||||
[modif-tree objects parent]
|
||||
(letfn [(apply-modifiers
|
||||
[child]
|
||||
(let [modifiers (dm/get-in modif-tree [(:id child) :modifiers])]
|
||||
(cond-> child
|
||||
(some? modifiers)
|
||||
(gtr/transform-shape modifiers)
|
||||
|
||||
(and (some? modifiers) (cph/group-like-shape? child))
|
||||
(gtr/apply-group-modifiers objects modif-tree))))
|
||||
|
||||
(set-parent-auto-width
|
||||
[modifiers parent auto-width]
|
||||
[objects parent]
|
||||
(letfn [(set-parent-auto-width
|
||||
[modifiers auto-width]
|
||||
(let [origin (-> parent :points first)
|
||||
scale-width (/ auto-width (-> parent :selrect :width) )]
|
||||
(-> modifiers
|
||||
(ctm/resize-parent (gpt/point scale-width 1) origin (:transform parent) (:transform-inverse parent)))))
|
||||
|
||||
(set-parent-auto-height
|
||||
[modifiers parent auto-height]
|
||||
[modifiers auto-height]
|
||||
(let [origin (-> parent :points first)
|
||||
scale-height (/ auto-height (-> parent :selrect :height) )]
|
||||
(-> modifiers
|
||||
(ctm/resize-parent (gpt/point 1 scale-height) origin (:transform parent) (:transform-inverse parent)))))]
|
||||
|
||||
(let [modifiers (dm/get-in modif-tree [(:id parent) :modifiers])
|
||||
children (->> parent
|
||||
:shapes
|
||||
(map (comp apply-modifiers (d/getf objects))))
|
||||
(let [children (->> parent :shapes (map (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))
|
||||
(gcl/layout-content-bounds parent children))]
|
||||
|
||||
modifiers
|
||||
(cond-> modifiers
|
||||
(and (some? auto-width) (ctl/auto-width? parent))
|
||||
(set-parent-auto-width parent auto-width)
|
||||
(cond-> (ctm/empty)
|
||||
(and (some? auto-width) (ctl/auto-width? parent))
|
||||
(set-parent-auto-width auto-width)
|
||||
|
||||
(and (some? auto-height) (ctl/auto-height? parent))
|
||||
(set-parent-auto-height parent auto-height))]
|
||||
|
||||
(assoc-in modif-tree [(:id parent) :modifiers] modifiers))))
|
||||
(and (some? auto-height) (ctl/auto-height? parent))
|
||||
(set-parent-auto-height auto-height)))))
|
||||
|
||||
(defn- propagate-modifiers
|
||||
"Propagate modifiers to its children"
|
||||
[objects ignore-constraints [modif-tree recalculate] parent]
|
||||
[objects ignore-constraints [modif-tree autolayouts] parent]
|
||||
(let [parent-id (:id parent)
|
||||
root? (= uuid/zero parent-id)
|
||||
modifiers (dm/get-in modif-tree [parent-id :modifiers])
|
||||
transformed-parent (gtr/transform-shape parent modifiers)
|
||||
|
||||
has-modifiers? (ctm/child-modifiers? modifiers)
|
||||
is-layout? (ctl/layout? parent)
|
||||
is-auto? (or (ctl/auto-height? transformed-parent) (ctl/auto-width? transformed-parent))
|
||||
is-parent? (or (cph/group-like-shape? parent) (cph/frame-shape? parent))
|
||||
layout? (ctl/layout? parent)
|
||||
auto? (or (ctl/auto-height? transformed-parent) (ctl/auto-width? transformed-parent))
|
||||
parent? (or (cph/group-like-shape? parent) (cph/frame-shape? parent))
|
||||
|
||||
;; If the current child is inside the layout we ignore the constraints
|
||||
is-inside-layout? (ctl/inside-layout? objects parent)]
|
||||
inside-layout? (ctl/inside-layout? objects parent)]
|
||||
|
||||
[(cond-> modif-tree
|
||||
(and (not is-layout?) has-modifiers? is-parent? (not root?))
|
||||
(set-children-modifiers objects parent transformed-parent (or ignore-constraints is-inside-layout?))
|
||||
(and (not layout?) has-modifiers? parent? (not root?))
|
||||
(set-children-modifiers objects parent transformed-parent (or ignore-constraints inside-layout?))
|
||||
|
||||
is-layout?
|
||||
layout?
|
||||
(-> (process-layout-children objects parent transformed-parent)
|
||||
(set-layout-modifiers objects transformed-parent))
|
||||
(set-layout-modifiers objects transformed-parent)))
|
||||
|
||||
is-auto?
|
||||
(set-auto-modifiers objects transformed-parent))
|
||||
;; Auto-width/height can change the positions in the parent so we need to recalculate
|
||||
(cond-> autolayouts auto? (conj (:id parent)))]))
|
||||
|
||||
(cond-> recalculate
|
||||
;; Auto-width/height can change the positions in the parent so we need to recalculate
|
||||
is-auto?
|
||||
(conj (:id parent)))]))
|
||||
(defn- apply-structure-modifiers
|
||||
[objects modif-tree]
|
||||
(letfn [(apply-shape [objects [id {:keys [modifiers]}]]
|
||||
(if (ctm/has-structure? modifiers)
|
||||
(let [shape (get objects id)]
|
||||
(update objects id ctm/apply-structure-modifiers modifiers))
|
||||
objects))]
|
||||
(reduce apply-shape objects modif-tree)))
|
||||
|
||||
(defn- calculate-reflow-layout
|
||||
[objects modif-tree parent]
|
||||
(let [is-layout? (ctl/layout? parent)
|
||||
is-auto? (or (ctl/auto-height? parent) (ctl/auto-width? parent))
|
||||
modifiers (dm/get-in modif-tree [(:id parent) :modifiers])
|
||||
transformed-parent (gtr/transform-shape parent modifiers)]
|
||||
(cond-> modif-tree
|
||||
is-layout?
|
||||
(set-layout-modifiers objects transformed-parent)
|
||||
(defn- apply-partial-objects-modifiers
|
||||
[objects tree-seq modif-tree]
|
||||
|
||||
is-auto?
|
||||
(set-auto-modifiers objects transformed-parent))))
|
||||
(letfn [(apply-shape [objects {:keys [id] :as shape}]
|
||||
(if (cph/group-shape? shape)
|
||||
(let [children (cph/get-children objects id)]
|
||||
(assoc objects id
|
||||
(cond
|
||||
(cph/mask-shape? shape)
|
||||
(gtr/update-mask-selrect shape children)
|
||||
|
||||
:else
|
||||
(gtr/update-group-selrect shape children))))
|
||||
|
||||
(let [modifiers (get-in modif-tree [id :modifiers])
|
||||
object (cond-> shape
|
||||
(some? modifiers)
|
||||
(gtr/transform-shape modifiers))]
|
||||
(assoc objects id object))))]
|
||||
|
||||
(reduce apply-shape objects (reverse tree-seq))))
|
||||
|
||||
(defn merge-modif-tree
|
||||
[modif-tree other-tree]
|
||||
(reduce (fn [modif-tree [id {:keys [modifiers]}]]
|
||||
(update-in modif-tree [id :modifiers] ctm/add-modifiers modifiers))
|
||||
modif-tree
|
||||
other-tree))
|
||||
|
||||
(defn sizing-auto-modifiers
|
||||
"Recalculates the layouts to adjust the sizing: auto new sizes"
|
||||
[modif-tree sizing-auto-layouts objects ignore-constraints]
|
||||
(loop [modif-tree modif-tree
|
||||
sizing-auto-layouts (reverse sizing-auto-layouts)]
|
||||
(if-let [current (first sizing-auto-layouts)]
|
||||
(let [parent-base (get objects current)
|
||||
tree-seq (resolve-tree-sequence #{current} objects)
|
||||
|
||||
;; Apply the current stack of transformations so we can calculate the auto-layouts
|
||||
objects (apply-partial-objects-modifiers objects tree-seq modif-tree)
|
||||
|
||||
resize-modif-tree
|
||||
{current {:modifiers (calc-auto-modifiers objects parent-base)}}
|
||||
|
||||
tree-seq (resolve-tree-sequence #{current} objects)
|
||||
|
||||
[resize-modif-tree _]
|
||||
(reduce (partial propagate-modifiers objects ignore-constraints) [resize-modif-tree #{}] tree-seq)
|
||||
|
||||
modif-tree (merge-modif-tree modif-tree resize-modif-tree)]
|
||||
(recur modif-tree (rest sizing-auto-layouts)))
|
||||
modif-tree)))
|
||||
|
||||
(defn set-objects-modifiers
|
||||
[modif-tree objects ignore-constraints snap-pixel?]
|
||||
|
||||
(let [shapes-tree (resolve-tree-sequence (-> modif-tree keys set) objects)
|
||||
(let [objects (apply-structure-modifiers objects modif-tree)
|
||||
shapes-tree (resolve-tree-sequence (-> modif-tree keys set) objects)
|
||||
|
||||
[modif-tree recalculate]
|
||||
[modif-tree sizing-auto-layouts]
|
||||
(reduce (partial propagate-modifiers objects ignore-constraints) [modif-tree #{}] shapes-tree)
|
||||
|
||||
shapes-tree (resolve-tree-sequence recalculate objects)
|
||||
|
||||
;; We need to go again and recalculate the layout positions+hug
|
||||
;; TODO LAYOUT: How to remove this recalculation?
|
||||
modif-tree
|
||||
(->> shapes-tree
|
||||
reverse
|
||||
(filter ctl/layout?)
|
||||
(reduce (partial calculate-reflow-layout objects) modif-tree))
|
||||
|
||||
modif-tree
|
||||
(->> shapes-tree
|
||||
(filter ctl/layout?)
|
||||
(reduce (partial calculate-reflow-layout objects) modif-tree))
|
||||
;; Calculate hug layouts positions
|
||||
modif-tree (sizing-auto-modifiers modif-tree sizing-auto-layouts objects ignore-constraints)
|
||||
|
||||
modif-tree
|
||||
(cond-> modif-tree
|
||||
|
|
|
@ -369,6 +369,9 @@
|
|||
;; Points for every shape inside the group
|
||||
points (->> children (mapcat :points))
|
||||
|
||||
;; Fixed problem with empty groups. Should not happen (but it does)
|
||||
points (if (empty? points) (:points group) points)
|
||||
|
||||
;; Invert to get the points minus the transforms applied to the group
|
||||
base-points (gco/transform-points points shape-center (:transform-inverse group (gmt/matrix)))
|
||||
|
||||
|
@ -478,43 +481,43 @@
|
|||
(declare apply-group-modifiers)
|
||||
|
||||
(defn apply-children-modifiers
|
||||
[objects modif-tree parent-modifiers children]
|
||||
[objects modif-tree parent-modifiers children propagate?]
|
||||
(->> children
|
||||
(map (fn [child]
|
||||
(let [modifiers (->> (get-in modif-tree [(:id child) :modifiers])
|
||||
(ctm/add-modifiers parent-modifiers))
|
||||
(let [modifiers (cond-> (get-in modif-tree [(:id child) :modifiers])
|
||||
propagate? (ctm/add-modifiers parent-modifiers))
|
||||
child (transform-shape child modifiers)
|
||||
parent? (cph/group-like-shape? child)]
|
||||
parent? (cph/group-like-shape? child)
|
||||
|
||||
modif-tree
|
||||
(cond-> modif-tree
|
||||
propagate?
|
||||
(assoc-in [(:id child) :modifiers] modifiers))]
|
||||
|
||||
(cond-> child
|
||||
parent?
|
||||
(apply-group-modifiers objects (assoc-in modif-tree [(:id child) :modifiers] modifiers))))))))
|
||||
(apply-group-modifiers objects modif-tree propagate?)))))))
|
||||
|
||||
(defn apply-group-modifiers
|
||||
"Apply the modifiers to the group children to calculate its selection rect"
|
||||
[group objects modif-tree]
|
||||
([group objects modif-tree]
|
||||
(apply-group-modifiers group objects modif-tree true))
|
||||
|
||||
(let [modifiers (get-in modif-tree [(:id group) :modifiers])
|
||||
children (->> (:shapes group)
|
||||
(map (d/getf objects))
|
||||
(apply-children-modifiers objects modif-tree modifiers))]
|
||||
(cond
|
||||
(cph/mask-shape? group)
|
||||
(update-mask-selrect group children)
|
||||
([group objects modif-tree propagate?]
|
||||
(let [modifiers (get-in modif-tree [(:id group) :modifiers])
|
||||
children
|
||||
(as-> (:shapes group) $
|
||||
(map (d/getf objects) $)
|
||||
(apply-children-modifiers objects modif-tree modifiers $ propagate?))]
|
||||
(cond
|
||||
(cph/mask-shape? group)
|
||||
(update-mask-selrect group children)
|
||||
|
||||
(cph/group-shape? group)
|
||||
(update-group-selrect group children)
|
||||
(cph/group-shape? group)
|
||||
(update-group-selrect group children)
|
||||
|
||||
:else
|
||||
group)))
|
||||
|
||||
(defn get-children-bounds
|
||||
[parent objects modif-tree]
|
||||
(let [modifiers (get-in modif-tree [(:id parent) :modifiers])
|
||||
children
|
||||
(->> (:shapes parent)
|
||||
(map (d/getf objects))
|
||||
(apply-children-modifiers objects modif-tree modifiers))]
|
||||
(->> children (mapcat :points) gpr/points->rect)))
|
||||
:else
|
||||
group))))
|
||||
|
||||
(defn parent-coords-rect
|
||||
[child parent]
|
||||
|
|
|
@ -384,7 +384,11 @@
|
|||
|
||||
(defn select-structure
|
||||
[modifiers]
|
||||
(select-keys modifiers [:structure-parent]))
|
||||
(select-keys modifiers [:structure-parent :structure-child]))
|
||||
|
||||
(defn select-geometry
|
||||
[modifiers]
|
||||
(select-keys modifiers [:geometry-parent :geometry-child]))
|
||||
|
||||
(defn added-children-frames
|
||||
"Returns the frames that have an 'add-children' operation"
|
||||
|
|
Loading…
Add table
Reference in a new issue