0
Fork 0
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:
alonso.torres 2022-11-02 14:14:22 +01:00
parent 0274567d83
commit 7f0054959f
17 changed files with 448 additions and 169 deletions

View file

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

View file

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

View file

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

View 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 $))))

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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