mirror of
https://github.com/penpot/penpot.git
synced 2025-04-01 09:31:26 -05:00
✨ Hug content to frames
This commit is contained in:
parent
0274567d83
commit
7f0054959f
17 changed files with 448 additions and 169 deletions
|
@ -13,7 +13,6 @@
|
|||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.corners :as gsc]
|
||||
[app.common.geom.shapes.flex-layout :as gcl]
|
||||
[app.common.geom.shapes.intersect :as gin]
|
||||
[app.common.geom.shapes.modifiers :as gsm]
|
||||
[app.common.geom.shapes.path :as gsp]
|
||||
|
@ -184,10 +183,6 @@
|
|||
;; Constratins
|
||||
(dm/export gct/calc-child-modifiers)
|
||||
|
||||
;; Layout
|
||||
(dm/export gcl/calc-layout-data)
|
||||
(dm/export gcl/calc-layout-modifiers)
|
||||
|
||||
;; PATHS
|
||||
(dm/export gsp/content->selrect)
|
||||
(dm/export gsp/transform-content)
|
||||
|
|
|
@ -265,7 +265,7 @@
|
|||
(if (and (= :scale constraints-h) (= :scale constraints-v))
|
||||
modifiers
|
||||
|
||||
(let [transformed-child (gst/transform-shape child modifiers)
|
||||
(let [transformed-child (gst/transform-shape child (ctm/select-child-modifiers modifiers))
|
||||
modifiers (normalize-modifiers constraints-h constraints-v modifiers child parent transformed-child transformed-parent)
|
||||
|
||||
transformed-child (gst/transform-shape child modifiers)
|
||||
|
|
|
@ -7,12 +7,15 @@
|
|||
(ns app.common.geom.shapes.flex-layout
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.shapes.flex-layout.bounds :as fbo]
|
||||
[app.common.geom.shapes.flex-layout.drop-area :as fdr]
|
||||
[app.common.geom.shapes.flex-layout.lines :as fli]
|
||||
[app.common.geom.shapes.flex-layout.modifiers :as fmo]))
|
||||
|
||||
(dm/export fli/calc-layout-data)
|
||||
(dm/export fmo/normalize-child-modifiers)
|
||||
(dm/export fmo/calc-layout-modifiers)
|
||||
(dm/export fdr/layout-drop-areas)
|
||||
(dm/export fbo/layout-content-bounds)
|
||||
(dm/export fdr/get-drop-index)
|
||||
(dm/export fdr/layout-drop-areas)
|
||||
(dm/export fli/calc-layout-data)
|
||||
(dm/export fmo/layout-child-modifiers)
|
||||
(dm/export fmo/normalize-child-modifiers)
|
||||
|
||||
|
|
113
common/src/app/common/geom/shapes/flex_layout/bounds.cljc
Normal file
113
common/src/app/common/geom/shapes/flex_layout/bounds.cljc
Normal file
|
@ -0,0 +1,113 @@
|
|||
;; 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.common.geom.shapes.flex-layout.bounds
|
||||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.geom.shapes.rect :as gre]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
(defn- child-layout-bound-points
|
||||
"Returns the bounds of the children as points"
|
||||
[parent child]
|
||||
|
||||
(let [row? (ctl/row? parent)
|
||||
col? (ctl/col? parent)
|
||||
|
||||
hv (partial gpo/start-hv (:points parent))
|
||||
vv (partial gpo/start-vv (:points parent))
|
||||
|
||||
v-start? (ctl/v-start? parent)
|
||||
v-center? (ctl/v-center? parent)
|
||||
v-end? (ctl/v-end? parent)
|
||||
h-start? (ctl/h-start? parent)
|
||||
h-center? (ctl/h-center? parent)
|
||||
h-end? (ctl/h-end? parent)
|
||||
|
||||
base-p (first (:points child))
|
||||
|
||||
width (-> child :selrect :width)
|
||||
height (-> child :selrect :height)
|
||||
|
||||
min-width (if (ctl/fill-width? child)
|
||||
(ctl/child-min-width child)
|
||||
width)
|
||||
|
||||
min-height (if (ctl/fill-height? child)
|
||||
(ctl/child-min-height child)
|
||||
height)
|
||||
|
||||
;; This is the leftmost (when row) or topmost (when col) point
|
||||
;; Will be added always to the bounds and then calculated the other limits
|
||||
;; from there
|
||||
base-p (cond-> base-p
|
||||
(and row? v-center?)
|
||||
(gpt/add (vv (/ height 2)))
|
||||
|
||||
(and row? v-end?)
|
||||
(gpt/add (vv height))
|
||||
|
||||
(and col? h-center?)
|
||||
(gpt/add (hv (/ width 2)))
|
||||
|
||||
(and col? h-end?)
|
||||
(gpt/add (hv width)))]
|
||||
|
||||
(cond-> [base-p]
|
||||
(and (mth/almost-zero? min-width) (mth/almost-zero? min-height))
|
||||
(conj (cond-> base-p
|
||||
row?
|
||||
(gpt/add (hv width))
|
||||
|
||||
col?
|
||||
(gpt/add (vv height))))
|
||||
|
||||
(not (mth/almost-zero? min-width))
|
||||
(conj (cond-> base-p
|
||||
(or row? h-start?)
|
||||
(gpt/add (hv min-width))
|
||||
|
||||
(and col? h-center?)
|
||||
(gpt/add (hv (/ min-width 2)))
|
||||
|
||||
(and col? h-center?)
|
||||
(gpt/subtract (hv min-width))))
|
||||
|
||||
(not (mth/almost-zero? min-height))
|
||||
(conj (cond-> base-p
|
||||
(or col? v-start?)
|
||||
(gpt/add (vv min-height))
|
||||
|
||||
(and row? v-center?)
|
||||
(gpt/add (vv (/ min-height 2)))
|
||||
|
||||
(and row? v-end?)
|
||||
(gpt/subtract (vv min-height)))))))
|
||||
|
||||
(defn layout-content-bounds
|
||||
[{:keys [layout-padding] :as parent} children]
|
||||
|
||||
(let [{pad-top :p1 pad-right :p2 pad-bottom :p3 pad-left :p4} layout-padding
|
||||
pad-top (or pad-top 0)
|
||||
pad-right (or pad-right 0)
|
||||
pad-bottom (or pad-bottom 0)
|
||||
pad-left (or pad-left 0)
|
||||
|
||||
child-bounds
|
||||
(fn [{:keys [points] :as child}]
|
||||
(if (or (ctl/fill-height? child) (ctl/fill-height? child))
|
||||
(child-layout-bound-points parent child)
|
||||
points))]
|
||||
|
||||
(as-> children $
|
||||
(mapcat child-bounds $)
|
||||
(gco/transform-points $ (gco/center-shape parent) (:transform-inverse parent))
|
||||
(gre/squared-points $)
|
||||
(gpo/pad-points $ (- pad-top) (- pad-right) (- pad-bottom) (- pad-left))
|
||||
(gre/points->rect $))))
|
|
@ -34,10 +34,13 @@
|
|||
"Calculates the lines basic data and accumulated values. The positions will be calculated in a different operation"
|
||||
[shape children layout-bounds]
|
||||
|
||||
(let [wrap? (ctl/wrap? shape)
|
||||
col? (ctl/col? shape)
|
||||
(let [col? (ctl/col? shape)
|
||||
row? (ctl/row? shape)
|
||||
|
||||
wrap? (and (ctl/wrap? shape)
|
||||
(or col? (not (ctl/auto-width? shape)))
|
||||
(or row? (not (ctl/auto-height? shape))))
|
||||
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
layout-width (gpo/width-points layout-bounds)
|
||||
layout-height (gpo/height-points layout-bounds)
|
||||
|
@ -278,6 +281,12 @@
|
|||
(update line-data :children-data
|
||||
(fn [children-data]
|
||||
(cond->> children-data
|
||||
row?
|
||||
(map #(assoc % :child-width (:child-min-width %)))
|
||||
|
||||
col?
|
||||
(map #(assoc % :child-height (:child-min-height %)))
|
||||
|
||||
row?
|
||||
(distribute-space :child-width :child-min-width :child-max-width line-min-width line-width)
|
||||
|
||||
|
@ -304,3 +313,4 @@
|
|||
|
||||
{:layout-lines layout-lines
|
||||
:reverse? reverse?}))
|
||||
|
||||
|
|
|
@ -13,10 +13,9 @@
|
|||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
|
||||
(defn normalize-child-modifiers
|
||||
"Apply the modifiers and then normalized them against the parent coordinates"
|
||||
[parent child modifiers {:keys [transform transform-inverse] :as transformed-parent}]
|
||||
[modifiers parent child {:keys [transform transform-inverse] :as transformed-parent}]
|
||||
|
||||
(let [transformed-child (gst/transform-shape child modifiers)
|
||||
child-bb-before (gst/parent-coords-rect child parent)
|
||||
|
@ -38,14 +37,16 @@
|
|||
{:keys [children-data line-width] :as layout-data}]
|
||||
|
||||
(cond
|
||||
(and (ctl/row? parent) (ctl/fill-width? child))
|
||||
(let [target-width (get-in children-data [(:id child) :child-width])
|
||||
(ctl/row? parent)
|
||||
(let [target-width (max (get-in children-data [(:id child) :child-width]) 0.01)
|
||||
fill-scale (/ target-width child-width)]
|
||||
{:width target-width
|
||||
:modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)})
|
||||
|
||||
(and (ctl/col? parent) (ctl/fill-width? child))
|
||||
(let [target-width (- line-width (ctl/child-width-margin child))
|
||||
(ctl/col? parent)
|
||||
(let [target-width (max (- line-width (ctl/child-width-margin child)) 0.01)
|
||||
max-width (ctl/child-max-width child)
|
||||
target-width (min max-width target-width)
|
||||
fill-scale (/ target-width child-width)]
|
||||
{:width target-width
|
||||
:modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)})))
|
||||
|
@ -58,19 +59,21 @@
|
|||
{:keys [children-data line-height] :as layout-data}]
|
||||
|
||||
(cond
|
||||
(and (ctl/col? parent) (ctl/fill-height? child))
|
||||
(let [target-height (get-in children-data [(:id child) :child-height])
|
||||
(ctl/col? parent)
|
||||
(let [target-height (max (get-in children-data [(:id child) :child-height]) 0.01)
|
||||
fill-scale (/ target-height child-height)]
|
||||
{:height target-height
|
||||
:modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)})
|
||||
|
||||
(and (ctl/row? parent) (ctl/fill-height? child))
|
||||
(let [target-height (- line-height (ctl/child-height-margin child))
|
||||
(ctl/row? parent)
|
||||
(let [target-height (max (- line-height (ctl/child-height-margin child)) 0.01)
|
||||
max-height (ctl/child-max-height child)
|
||||
target-height (min max-height target-height)
|
||||
fill-scale (/ target-height child-height)]
|
||||
{:height target-height
|
||||
:modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)})))
|
||||
|
||||
(defn calc-layout-modifiers
|
||||
(defn layout-child-modifiers
|
||||
"Calculates the modifiers for the layout"
|
||||
[parent child layout-line]
|
||||
(let [child-bounds (gst/parent-coords-points child parent)
|
||||
|
@ -79,8 +82,8 @@
|
|||
child-width (gpo/width-points child-bounds)
|
||||
child-height (gpo/height-points child-bounds)
|
||||
|
||||
fill-width (calc-fill-width-data parent child child-origin child-width layout-line)
|
||||
fill-height (calc-fill-height-data parent child child-origin child-height layout-line)
|
||||
fill-width (when (ctl/fill-width? child) (calc-fill-width-data parent child child-origin child-width layout-line))
|
||||
fill-height (when (ctl/fill-height? child) (calc-fill-height-data parent child child-origin child-height layout-line))
|
||||
|
||||
child-width (or (:width fill-width) child-width)
|
||||
child-height (or (:height fill-height) child-height)
|
||||
|
|
|
@ -7,27 +7,42 @@
|
|||
(ns app.common.geom.shapes.modifiers
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.flex-layout :as gcl]
|
||||
[app.common.geom.shapes.pixel-precision :as gpp]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.common.uuid :as uuid]))
|
||||
|
||||
;;#?(:cljs
|
||||
;; (defn modif->js
|
||||
;; [modif-tree objects]
|
||||
;; (clj->js (into {}
|
||||
;; (map (fn [[k v]]
|
||||
;; [(get-in objects [k :name]) v]))
|
||||
;; modif-tree))))
|
||||
|
||||
|
||||
(defn set-children-modifiers
|
||||
[modif-tree objects parent ignore-constraints snap-pixel?]
|
||||
(letfn [(set-child [transformed-parent _snap-pixel? modif-tree child]
|
||||
(let [modifiers (get-in modif-tree [(:id parent) :modifiers])
|
||||
child-modifiers (gct/calc-child-modifiers parent child modifiers ignore-constraints transformed-parent)
|
||||
child-modifiers (cond-> child-modifiers snap-pixel? (gpp/set-pixel-precision child))]
|
||||
(cond-> modif-tree
|
||||
(not (ctm/empty-modifiers? child-modifiers))
|
||||
(update-in [(:id child) :modifiers] ctm/add-modifiers child-modifiers))))]
|
||||
(let [children (map (d/getf objects) (:shapes parent))
|
||||
modifiers (get-in modif-tree [(:id parent) :modifiers])
|
||||
transformed-parent (gtr/transform-shape parent modifiers)]
|
||||
(reduce (partial set-child transformed-parent snap-pixel?) modif-tree children))))
|
||||
(let [children (map (d/getf objects) (:shapes parent))
|
||||
modifiers (get-in modif-tree [(:id parent) :modifiers])
|
||||
transformed-parent (gtr/transform-shape parent modifiers)
|
||||
parent (gtr/transform-shape parent (ctm/select-parent-modifiers modifiers))
|
||||
|
||||
set-child
|
||||
(fn [modif-tree child]
|
||||
(let [child-modifiers (gct/calc-child-modifiers parent child modifiers ignore-constraints transformed-parent)
|
||||
child-modifiers (cond-> child-modifiers snap-pixel? (gpp/set-pixel-precision child))]
|
||||
(cond-> modif-tree
|
||||
(not (ctm/empty-modifiers? child-modifiers))
|
||||
(update-in [(:id child) :modifiers] ctm/add-modifiers child-modifiers))))]
|
||||
|
||||
(reduce set-child modif-tree children)))
|
||||
|
||||
(defn group? [shape]
|
||||
(or (= :group (:type shape))
|
||||
|
@ -36,17 +51,15 @@
|
|||
(defn frame? [shape]
|
||||
(= :frame (:type shape)))
|
||||
|
||||
(defn layout? [shape]
|
||||
(and (frame? shape)
|
||||
(:layout shape)))
|
||||
|
||||
(defn set-layout-modifiers
|
||||
;; TODO LAYOUT: SNAP PIXEL!
|
||||
[modif-tree objects parent _snap-pixel?]
|
||||
|
||||
(letfn [(normalize-child [transformed-parent _snap-pixel? modif-tree child]
|
||||
(letfn [(process-child [transformed-parent _snap-pixel? modif-tree child]
|
||||
(let [modifiers (get-in modif-tree [(:id parent) :modifiers])
|
||||
child-modifiers (gcl/normalize-child-modifiers parent child modifiers transformed-parent)]
|
||||
child-modifiers (-> modifiers
|
||||
(ctm/select-child-geometry-modifiers)
|
||||
(gcl/normalize-child-modifiers parent child transformed-parent))]
|
||||
(cond-> modif-tree
|
||||
(not (ctm/empty-modifiers? child-modifiers))
|
||||
(update-in [(:id child) :modifiers] ctm/add-modifiers child-modifiers))))
|
||||
|
@ -60,9 +73,9 @@
|
|||
(and (some? modifiers) (group? child))
|
||||
(gtr/apply-group-modifiers objects modif-tree))))
|
||||
|
||||
(set-layout-modifiers [parent [layout-line modif-tree] child]
|
||||
(set-child-modifiers [parent [layout-line modif-tree] child]
|
||||
(let [[modifiers layout-line]
|
||||
(gcl/calc-layout-modifiers parent child layout-line)
|
||||
(gcl/layout-child-modifiers parent child layout-line)
|
||||
|
||||
modif-tree
|
||||
(cond-> modif-tree
|
||||
|
@ -75,8 +88,9 @@
|
|||
transformed-parent (gtr/transform-shape parent modifiers)
|
||||
children (map (d/getf objects) (:shapes transformed-parent))
|
||||
|
||||
modif-tree (reduce (partial normalize-child transformed-parent _snap-pixel?) modif-tree children)
|
||||
modif-tree (reduce (partial process-child transformed-parent _snap-pixel?) modif-tree children)
|
||||
children (->> children (map (partial apply-modifiers modif-tree)))
|
||||
|
||||
layout-data (gcl/calc-layout-data transformed-parent children)
|
||||
children (into [] (cond-> children (:reverse? layout-data) reverse))
|
||||
max-idx (dec (count children))
|
||||
|
@ -92,11 +106,56 @@
|
|||
children (subvec children from-idx to-idx)
|
||||
|
||||
[_ modif-tree]
|
||||
(reduce (partial set-layout-modifiers transformed-parent) [layout-line modif-tree] children)]
|
||||
(reduce (partial set-child-modifiers transformed-parent) [layout-line modif-tree] children)]
|
||||
(recur modif-tree (first pending) (rest pending) to-idx))
|
||||
|
||||
modif-tree)))))
|
||||
|
||||
(defn set-auto-modifiers
|
||||
[modif-tree objects parent]
|
||||
(letfn [(apply-modifiers [child]
|
||||
(let [modifiers (get-in modif-tree [(:id child) :modifiers])]
|
||||
(cond-> child
|
||||
(some? modifiers)
|
||||
(gtr/transform-shape modifiers)
|
||||
|
||||
(and (some? modifiers) (group? child))
|
||||
(gtr/apply-group-modifiers objects modif-tree))))
|
||||
|
||||
(set-parent-auto-width
|
||||
[modifiers parent auto-width]
|
||||
(let [origin (-> parent :points first)
|
||||
scale-width (/ auto-width (-> parent :selrect :width) )]
|
||||
(-> modifiers
|
||||
(ctm/set-resize-parent (gpt/point scale-width 1) origin (:transform parent) (:transform-inverse parent)))))
|
||||
|
||||
(set-parent-auto-height
|
||||
[modifiers parent auto-height]
|
||||
(let [origin (-> parent :points first)
|
||||
scale-height (/ auto-height (-> parent :selrect :height) )]
|
||||
(-> modifiers
|
||||
(ctm/set-resize-parent (gpt/point 1 scale-height) origin (:transform parent) (:transform-inverse parent)))))]
|
||||
|
||||
(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))
|
||||
|
||||
modifiers
|
||||
(cond-> modifiers
|
||||
(and (some? auto-width) (ctl/auto-width? parent))
|
||||
(set-parent-auto-width transformed-parent auto-width)
|
||||
|
||||
(and (some? auto-height) (ctl/auto-height? parent))
|
||||
(set-parent-auto-height transformed-parent auto-height))]
|
||||
|
||||
(assoc-in modif-tree [(:id parent) :modifiers] modifiers))))
|
||||
|
||||
(defn get-tree-root
|
||||
[id objects]
|
||||
|
||||
|
@ -109,7 +168,9 @@
|
|||
result
|
||||
|
||||
;; Frame found, but not layout we return the last layout found (or the id)
|
||||
(and (= :frame (:type parent))
|
||||
(and (and (= :frame (:type parent))
|
||||
(not (ctl/auto-width? parent))
|
||||
(not (ctl/auto-height? parent)))
|
||||
(not (:layout parent)))
|
||||
result
|
||||
|
||||
|
@ -124,7 +185,9 @@
|
|||
|
||||
(defn resolve-tree-sequence
|
||||
"Given the ids that have changed search for layout roots to recalculate"
|
||||
[modif-tree objects]
|
||||
[ids objects]
|
||||
|
||||
(assert (or (nil? ids) (set? ids)) (dm/str "tree sequence from not set: " ids))
|
||||
|
||||
(let [redfn
|
||||
(fn [result id]
|
||||
|
@ -152,10 +215,10 @@
|
|||
|
||||
(map #(get objects %))))
|
||||
|
||||
roots (->> modif-tree keys (reduce redfn #{}))]
|
||||
roots (->> ids (reduce redfn #{}))]
|
||||
|
||||
(concat
|
||||
(when (contains? modif-tree uuid/zero) [(get objects uuid/zero)])
|
||||
(when (contains? ids uuid/zero) [(get objects uuid/zero)])
|
||||
(mapcat generate-tree roots))))
|
||||
|
||||
(defn inside-layout?
|
||||
|
@ -173,48 +236,55 @@
|
|||
:else
|
||||
(recur (:parent-id current))))))
|
||||
|
||||
;;#?(:cljs
|
||||
;; (defn modif->js
|
||||
;; [modif-tree objects]
|
||||
;; (clj->js (into {}
|
||||
;; (map (fn [[k v]]
|
||||
;; [(get-in objects [k :name]) v]))
|
||||
;; modif-tree))))
|
||||
(defn- calculate-modifiers
|
||||
([objects snap-pixel? ignore-constraints [modif-tree recalculate] shape]
|
||||
(calculate-modifiers objects snap-pixel? ignore-constraints false [modif-tree recalculate] shape))
|
||||
|
||||
([objects snap-pixel? ignore-constraints ignore-auto? [modif-tree recalculate] shape]
|
||||
(let [shape-id (:id shape)
|
||||
root? (= uuid/zero shape-id)
|
||||
modifiers (get-in modif-tree [shape-id :modifiers])
|
||||
|
||||
modifiers (cond-> modifiers
|
||||
(and (not root?) (ctm/has-geometry? modifiers) snap-pixel?)
|
||||
(gpp/set-pixel-precision shape))
|
||||
|
||||
modif-tree (-> modif-tree (assoc-in [shape-id :modifiers] modifiers))
|
||||
|
||||
has-modifiers? (ctm/child-modifiers? modifiers)
|
||||
is-layout? (ctl/layout? shape)
|
||||
is-auto? (or (ctl/auto-height? shape) (ctl/auto-width? shape))
|
||||
is-parent? (or (group? shape) (and (frame? shape) (not (ctl/layout? shape))))
|
||||
|
||||
;; If the current child is inside the layout we ignore the constraints
|
||||
is-inside-layout? (inside-layout? objects shape)]
|
||||
|
||||
[(cond-> modif-tree
|
||||
(and has-modifiers? is-parent? (not root?))
|
||||
(set-children-modifiers objects shape (or ignore-constraints is-inside-layout?) snap-pixel?)
|
||||
|
||||
is-layout?
|
||||
(set-layout-modifiers objects shape snap-pixel?)
|
||||
|
||||
(and (not ignore-auto?) is-auto?)
|
||||
(set-auto-modifiers objects shape))
|
||||
|
||||
(cond-> recalculate
|
||||
;; Auto-width/height can change the positions in the parent so we need to recalculate
|
||||
(and (not ignore-auto?) is-auto?)
|
||||
(conj (:id shape)))])))
|
||||
|
||||
(defn set-objects-modifiers
|
||||
[modif-tree objects ignore-constraints snap-pixel?]
|
||||
|
||||
(let [shapes-tree (resolve-tree-sequence modif-tree objects)
|
||||
(let [shapes-tree (resolve-tree-sequence (-> modif-tree keys set) objects)
|
||||
|
||||
modif-tree
|
||||
(->> shapes-tree
|
||||
(reduce
|
||||
(fn [modif-tree shape]
|
||||
|
||||
(let [root? (= uuid/zero (:id shape))
|
||||
[modif-tree recalculate]
|
||||
(reduce (partial calculate-modifiers objects snap-pixel? ignore-constraints) [modif-tree #{}] shapes-tree)
|
||||
|
||||
modifiers (get-in modif-tree [(:id shape) :modifiers])
|
||||
modifiers (cond-> modifiers
|
||||
(and (not root?) (ctm/has-geometry? modifiers) snap-pixel?)
|
||||
(gpp/set-pixel-precision shape))
|
||||
|
||||
modif-tree (-> modif-tree (assoc-in [(:id shape) :modifiers] modifiers))
|
||||
|
||||
has-modifiers? (ctm/child-modifiers? modifiers)
|
||||
is-layout? (layout? shape)
|
||||
is-parent? (or (group? shape) (and (frame? shape) (not (layout? shape))))
|
||||
|
||||
;; If the current child is inside the layout we ignore the constraints
|
||||
is-inside-layout? (inside-layout? objects shape)]
|
||||
|
||||
(cond-> modif-tree
|
||||
(and has-modifiers? is-parent? (not root?))
|
||||
(set-children-modifiers objects shape (or ignore-constraints is-inside-layout?) snap-pixel?)
|
||||
|
||||
is-layout?
|
||||
(set-layout-modifiers objects shape snap-pixel?))))
|
||||
|
||||
modif-tree))]
|
||||
shapes-tree (resolve-tree-sequence recalculate objects)
|
||||
[modif-tree _]
|
||||
(reduce (partial calculate-modifiers objects snap-pixel? ignore-constraints true) [modif-tree #{}] shapes-tree)]
|
||||
|
||||
;;#?(:cljs
|
||||
;; (.log js/console ">result" (modif->js modif-tree objects)))
|
||||
|
|
|
@ -50,12 +50,13 @@
|
|||
|
||||
(defn pad-points
|
||||
[[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left]
|
||||
(let [top-v (start-vv points pad-top)
|
||||
right-v (end-hv points pad-right)
|
||||
bottom-v (end-vv points pad-bottom)
|
||||
left-v (start-hv points pad-left)]
|
||||
(when (some? points)
|
||||
(let [top-v (start-vv points pad-top)
|
||||
right-v (end-hv points pad-right)
|
||||
bottom-v (end-vv points pad-bottom)
|
||||
left-v (start-hv points pad-left)]
|
||||
|
||||
[(-> p0 (gpt/add left-v) (gpt/add top-v))
|
||||
(-> p1 (gpt/add right-v) (gpt/add top-v))
|
||||
(-> p2 (gpt/add right-v) (gpt/add bottom-v))
|
||||
(-> p3 (gpt/add left-v) (gpt/add bottom-v))]))
|
||||
[(-> p0 (gpt/add left-v) (gpt/add top-v))
|
||||
(-> p1 (gpt/add right-v) (gpt/add top-v))
|
||||
(-> p2 (gpt/add right-v) (gpt/add bottom-v))
|
||||
(-> p3 (gpt/add left-v) (gpt/add bottom-v))])))
|
||||
|
|
|
@ -87,6 +87,19 @@
|
|||
(when (d/num? minx miny maxx maxy)
|
||||
(make-rect minx miny (- maxx minx) (- maxy miny))))))
|
||||
|
||||
(defn squared-points
|
||||
[points]
|
||||
(when (d/not-empty? points)
|
||||
(let [minx (transduce (keep :x) min ##Inf points)
|
||||
miny (transduce (keep :y) min ##Inf points)
|
||||
maxx (transduce (keep :x) max ##-Inf points)
|
||||
maxy (transduce (keep :y) max ##-Inf points)]
|
||||
(when (d/num? minx miny maxx maxy)
|
||||
[(gpt/point minx miny)
|
||||
(gpt/point maxx miny)
|
||||
(gpt/point maxx maxy)
|
||||
(gpt/point minx maxy)]))))
|
||||
|
||||
(defn points->selrect [points]
|
||||
(when-let [rect (points->rect points)]
|
||||
(let [{:keys [x y width height]} rect]
|
||||
|
|
|
@ -434,20 +434,35 @@
|
|||
(map (comp gpr/points->selrect :points transform-shape))
|
||||
(gpr/join-selrects)))
|
||||
|
||||
(defn apply-children-modifiers
|
||||
[objects modif-tree children]
|
||||
(->> children
|
||||
(map (fn [child]
|
||||
(let [modifiers (get-in modif-tree [(:id child) :modifiers])
|
||||
child (transform-shape child modifiers)
|
||||
parent? (or (= :group (:type child)) (= :bool (:type child)))]
|
||||
(cond-> child
|
||||
parent?
|
||||
(apply-children-modifiers objects modif-tree)))))))
|
||||
|
||||
(defn apply-group-modifiers
|
||||
"Apply the modifiers to the group children to calculate its selection rect"
|
||||
[group objects modif-tree]
|
||||
[parent objects modif-tree]
|
||||
|
||||
(let [children (->> (:shapes parent)
|
||||
(map (d/getf objects))
|
||||
(apply-children-modifiers objects modif-tree))]
|
||||
(cond-> parent
|
||||
(= :group (:type parent))
|
||||
(update-group-selrect children))))
|
||||
|
||||
(defn get-children-bounds
|
||||
[parent objects modif-tree]
|
||||
(let [children
|
||||
(->> (:shapes group)
|
||||
(->> (:shapes parent)
|
||||
(map (d/getf objects))
|
||||
(map (fn [shape]
|
||||
(let [modifiers (get modif-tree (:id shape))
|
||||
shape (-> shape (merge modifiers) transform-shape)]
|
||||
(if (= :group (:type shape))
|
||||
(apply-group-modifiers shape objects modif-tree)
|
||||
shape)))))]
|
||||
(update-group-selrect group children)))
|
||||
(apply-children-modifiers objects modif-tree))]
|
||||
(->> children (mapcat :points) gpr/points->rect)))
|
||||
|
||||
(defn parent-coords-rect
|
||||
[child parent]
|
||||
|
|
|
@ -17,7 +17,11 @@
|
|||
;; --- Modifiers
|
||||
|
||||
;; Moodifiers types
|
||||
;; - geometry: Geometry
|
||||
;; - geometry-parent: Geometry non-recursive
|
||||
;; * move
|
||||
;; * resize
|
||||
;; * rotation
|
||||
;; - geometry-child: Geometry recursive
|
||||
;; * move
|
||||
;; * resize
|
||||
;; * rotation
|
||||
|
@ -28,7 +32,6 @@
|
|||
;; - structure-child: Structure recursive
|
||||
;; * scale-content
|
||||
;; * rotation
|
||||
;;
|
||||
|
||||
(def conjv (fnil conj []))
|
||||
|
||||
|
@ -37,37 +40,59 @@
|
|||
(defn empty-modifiers []
|
||||
{})
|
||||
|
||||
(defn set-move-parent
|
||||
([modifiers x y]
|
||||
(set-move-parent modifiers (gpt/point x y)))
|
||||
|
||||
([modifiers vector]
|
||||
(-> modifiers
|
||||
(update :geometry-parent conjv {:type :move :vector vector}))))
|
||||
|
||||
(defn set-resize-parent
|
||||
([modifiers vector origin]
|
||||
(-> modifiers
|
||||
(update :geometry-parent conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
|
||||
([modifiers vector origin transform transform-inverse]
|
||||
(-> modifiers
|
||||
(update :geometry-parent conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
(defn set-move
|
||||
([modifiers x y]
|
||||
(set-move modifiers (gpt/point x y)))
|
||||
|
||||
([modifiers vector]
|
||||
(-> modifiers
|
||||
(update :geometry conjv {:type :move :vector vector}))))
|
||||
(update :geometry-child conjv {:type :move :vector vector}))))
|
||||
|
||||
(defn set-resize
|
||||
([modifiers vector origin]
|
||||
(-> modifiers
|
||||
(update :geometry conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
(update :geometry-child conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin})))
|
||||
|
||||
([modifiers vector origin transform transform-inverse]
|
||||
(-> modifiers
|
||||
(update :geometry conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
(update :geometry-child conjv {:type :resize
|
||||
:vector vector
|
||||
:origin origin
|
||||
:transform transform
|
||||
:transform-inverse transform-inverse}))))
|
||||
|
||||
(defn set-rotation
|
||||
[modifiers center angle]
|
||||
(-> modifiers
|
||||
(update :structure-child conjv {:type :rotation
|
||||
:rotation angle})
|
||||
(update :geometry conjv {:type :rotation
|
||||
:center center
|
||||
:rotation angle})))
|
||||
(update :geometry-child conjv {:type :rotation
|
||||
:center center
|
||||
:rotation angle})))
|
||||
|
||||
(defn set-remove-children
|
||||
[modifiers shapes]
|
||||
|
@ -97,8 +122,11 @@
|
|||
[modifiers new-modifiers]
|
||||
|
||||
(cond-> modifiers
|
||||
(some? (:geometry new-modifiers))
|
||||
(update :geometry #(d/concat-vec [] % (:geometry new-modifiers)))
|
||||
(some? (:geometry-child new-modifiers))
|
||||
(update :geometry-child #(d/concat-vec [] % (:geometry-child new-modifiers)))
|
||||
|
||||
(some? (:geometry-parent new-modifiers))
|
||||
(update :geometry-parent #(d/concat-vec [] % (:geometry-parent new-modifiers)))
|
||||
|
||||
(some? (:structure-parent new-modifiers))
|
||||
(update :structure-parent #(d/concat-vec [] % (:structure-parent new-modifiers)))
|
||||
|
@ -116,6 +144,13 @@
|
|||
([vector]
|
||||
(set-move (empty-modifiers) vector)))
|
||||
|
||||
(defn move-parent
|
||||
([x y]
|
||||
(set-move-parent (empty-modifiers) (gpt/point x y)))
|
||||
|
||||
([vector]
|
||||
(set-move-parent (empty-modifiers) vector)))
|
||||
|
||||
(defn resize
|
||||
([vector origin]
|
||||
(set-resize (empty-modifiers) vector origin))
|
||||
|
@ -123,6 +158,13 @@
|
|||
([vector origin transform transform-inverse]
|
||||
(set-resize (empty-modifiers) vector origin transform transform-inverse)))
|
||||
|
||||
(defn resize-parent
|
||||
([vector origin]
|
||||
(set-resize-parent (empty-modifiers) vector origin))
|
||||
|
||||
([vector origin transform transform-inverse]
|
||||
(set-resize-parent (empty-modifiers) vector origin transform transform-inverse)))
|
||||
|
||||
(defn rotation
|
||||
[shape center angle]
|
||||
(let [shape-center (gco/center-shape shape)
|
||||
|
@ -155,32 +197,30 @@
|
|||
(set-scale-content value)))
|
||||
|
||||
(defn child-modifiers?
|
||||
[{:keys [geometry structure-child]}]
|
||||
(or (d/not-empty? geometry)
|
||||
[{:keys [geometry-child structure-child]}]
|
||||
(or (d/not-empty? geometry-child)
|
||||
(d/not-empty? structure-child)))
|
||||
|
||||
(defn select-child-modifiers
|
||||
[modifiers]
|
||||
(select-keys modifiers [:geometry :structure-child]))
|
||||
(select-keys modifiers [:geometry-child :structure-child]))
|
||||
|
||||
(defn select-child-geometry-modifiers
|
||||
[modifiers]
|
||||
(select-keys modifiers [:geometry-child]))
|
||||
|
||||
(defn select-parent-modifiers
|
||||
[modifiers]
|
||||
(select-keys modifiers [:geometry-parent :structure-parent]))
|
||||
|
||||
(defn select-structure
|
||||
[modifiers]
|
||||
(select-keys modifiers [:structure-parent]))
|
||||
|
||||
(defn add-move
|
||||
([object x y]
|
||||
(add-move object (gpt/point x y)))
|
||||
|
||||
([object vector]
|
||||
(update object :modifiers (move vector))))
|
||||
|
||||
(defn add-resize
|
||||
[object vector origin]
|
||||
(update object :modifiers (resize vector origin)))
|
||||
|
||||
(defn empty-modifiers?
|
||||
[modifiers]
|
||||
(and (empty? (:geometry modifiers))
|
||||
(and (empty? (:geometry-child modifiers))
|
||||
(empty? (:geometry-parent modifiers))
|
||||
(empty? (:structure-parent modifiers))
|
||||
(empty? (:structure-child modifiers))))
|
||||
|
||||
|
@ -253,8 +293,10 @@
|
|||
|
||||
(defn only-move?
|
||||
[modifier]
|
||||
(and (= 1 (-> modifier :geometry count))
|
||||
(= :move (-> modifier :geometry first :type))))
|
||||
(or (and (= 1 (-> modifier :geometry-child count))
|
||||
(= :move (-> modifier :geometry-child first :type)))
|
||||
(and (= 1 (-> modifier :geometry-parent count))
|
||||
(= :move (-> modifier :geometry-parent first :type)))))
|
||||
|
||||
(defn get-frame-add-children
|
||||
[modif-tree]
|
||||
|
@ -300,8 +342,11 @@
|
|||
(gmt/multiply (gmt/rotate-matrix rotation))
|
||||
(gmt/translate (gpt/negate center)))
|
||||
matrix)))]
|
||||
(->> modifiers :geometry
|
||||
(reduce apply-modifier (gmt/matrix)))))
|
||||
(let [modifiers (if (d/not-empty? (:geometry-parent modifiers))
|
||||
(d/concat-vec (:geometry-parent modifiers) (:geometry-child modifiers))
|
||||
(:geometry-child modifiers))]
|
||||
(->> modifiers
|
||||
(reduce apply-modifier (gmt/matrix))))))
|
||||
|
||||
(defn scale-text-content
|
||||
[content value]
|
||||
|
@ -357,5 +402,6 @@
|
|||
(reduce apply-modifier $ (:structure-child modifiers)))))
|
||||
|
||||
(defn has-geometry?
|
||||
[{:keys [geometry]}]
|
||||
(d/not-empty? geometry))
|
||||
[{:keys [geometry-parent geometry-child]}]
|
||||
(or (d/not-empty? geometry-parent)
|
||||
(d/not-empty? geometry-child)))
|
||||
|
|
|
@ -109,6 +109,12 @@
|
|||
(defn fill-height? [child]
|
||||
(= :fill (:layout-item-v-sizing child)))
|
||||
|
||||
(defn auto-width? [child]
|
||||
(= :auto (:layout-item-h-sizing child)))
|
||||
|
||||
(defn auto-height? [child]
|
||||
(= :auto (:layout-item-v-sizing child)))
|
||||
|
||||
(defn col?
|
||||
[{:keys [layout-flex-dir]}]
|
||||
(or (= :column layout-flex-dir) (= :reverse-column layout-flex-dir)))
|
||||
|
|
|
@ -142,8 +142,6 @@
|
|||
shape-before (assoc shape-before :modifiers modifiers)
|
||||
shape-after (gsh/transform-shape shape-before)]
|
||||
|
||||
(t/is (not= (:selrect shape-before) (:selrect shape-after)))
|
||||
|
||||
(t/is (close? (get-in shape-before [:selrect :x])
|
||||
(get-in shape-after [:selrect :x])))
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.changes :as dwc]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.data.workspace.transforms :as dwt]
|
||||
|
@ -68,7 +69,6 @@
|
|||
(rx/of (dwc/update-shapes ids #(merge % initial-grid-layout))
|
||||
(update-layout-positions ids))))))
|
||||
|
||||
|
||||
(defn remove-layout
|
||||
[ids]
|
||||
(ptk/reify ::remove-layout
|
||||
|
@ -91,6 +91,7 @@
|
|||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
parent-ids (->> ids (map #(cph/get-parent-id objects %)))]
|
||||
parent-ids (->> ids (map #(cph/get-parent-id objects %)))
|
||||
layout-ids (->> ids (filter (comp ctl/layout? (d/getf objects))))]
|
||||
(rx/of (dwc/update-shapes ids #(d/deep-merge (or % {}) changes))
|
||||
(update-layout-positions parent-ids))))))
|
||||
(update-layout-positions (d/concat-vec layout-ids parent-ids)))))))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.data.macros :as dm]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.store :as st]
|
||||
[okulary.core :as l]))
|
||||
|
@ -442,7 +443,7 @@
|
|||
(l/derived
|
||||
(fn [objects]
|
||||
(->> ids
|
||||
(some #(-> (cph/get-parent objects %) :layout))))
|
||||
(some #(-> (cph/get-parent objects %) ctl/layout?))))
|
||||
workspace-page-objects))
|
||||
|
||||
(defn get-flex-child-viewer?
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
(mf/defc element-behavior
|
||||
[{:keys [is-layout-container? is-layout-child? layout-item-h-sizing layout-item-v-sizing on-change-behavior] :as props}]
|
||||
(let [fill? is-layout-child?
|
||||
auto? is-layout-container?]
|
||||
auto? is-layout-container?]
|
||||
|
||||
[:div.btn-wrapper
|
||||
[:div.layout-behavior.horizontal
|
||||
|
@ -98,7 +98,7 @@
|
|||
(when auto?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Fit content"
|
||||
:class (dom/classnames :active (= layout-item-v-sizing :auto))
|
||||
:class (dom/classnames :active (= layout-item-h-sizing :auto))
|
||||
:on-click #(on-change-behavior :h :auto)}
|
||||
i/auto-hug])]
|
||||
|
||||
|
@ -188,9 +188,11 @@
|
|||
:on-change-behavior on-change-behavior}]]
|
||||
|
||||
|
||||
[:& margin-section {:values values
|
||||
:change-margin-style change-margin-style
|
||||
:on-margin-change on-margin-change}]
|
||||
(when is-layout-child?
|
||||
[:& margin-section {:values values
|
||||
:change-margin-style change-margin-style
|
||||
:on-margin-change on-margin-change}])
|
||||
|
||||
[:div.advanced-ops-container
|
||||
[:button.advanced-ops.toltip.tooltip-bottom
|
||||
{:on-click toggle-open
|
||||
|
@ -200,12 +202,13 @@
|
|||
|
||||
(when @open?
|
||||
[:div.advanced-ops-body
|
||||
[:div.layout-row
|
||||
[:div.direction-wrap.row-title "Align"]
|
||||
[:div.btn-wrapper
|
||||
[:& align-self-row {:is-col? is-col?
|
||||
:align-self align-self
|
||||
:set-align-self set-align-self}]]]
|
||||
(when is-layout-child?
|
||||
[:div.layout-row
|
||||
[:div.direction-wrap.row-title "Align"]
|
||||
[:div.btn-wrapper
|
||||
[:& align-self-row {:is-col? is-col?
|
||||
:align-self align-self
|
||||
:set-align-self set-align-self}]]])
|
||||
[:div.input-wrapper
|
||||
(for [item [:layout-item-max-h :layout-item-min-h :layout-item-max-w :layout-item-min-w]]
|
||||
[:div.tooltip.tooltip-bottom
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.main.ui.workspace.sidebar.options.shapes.frame
|
||||
(:require
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
|
||||
|
@ -35,7 +36,8 @@
|
|||
layout-item-values (select-keys shape layout-item-attrs)
|
||||
|
||||
is-layout-child-ref (mf/use-memo (mf/deps ids) #(refs/is-layout-child? ids))
|
||||
is-layout-child? (mf/deref is-layout-child-ref)]
|
||||
is-layout-child? (mf/deref is-layout-child-ref)
|
||||
is-layout-container? (ctl/layout? shape)]
|
||||
[:*
|
||||
[:& measures-menu {:ids [(:id shape)]
|
||||
:values measure-values
|
||||
|
@ -43,18 +45,17 @@
|
|||
:shape shape}]
|
||||
[:& constraints-menu {:ids ids
|
||||
:values constraint-values}]
|
||||
(when layout-active?
|
||||
[:*
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values}]
|
||||
(when (or layout-active? is-layout-container?)
|
||||
[:& layout-container-menu {:type type :ids [(:id shape)] :values layout-container-values}])
|
||||
|
||||
(when is-layout-child?
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? is-layout-child?
|
||||
:is-layout-container? (:layout shape)
|
||||
:shape shape}])])
|
||||
(when (and layout-active? (or is-layout-child? is-layout-container?))
|
||||
[:& layout-item-menu
|
||||
{:ids ids
|
||||
:type type
|
||||
:values layout-item-values
|
||||
:is-layout-child? is-layout-child?
|
||||
:is-layout-container? is-layout-container?
|
||||
:shape shape}])
|
||||
|
||||
[:& layer-menu {:ids ids
|
||||
:type type
|
||||
|
|
Loading…
Add table
Reference in a new issue