0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

Align self and stretch fixes

This commit is contained in:
alonso.torres 2022-10-27 12:22:50 +02:00
parent 81d2f9dd9d
commit 503a1dabac
3 changed files with 242 additions and 219 deletions

View file

@ -7,7 +7,7 @@
(ns app.common.geom.shapes.flex-layout.lines
(:require
[app.common.data :as d]
[app.common.geom.point :as gpt]
[app.common.geom.shapes.flex-layout.positions :as flp]
[app.common.geom.shapes.points :as gpo]
[app.common.geom.shapes.transforms :as gst]
[app.common.math :as mth]
@ -104,172 +104,6 @@
(cond-> layout-lines (some? line-data) (conj line-data))))
(defn get-base-line
"Main axis line"
[parent layout-bounds total-width total-height num-lines]
(let [layout-width (gpo/width-points layout-bounds)
layout-height (gpo/height-points layout-bounds)
row? (ctl/row? parent)
col? (ctl/col? parent)
hv (partial gpo/start-hv layout-bounds)
vv (partial gpo/start-vv layout-bounds)
end? (ctl/content-end? parent)
center? (ctl/content-center? parent)
around? (ctl/content-around? parent)
;; Adjust the totals so it takes into account the gaps
[layout-gap-row layout-gap-col] (ctl/gaps parent)
lines-gap-row (* (dec num-lines) layout-gap-row)
lines-gap-col (* (dec num-lines) layout-gap-col)
free-width-gap (- layout-width total-width lines-gap-row)
free-height-gap (- layout-height total-height lines-gap-col)
free-width (- layout-width total-width)
free-height (- layout-height total-height)]
(cond-> (gpo/origin layout-bounds)
row?
(cond-> center?
(gpt/add (vv (/ free-height-gap 2)))
end?
(gpt/add (vv free-height-gap))
around?
(gpt/add (vv (/ free-height (inc num-lines)))))
col?
(cond-> center?
(gpt/add (hv (/ free-width-gap 2)))
end?
(gpt/add (hv free-width-gap))
around?
(gpt/add (hv (/ free-width (inc num-lines))))))))
(defn get-next-line
[parent layout-bounds {:keys [line-width line-height]} base-p total-width total-height num-lines]
(let [layout-width (gpo/width-points layout-bounds)
layout-height (gpo/height-points layout-bounds)
row? (ctl/row? parent)
col? (ctl/col? parent)
[layout-gap-row layout-gap-col] (ctl/gaps parent)
hv #(gpo/start-hv layout-bounds %)
vv #(gpo/start-vv layout-bounds %)
stretch? (ctl/content-stretch? parent)
between? (ctl/content-between? parent)
around? (ctl/content-around? parent)
free-width (- layout-width total-width)
free-height (- layout-height total-height)
line-gap-row (cond
stretch?
(/ free-width num-lines)
between?
(/ free-width (dec num-lines))
around?
(/ free-width (inc num-lines))
:else
layout-gap-row)
line-gap-col (cond
stretch?
(/ free-height num-lines)
between?
(/ free-height (dec num-lines))
around?
(/ free-height (inc num-lines))
:else
layout-gap-col)]
(cond-> base-p
row?
(gpt/add (vv (+ line-height (max layout-gap-col line-gap-col))))
col?
(gpt/add (hv (+ line-width (max layout-gap-row line-gap-row)))))))
(defn get-start-line
"Cross axis line. It's position is fixed along the different lines"
[parent layout-bounds {:keys [line-width line-height num-children]} base-p total-width total-height num-lines]
(let [layout-width (gpo/width-points layout-bounds)
layout-height (gpo/height-points layout-bounds)
[layout-gap-row layout-gap-col] (ctl/gaps parent)
row? (ctl/row? parent)
col? (ctl/col? parent)
space-between? (ctl/space-between? parent)
space-around? (ctl/space-around? parent)
h-center? (ctl/h-center? parent)
h-end? (ctl/h-end? parent)
v-center? (ctl/v-center? parent)
v-end? (ctl/v-end? parent)
content-stretch? (ctl/content-stretch? parent)
hv #(gpo/start-hv layout-bounds %)
vv #(gpo/start-vv layout-bounds %)
children-gap-width (* layout-gap-row (dec num-children))
children-gap-height (* layout-gap-col (dec num-children))
line-height
(if (and row? content-stretch?)
(+ line-height (/ (- layout-height total-height) num-lines))
line-height)
line-width
(if (and col? content-stretch?)
(+ line-width (/ (- layout-width total-width) num-lines))
line-width)
start-p
(cond-> base-p
;; X AXIS
(and row? h-center? (not space-around?) (not space-between?))
(-> (gpt/add (hv (/ layout-width 2)))
(gpt/subtract (hv (/ (+ line-width children-gap-width) 2))))
(and row? h-end? (not space-around?) (not space-between?))
(-> (gpt/add (hv layout-width))
(gpt/subtract (hv (+ line-width children-gap-width))))
(and col? h-center?)
(gpt/add (hv (/ line-width 2)))
(and col? h-end?)
(gpt/add (hv line-width))
;; Y AXIS
(and col? v-center? (not space-around?) (not space-between?))
(-> (gpt/add (vv (/ layout-height 2)))
(gpt/subtract (vv (/ (+ line-height children-gap-height) 2))))
(and col? v-end? (not space-around?) (not space-between?))
(-> (gpt/add (vv layout-height))
(gpt/subtract (vv (+ line-height children-gap-height))))
(and row? v-center?)
(gpt/add (vv (/ line-height 2)))
(and row? v-end?)
(gpt/add (vv line-height)))]
start-p))
(defn add-space-to-items
;; Distributes the remainder space between the lines
@ -327,8 +161,8 @@
(+ total-max-height line-max-height)])
(add-starts [total-width total-height num-lines [result base-p] layout-line]
(let [start-p (get-start-line parent layout-bounds layout-line base-p total-width total-height num-lines)
next-p (get-next-line parent layout-bounds layout-line base-p total-width total-height num-lines)]
(let [start-p (flp/get-start-line parent layout-bounds layout-line base-p total-width total-height num-lines)
next-p (flp/get-next-line parent layout-bounds layout-line base-p total-width total-height num-lines)]
[(conj result
(assoc layout-line :start-p start-p))
@ -342,6 +176,17 @@
num-lines (count layout-lines)
;; When align-items is stretch we need to adjust the main axis size to grow for the full content
stretch-width-fix
(if (and col? (ctl/content-stretch? parent))
(/ (- layout-width (* layout-gap-row (dec num-lines)) total-max-width) num-lines)
0)
stretch-height-fix
(if (and row? (ctl/content-stretch? parent))
(/ (- layout-height (* layout-gap-col (dec num-lines)) total-max-height) num-lines)
0)
;; Distributes the space between the layout lines based on its max/min constraints
layout-lines
(cond->> layout-lines
@ -355,7 +200,7 @@
(map #(assoc % :line-height (:line-min-height %)))
(and row? (<= total-max-height layout-height))
(map #(assoc % :line-height (:line-max-height %)))
(map #(assoc % :line-height (+ (:line-max-height %) stretch-height-fix)))
(and row? (< total-min-height layout-height total-max-height))
(distribute-space :line-height :line-min-height :line-max-height total-min-height (- layout-height (* (dec num-lines) layout-gap-col)))
@ -364,14 +209,14 @@
(map #(assoc % :line-width (:line-min-width %)))
(and col? (<= total-max-width layout-width))
(map #(assoc % :line-width (:line-max-width %)))
(map #(assoc % :line-width (+ (:line-max-width %) stretch-width-fix)))
(and col? (< total-min-width layout-width total-max-width))
(distribute-space :line-width :line-min-width :line-max-width total-min-width (- layout-width (* (dec num-lines) layout-gap-row))))
[total-width total-height] (->> layout-lines (reduce add-lines [0 0]))
base-p (get-base-line parent layout-bounds total-width total-height num-lines)]
base-p (flp/get-base-line parent layout-bounds total-width total-height num-lines)]
(first (reduce (partial add-starts total-width total-height num-lines) [[] base-p] layout-lines))))))

View file

@ -10,69 +10,239 @@
[app.common.geom.shapes.points :as gpo]
[app.common.types.shape.layout :as ctl]))
(defn get-base-line
[parent layout-bounds total-width total-height num-lines]
(let [layout-width (gpo/width-points layout-bounds)
layout-height (gpo/height-points layout-bounds)
row? (ctl/row? parent)
col? (ctl/col? parent)
hv (partial gpo/start-hv layout-bounds)
vv (partial gpo/start-vv layout-bounds)
end? (ctl/content-end? parent)
center? (ctl/content-center? parent)
around? (ctl/content-around? parent)
;; Adjust the totals so it takes into account the gaps
[layout-gap-row layout-gap-col] (ctl/gaps parent)
lines-gap-row (* (dec num-lines) layout-gap-row)
lines-gap-col (* (dec num-lines) layout-gap-col)
free-width-gap (- layout-width total-width lines-gap-row)
free-height-gap (- layout-height total-height lines-gap-col)
free-width (- layout-width total-width)
free-height (- layout-height total-height)]
(cond-> (gpo/origin layout-bounds)
row?
(cond-> center?
(gpt/add (vv (/ free-height-gap 2)))
end?
(gpt/add (vv free-height-gap))
around?
(gpt/add (vv (/ free-height (inc num-lines)))))
col?
(cond-> center?
(gpt/add (hv (/ free-width-gap 2)))
end?
(gpt/add (hv free-width-gap))
around?
(gpt/add (hv (/ free-width (inc num-lines))))))))
(defn get-next-line
[parent layout-bounds {:keys [line-width line-height]} base-p total-width total-height num-lines]
(let [layout-width (gpo/width-points layout-bounds)
layout-height (gpo/height-points layout-bounds)
row? (ctl/row? parent)
col? (ctl/col? parent)
[layout-gap-row layout-gap-col] (ctl/gaps parent)
hv #(gpo/start-hv layout-bounds %)
vv #(gpo/start-vv layout-bounds %)
stretch? (ctl/content-stretch? parent)
between? (ctl/content-between? parent)
around? (ctl/content-around? parent)
free-width (- layout-width total-width)
free-height (- layout-height total-height)
line-gap-row
(cond
stretch?
(/ free-width num-lines)
between?
(/ free-width (dec num-lines))
around?
(/ free-width (inc num-lines))
:else
layout-gap-row)
line-gap-col
(cond
stretch?
(/ free-height num-lines)
between?
(/ free-height (dec num-lines))
around?
(/ free-height (inc num-lines))
:else
layout-gap-col)]
(cond-> base-p
row?
(gpt/add (vv (+ line-height (max layout-gap-col line-gap-col))))
col?
(gpt/add (hv (+ line-width (max layout-gap-row line-gap-row)))))))
(defn get-start-line
"Cross axis line. It's position is fixed along the different lines"
[parent layout-bounds {:keys [line-width line-height num-children]} base-p total-width total-height num-lines]
(let [layout-width (gpo/width-points layout-bounds)
layout-height (gpo/height-points layout-bounds)
[layout-gap-row layout-gap-col] (ctl/gaps parent)
row? (ctl/row? parent)
col? (ctl/col? parent)
space-between? (ctl/space-between? parent)
space-around? (ctl/space-around? parent)
h-center? (ctl/h-center? parent)
h-end? (ctl/h-end? parent)
v-center? (ctl/v-center? parent)
v-end? (ctl/v-end? parent)
content-stretch? (ctl/content-stretch? parent)
hv #(gpo/start-hv layout-bounds %)
vv #(gpo/start-vv layout-bounds %)
children-gap-width (* layout-gap-row (dec num-children))
children-gap-height (* layout-gap-col (dec num-children))
line-height
(if (and row? content-stretch?)
(+ line-height (/ (- layout-height total-height) num-lines))
line-height)
line-width
(if (and col? content-stretch?)
(+ line-width (/ (- layout-width total-width) num-lines))
line-width)
start-p
(cond-> base-p
;; X AXIS
(and row? h-center? (not space-around?) (not space-between?))
(-> (gpt/add (hv (/ layout-width 2)))
(gpt/subtract (hv (/ (+ line-width children-gap-width) 2))))
(and row? h-end? (not space-around?) (not space-between?))
(-> (gpt/add (hv layout-width))
(gpt/subtract (hv (+ line-width children-gap-width))))
;; Y AXIS
(and col? v-center? (not space-around?) (not space-between?))
(-> (gpt/add (vv (/ layout-height 2)))
(gpt/subtract (vv (/ (+ line-height children-gap-height) 2))))
(and col? v-end? (not space-around?) (not space-between?))
(-> (gpt/add (vv layout-height))
(gpt/subtract (vv (+ line-height children-gap-height)))))]
start-p))
(defn get-child-position
"Calculates the position for the current shape given the layout-data context"
[parent child
child-width child-height
{:keys [start-p layout-gap-row layout-gap-col margin-x margin-y] :as layout-data}]
{:keys [start-p layout-gap-row layout-gap-col margin-x margin-y line-height line-width] :as layout-data}]
(let [row? (ctl/row? parent)
col? (ctl/col? parent)
(let [row? (ctl/row? parent)
col? (ctl/col? parent)
h-start? (ctl/h-start? parent)
h-center? (ctl/h-center? parent)
h-end? (ctl/h-end? 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)
v-start? (ctl/v-start? parent)
v-center? (ctl/v-center? parent)
v-end? (ctl/v-end? parent)
points (:points parent)
self-start? (ctl/align-self-start? child)
self-end? (ctl/align-self-end? child)
self-center? (ctl/align-self-center? child)
align-self? (or self-start? self-end? self-center?)
hv (partial gpo/start-hv points)
vv (partial gpo/start-vv points)
v-start? (if (or col? (not align-self?)) v-start? self-start?)
v-center? (if (or col? (not align-self?)) v-center? self-center?)
v-end? (if (or col? (not align-self?)) v-end? self-end?)
h-start? (if (or row? (not align-self?)) h-start? self-start?)
h-center? (if (or row? (not align-self?)) h-center? self-center?)
h-end? (if (or row? (not align-self?)) h-end? self-end?)
[margin-top margin-right margin-bottom margin-left] (ctl/child-margins child)
points (:points parent)
hv (partial gpo/start-hv points)
vv (partial gpo/start-vv points)
corner-p
(cond-> start-p
(and col? h-center?)
(gpt/add (hv (- (/ child-width 2))))
(and col? h-end?)
(gpt/add (hv (- child-width)))
;; COLUMN DIRECTION
col?
(gpt/add (vv margin-top))
(cond-> (some? margin-top)
(gpt/add (vv margin-top))
(and col? h-start?)
(gpt/add (hv margin-left))
h-center?
(gpt/add (hv (- (/ child-width 2))))
(and col? h-center?)
(gpt/add (hv (/ (- margin-left margin-right) 2)))
h-end?
(gpt/add (hv (- child-width)))
(and col? h-end?)
(gpt/add (hv (- margin-right)))
h-start?
(gpt/add (hv margin-left))
;; X COORD
(and row? v-center?)
(gpt/add (vv (- (/ child-height 2))))
h-center?
(gpt/add (hv (+ (/ line-width 2) (/ (- margin-left margin-right) 2))))
(and row? v-end?)
(gpt/add (vv (- child-height)))
h-end?
(gpt/add (hv (+ line-width (- margin-right)))))
;; ROW DIRECTION
row?
(gpt/add (hv margin-left))
(cond-> v-center?
(gpt/add (vv (- (/ child-height 2))))
(and row? v-start?)
(gpt/add (vv margin-top))
v-end?
(gpt/add (vv (- child-height)))
(and row? v-center?)
(gpt/add (vv (/ (- margin-top margin-bottom) 2)))
(some? margin-left)
(gpt/add (hv margin-left))
(and row? v-end?)
(gpt/add (vv (- margin-bottom)))
v-start?
(gpt/add (vv margin-top))
v-center?
(gpt/add (vv (+ (/ line-height 2) (/ (- margin-top margin-bottom) 2))))
v-end?
(gpt/add (vv (+ line-height (- margin-bottom)))))
;; Margins
(some? margin-x)
(gpt/add (hv margin-x))
@ -81,18 +251,14 @@
next-p
(cond-> start-p
(and row? (or (> margin-left 0) (> margin-right 0)))
(gpt/add (hv (+ margin-left margin-right)))
(and col? (or (> margin-top 0) (> margin-bottom 0)))
(gpt/add (vv (+ margin-top margin-bottom)))
row?
(gpt/add (hv (+ child-width layout-gap-row)))
(-> (gpt/add (hv (+ child-width layout-gap-row)))
(gpt/add (hv (+ margin-left margin-right))))
col?
(gpt/add (vv (+ child-height layout-gap-col)))
(-> (gpt/add (vv (+ margin-top margin-bottom)))
(gpt/add (vv (+ child-height layout-gap-col))))
(some? margin-x)
(gpt/add (hv margin-x))

View file

@ -251,3 +251,15 @@
(defn space-around?
[{:keys [layout-justify-content]}]
(= layout-justify-content :space-around))
(defn align-self-start? [{:keys [layout-align-self]}]
(= :start layout-align-self))
(defn align-self-end? [{:keys [layout-align-self]}]
(= :end layout-align-self))
(defn align-self-center? [{:keys [layout-align-self]}]
(= :center layout-align-self))
(defn align-self-stretch? [{:keys [layout-align-self]}]
(= :stretch layout-align-self))