mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 19:28:12 +00:00
Merge pull request #3688 from penpot/alotor-grid-codegenn
Grid area attributes for html generation
This commit is contained in:
commit
e7f05f2efc
@ -237,6 +237,36 @@
|
||||
(persistent! (reduce dissoc! (transient data) keys))
|
||||
(reduce dissoc data keys)))
|
||||
|
||||
(defn patch-object
|
||||
"Changes is some attributes that need to change in object.
|
||||
When the attribute is nil it will be removed.
|
||||
|
||||
For example
|
||||
- object: {:a 1 :b {:foo 1 :bar 2} :c 10}
|
||||
- changes: {:a 2 :b {:foo nil :k 3}}
|
||||
- result: {:a 2 :b {:bar 2 :k 3} :c 10}
|
||||
"
|
||||
([changes]
|
||||
#(patch-object % changes))
|
||||
|
||||
([object changes]
|
||||
(->> changes
|
||||
(reduce-kv
|
||||
(fn [object key value]
|
||||
(cond
|
||||
(map? value)
|
||||
(update object key patch-object value)
|
||||
|
||||
(and (nil? value) (record? object))
|
||||
(assoc object key nil)
|
||||
|
||||
(nil? value)
|
||||
(dissoc object key value)
|
||||
|
||||
:else
|
||||
(assoc object key value)))
|
||||
object))))
|
||||
|
||||
(defn remove-at-index
|
||||
"Takes a vector and returns a vector with an element in the
|
||||
specified index removed."
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
[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.layout-data :as fld]
|
||||
[app.common.geom.shapes.flex-layout.modifiers :as fmo]))
|
||||
|
||||
(dm/export fbo/layout-content-bounds)
|
||||
@ -17,6 +17,5 @@
|
||||
(dm/export fbo/child-layout-bound-points)
|
||||
(dm/export fdr/get-drop-index)
|
||||
(dm/export fdr/get-drop-areas)
|
||||
(dm/export fli/calc-layout-data)
|
||||
(dm/export fld/calc-layout-data)
|
||||
(dm/export fmo/layout-child-modifiers)
|
||||
|
||||
|
||||
@ -11,9 +11,23 @@
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
;; Setted in app.common.geom.shapes.common-layout
|
||||
;; We do it this way because circular dependencies
|
||||
(def -child-min-width nil)
|
||||
|
||||
(defn child-min-width
|
||||
[child child-bounds bounds objects]
|
||||
(-child-min-width child child-bounds bounds objects))
|
||||
|
||||
(def -child-min-height nil)
|
||||
|
||||
(defn child-min-height
|
||||
[child child-bounds bounds objects]
|
||||
(-child-min-height child child-bounds bounds objects))
|
||||
|
||||
(defn child-layout-bound-points
|
||||
"Returns the bounds of the children as points"
|
||||
[parent child parent-bounds child-bounds]
|
||||
[parent child parent-bounds child-bounds correct-v bounds objects]
|
||||
|
||||
(let [row? (ctl/row? parent)
|
||||
col? (ctl/col? parent)
|
||||
@ -28,21 +42,13 @@
|
||||
h-center? (ctl/h-center? parent)
|
||||
h-end? (ctl/h-end? parent)
|
||||
|
||||
fill-w? (ctl/fill-width? child)
|
||||
fill-h? (ctl/fill-height? child)
|
||||
|
||||
base-p (gpo/origin child-bounds)
|
||||
|
||||
width (gpo/width-points child-bounds)
|
||||
height (gpo/height-points child-bounds)
|
||||
|
||||
min-width (if fill-w?
|
||||
(ctl/child-min-width child)
|
||||
width)
|
||||
|
||||
min-height (if fill-h?
|
||||
(ctl/child-min-height child)
|
||||
height)
|
||||
min-width (child-min-width child child-bounds bounds objects)
|
||||
min-height (child-min-height child child-bounds bounds objects)
|
||||
|
||||
;; This is the leftmost (when row) or topmost (when col) point
|
||||
;; Will be added always to the bounds and then calculated the other limits
|
||||
@ -62,67 +68,85 @@
|
||||
|
||||
;; We need some height/width to calculate the bounds. We stablish the minimum
|
||||
min-width (max min-width 0.01)
|
||||
min-height (max min-height 0.01)]
|
||||
min-height (max min-height 0.01)
|
||||
|
||||
(cond-> [base-p
|
||||
(gpt/add base-p (hv 0.01))
|
||||
(gpt/add base-p (vv 0.01))]
|
||||
base-p (gpt/add base-p correct-v)
|
||||
|
||||
col?
|
||||
(conj (gpt/add base-p (vv min-height)))
|
||||
result
|
||||
(cond-> [base-p
|
||||
(gpt/add base-p (hv 0.01))
|
||||
(gpt/add base-p (vv 0.01))]
|
||||
|
||||
row?
|
||||
(conj (gpt/add base-p (hv min-width)))
|
||||
col?
|
||||
(conj (gpt/add base-p (vv min-height)))
|
||||
|
||||
(and col? h-start?)
|
||||
(conj (gpt/add base-p (hv min-width)))
|
||||
row?
|
||||
(conj (gpt/add base-p (hv min-width)))
|
||||
|
||||
(and col? h-center?)
|
||||
(conj (gpt/add base-p (hv (/ min-width 2)))
|
||||
(gpt/subtract base-p (hv (/ min-width 2))))
|
||||
(and col? h-start?)
|
||||
(conj (gpt/add base-p (hv min-width)))
|
||||
|
||||
(and col? h-end?)
|
||||
(conj (gpt/subtract base-p (hv min-width)))
|
||||
(and col? h-center?)
|
||||
(conj (gpt/add base-p (hv (/ min-width 2)))
|
||||
(gpt/subtract base-p (hv (/ min-width 2))))
|
||||
|
||||
(and row? v-start?)
|
||||
(conj (gpt/add base-p (vv min-height)))
|
||||
(and col? h-end?)
|
||||
(conj (gpt/subtract base-p (hv min-width)))
|
||||
|
||||
(and row? v-center?)
|
||||
(conj (gpt/add base-p (vv (/ min-height 2)))
|
||||
(gpt/subtract base-p (vv (/ min-height 2))))
|
||||
(and row? v-start?)
|
||||
(conj (gpt/add base-p (vv min-height)))
|
||||
|
||||
(and row? v-end?)
|
||||
(conj (gpt/subtract base-p (vv min-height))))))
|
||||
(and row? v-center?)
|
||||
(conj (gpt/add base-p (vv (/ min-height 2)))
|
||||
(gpt/subtract base-p (vv (/ min-height 2))))
|
||||
|
||||
(and row? v-end?)
|
||||
(conj (gpt/subtract base-p (vv min-height))))
|
||||
|
||||
correct-v
|
||||
(cond-> correct-v
|
||||
(and row? (ctl/fill-width? child))
|
||||
(gpt/subtract (hv (+ width min-width)))
|
||||
|
||||
(and col? (ctl/fill-height? child))
|
||||
(gpt/subtract (vv (+ height min-height)))
|
||||
)]
|
||||
[result correct-v]))
|
||||
|
||||
(defn layout-content-points
|
||||
[bounds parent children]
|
||||
[bounds parent children objects]
|
||||
|
||||
(let [parent-id (:id parent)
|
||||
parent-bounds @(get bounds parent-id)
|
||||
get-child-bounds
|
||||
(fn [child]
|
||||
(fn [[result correct-v] child]
|
||||
(let [child-id (:id child)
|
||||
child-bounds @(get bounds child-id)
|
||||
child-bounds @(get bounds child-id)
|
||||
[margin-top margin-right margin-bottom margin-left] (ctl/child-margins child)
|
||||
|
||||
child-bounds
|
||||
[child-bounds correct-v]
|
||||
(if (or (ctl/fill-width? child) (ctl/fill-height? child))
|
||||
(child-layout-bound-points parent child parent-bounds child-bounds)
|
||||
child-bounds)
|
||||
(child-layout-bound-points parent child parent-bounds child-bounds correct-v bounds objects)
|
||||
[(->> child-bounds (map #(gpt/add % correct-v))) correct-v])
|
||||
|
||||
child-bounds
|
||||
(when (d/not-empty? child-bounds)
|
||||
(-> (gpo/parent-coords-bounds child-bounds parent-bounds)
|
||||
(gpo/pad-points (- margin-top) (- margin-right) (- margin-bottom) (- margin-left))))]
|
||||
|
||||
child-bounds))]
|
||||
[(cond-> result (some? child-bounds) (conj child-bounds))
|
||||
correct-v]))
|
||||
|
||||
reverse? (ctl/reverse? parent)
|
||||
children (cond->> children (not reverse?) reverse)]
|
||||
|
||||
(->> children
|
||||
(remove ctl/layout-absolute?)
|
||||
(map get-child-bounds))))
|
||||
(reduce get-child-bounds [[] (gpt/point 0)])
|
||||
(first))))
|
||||
|
||||
(defn layout-content-bounds
|
||||
[bounds {:keys [layout-padding] :as parent} children]
|
||||
[bounds {:keys [layout-padding] :as parent} children objects]
|
||||
|
||||
(let [parent-id (:id parent)
|
||||
parent-bounds @(get bounds parent-id)
|
||||
@ -153,7 +177,7 @@
|
||||
pad-left (+ (or pad-left 0) col-pad)
|
||||
|
||||
layout-points
|
||||
(layout-content-points bounds parent children)]
|
||||
(layout-content-points bounds parent children objects)]
|
||||
|
||||
(if (d/not-empty? layout-points)
|
||||
(-> layout-points
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.rect :as grc]
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.flex-layout.lines :as fli]
|
||||
[app.common.geom.shapes.flex-layout.layout-data :as fld]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
[app.common.pages.helpers :as cph]
|
||||
@ -197,21 +197,22 @@
|
||||
[shape nil]))
|
||||
|
||||
(defn get-drop-areas
|
||||
[frame objects]
|
||||
[frame objects bounds]
|
||||
(let [[frame modifiers] (get-flip-modifiers frame)
|
||||
children (->> (cph/get-immediate-children objects (:id frame))
|
||||
(remove :hidden)
|
||||
(map #(cond-> % (some? modifiers)
|
||||
(gtr/transform-shape modifiers)))
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points frame)) %)))
|
||||
layout-data (fli/calc-layout-data frame children (:points frame))
|
||||
layout-data (fld/calc-layout-data frame (:points frame) children bounds objects)
|
||||
drop-areas (layout-drop-areas frame layout-data children)]
|
||||
drop-areas))
|
||||
|
||||
(defn get-drop-index
|
||||
[frame-id objects position]
|
||||
(let [frame (get objects frame-id)
|
||||
drop-areas (get-drop-areas frame objects)
|
||||
bounds (d/lazy-map (keys objects) #(gco/shape->points (get objects %)))
|
||||
drop-areas (get-drop-areas frame objects bounds)
|
||||
position (gmt/transform-point-center position (gco/shape->center frame) (:transform-inverse frame))
|
||||
area (d/seek #(grc/contains-point? % position) drop-areas)]
|
||||
(:index area)))
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
(ns app.common.geom.shapes.flex-layout.lines
|
||||
(ns app.common.geom.shapes.flex-layout.layout-data
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes.flex-layout.positions :as flp]
|
||||
@ -14,6 +14,20 @@
|
||||
|
||||
(def conjv (fnil conj []))
|
||||
|
||||
;; Setted in app.common.geom.shapes.common-layout
|
||||
;; We do it this way because circular dependencies
|
||||
(def -child-min-width nil)
|
||||
|
||||
(defn child-min-width
|
||||
[child child-bounds bounds objects]
|
||||
(-child-min-width child child-bounds bounds objects))
|
||||
|
||||
(def -child-min-height nil)
|
||||
|
||||
(defn child-min-height
|
||||
[child child-bounds bounds objects]
|
||||
(-child-min-height child child-bounds bounds objects))
|
||||
|
||||
(defn layout-bounds
|
||||
[parent shape-bounds]
|
||||
(let [[pad-top pad-right pad-bottom pad-left] (ctl/paddings parent)]
|
||||
@ -21,16 +35,17 @@
|
||||
|
||||
(defn init-layout-lines
|
||||
"Calculates the lines basic data and accumulated values. The positions will be calculated in a different operation"
|
||||
[shape children layout-bounds]
|
||||
[shape children layout-bounds bounds objects auto?]
|
||||
|
||||
(let [col? (ctl/col? shape)
|
||||
row? (ctl/row? shape)
|
||||
space-around? (ctl/space-around? shape)
|
||||
space-evenly? (ctl/space-evenly? shape)
|
||||
|
||||
wrap? (and (ctl/wrap? shape)
|
||||
(or col? (not (ctl/auto-width? shape)))
|
||||
(or row? (not (ctl/auto-height? shape))))
|
||||
auto-width? (or (ctl/auto-width? shape) auto?)
|
||||
auto-height? (or (ctl/auto-height? shape) auto?)
|
||||
|
||||
wrap? (and (ctl/wrap? shape) (or col? (not auto-width?)) (or row? (not auto-height?)))
|
||||
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
|
||||
@ -52,8 +67,6 @@
|
||||
|
||||
child-width (gpo/width-points child-bounds)
|
||||
child-height (gpo/height-points child-bounds)
|
||||
child-min-width (ctl/child-min-width child)
|
||||
child-min-height (ctl/child-min-height child)
|
||||
child-max-width (ctl/child-max-width child)
|
||||
child-max-height (ctl/child-max-height child)
|
||||
|
||||
@ -68,15 +81,15 @@
|
||||
|
||||
;; We need this info later to calculate the child resizes when fill
|
||||
child-data {:id (:id child)
|
||||
:child-min-width (if fill-width? child-min-width child-width)
|
||||
:child-min-height (if fill-height? child-min-height child-height)
|
||||
:child-min-width (child-min-width child child-bounds bounds objects)
|
||||
:child-min-height (child-min-height child child-bounds bounds objects)
|
||||
:child-max-width (if fill-width? child-max-width child-width)
|
||||
:child-max-height (if fill-height? child-max-height child-height)}
|
||||
|
||||
next-min-width (+ child-margin-width (if fill-width? child-min-width child-width))
|
||||
next-min-height (+ child-margin-height (if fill-height? child-min-height child-height))
|
||||
next-max-width (+ child-margin-width (if fill-width? child-max-width child-width))
|
||||
next-max-height (+ child-margin-height (if fill-height? child-max-height child-height))
|
||||
next-min-width (+ child-margin-width (:child-min-width child-data))
|
||||
next-min-height (+ child-margin-height (:child-min-height child-data))
|
||||
next-max-width (+ child-margin-width (:child-max-width child-data))
|
||||
next-max-height (+ child-margin-height (:child-max-height child-data))
|
||||
|
||||
total-gap-col (cond
|
||||
space-evenly?
|
||||
@ -160,11 +173,11 @@
|
||||
(recur remainder items))))))
|
||||
|
||||
(defn add-lines-positions
|
||||
[parent layout-bounds layout-lines]
|
||||
[parent layout-bounds auto? layout-lines]
|
||||
(let [row? (ctl/row? parent)
|
||||
col? (ctl/col? parent)
|
||||
auto-width? (ctl/auto-width? parent)
|
||||
auto-height? (ctl/auto-height? parent)
|
||||
auto-width? (or (ctl/auto-width? parent) auto?)
|
||||
auto-height? (or (ctl/auto-height? parent) auto?)
|
||||
space-evenly? (ctl/space-evenly? parent)
|
||||
space-around? (ctl/space-around? parent)
|
||||
|
||||
@ -178,7 +191,7 @@
|
||||
[(+ total-width line-width) (+ total-height line-height)])
|
||||
|
||||
(add-ranges [[total-min-width total-min-height total-max-width total-max-height]
|
||||
{:keys [line-min-width line-min-height line-max-width line-max-height]}]
|
||||
{:keys [line-min-width line-min-height line-max-width line-max-height]}]
|
||||
[(+ total-min-width line-min-width)
|
||||
(+ total-min-height line-min-height)
|
||||
(+ total-max-width line-max-width)
|
||||
@ -238,32 +251,32 @@
|
||||
(cond->> layout-lines
|
||||
row?
|
||||
(map #(assoc % :line-width
|
||||
(if (ctl/auto-width? parent)
|
||||
(if auto-width?
|
||||
(:line-min-width %)
|
||||
(max (:line-min-width %) (min (get-layout-width %) (:line-max-width %))))))
|
||||
|
||||
col?
|
||||
(map #(assoc % :line-height
|
||||
(if (ctl/auto-height? parent)
|
||||
(if auto-height?
|
||||
(:line-min-height %)
|
||||
(max (:line-min-height %) (min (get-layout-height %) (:line-max-height %))))))
|
||||
|
||||
(and row? (or (>= total-min-height rest-layout-height) (ctl/auto-height? parent)))
|
||||
(and row? (or (>= total-min-height rest-layout-height) auto-height?))
|
||||
(map #(assoc % :line-height (:line-min-height %)))
|
||||
|
||||
(and row? (<= total-max-height rest-layout-height) (not (ctl/auto-height? parent)))
|
||||
(and row? (<= total-max-height rest-layout-height) (not auto-height?))
|
||||
(map #(assoc % :line-height (+ (:line-max-height %) stretch-height-fix)))
|
||||
|
||||
(and row? (< total-min-height rest-layout-height total-max-height) (not (ctl/auto-height? parent)))
|
||||
(and row? (< total-min-height rest-layout-height total-max-height) (not auto-height?))
|
||||
(distribute-space :line-height :line-min-height :line-max-height total-min-height rest-layout-height)
|
||||
|
||||
(and col? (or (>= total-min-width rest-layout-width) (ctl/auto-width? parent)))
|
||||
(and col? (or (>= total-min-width rest-layout-width) auto-width?))
|
||||
(map #(assoc % :line-width (:line-min-width %)))
|
||||
|
||||
(and col? (<= total-max-width rest-layout-width) (not (ctl/auto-width? parent)))
|
||||
(and col? (<= total-max-width rest-layout-width) (not auto-width?))
|
||||
(map #(assoc % :line-width (+ (:line-max-width %) stretch-width-fix)))
|
||||
|
||||
(and col? (< total-min-width rest-layout-width total-max-width) (not (ctl/auto-width? parent)))
|
||||
(and col? (< total-min-width rest-layout-width total-max-width) (not auto-width?))
|
||||
(distribute-space :line-width :line-min-width :line-max-width total-min-width rest-layout-width))
|
||||
|
||||
;; Add information to limit the growth of width: 100% shapes to the bounds of the layout
|
||||
@ -298,15 +311,15 @@
|
||||
|
||||
(defn add-line-spacing
|
||||
"Calculates the baseline for a flex layout"
|
||||
[shape layout-bounds {:keys [num-children line-width line-height] :as line-data}]
|
||||
[shape layout-bounds auto? {:keys [num-children line-width line-height] :as line-data}]
|
||||
|
||||
(let [width (gpo/width-points layout-bounds)
|
||||
height (gpo/height-points layout-bounds)
|
||||
|
||||
row? (ctl/row? shape)
|
||||
col? (ctl/col? shape)
|
||||
auto-height? (ctl/auto-height? shape)
|
||||
auto-width? (ctl/auto-width? shape)
|
||||
auto-height? (or (ctl/auto-height? shape) auto?)
|
||||
auto-width? (or (ctl/auto-width? shape) auto?)
|
||||
space-between? (ctl/space-between? shape)
|
||||
space-evenly? (ctl/space-evenly? shape)
|
||||
space-around? (ctl/space-around? shape)
|
||||
@ -402,22 +415,25 @@
|
||||
|
||||
(defn calc-layout-data
|
||||
"Digest the layout data to pass it to the constrains"
|
||||
[shape children shape-bounds]
|
||||
([shape shape-bounds children bounds objects]
|
||||
(calc-layout-data shape shape-bounds children bounds objects false))
|
||||
|
||||
(let [layout-bounds (layout-bounds shape shape-bounds)
|
||||
reverse? (ctl/reverse? shape)
|
||||
children (cond->> children (not reverse?) reverse)
|
||||
([shape shape-bounds children bounds objects auto?]
|
||||
|
||||
;; Don't take into account absolute children
|
||||
children (->> children (remove (comp ctl/layout-absolute? second)))
|
||||
(let [layout-bounds (layout-bounds shape shape-bounds)
|
||||
reverse? (ctl/reverse? shape)
|
||||
children (cond->> children (not reverse?) reverse)
|
||||
|
||||
;; Creates the layout lines information
|
||||
layout-lines
|
||||
(->> (init-layout-lines shape children layout-bounds)
|
||||
(add-lines-positions shape layout-bounds)
|
||||
(into [] (comp (map (partial add-line-spacing shape layout-bounds))
|
||||
(map (partial add-children-resizes shape)))))]
|
||||
;; Don't take into account absolute children
|
||||
children (->> children (remove (comp ctl/layout-absolute? second)))
|
||||
|
||||
{:layout-lines layout-lines
|
||||
:layout-bounds layout-bounds
|
||||
:reverse? reverse?}))
|
||||
;; Creates the layout lines information
|
||||
layout-lines
|
||||
(->> (init-layout-lines shape children layout-bounds bounds objects auto?)
|
||||
(add-lines-positions shape layout-bounds auto?)
|
||||
(into [] (comp (map (partial add-line-spacing shape layout-bounds auto?))
|
||||
(map (partial add-children-resizes shape)))))]
|
||||
|
||||
{:layout-lines layout-lines
|
||||
:layout-bounds layout-bounds
|
||||
:reverse? reverse?})))
|
||||
@ -34,7 +34,8 @@
|
||||
(let [line-width (min line-width (or to-bound-width line-width))
|
||||
target-width (max (- line-width (ctl/child-width-margin child)) 0.01)
|
||||
max-width (max (ctl/child-max-width child) 0.01)
|
||||
target-width (mth/clamp target-width (ctl/child-min-width child) max-width)
|
||||
child-min-width (get-in children-data [(:id child) :child-min-width])
|
||||
target-width (mth/clamp target-width child-min-width max-width)
|
||||
fill-scale (/ target-width child-width)]
|
||||
{:width target-width
|
||||
:modifiers (ctm/resize-modifiers (gpt/point fill-scale 1) child-origin transform transform-inverse)})))
|
||||
@ -58,7 +59,8 @@
|
||||
(let [line-height (min line-height (or to-bound-height line-height))
|
||||
target-height (max (- line-height (ctl/child-height-margin child)) 0.01)
|
||||
max-height (max (ctl/child-max-height child) 0.01)
|
||||
target-height (mth/clamp target-height (ctl/child-min-height child) max-height)
|
||||
child-min-height (get-in children-data [(:id child) :child-min-height])
|
||||
target-height (mth/clamp target-height child-min-height max-height)
|
||||
fill-scale (/ target-height child-height)]
|
||||
{:height target-height
|
||||
:modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)})))
|
||||
|
||||
@ -8,21 +8,15 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.grid-layout.layout-data :as ld]
|
||||
[app.common.geom.shapes.points :as gpo]))
|
||||
|
||||
(defn layout-content-points
|
||||
[bounds parent children]
|
||||
[bounds parent {:keys [row-tracks column-tracks]}]
|
||||
(let [parent-id (:id parent)
|
||||
parent-bounds @(get bounds parent-id)
|
||||
|
||||
hv #(gpo/start-hv parent-bounds %)
|
||||
vv #(gpo/start-vv parent-bounds %)
|
||||
|
||||
children (->> children
|
||||
(map #(vector @(get bounds (:id %)) %)))
|
||||
|
||||
{:keys [row-tracks column-tracks]} (ld/calc-layout-data parent children parent-bounds)]
|
||||
vv #(gpo/start-vv parent-bounds %)]
|
||||
(d/concat-vec
|
||||
(->> row-tracks
|
||||
(mapcat #(vector (:start-p %)
|
||||
@ -32,7 +26,7 @@
|
||||
(gpt/add (:start-p %) (hv (:size %)))))))))
|
||||
|
||||
(defn layout-content-bounds
|
||||
[bounds {:keys [layout-padding] :as parent} children]
|
||||
[bounds {:keys [layout-padding] :as parent} layout-data]
|
||||
|
||||
(let [parent-id (:id parent)
|
||||
parent-bounds @(get bounds parent-id)
|
||||
@ -43,7 +37,7 @@
|
||||
pad-bottom (or pad-bottom 0)
|
||||
pad-left (or pad-left 0)
|
||||
|
||||
layout-points (layout-content-points bounds parent children)]
|
||||
layout-points (layout-content-points bounds parent layout-data)]
|
||||
|
||||
(if (d/not-empty? layout-points)
|
||||
(-> layout-points
|
||||
|
||||
@ -55,25 +55,25 @@
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
;; Setted in app.common.geom.shapes.common-layout
|
||||
;; We do it this way because circular dependencies
|
||||
(def -child-min-width nil)
|
||||
|
||||
(defn child-min-width
|
||||
[child child-bounds bounds objects]
|
||||
(-child-min-width child child-bounds bounds objects))
|
||||
|
||||
(def -child-min-height nil)
|
||||
|
||||
(defn child-min-height
|
||||
[child child-bounds bounds objects]
|
||||
(-child-min-height child child-bounds bounds objects))
|
||||
|
||||
(defn layout-bounds
|
||||
[parent shape-bounds]
|
||||
(let [[pad-top pad-right pad-bottom pad-left] (ctl/paddings parent)]
|
||||
(gpo/pad-points shape-bounds pad-top pad-right pad-bottom pad-left)))
|
||||
|
||||
(defn child-min-width
|
||||
[child bounds]
|
||||
(+ (if (ctl/fill-width? child)
|
||||
(ctl/child-min-width child)
|
||||
(gpo/width-points bounds))
|
||||
(ctl/child-width-margin child)))
|
||||
|
||||
(defn child-min-height
|
||||
[child bounds]
|
||||
(+ (if (ctl/fill-height? child)
|
||||
(ctl/child-min-height child)
|
||||
(gpo/height-points bounds))
|
||||
(ctl/child-height-margin child)))
|
||||
|
||||
(defn calculate-initial-track-size
|
||||
[total-value {:keys [type value] :as track}]
|
||||
|
||||
@ -91,12 +91,12 @@
|
||||
(assoc track :size size :max-size max-size)))
|
||||
|
||||
(defn set-auto-base-size
|
||||
[track-list children shape-cells type]
|
||||
[track-list children shape-cells bounds objects type]
|
||||
|
||||
(let [[prop prop-span size-fn]
|
||||
(if (= type :column)
|
||||
[:column :column-span child-min-width]
|
||||
[:row :row-span child-min-height])]
|
||||
[:column :column-span child-min-width]
|
||||
[:row :row-span child-min-height])]
|
||||
|
||||
(reduce (fn [tracks [child-bounds child-shape]]
|
||||
(let [cell (get shape-cells (:id child-shape))
|
||||
@ -105,7 +105,7 @@
|
||||
(cond-> tracks
|
||||
(and (= (get cell prop-span) 1)
|
||||
(contains? #{:flex :auto} (:type track)))
|
||||
(update-in [idx :size] max (size-fn child-shape child-bounds)))))
|
||||
(update-in [idx :size] max (size-fn child-shape child-bounds bounds objects)))))
|
||||
track-list
|
||||
children)))
|
||||
|
||||
@ -216,28 +216,29 @@
|
||||
(some? (->> tracks (d/seek #(= :flex (:type %)))))))
|
||||
|
||||
(defn size-to-allocate
|
||||
[type parent [child-bounds child] cell]
|
||||
[type parent [child-bounds child] cell bounds objects]
|
||||
(let [[row-gap column-gap] (ctl/gaps parent)
|
||||
[sfn gap prop-span]
|
||||
(if (= type :column)
|
||||
[child-min-width column-gap :column-span]
|
||||
[child-min-height row-gap :row-span])
|
||||
span (get cell prop-span)]
|
||||
(- (sfn child child-bounds) (* gap (dec span)))))
|
||||
(- (sfn child child-bounds bounds objects) (* gap (dec span)))))
|
||||
|
||||
(defn allocate-auto-tracks
|
||||
[allocations indexed-tracks to-allocate]
|
||||
(if (empty? indexed-tracks)
|
||||
allocations
|
||||
[allocations to-allocate]
|
||||
(let [[idx track] (first indexed-tracks)
|
||||
old-allocated (get allocations idx 0.01)
|
||||
auto-track? (= :auto (:type track))
|
||||
|
||||
allocated (if auto-track?
|
||||
(max old-allocated
|
||||
(/ to-allocate (count indexed-tracks))
|
||||
(:size track))
|
||||
(:size track))]
|
||||
allocated
|
||||
(if auto-track?
|
||||
(max old-allocated
|
||||
(/ to-allocate (count indexed-tracks))
|
||||
(:size track))
|
||||
(:size track))]
|
||||
(recur (cond-> allocations
|
||||
auto-track?
|
||||
(assoc idx allocated))
|
||||
@ -270,7 +271,7 @@
|
||||
fr-value))))
|
||||
|
||||
(defn set-auto-multi-span
|
||||
[parent track-list children-map shape-cells type]
|
||||
[parent track-list children-map shape-cells bounds objects type]
|
||||
|
||||
(let [[prop prop-span]
|
||||
(if (= type :column)
|
||||
@ -292,7 +293,7 @@
|
||||
to-idx (+ (dec (get cell prop)) (get cell prop-span))
|
||||
|
||||
indexed-tracks (subvec (d/enumerate track-list) from-idx to-idx)
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell)
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell bounds objects)
|
||||
|
||||
;; Remove the size and the tracks that are not allocated
|
||||
[to-allocate indexed-tracks]
|
||||
@ -304,8 +305,21 @@
|
||||
[to-allocate (conj result idx-track)]
|
||||
;; If fixed, we remove from allocate and don't add the track
|
||||
[(- to-allocate (:size track)) result]))
|
||||
[to-allocate []]))]
|
||||
(allocate-auto-tracks allocated indexed-tracks (max to-allocate 0))))
|
||||
[to-allocate []]))
|
||||
|
||||
non-assigned-indexed-tracks
|
||||
(->> indexed-tracks
|
||||
(remove (fn [[idx _]] (contains? allocated idx))))
|
||||
|
||||
;; First we try to assign into the non-assigned tracks
|
||||
[allocated to-allocate]
|
||||
(allocate-auto-tracks allocated non-assigned-indexed-tracks (max to-allocate 0))
|
||||
|
||||
;; In the second pass we use every track for the rest of the space
|
||||
[allocated _]
|
||||
(allocate-auto-tracks allocated indexed-tracks (max to-allocate 0))]
|
||||
|
||||
allocated))
|
||||
{}))
|
||||
|
||||
;; Apply the allocations to the tracks
|
||||
@ -316,7 +330,7 @@
|
||||
track-list))
|
||||
|
||||
(defn set-flex-multi-span
|
||||
[parent track-list children-map shape-cells type]
|
||||
[parent track-list children-map shape-cells bounds objects type]
|
||||
|
||||
(let [[prop prop-span]
|
||||
(if (= type :column)
|
||||
@ -337,7 +351,7 @@
|
||||
to-idx (+ (dec (get cell prop)) (get cell prop-span))
|
||||
indexed-tracks (subvec (d/enumerate track-list) from-idx to-idx)
|
||||
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell)
|
||||
to-allocate (size-to-allocate type parent (get children-map shape-id) cell bounds objects)
|
||||
|
||||
;; Remove the size and the tracks that are not allocated
|
||||
[to-allocate total-frs indexed-tracks]
|
||||
@ -375,197 +389,202 @@
|
||||
(recur (rest tracks) min-fr)))))
|
||||
|
||||
(defn calc-layout-data
|
||||
[parent children transformed-parent-bounds]
|
||||
([parent transformed-parent-bounds children bounds objects]
|
||||
(calc-layout-data parent transformed-parent-bounds children bounds objects false))
|
||||
|
||||
(let [hv #(gpo/start-hv transformed-parent-bounds %)
|
||||
vv #(gpo/start-vv transformed-parent-bounds %)
|
||||
([parent transformed-parent-bounds children bounds objects auto?]
|
||||
(let [hv #(gpo/start-hv transformed-parent-bounds %)
|
||||
vv #(gpo/start-vv transformed-parent-bounds %)
|
||||
|
||||
layout-bounds (layout-bounds parent transformed-parent-bounds)
|
||||
layout-bounds (layout-bounds parent transformed-parent-bounds)
|
||||
|
||||
bound-height (gpo/height-points layout-bounds)
|
||||
bound-width (gpo/width-points layout-bounds)
|
||||
bound-corner (gpo/origin layout-bounds)
|
||||
bound-height (gpo/height-points layout-bounds)
|
||||
bound-width (gpo/width-points layout-bounds)
|
||||
bound-corner (gpo/origin layout-bounds)
|
||||
|
||||
[row-gap column-gap] (ctl/gaps parent)
|
||||
auto-height? (ctl/auto-height? parent)
|
||||
auto-width? (ctl/auto-width? parent)
|
||||
[row-gap column-gap] (ctl/gaps parent)
|
||||
auto-height? (or (ctl/auto-height? parent) auto?)
|
||||
auto-width? (or (ctl/auto-width? parent) auto?)
|
||||
|
||||
{:keys [layout-grid-columns layout-grid-rows layout-grid-cells]} parent
|
||||
num-columns (count layout-grid-columns)
|
||||
num-rows (count layout-grid-rows)
|
||||
{:keys [layout-grid-columns layout-grid-rows layout-grid-cells]} parent
|
||||
num-columns (count layout-grid-columns)
|
||||
num-rows (count layout-grid-rows)
|
||||
|
||||
column-total-gap (* column-gap (dec num-columns))
|
||||
row-total-gap (* row-gap (dec num-rows))
|
||||
column-total-gap (* column-gap (dec num-columns))
|
||||
row-total-gap (* row-gap (dec num-rows))
|
||||
|
||||
;; Map shape->cell
|
||||
shape-cells
|
||||
(into {}
|
||||
(mapcat (fn [[_ cell]]
|
||||
(->> (:shapes cell) (map #(vector % cell)))))
|
||||
layout-grid-cells)
|
||||
;; Map shape->cell
|
||||
shape-cells
|
||||
(into {}
|
||||
(mapcat (fn [[_ cell]]
|
||||
(->> (:shapes cell) (map #(vector % cell)))))
|
||||
layout-grid-cells)
|
||||
|
||||
children (->> children (remove #(ctl/layout-absolute? (second %))))
|
||||
children-map
|
||||
(into {}
|
||||
(map #(vector (:id (second %)) %))
|
||||
children)
|
||||
children
|
||||
(->> children
|
||||
(remove #(ctl/layout-absolute? (second %))))
|
||||
|
||||
;; Initialize tracks
|
||||
column-tracks
|
||||
(->> layout-grid-columns
|
||||
(mapv (partial calculate-initial-track-size bound-width)))
|
||||
children-map
|
||||
(into {}
|
||||
(map #(vector (:id (second %)) %))
|
||||
children)
|
||||
|
||||
row-tracks
|
||||
(->> layout-grid-rows
|
||||
(mapv (partial calculate-initial-track-size bound-height)))
|
||||
;; Initialize tracks
|
||||
column-tracks
|
||||
(->> layout-grid-columns
|
||||
(mapv (partial calculate-initial-track-size bound-width)))
|
||||
|
||||
;; Go through cells to adjust auto sizes for span=1. Base is the max of its children
|
||||
column-tracks (set-auto-base-size column-tracks children shape-cells :column)
|
||||
row-tracks (set-auto-base-size row-tracks children shape-cells :row)
|
||||
row-tracks
|
||||
(->> layout-grid-rows
|
||||
(mapv (partial calculate-initial-track-size bound-height)))
|
||||
|
||||
;; Adjust multi-spaned cells with no flex columns
|
||||
column-tracks (set-auto-multi-span parent column-tracks children-map shape-cells :column)
|
||||
row-tracks (set-auto-multi-span parent row-tracks children-map shape-cells :row)
|
||||
;; Go through cells to adjust auto sizes for span=1. Base is the max of its children
|
||||
column-tracks (set-auto-base-size column-tracks children shape-cells bounds objects :column)
|
||||
row-tracks (set-auto-base-size row-tracks children shape-cells bounds objects :row)
|
||||
|
||||
;; Calculate the `fr` unit and adjust the size
|
||||
column-total-size-nofr (tracks-total-size (->> column-tracks (remove #(= :flex (:type %)))))
|
||||
row-total-size-nofr (tracks-total-size (->> row-tracks (remove #(= :flex (:type %)))))
|
||||
;; Adjust multi-spaned cells with no flex columns
|
||||
column-tracks (set-auto-multi-span parent column-tracks children-map shape-cells bounds objects :column)
|
||||
row-tracks (set-auto-multi-span parent row-tracks children-map shape-cells bounds objects :row)
|
||||
|
||||
column-frs (tracks-total-frs column-tracks)
|
||||
row-frs (tracks-total-frs row-tracks)
|
||||
;; Calculate the `fr` unit and adjust the size
|
||||
column-total-size-nofr (tracks-total-size (->> column-tracks (remove #(= :flex (:type %)))))
|
||||
row-total-size-nofr (tracks-total-size (->> row-tracks (remove #(= :flex (:type %)))))
|
||||
|
||||
;; Assign minimum size to the multi-span flex tracks. We do this after calculating
|
||||
;; the fr size because will affect only the minimum. The maximum will be set by the
|
||||
;; fracion
|
||||
column-tracks (set-flex-multi-span parent column-tracks children-map shape-cells :column)
|
||||
row-tracks (set-flex-multi-span parent row-tracks children-map shape-cells :row)
|
||||
column-frs (tracks-total-frs column-tracks)
|
||||
row-frs (tracks-total-frs row-tracks)
|
||||
|
||||
;; Once auto sizes have been calculated we get calculate the `fr` unit with the remainining size and adjust the size
|
||||
free-column-space (max 0 (- bound-width (+ column-total-size-nofr column-total-gap)))
|
||||
free-row-space (max 0 (- bound-height (+ row-total-size-nofr row-total-gap)))
|
||||
;; Assign minimum size to the multi-span flex tracks. We do this after calculating
|
||||
;; the fr size because will affect only the minimum. The maximum will be set by the
|
||||
;; fracion
|
||||
column-tracks (set-flex-multi-span parent column-tracks children-map shape-cells bounds objects :column)
|
||||
row-tracks (set-flex-multi-span parent row-tracks children-map shape-cells bounds objects :row)
|
||||
|
||||
;; Get the minimum values for fr's
|
||||
min-column-fr (min-fr-value column-tracks)
|
||||
min-row-fr (min-fr-value row-tracks)
|
||||
;; Once auto sizes have been calculated we get calculate the `fr` unit with the remainining size and adjust the size
|
||||
free-column-space (max 0 (- bound-width (+ column-total-size-nofr column-total-gap)))
|
||||
free-row-space (max 0 (- bound-height (+ row-total-size-nofr row-total-gap)))
|
||||
|
||||
column-fr (if auto-width? min-column-fr (mth/finite (/ free-column-space column-frs) 0))
|
||||
row-fr (if auto-height? min-row-fr (mth/finite (/ free-row-space row-frs) 0))
|
||||
;; Get the minimum values for fr's
|
||||
min-column-fr (min-fr-value column-tracks)
|
||||
min-row-fr (min-fr-value row-tracks)
|
||||
|
||||
column-tracks (set-fr-value column-tracks column-fr auto-width?)
|
||||
row-tracks (set-fr-value row-tracks row-fr auto-height?)
|
||||
column-fr (if auto-width? min-column-fr (mth/finite (/ free-column-space column-frs) 0))
|
||||
row-fr (if auto-height? min-row-fr (mth/finite (/ free-row-space row-frs) 0))
|
||||
|
||||
;; Distribute free space between `auto` tracks
|
||||
column-total-size (tracks-total-size column-tracks)
|
||||
row-total-size (tracks-total-size row-tracks)
|
||||
column-tracks (set-fr-value column-tracks column-fr auto-width?)
|
||||
row-tracks (set-fr-value row-tracks row-fr auto-height?)
|
||||
|
||||
free-column-space (max 0 (if auto-width? 0 (- bound-width (+ column-total-size column-total-gap))))
|
||||
free-row-space (max 0 (if auto-height? 0 (- bound-height (+ row-total-size row-total-gap))))
|
||||
column-autos (tracks-total-autos column-tracks)
|
||||
row-autos (tracks-total-autos row-tracks)
|
||||
;; Distribute free space between `auto` tracks
|
||||
column-total-size (tracks-total-size column-tracks)
|
||||
row-total-size (tracks-total-size row-tracks)
|
||||
|
||||
column-add-auto (/ free-column-space column-autos)
|
||||
row-add-auto (/ free-row-space row-autos)
|
||||
free-column-space (max 0 (if auto-width? 0 (- bound-width (+ column-total-size column-total-gap))))
|
||||
free-row-space (max 0 (if auto-height? 0 (- bound-height (+ row-total-size row-total-gap))))
|
||||
column-autos (tracks-total-autos column-tracks)
|
||||
row-autos (tracks-total-autos row-tracks)
|
||||
|
||||
column-tracks (cond-> column-tracks
|
||||
(= :stretch (:layout-justify-content parent))
|
||||
(add-auto-size column-add-auto))
|
||||
column-add-auto (/ free-column-space column-autos)
|
||||
row-add-auto (/ free-row-space row-autos)
|
||||
|
||||
row-tracks (cond-> row-tracks
|
||||
(= :stretch (:layout-align-content parent))
|
||||
(add-auto-size row-add-auto))
|
||||
column-tracks (cond-> column-tracks
|
||||
(= :stretch (:layout-justify-content parent))
|
||||
(add-auto-size column-add-auto))
|
||||
|
||||
column-total-size (tracks-total-size column-tracks)
|
||||
row-total-size (tracks-total-size row-tracks)
|
||||
row-tracks (cond-> row-tracks
|
||||
(= :stretch (:layout-align-content parent))
|
||||
(add-auto-size row-add-auto))
|
||||
|
||||
num-columns (count column-tracks)
|
||||
column-gap
|
||||
(case (:layout-justify-content parent)
|
||||
auto-width?
|
||||
column-gap
|
||||
column-total-size (tracks-total-size column-tracks)
|
||||
row-total-size (tracks-total-size row-tracks)
|
||||
|
||||
:space-evenly
|
||||
(max column-gap (/ (- bound-width column-total-size) (inc num-columns)))
|
||||
num-columns (count column-tracks)
|
||||
column-gap
|
||||
(case (:layout-justify-content parent)
|
||||
auto-width?
|
||||
column-gap
|
||||
|
||||
:space-around
|
||||
(max column-gap (/ (- bound-width column-total-size) num-columns))
|
||||
:space-evenly
|
||||
(max column-gap (/ (- bound-width column-total-size) (inc num-columns)))
|
||||
|
||||
:space-between
|
||||
(max column-gap (if (= num-columns 1) column-gap (/ (- bound-width column-total-size) (dec num-columns))))
|
||||
:space-around
|
||||
(max column-gap (/ (- bound-width column-total-size) num-columns))
|
||||
|
||||
column-gap)
|
||||
:space-between
|
||||
(max column-gap (if (= num-columns 1) column-gap (/ (- bound-width column-total-size) (dec num-columns))))
|
||||
|
||||
num-rows (count row-tracks)
|
||||
row-gap
|
||||
(case (:layout-align-content parent)
|
||||
auto-height?
|
||||
row-gap
|
||||
column-gap)
|
||||
|
||||
:space-evenly
|
||||
(max row-gap (/ (- bound-height row-total-size) (inc num-rows)))
|
||||
num-rows (count row-tracks)
|
||||
row-gap
|
||||
(case (:layout-align-content parent)
|
||||
auto-height?
|
||||
row-gap
|
||||
|
||||
:space-around
|
||||
(max row-gap (/ (- bound-height row-total-size) num-rows))
|
||||
:space-evenly
|
||||
(max row-gap (/ (- bound-height row-total-size) (inc num-rows)))
|
||||
|
||||
:space-between
|
||||
(max row-gap (if (= num-rows 1) row-gap (/ (- bound-height row-total-size) (dec num-rows))))
|
||||
:space-around
|
||||
(max row-gap (/ (- bound-height row-total-size) num-rows))
|
||||
|
||||
row-gap)
|
||||
:space-between
|
||||
(max row-gap (if (= num-rows 1) row-gap (/ (- bound-height row-total-size) (dec num-rows))))
|
||||
|
||||
start-p
|
||||
(cond-> bound-corner
|
||||
(and (not auto-width?) (= :end (:layout-justify-content parent)))
|
||||
(gpt/add (hv (- bound-width (+ column-total-size column-total-gap))))
|
||||
row-gap)
|
||||
|
||||
(and (not auto-width?) (= :center (:layout-justify-content parent)))
|
||||
(gpt/add (hv (/ (- bound-width (+ column-total-size column-total-gap)) 2)))
|
||||
start-p
|
||||
(cond-> bound-corner
|
||||
(and (not auto-width?) (= :end (:layout-justify-content parent)))
|
||||
(gpt/add (hv (- bound-width (+ column-total-size column-total-gap))))
|
||||
|
||||
(and (not auto-height?) (= :end (:layout-align-content parent)))
|
||||
(gpt/add (vv (- bound-height (+ row-total-size row-total-gap))))
|
||||
(and (not auto-width?) (= :center (:layout-justify-content parent)))
|
||||
(gpt/add (hv (/ (- bound-width (+ column-total-size column-total-gap)) 2)))
|
||||
|
||||
(and (not auto-height?) (= :center (:layout-align-content parent)))
|
||||
(gpt/add (vv (/ (- bound-height (+ row-total-size row-total-gap)) 2)))
|
||||
(and (not auto-height?) (= :end (:layout-align-content parent)))
|
||||
(gpt/add (vv (- bound-height (+ row-total-size row-total-gap))))
|
||||
|
||||
(and (not auto-width?) (= :space-around (:layout-justify-content parent)))
|
||||
(gpt/add (hv (/ column-gap 2)))
|
||||
(and (not auto-height?) (= :center (:layout-align-content parent)))
|
||||
(gpt/add (vv (/ (- bound-height (+ row-total-size row-total-gap)) 2)))
|
||||
|
||||
(and (not auto-width?) (= :space-evenly (:layout-justify-content parent)))
|
||||
(gpt/add (hv column-gap))
|
||||
(and (not auto-width?) (= :space-around (:layout-justify-content parent)))
|
||||
(gpt/add (hv (/ column-gap 2)))
|
||||
|
||||
(and (not auto-height?) (= :space-around (:layout-align-content parent)))
|
||||
(gpt/add (vv (/ row-gap 2)))
|
||||
(and (not auto-width?) (= :space-evenly (:layout-justify-content parent)))
|
||||
(gpt/add (hv column-gap))
|
||||
|
||||
(and (not auto-height?) (= :space-evenly (:layout-align-content parent)))
|
||||
(gpt/add (vv row-gap)))
|
||||
(and (not auto-height?) (= :space-around (:layout-align-content parent)))
|
||||
(gpt/add (vv (/ row-gap 2)))
|
||||
|
||||
column-tracks
|
||||
(->> column-tracks
|
||||
(reduce (fn [[tracks start-p] {:keys [size] :as track}]
|
||||
[(conj tracks (assoc track :start-p start-p))
|
||||
(gpt/add start-p (hv (+ size column-gap)))])
|
||||
[[] start-p])
|
||||
(first))
|
||||
(and (not auto-height?) (= :space-evenly (:layout-align-content parent)))
|
||||
(gpt/add (vv row-gap)))
|
||||
|
||||
row-tracks
|
||||
(->> row-tracks
|
||||
(reduce (fn [[tracks start-p] {:keys [size] :as track}]
|
||||
[(conj tracks (assoc track :start-p start-p))
|
||||
(gpt/add start-p (vv (+ size row-gap)))])
|
||||
[[] start-p])
|
||||
(first))]
|
||||
column-tracks
|
||||
(->> column-tracks
|
||||
(reduce (fn [[tracks start-p] {:keys [size] :as track}]
|
||||
[(conj tracks (assoc track :start-p start-p))
|
||||
(gpt/add start-p (hv (+ size column-gap)))])
|
||||
[[] start-p])
|
||||
(first))
|
||||
|
||||
{:origin start-p
|
||||
:layout-bounds layout-bounds
|
||||
:row-tracks row-tracks
|
||||
:column-tracks column-tracks
|
||||
:shape-cells shape-cells
|
||||
:column-gap column-gap
|
||||
:row-gap row-gap
|
||||
row-tracks
|
||||
(->> row-tracks
|
||||
(reduce (fn [[tracks start-p] {:keys [size] :as track}]
|
||||
[(conj tracks (assoc track :start-p start-p))
|
||||
(gpt/add start-p (vv (+ size row-gap)))])
|
||||
[[] start-p])
|
||||
(first))]
|
||||
|
||||
;; Convenient informaton for visualization
|
||||
:column-total-size column-total-size
|
||||
:column-total-gap column-total-gap
|
||||
:row-total-size row-total-size
|
||||
:row-total-gap row-total-gap}))
|
||||
{:origin start-p
|
||||
:layout-bounds layout-bounds
|
||||
:row-tracks row-tracks
|
||||
:column-tracks column-tracks
|
||||
:shape-cells shape-cells
|
||||
:column-gap column-gap
|
||||
:row-gap row-gap
|
||||
|
||||
;; Convenient informaton for visualization
|
||||
:column-total-size column-total-size
|
||||
:column-total-gap column-total-gap
|
||||
:row-total-size row-total-size
|
||||
:row-total-gap row-total-gap})))
|
||||
|
||||
(defn get-cell-data
|
||||
[{:keys [origin row-tracks column-tracks shape-cells]} _transformed-parent-bounds [_ child]]
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.grid-layout.layout-data :as ld]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
@ -254,6 +255,8 @@
|
||||
children (->> (cph/get-immediate-children objects (:id frame))
|
||||
(remove :hidden)
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points frame)) %)))
|
||||
layout-data (ld/calc-layout-data frame children (:points frame))]
|
||||
|
||||
bounds (d/lazy-map (keys objects) #(gco/shape->points (get objects %)))
|
||||
layout-data (ld/calc-layout-data frame (:points frame) children bounds objects)]
|
||||
|
||||
(get-position-grid-coord layout-data position)))
|
||||
|
||||
79
common/src/app/common/geom/shapes/min_size_layout.cljc
Normal file
79
common/src/app/common/geom/shapes/min_size_layout.cljc
Normal file
@ -0,0 +1,79 @@
|
||||
;; 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.min-size-layout
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes.flex-layout.bounds :as fb]
|
||||
[app.common.geom.shapes.flex-layout.layout-data :as fd]
|
||||
[app.common.geom.shapes.grid-layout.bounds :as gb]
|
||||
[app.common.geom.shapes.grid-layout.layout-data :as gd]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
(defn child-min-width
|
||||
[child child-bounds bounds objects]
|
||||
(let [min-width
|
||||
(cond
|
||||
(and (ctl/fill-width? child)
|
||||
(ctl/flex-layout? child))
|
||||
(let [children (->> child :shapes (map (d/getf objects)))]
|
||||
(gpo/width-points (fb/layout-content-bounds bounds child children objects)))
|
||||
|
||||
(and (ctl/fill-width? child)
|
||||
(ctl/grid-layout? child))
|
||||
(let [children
|
||||
(->> (cph/get-immediate-children objects (:id child) {:remove-hidden true})
|
||||
(map #(vector @(get bounds (:id %)) %)))
|
||||
layout-data (gd/calc-layout-data child @(get bounds (:id child)) children bounds objects true)]
|
||||
(gpo/width-points (gb/layout-content-bounds bounds child layout-data)))
|
||||
|
||||
(ctl/fill-width? child)
|
||||
(ctl/child-min-width child)
|
||||
|
||||
:else
|
||||
(gpo/width-points child-bounds))]
|
||||
(+ min-width (ctl/child-width-margin child))))
|
||||
|
||||
(defn child-min-height
|
||||
[child child-bounds bounds objects]
|
||||
(let [min-height
|
||||
(cond
|
||||
(and (ctl/fill-height? child) (ctl/flex-layout? child))
|
||||
(gpo/height-points (fb/layout-content-bounds bounds child (->> child :shapes (map (d/getf objects))) objects))
|
||||
|
||||
(and (ctl/fill-height? child) (ctl/grid-layout? child))
|
||||
(let [children (->> child :shapes
|
||||
(map (d/getf objects))
|
||||
(map (fn [child] [@(get bounds (:id child)) child])))
|
||||
layout-data (gd/calc-layout-data child (:points child) children bounds objects true)
|
||||
auto-bounds (gb/layout-content-bounds bounds child layout-data)]
|
||||
(gpo/height-points auto-bounds))
|
||||
|
||||
(ctl/fill-height? child)
|
||||
(ctl/child-min-height child)
|
||||
|
||||
:else
|
||||
(gpo/height-points child-bounds))]
|
||||
(+ min-height (ctl/child-height-margin child))))
|
||||
|
||||
#?(:cljs
|
||||
(do (set! fd/-child-min-width child-min-width)
|
||||
(set! fd/-child-min-height child-min-height)
|
||||
(set! fb/-child-min-width child-min-width)
|
||||
(set! fb/-child-min-height child-min-height)
|
||||
(set! gd/-child-min-width child-min-width)
|
||||
(set! gd/-child-min-height child-min-height))
|
||||
|
||||
:clj
|
||||
(do (alter-var-root #'fd/-child-min-width (constantly child-min-width))
|
||||
(alter-var-root #'fd/-child-min-height (constantly child-min-height))
|
||||
(alter-var-root #'fb/-child-min-width (constantly child-min-width))
|
||||
(alter-var-root #'fb/-child-min-height (constantly child-min-height))
|
||||
(alter-var-root #'gd/-child-min-width (constantly child-min-width))
|
||||
(alter-var-root #'gd/-child-min-height (constantly child-min-height))))
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.flex-layout :as gcfl]
|
||||
[app.common.geom.shapes.grid-layout :as gcgl]
|
||||
[app.common.geom.shapes.min-size-layout]
|
||||
[app.common.geom.shapes.pixel-precision :as gpp]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
@ -181,7 +182,8 @@
|
||||
(remove :hidden)
|
||||
(remove gco/invalid-geometry?)
|
||||
(map apply-modifiers))
|
||||
layout-data (gcfl/calc-layout-data parent children @transformed-parent-bounds)
|
||||
|
||||
layout-data (gcfl/calc-layout-data parent @transformed-parent-bounds children bounds objects)
|
||||
children (into [] (cond-> children (not (:reverse? layout-data)) reverse))
|
||||
max-idx (dec (count children))
|
||||
layout-lines (:layout-lines layout-data)]
|
||||
@ -220,7 +222,7 @@
|
||||
(remove :hidden)
|
||||
(remove gco/invalid-geometry?)
|
||||
(map apply-modifiers))
|
||||
grid-data (gcgl/calc-layout-data parent children @transformed-parent-bounds)]
|
||||
grid-data (gcgl/calc-layout-data parent @transformed-parent-bounds children bounds objects)]
|
||||
(loop [modif-tree modif-tree
|
||||
bound+child (first children)
|
||||
pending (rest children)]
|
||||
@ -260,10 +262,13 @@
|
||||
(when (and (d/not-empty? children) (or (ctl/auto-height? parent) (ctl/auto-width? parent)))
|
||||
(cond
|
||||
(ctl/flex-layout? parent)
|
||||
(gcfl/layout-content-bounds bounds parent children)
|
||||
(gcfl/layout-content-bounds bounds parent children objects)
|
||||
|
||||
(ctl/grid-layout? parent)
|
||||
(gcgl/layout-content-bounds bounds parent children)))
|
||||
(let [children (->> children
|
||||
(map (fn [child] [@(get bounds (:id child)) child])))
|
||||
layout-data (gcgl/calc-layout-data parent @parent-bounds children bounds objects)]
|
||||
(gcgl/layout-content-bounds bounds parent layout-data))))
|
||||
|
||||
auto-width (when content-bounds (gpo/width-points content-bounds))
|
||||
auto-height (when content-bounds (gpo/height-points content-bounds))]
|
||||
@ -302,6 +307,8 @@
|
||||
flex-layout? (ctl/flex-layout? parent)
|
||||
grid-layout? (ctl/grid-layout? parent)
|
||||
auto? (or (ctl/auto-height? parent) (ctl/auto-width? parent))
|
||||
fill-with-grid? (and (ctl/grid-layout? objects (:parent-id parent))
|
||||
(or (ctl/fill-width? parent) (ctl/fill-height? parent)))
|
||||
parent? (or (cph/group-like-shape? parent) (cph/frame-shape? parent))
|
||||
|
||||
transformed-parent-bounds (delay (gtr/transform-bounds @(get bounds parent-id) modifiers))
|
||||
@ -328,7 +335,8 @@
|
||||
(set-grid-layout-modifiers objects bounds parent transformed-parent-bounds))
|
||||
|
||||
;; Auto-width/height can change the positions in the parent so we need to recalculate
|
||||
(cond-> autolayouts auto? (conj (:id parent)))]))
|
||||
;; also if the child is fill width/height inside a grid layout
|
||||
(cond-> autolayouts (or auto? fill-with-grid?) (conj (:id parent)))]))
|
||||
|
||||
(defn- apply-structure-modifiers
|
||||
[objects modif-tree]
|
||||
@ -410,7 +418,8 @@
|
||||
(contains? to-reflow current)
|
||||
(disj current))]
|
||||
|
||||
(if (ctm/empty? auto-resize-modifiers)
|
||||
(if (and (ctm/empty? auto-resize-modifiers)
|
||||
(not (ctl/grid-layout? objects (:parent-id parent-base))))
|
||||
(recur modif-tree
|
||||
bounds
|
||||
(rest sizing-auto-layouts)
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
@ -266,12 +267,18 @@
|
||||
(defn get-immediate-children
|
||||
"Retrieve resolved shape objects that are immediate children
|
||||
of the specified shape-id"
|
||||
([objects] (get-immediate-children objects uuid/zero))
|
||||
([objects shape-id]
|
||||
([objects] (get-immediate-children objects uuid/zero nil))
|
||||
([objects shape-id] (get-immediate-children objects shape-id nil))
|
||||
([objects shape-id {:keys [remove-hidden remove-blocked] :or {remove-hidden false remove-blocked false}}]
|
||||
(let [lookup (d/getf objects)]
|
||||
(->> (lookup shape-id)
|
||||
(:shapes)
|
||||
(keep lookup)))))
|
||||
(keep (fn [cid]
|
||||
(when-let [child (lookup cid)]
|
||||
(when (and (or (not remove-hidden) (not (:hidden child)))
|
||||
(or (not remove-blocked) (not (:blocked child))))
|
||||
child))))
|
||||
(remove gco/invalid-geometry?)))))
|
||||
|
||||
(declare indexed-shapes)
|
||||
|
||||
|
||||
@ -715,42 +715,38 @@
|
||||
[parent from-index to-index]
|
||||
(reorder-grid-track :layout-grid-rows parent from-index to-index))
|
||||
|
||||
(defn get-cells
|
||||
([parent]
|
||||
(get-cells parent nil))
|
||||
(defn cells-seq
|
||||
[{:keys [layout-grid-cells layout-grid-dir]} & {:keys [sort?] :or {sort? false}}]
|
||||
|
||||
([{:keys [layout-grid-cells layout-grid-dir]} {:keys [sort? remove-empty?] :or {sort? false remove-empty? false}}]
|
||||
(let [comp-fn (if (= layout-grid-dir :row)
|
||||
(juxt :row :column)
|
||||
(juxt :column :row))
|
||||
(let [comp-fn (if (= layout-grid-dir :row)
|
||||
(juxt :row :column)
|
||||
(juxt :column :row))
|
||||
maybe-sort?
|
||||
(if sort? (partial sort-by (comp comp-fn second)) identity)]
|
||||
|
||||
maybe-sort?
|
||||
(if sort? (partial sort-by (comp comp-fn second)) identity)
|
||||
|
||||
maybe-remove?
|
||||
(if remove-empty? (partial remove #(empty? (:shapes (second %)))) identity)]
|
||||
|
||||
(->> layout-grid-cells
|
||||
(maybe-sort?)
|
||||
(maybe-remove?)
|
||||
(map (fn [[id cell]] (assoc cell :id id)))))))
|
||||
(->> layout-grid-cells
|
||||
(maybe-sort?)
|
||||
(map second))))
|
||||
|
||||
(defn get-free-cells
|
||||
([parent]
|
||||
(get-free-cells parent nil))
|
||||
|
||||
([{:keys [layout-grid-cells layout-grid-dir]} {:keys [sort?] :or {sort? false}}]
|
||||
(let [comp-fn (if (= layout-grid-dir :row)
|
||||
(juxt :row :column)
|
||||
(juxt :column :row))
|
||||
([parent {:keys [sort?] :or {sort? false}}]
|
||||
(->> (cells-seq parent :sort? sort?)
|
||||
(filter (comp empty? :shapes))
|
||||
(map :id))))
|
||||
|
||||
maybe-sort?
|
||||
(if sort? (partial sort-by (comp comp-fn second)) identity)]
|
||||
(defn get-cells
|
||||
([parent]
|
||||
(get-cells parent nil))
|
||||
|
||||
(->> layout-grid-cells
|
||||
(filter (comp empty? :shapes second))
|
||||
(maybe-sort?)
|
||||
(map first)))))
|
||||
([parent {:keys [sort? remove-empty?] :or {sort? false remove-empty? false}}]
|
||||
(let [maybe-remove?
|
||||
(if remove-empty? (partial remove (comp empty? :shapes)) identity)]
|
||||
|
||||
(->> (cells-seq parent :sort? sort?)
|
||||
(maybe-remove?)))))
|
||||
|
||||
(defn check-deassigned-cells
|
||||
"Clean the cells whith shapes that are no longer in the layout"
|
||||
@ -782,7 +778,7 @@
|
||||
(reduce find-overlaps #{} cells)))
|
||||
|
||||
;; FIXME: This is only for development
|
||||
#_(defn fix-overlaps
|
||||
(defn fix-overlaps
|
||||
[parent overlaps]
|
||||
(reduce (fn [parent ids]
|
||||
(let [id (if (empty? (get-in parent [:layout-grid-cells (first ids)]))
|
||||
@ -792,6 +788,32 @@
|
||||
parent
|
||||
overlaps))
|
||||
|
||||
(defn position-auto-shapes
|
||||
[parent]
|
||||
;; Iterate through the cells. While auto and contains shape no changes.
|
||||
;; If auto without shape start moving auto
|
||||
;; Move shapes in auto-cells to the first free auto.
|
||||
(let [auto-cells (->> (cells-seq parent :sort? true)
|
||||
(filter #(and (= (:position %) :auto)
|
||||
(= (:row-span %) 1)
|
||||
(= (:column-span %) 1))))
|
||||
|
||||
shapes (->> auto-cells (mapcat :shapes))
|
||||
|
||||
parent
|
||||
(loop [parent parent
|
||||
cells (seq auto-cells)
|
||||
shapes (seq shapes)]
|
||||
(if (empty? cells)
|
||||
parent
|
||||
(let [shape (first shapes)
|
||||
cell (first cells)
|
||||
parent (assoc-in parent [:layout-grid-cells (:id cell) :shapes] (if (some? shape) [shape] []))]
|
||||
(recur parent
|
||||
(rest cells)
|
||||
(rest shapes)))))]
|
||||
parent))
|
||||
|
||||
;; Assign cells takes the children and move them into the allotted cells. If there are not enough cells it creates
|
||||
;; not-tracked rows/columns and put the shapes there
|
||||
;; Non-tracked tracks need to be deleted when they are empty and there are no more shapes unallocated
|
||||
@ -803,13 +825,21 @@
|
||||
;; - (maybe) create group/frames. This case will assigna a cell that had one of its children
|
||||
(defn assign-cells
|
||||
[parent]
|
||||
(let [parent (-> parent check-deassigned-cells)
|
||||
(let [;; TODO: Remove this, shouldn't be happening
|
||||
;;overlaps (overlapping-cells parent)
|
||||
;;_ (when (not (empty? overlaps))
|
||||
;; (.warn js/console "OVERLAPS" overlaps))
|
||||
parent (cond-> (check-deassigned-cells parent)
|
||||
#_(d/not-empty? overlaps)
|
||||
#_(fix-overlaps overlaps))
|
||||
|
||||
shape-has-cell?
|
||||
(into #{} (mapcat (comp :shapes second)) (:layout-grid-cells parent))
|
||||
|
||||
no-cell-shapes
|
||||
(->> (:shapes parent) (remove shape-has-cell?))]
|
||||
(->> (:shapes parent) (remove shape-has-cell?))
|
||||
|
||||
parent (position-auto-shapes parent)]
|
||||
|
||||
(if (empty? no-cell-shapes)
|
||||
;; All shapes are within a cell. No need to assign
|
||||
@ -840,9 +870,10 @@
|
||||
(reduce (fn [parent _] (add-track parent default-track-value)) parent))
|
||||
|
||||
cells
|
||||
(loop [cells (:layout-grid-cells parent)
|
||||
(loop [cells (:layout-grid-cells parent)
|
||||
free-cells (get-free-cells parent {:sort? true})
|
||||
pending no-cell-shapes]
|
||||
pending no-cell-shapes]
|
||||
|
||||
(if (or (empty? free-cells) (empty? pending))
|
||||
cells
|
||||
(let [next-free (first free-cells)
|
||||
@ -924,7 +955,8 @@
|
||||
(reduce (fn [[parent cells] [shape-id idx]]
|
||||
(let [[parent cells] (free-cell-push parent cells idx)]
|
||||
[(update-in parent [:layout-grid-cells (get-in cells [idx :id])]
|
||||
assoc :position :manual :shapes [shape-id])
|
||||
assoc :position :manual
|
||||
:shapes [shape-id])
|
||||
cells]))
|
||||
[parent cells])
|
||||
(first)))
|
||||
|
||||
@ -369,7 +369,7 @@
|
||||
(watch [_ _ _]
|
||||
(let [undo-id (js/Symbol)]
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwc/update-shapes ids #(d/deep-merge % changes))
|
||||
(dwc/update-shapes ids (d/patch-object changes))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
@ -553,14 +553,15 @@
|
||||
parent-ids (->> ids (map #(cph/get-parent-id objects %)))
|
||||
undo-id (js/Symbol)]
|
||||
(rx/of (dwu/start-undo-transaction undo-id)
|
||||
(dwc/update-shapes ids #(d/deep-merge (or % {}) changes))
|
||||
(dwc/update-shapes ids (d/patch-object changes))
|
||||
(dwc/update-shapes children-ids (partial fix-child-sizing objects changes))
|
||||
(dwc/update-shapes parent-ids
|
||||
(fn [parent]
|
||||
(-> parent
|
||||
(fix-parent-sizing objects (set ids) changes)
|
||||
(cond-> (ctl/grid-layout? parent)
|
||||
(ctl/assign-cells)))))
|
||||
(dwc/update-shapes
|
||||
parent-ids
|
||||
(fn [parent]
|
||||
(-> parent
|
||||
(fix-parent-sizing objects (set ids) changes)
|
||||
(cond-> (ctl/grid-layout? parent)
|
||||
(ctl/assign-cells)))))
|
||||
(ptk/data-event :layout/update ids)
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
@ -577,11 +578,13 @@
|
||||
[layout-id]
|
||||
(fn [shape]
|
||||
(->> ids
|
||||
(reduce (fn [shape cell-id]
|
||||
(-> shape
|
||||
(d/update-in-when [:layout-grid-cells cell-id]
|
||||
#(d/without-nils (merge % props)))))
|
||||
shape))))
|
||||
(reduce
|
||||
(fn [shape cell-id]
|
||||
(d/update-in-when
|
||||
shape
|
||||
[:layout-grid-cells cell-id]
|
||||
d/patch-object props))
|
||||
shape))))
|
||||
(ptk/data-event :layout/update [layout-id])
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
@ -598,8 +601,34 @@
|
||||
(dwc/update-shapes
|
||||
[layout-id]
|
||||
(fn [shape]
|
||||
(cond
|
||||
(= mode :area)
|
||||
(case mode
|
||||
:auto
|
||||
;; change the manual cells and move to auto
|
||||
(->> ids
|
||||
(reduce
|
||||
(fn [shape cell-id]
|
||||
(let [cell (get-in shape [:layout-grid-cells cell-id])]
|
||||
(cond-> shape
|
||||
(or (contains? #{:area :manual} (:position cell))
|
||||
(> (:row-span cell) 1)
|
||||
(> (:column-span cell) 1))
|
||||
(-> (d/update-in-when [:layout-grid-cells cell-id] assoc :shapes [] :position :auto)
|
||||
(ctl/resize-cell-area (:row cell) (:column cell) (:row cell) (:column cell) 1 1)
|
||||
(ctl/assign-cells)))))
|
||||
shape))
|
||||
|
||||
:manual
|
||||
(->> ids
|
||||
(reduce
|
||||
(fn [shape cell-id]
|
||||
(let [cell (get-in shape [:layout-grid-cells cell-id])]
|
||||
(cond-> shape
|
||||
(contains? #{:area :auto} (:position cell))
|
||||
(-> (d/assoc-in-when [:layout-grid-cells cell-id :position] :manual)
|
||||
(ctl/assign-cells)))))
|
||||
shape))
|
||||
|
||||
:area
|
||||
;; Create area with the selected cells
|
||||
(let [{:keys [first-row first-column last-row last-column]}
|
||||
(ctl/cells-coordinates (->> ids (map #(get-in shape [:layout-grid-cells %]))))
|
||||
@ -618,18 +647,7 @@
|
||||
(ctl/assign-cells))]
|
||||
|
||||
(-> shape
|
||||
(d/update-in-when [:layout-grid-cells (:id target-cell)] assoc :position :area)))
|
||||
|
||||
(= mode :auto)
|
||||
;; change the manual cells and move to auto
|
||||
(->> ids
|
||||
(reduce
|
||||
(fn [shape cell-id]
|
||||
(cond-> shape
|
||||
(contains? #{:area :manual} (get-in shape [:layout-grid-cells cell-id :position]))
|
||||
(-> (d/update-in-when [:layout-grid-cells cell-id] assoc :shapes [] :position :auto)
|
||||
(ctl/assign-cells))))
|
||||
shape)))))
|
||||
(d/update-in-when [:layout-grid-cells (:id target-cell)] assoc :position :area))))))
|
||||
(dwge/clean-selection layout-id)
|
||||
(ptk/data-event :layout/update [layout-id])
|
||||
(dwu/commit-undo-transaction undo-id))))))
|
||||
|
||||
@ -611,7 +611,9 @@
|
||||
(ctl/swap-shapes id (:id next-cell)))))
|
||||
parent))]
|
||||
(-> changes
|
||||
(pcb/update-shapes [(:id parent)] (fn [shape] (assoc shape :layout-grid-cells layout-grid-cells)))
|
||||
(pcb/update-shapes [(:id parent)] (fn [shape] (-> shape
|
||||
(assoc :layout-grid-cells layout-grid-cells)
|
||||
(ctl/assign-cells))))
|
||||
(pcb/reorder-grid-children [(:id parent)]))))
|
||||
|
||||
changes
|
||||
@ -710,7 +712,6 @@
|
||||
(defn update-position
|
||||
"Move shapes to a new position"
|
||||
[id position]
|
||||
(js/console.log "DEBUG" (pr-str position))
|
||||
(dm/assert! (uuid? id))
|
||||
|
||||
(ptk/reify ::update-position
|
||||
|
||||
@ -706,7 +706,9 @@
|
||||
wrap-blocks
|
||||
(let [block-children (->> children
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points frame)) %)))
|
||||
layout-data (gsl/calc-layout-data frame block-children (:points frame))
|
||||
bounds (d/lazy-map (keys objects) #(gsh/shape->points (get objects %)))
|
||||
|
||||
layout-data (gsl/calc-layout-data frame (:points frame) block-children bounds objects)
|
||||
layout-bounds (:layout-bounds layout-data)
|
||||
xv #(gpo/start-hv layout-bounds %)
|
||||
yv #(gpo/start-vv layout-bounds %)]
|
||||
|
||||
@ -6,13 +6,16 @@
|
||||
|
||||
(ns app.main.ui.shapes.grid-layout-viewer
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.geom.shapes.grid-layout :as gsg]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.refs :as refs]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(mf/defc grid-cell-area-label
|
||||
@ -82,14 +85,15 @@
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
childs (unchecked-get props "childs")
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
bounds (d/lazy-map (keys objects) #(gsh/shape->points (get objects %)))
|
||||
|
||||
children
|
||||
(->> childs
|
||||
(->> (cph/get-immediate-children objects (:id shape))
|
||||
(remove :hidden)
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
|
||||
|
||||
layout-data (gsg/calc-layout-data shape children (:points shape))]
|
||||
layout-data (gsg/calc-layout-data shape (:points shape) children bounds objects)]
|
||||
|
||||
[:g.cells
|
||||
(for [cell (ctl/get-cells shape {:sort? true})]
|
||||
|
||||
@ -525,6 +525,7 @@
|
||||
:on-focus #(do
|
||||
(dom/select-target %)
|
||||
(select-paddings true false true false))
|
||||
:nillable true
|
||||
:min 0
|
||||
:value p1}]]
|
||||
[:div {:class (stl/css :padding-simple)
|
||||
@ -539,6 +540,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-paddings false true false true))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value p2}]]]
|
||||
(= padding-type :multiple)
|
||||
@ -555,6 +557,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-padding :p1))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:p1 (:layout-padding values))}]]
|
||||
|
||||
@ -569,6 +572,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-padding :p2))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:p2 (:layout-padding values))}]]
|
||||
|
||||
@ -583,6 +587,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-padding :p3))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:p3 (:layout-padding values))}]]
|
||||
|
||||
@ -597,6 +602,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-padding :p4))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:p4 (:layout-padding values))}]]])]
|
||||
[:button {:class (stl/css-case :padding-toggle true
|
||||
@ -618,6 +624,7 @@
|
||||
:on-focus #(do
|
||||
(dom/select-target %)
|
||||
(select-paddings true false true false))
|
||||
:nillable true
|
||||
:min 0
|
||||
:value p1}]]
|
||||
|
||||
@ -630,6 +637,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-paddings false true false true))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value p2}]]]
|
||||
|
||||
@ -650,6 +658,7 @@
|
||||
:on-focus #(do (dom/select-target %)
|
||||
(select-padding num))
|
||||
:on-blur #(select-paddings false false false false)
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (num (:layout-padding values))}]]])])
|
||||
|
||||
@ -691,6 +700,7 @@
|
||||
:on-blur (fn [_]
|
||||
(select-gap nil)
|
||||
(reset! gap-selected? :none))
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:row-gap gap-value)
|
||||
:disabled (and (= :nowrap wrap-type) (not is-col?))}]]
|
||||
@ -710,6 +720,7 @@
|
||||
:on-blur (fn [_]
|
||||
(select-gap nil)
|
||||
(reset! gap-selected? :none))
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:column-gap gap-value)
|
||||
:disabled (and (= :nowrap wrap-type) is-col?)}]]]
|
||||
@ -731,6 +742,7 @@
|
||||
:on-blur (fn [_]
|
||||
(select-gap nil)
|
||||
(reset! gap-selected? :none))
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:column-gap gap-value)
|
||||
:disabled (and (= :nowrap wrap-type) is-col?)}]]
|
||||
@ -749,6 +761,7 @@
|
||||
:on-blur (fn [_]
|
||||
(select-gap nil)
|
||||
(reset! gap-selected? :none))
|
||||
:nillable true
|
||||
:min 0
|
||||
:value (:row-gap gap-value)
|
||||
:disabled (and (= :nowrap wrap-type) (not is-col?))}]]]])))
|
||||
|
||||
@ -45,21 +45,18 @@
|
||||
m1 (when (and (not (= :multiple (:layout-item-margin values)))
|
||||
(= (dm/get-in values [:layout-item-margin :m1])
|
||||
(dm/get-in values [:layout-item-margin :m3])))
|
||||
(dm/get-in values [:layout-item-margin :m1])
|
||||
)
|
||||
(dm/get-in values [:layout-item-margin :m1]))
|
||||
|
||||
m2 (when (and (not (= :multiple (:layout-item-margin values)))
|
||||
(= (dm/get-in values [:layout-item-margin :m2])
|
||||
(dm/get-in values [:layout-item-margin :m4])))
|
||||
(dm/get-in values [:layout-item-margin :m2])
|
||||
)
|
||||
(dm/get-in values [:layout-item-margin :m2]))
|
||||
select-margins
|
||||
(fn [m1? m2? m3? m4?]
|
||||
(st/emit! (udw/set-margins-selected {:m1 m1? :m2 m2? :m3 m3? :m4 m4?})))
|
||||
|
||||
select-margin #(select-margins (= % :m1) (= % :m2) (= % :m3) (= % :m4))]
|
||||
|
||||
|
||||
(mf/use-effect
|
||||
(fn []
|
||||
(fn []
|
||||
|
||||
@ -40,18 +40,25 @@
|
||||
(let [children (->> (cph/get-immediate-children objects (:id shape))
|
||||
(remove :hidden))
|
||||
bounds (d/lazy-map (keys objects) #(dm/get-in objects [% :points]))
|
||||
|
||||
children+bounds (->> children (map (fn [shape] [@(get bounds (:id shape)) shape])))
|
||||
|
||||
grid-layout-data
|
||||
(when (ctl/grid-layout? shape)
|
||||
(gsg/calc-layout-data shape (:points shape) children+bounds bounds objects))
|
||||
|
||||
layout-bounds
|
||||
(cond (ctl/flex-layout? shape)
|
||||
(gsl/layout-content-bounds bounds shape children)
|
||||
(gsl/layout-content-bounds bounds shape children objects)
|
||||
|
||||
(ctl/grid-layout? shape)
|
||||
(gsg/layout-content-bounds bounds shape children))
|
||||
(gsg/layout-content-bounds bounds shape grid-layout-data))
|
||||
layout-points
|
||||
(cond (ctl/flex-layout? shape)
|
||||
(flatten (gsl/layout-content-points bounds shape children))
|
||||
(flatten (gsl/layout-content-points bounds shape children objects))
|
||||
|
||||
(ctl/grid-layout? shape)
|
||||
(flatten (gsg/layout-content-points bounds shape children)))]
|
||||
(flatten (gsg/layout-content-points bounds shape grid-layout-data)))]
|
||||
|
||||
[:g.debug-layout {:pointer-events "none"}
|
||||
[:polygon {:points (->> layout-bounds (map #(dm/fmt "%, %" (:x %) (:y %))) (str/join " "))
|
||||
@ -87,7 +94,10 @@
|
||||
children (->> (cph/get-immediate-children objects (:id shape))
|
||||
(remove :hidden)
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
|
||||
layout-data (gsl/calc-layout-data shape children (:points shape))
|
||||
|
||||
bounds (d/lazy-map (keys objects) #(dm/get-in objects [% :points]))
|
||||
|
||||
layout-data (gsl/calc-layout-data shape (:points shape) children bounds objects)
|
||||
|
||||
layout-bounds (:layout-bounds layout-data)
|
||||
xv #(gpo/start-hv layout-bounds %)
|
||||
@ -121,10 +131,12 @@
|
||||
(when (and (= (count selected-shapes) 1) (= :frame (-> selected-shapes first :type)))
|
||||
(first selected-shapes))
|
||||
|
||||
shape (or selected-frame (get objects hover-top-frame-id))]
|
||||
shape (or selected-frame (get objects hover-top-frame-id))
|
||||
|
||||
bounds (d/lazy-map (keys objects) #(dm/get-in objects [% :points]))]
|
||||
|
||||
(when (and shape (:layout shape))
|
||||
(let [drop-areas (gsl/get-drop-areas shape objects)]
|
||||
(let [drop-areas (gsl/get-drop-areas shape objects bounds)]
|
||||
[:g.debug-layout {:pointer-events "none"
|
||||
:transform (gsh/transform-str shape)}
|
||||
(for [[idx drop-area] (d/enumerate drop-areas)]
|
||||
@ -184,7 +196,9 @@
|
||||
(first selected-shapes))
|
||||
|
||||
parent (or selected-frame (get objects hover-top-frame-id))
|
||||
parent-bounds (:points parent)]
|
||||
parent-bounds (:points parent)
|
||||
|
||||
bounds (d/lazy-map (keys objects) #(dm/get-in objects [% :points]))]
|
||||
|
||||
(when (and (some? parent) (not= uuid/zero (:id parent)))
|
||||
(let [children (->> (cph/get-immediate-children objects (:id parent))
|
||||
@ -200,7 +214,7 @@
|
||||
(let [child-bounds (:points child)
|
||||
points
|
||||
(if (or (ctl/fill-height? child) (ctl/fill-height? child))
|
||||
(gsl/child-layout-bound-points parent child parent-bounds child-bounds)
|
||||
(gsl/child-layout-bound-points parent child parent-bounds child-bounds bounds objects)
|
||||
child-bounds)]
|
||||
(for [point points]
|
||||
[:circle {:cx (:x point)
|
||||
@ -222,7 +236,9 @@
|
||||
(first selected-shapes))
|
||||
|
||||
parent (or selected-frame (get objects hover-top-frame-id))
|
||||
parent-bounds (:points parent)]
|
||||
parent-bounds (:points parent)
|
||||
|
||||
bounds (d/lazy-map (keys objects) #(dm/get-in objects [% :points]))]
|
||||
|
||||
(when (and (some? parent) (not= uuid/zero (:id parent)))
|
||||
(let [children (->> (cph/get-immediate-children objects (:id parent))
|
||||
@ -237,7 +253,7 @@
|
||||
origin (gpo/origin parent-bounds)
|
||||
|
||||
{:keys [row-tracks column-tracks]}
|
||||
(gsg/calc-layout-data parent children parent-bounds)]
|
||||
(gsg/calc-layout-data parent parent-bounds children bounds objects)]
|
||||
|
||||
[:*
|
||||
(for [row-data row-tracks]
|
||||
|
||||
@ -748,10 +748,10 @@
|
||||
objects (-> objects
|
||||
(gsh/apply-objects-modifiers (select-keys modifiers ids))
|
||||
(gsh/update-shapes-geometry (reverse ids)))]
|
||||
(->> (:shapes shape)
|
||||
(map (d/getf objects))
|
||||
(remove :hidden)
|
||||
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %))))))
|
||||
(->> (cph/get-immediate-children objects (:id shape))
|
||||
(keep (fn [child]
|
||||
(when-not (:hidden child)
|
||||
[(gpo/parent-coords-bounds (:points child) (:points shape)) child])))))))
|
||||
|
||||
children (hooks/use-equal-memo children)
|
||||
|
||||
@ -762,10 +762,12 @@
|
||||
height (gpo/height-points bounds)
|
||||
origin (gpo/origin bounds)
|
||||
|
||||
all-bounds (d/lazy-map (keys objects) #(gsh/shape->points (get objects %)))
|
||||
|
||||
{:keys [row-tracks column-tracks] :as layout-data}
|
||||
(mf/use-memo
|
||||
(mf/deps shape children)
|
||||
#(gsg/calc-layout-data shape children bounds))
|
||||
#(gsg/calc-layout-data shape bounds children all-bounds objects))
|
||||
|
||||
handle-pointer-down
|
||||
(mf/use-callback
|
||||
|
||||
@ -100,6 +100,7 @@ body {
|
||||
;; Grid related properties
|
||||
:grid-template-rows
|
||||
:grid-template-columns
|
||||
:grid-template-areas
|
||||
|
||||
;; Flex/grid self properties
|
||||
:flex-shrink
|
||||
@ -114,6 +115,7 @@ body {
|
||||
;; Grid cell properties
|
||||
:grid-column
|
||||
:grid-row
|
||||
:grid-area
|
||||
])
|
||||
|
||||
(def text-node-css-properties
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.ui.formats :as fmt]
|
||||
[app.util.code-gen.common :as cgc]))
|
||||
[app.util.code-gen.common :as cgc]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn fill->color
|
||||
[{:keys [fill-color fill-opacity fill-color-gradient]}]
|
||||
@ -74,9 +75,9 @@
|
||||
[_ shape objects]
|
||||
(let [parent (cph/get-parent objects (:id shape))]
|
||||
(when (and (ctl/flex-layout-immediate-child? objects shape)
|
||||
(or (and (contains? #{:row :reverse-row} (:layout-flex-dir parent))
|
||||
(or (and (contains? #{:row :row-reverse} (:layout-flex-dir parent))
|
||||
(= :fill (:layout-item-h-sizing shape)))
|
||||
(and (contains? #{:column :column-row} (:layout-flex-dir parent))
|
||||
(and (contains? #{:column :column-reverse} (:layout-flex-dir parent))
|
||||
(= :fill (:layout-item-v-sizing shape)))))
|
||||
1)))
|
||||
|
||||
@ -89,10 +90,10 @@
|
||||
(cond
|
||||
(and (ctl/flex-layout-immediate-child? objects shape)
|
||||
(or (and (= type :height)
|
||||
(contains? #{:row :reverse-row} (:layout-flex-dir parent))
|
||||
(contains? #{:row :row-reverse} (:layout-flex-dir parent))
|
||||
(= :fill (:layout-item-v-sizing shape)))
|
||||
(and (= type :width)
|
||||
(contains? #{:column :column-row} (:layout-flex-dir parent))
|
||||
(contains? #{:column :column-reverse} (:layout-flex-dir parent))
|
||||
(= :fill (:layout-item-h-sizing shape)))))
|
||||
:fill
|
||||
|
||||
@ -279,15 +280,43 @@
|
||||
[_ shape _]
|
||||
(:layout-grid-columns shape))
|
||||
|
||||
(defn area-cell?
|
||||
[{:keys [position area-name]}]
|
||||
(and (= position :area) (d/not-empty? area-name)))
|
||||
|
||||
(defmethod get-value :grid-template-areas
|
||||
[_ shape _]
|
||||
(when (and (ctl/grid-layout? shape)
|
||||
(some area-cell? (vals (:layout-grid-cells shape))))
|
||||
(let [result
|
||||
(->> (d/enumerate (:layout-grid-rows shape))
|
||||
(map
|
||||
(fn [[row _]]
|
||||
(dm/str
|
||||
"\""
|
||||
(->> (d/enumerate (:layout-grid-columns shape))
|
||||
(map (fn [[column _]]
|
||||
(let [cell (ctl/get-cell-by-position shape (inc row) (inc column))]
|
||||
(str/replace (:area-name cell ".") " " "-"))))
|
||||
(str/join " "))
|
||||
"\"")))
|
||||
(str/join "\n"))]
|
||||
result)))
|
||||
|
||||
(defn get-grid-coord
|
||||
[shape objects prop span-prop]
|
||||
(when (and (ctl/grid-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))]
|
||||
(if (> (get cell span-prop) 1)
|
||||
(dm/str (get cell prop) " / " (+ (get cell prop) (get cell span-prop)))
|
||||
(get cell prop)))))
|
||||
(when (and
|
||||
(not (and (= (:position cell) :area) (d/not-empty? (:area-name cell))))
|
||||
(or (= (:position cell) :manual)
|
||||
(> (:row-span cell) 1)
|
||||
(> (:column-span cell) 1)))
|
||||
(if (> (get cell span-prop) 1)
|
||||
(dm/str (get cell prop) " / " (+ (get cell prop) (get cell span-prop)))
|
||||
(get cell prop))))))
|
||||
|
||||
(defmethod get-value :grid-column
|
||||
[_ shape objects]
|
||||
@ -297,6 +326,15 @@
|
||||
[_ shape objects]
|
||||
(get-grid-coord shape objects :row :row-span))
|
||||
|
||||
(defmethod get-value :grid-area
|
||||
[_ shape objects]
|
||||
(when (and (ctl/grid-layout-immediate-child? objects shape)
|
||||
(not (ctl/layout-absolute? shape)))
|
||||
(let [parent (get objects (:parent-id shape))
|
||||
cell (ctl/get-cell-by-shape-id parent (:id shape))]
|
||||
(when (and (= (:position cell) :area) (d/not-empty? (:area-name cell)))
|
||||
(str/replace (:area-name cell) " " "-")))))
|
||||
|
||||
(defmethod get-value :flex-shrink
|
||||
[_ shape objects]
|
||||
(when (and (ctl/flex-layout-immediate-child? objects shape)
|
||||
@ -334,13 +372,13 @@
|
||||
(defmethod get-value :max-height
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(ctl/any-layout-immediate-child? objects shape)
|
||||
(:layout-item-max-h shape)))
|
||||
|
||||
(defmethod get-value :min-height
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(and (ctl/flex-layout-immediate-child? objects shape) (some? (:layout-item-min-h shape)))
|
||||
(and (ctl/any-layout-immediate-child? objects shape) (some? (:layout-item-min-h shape)))
|
||||
(:layout-item-min-h shape)
|
||||
|
||||
(and (ctl/auto-height? shape) (cph/frame-shape? shape) (not (:show-content shape)))
|
||||
@ -349,13 +387,13 @@
|
||||
(defmethod get-value :max-width
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(ctl/flex-layout-immediate-child? objects shape)
|
||||
(ctl/any-layout-immediate-child? objects shape)
|
||||
(:layout-item-max-w shape)))
|
||||
|
||||
(defmethod get-value :min-width
|
||||
[_ shape objects]
|
||||
(cond
|
||||
(and (ctl/flex-layout-immediate-child? objects shape) (some? (:layout-item-min-w shape)))
|
||||
(and (ctl/any-layout-immediate-child? objects shape) (some? (:layout-item-min-w shape)))
|
||||
(:layout-item-min-w shape)
|
||||
|
||||
(and (ctl/auto-width? shape) (cph/frame-shape? shape) (not (:show-content shape)))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user