From 503a1dabac2f20422f5a9f5086f39be57d5bb35d Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 27 Oct 2022 12:22:50 +0200 Subject: [PATCH] :sparkles: Align self and stretch fixes --- .../common/geom/shapes/flex_layout/lines.cljc | 189 ++----------- .../geom/shapes/flex_layout/positions.cljc | 260 ++++++++++++++---- common/src/app/common/types/shape/layout.cljc | 12 + 3 files changed, 242 insertions(+), 219 deletions(-) diff --git a/common/src/app/common/geom/shapes/flex_layout/lines.cljc b/common/src/app/common/geom/shapes/flex_layout/lines.cljc index 478bbc746..c05a0cf52 100644 --- a/common/src/app/common/geom/shapes/flex_layout/lines.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/lines.cljc @@ -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)))))) diff --git a/common/src/app/common/geom/shapes/flex_layout/positions.cljc b/common/src/app/common/geom/shapes/flex_layout/positions.cljc index c9b4c13aa..30437fd16 100644 --- a/common/src/app/common/geom/shapes/flex_layout/positions.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/positions.cljc @@ -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)) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 23b02cd6d..98a767711 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -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))