From 81d2f9dd9d38575efd2b984f568ecb7f6a8f51b8 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 26 Oct 2022 15:45:09 +0200 Subject: [PATCH] :sparkles: Adds align-content options --- .../common/geom/shapes/flex_layout/lines.cljc | 123 +++++++++++++----- .../geom/shapes/flex_layout/modifiers.cljc | 12 +- .../geom/shapes/flex_layout/positions.cljc | 39 +++++- common/src/app/common/types/shape/layout.cljc | 57 +++++++- .../app/main/data/workspace/shape_layout.cljs | 2 +- .../options/menus/layout_container.cljs | 20 +-- .../sidebar/options/menus/layout_item.cljs | 4 +- 7 files changed, 204 insertions(+), 53 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 2ac988748f..478bbc746a 100644 --- a/common/src/app/common/geom/shapes/flex_layout/lines.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/lines.cljc @@ -56,6 +56,12 @@ child-max-width (ctl/child-max-width child) child-max-height (ctl/child-max-height child) + [child-margin-top child-margin-right child-margin-bottom child-margin-left] + (ctl/child-margins child) + + child-margin-width (+ child-margin-left child-margin-right) + child-margin-height (+ child-margin-top child-margin-bottom) + fill-width? (ctl/fill-width? child) fill-height? (ctl/fill-height? child) @@ -66,10 +72,10 @@ :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 (if fill-width? child-min-width child-width) - next-min-height (if fill-height? child-min-height child-height) - next-max-width (if fill-width? child-max-width child-width) - next-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-line-min-width (+ line-min-width next-min-width (* layout-gap-row num-children)) next-line-min-height (+ line-min-height next-min-height (* layout-gap-col num-children))] @@ -106,52 +112,100 @@ layout-height (gpo/height-points layout-bounds) row? (ctl/row? parent) col? (ctl/col? 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) 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)] + 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) - (and row? v-center?) - (gpt/add (vv (/ (- layout-height total-height lines-gap-col) 2))) + row? + (cond-> center? + (gpt/add (vv (/ free-height-gap 2))) - (and row? v-end?) - (gpt/add (vv (- layout-height total-height lines-gap-col))) + end? + (gpt/add (vv free-height-gap)) - (and col? h-center?) - (gpt/add (hv (/ (- layout-width total-width lines-gap-row) 2))) + around? + (gpt/add (vv (/ free-height (inc num-lines))))) - (and col? h-end?) - (gpt/add (hv (- layout-width total-width lines-gap-row)))))) + 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] + [parent layout-bounds {:keys [line-width line-height]} base-p total-width total-height num-lines] - (let [row? (ctl/row? parent) + (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 %)] + 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 - col? - (gpt/add (hv (+ line-width layout-gap-row))) - row? - (gpt/add (vv (+ line-height layout-gap-col)))))) + (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 child-fill? ]} base-p] + [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) @@ -165,6 +219,7 @@ 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 %) @@ -172,6 +227,16 @@ 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 @@ -261,9 +326,9 @@ (+ total-max-width line-max-width) (+ total-max-height line-max-height)]) - (add-starts [[result base-p] layout-line] - (let [start-p (get-start-line parent layout-bounds layout-line base-p) - next-p (get-next-line parent layout-bounds layout-line base-p)] + (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)] [(conj result (assoc layout-line :start-p start-p)) @@ -308,7 +373,7 @@ base-p (get-base-line parent layout-bounds total-width total-height num-lines)] - (first (reduce add-starts [[] base-p] layout-lines)))))) + (first (reduce (partial add-starts total-width total-height num-lines) [[] base-p] layout-lines)))))) (defn add-line-spacing "Calculates the baseline for a flex layout" diff --git a/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc b/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc index 731df28a59..02e778550f 100644 --- a/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc @@ -45,8 +45,9 @@ :modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)}) (and (ctl/col? parent) (ctl/fill-width? child)) - (let [fill-scale (/ line-width child-width)] - {:width line-width + (let [target-width (- line-width (ctl/child-width-margin child)) + fill-scale (/ target-width child-width)] + {:width target-width :modifiers (ctm/resize (gpt/point fill-scale 1) child-origin transform transform-inverse)}))) (defn calc-fill-height-data @@ -64,8 +65,9 @@ :modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)}) (and (ctl/row? parent) (ctl/fill-height? child)) - (let [fill-scale (/ line-height child-height)] - {:height line-height + (let [target-height (- line-height (ctl/child-height-margin child)) + fill-scale (/ target-height child-height)] + {:height target-height :modifiers (ctm/resize (gpt/point 1 fill-scale) child-origin transform transform-inverse)}))) (defn calc-layout-modifiers @@ -83,7 +85,7 @@ child-width (or (:width fill-width) child-width) child-height (or (:height fill-height) child-height) - [corner-p layout-line] (fpo/get-child-position parent child-width child-height layout-line) + [corner-p layout-line] (fpo/get-child-position parent child child-width child-height layout-line) move-vec (gpt/to-vec child-origin corner-p) 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 e230da22e2..c9b4c13aad 100644 --- a/common/src/app/common/geom/shapes/flex_layout/positions.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/positions.cljc @@ -12,15 +12,17 @@ (defn get-child-position "Calculates the position for the current shape given the layout-data context" - [parent + [parent child child-width child-height {:keys [start-p layout-gap-row layout-gap-col margin-x margin-y] :as layout-data}] (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) points (:points parent) @@ -28,6 +30,8 @@ hv (partial gpo/start-hv points) vv (partial gpo/start-vv points) + [margin-top margin-right margin-bottom margin-left] (ctl/child-margins child) + corner-p (cond-> start-p (and col? h-center?) @@ -36,12 +40,39 @@ (and col? h-end?) (gpt/add (hv (- child-width))) + col? + (gpt/add (vv margin-top)) + + (and col? h-start?) + (gpt/add (hv margin-left)) + + (and col? h-center?) + (gpt/add (hv (/ (- margin-left margin-right) 2))) + + (and col? h-end?) + (gpt/add (hv (- margin-right))) + + ;; X COORD (and row? v-center?) (gpt/add (vv (- (/ child-height 2)))) (and row? v-end?) (gpt/add (vv (- child-height))) + row? + (gpt/add (hv margin-left)) + + (and row? v-start?) + (gpt/add (vv margin-top)) + + (and row? v-center?) + (gpt/add (vv (/ (- margin-top margin-bottom) 2))) + + (and row? v-end?) + (gpt/add (vv (- margin-bottom))) + + ;; Margins + (some? margin-x) (gpt/add (hv margin-x)) @@ -50,6 +81,12 @@ 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))) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 8f4b431288..23b02cd6df 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -13,9 +13,9 @@ ;; :layout-flex-dir ;; :row, :reverse-row, :column, :reverse-column ;; :layout-gap-type ;; :simple, :multiple ;; :layout-gap ;; {:row-gap number , :column-gap number} -;; :layout-align-items ;; :start :end :center :strech +;; :layout-align-items ;; :start :end :center :stretch ;; :layout-justify-content ;; :start :center :end :space-between :space-around -;; :layout-align-content ;; :start :center :end :space-between :space-around :strech (by default) +;; :layout-align-content ;; :start :center :end :space-between :space-around :stretch (by default) ;; :layout-wrap-type ;; :wrap, :no-wrap ;; :layout-padding-type ;; :simple, :multiple ;; :layout-padding ;; {:p1 num :p2 num :p3 num :p4 num} number could be negative @@ -34,8 +34,8 @@ (s/def ::layout-flex-dir #{:row :reverse-row :column :reverse-column}) (s/def ::layout-gap-type #{:simple :multiple}) (s/def ::layout-gap ::us/safe-number) -(s/def ::layout-align-items #{:start :end :center :strech}) -(s/def ::layout-align-content #{:start :end :center :space-between :space-around :strech}) +(s/def ::layout-align-items #{:start :end :center :stretch}) +(s/def ::layout-align-content #{:start :end :center :space-between :space-around :stretch}) (s/def ::layout-justify-content #{:start :center :end :space-between :space-around}) (s/def ::layout-wrap-type #{:wrap :no-wrap}) (s/def ::layout-padding-type #{:simple :multiple}) @@ -80,7 +80,7 @@ (s/def ::layout-margin-type #{:simple :multiple}) (s/def ::layout-h-behavior #{:fill :fix :auto}) (s/def ::layout-v-behavior #{:fill :fix :auto}) -(s/def ::layout-align-self #{:start :end :center :strech}) +(s/def ::layout-align-self #{:start :end :center :stretch}) (s/def ::layout-max-h ::us/safe-number) (s/def ::layout-min-h ::us/safe-number) (s/def ::layout-max-w ::us/safe-number) @@ -151,6 +151,26 @@ (max 0 (:layout-max-h child)) ##Inf)) +(defn child-margins + [{{:keys [m1 m2 m3 m4]} :layout-margin :keys [layout-margin-type]}] + (let [m1 (or m1 0) + m2 (or m2 0) + m3 (or m3 0) + m4 (or m4 0)] + (if (= layout-margin-type :multiple) + [m1 m2 m3 m4] + [m1 m1 m1 m1]))) + +(defn child-height-margin + [child] + (let [[top _ bottom _] (child-margins child)] + (+ top bottom))) + +(defn child-width-margin + [child] + (let [[_ right _ left] (child-margins child)] + (+ right left))) + (defn h-start? [{:keys [layout-align-items layout-justify-content] :as shape}] (or (and (col? shape) @@ -192,6 +212,33 @@ (= layout-align-items :end)) (and (col? shape) (= layout-justify-content :end)))) + +(defn content-start? + [{:keys [layout-align-content]}] + (= :start layout-align-content)) + +(defn content-center? + [{:keys [layout-align-content]}] + (= :center layout-align-content)) + +(defn content-end? + [{:keys [layout-align-content]}] + (= :end layout-align-content)) + +(defn content-between? + [{:keys [layout-align-content]}] + (= :space-between layout-align-content)) + +(defn content-around? + [{:keys [layout-align-content]}] + (= :space-around layout-align-content)) + +(defn content-stretch? + [{:keys [layout-align-content]}] + (or (= :stretch layout-align-content) + (nil? layout-align-content))) + + (defn reverse? [{:keys [layout-flex-dir]}] (or (= :reverse-row layout-flex-dir) diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index da2262c536..9ab3536bca 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -35,7 +35,7 @@ :layout-gap {:row-gap 0 :column-gap 0} :layout-align-items :start :layout-justify-content :start - :layout-align-content :strech + :layout-align-content :stretch :layout-wrap-type :no-wrap :layout-padding-type :simple :layout-padding {:p1 0 :p2 0 :p3 0 :p4 0}}) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs index 1d1191a747..4eb03a287f 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_container.cljs @@ -21,9 +21,9 @@ :layout-flex-dir ;; :row, :reverse-row, :column, :reverse-column :layout-gap-type ;; :simple, :multiple :layout-gap ;; {:row-gap number , :column-gap number} - :layout-align-items ;; :start :end :center :strech + :layout-align-items ;; :start :end :center :stretch :layout-justify-content ;; :start :center :end :space-between :space-around - :layout-align-content ;; :start :center :end :space-between :space-around :strech (by default) + :layout-align-content ;; :start :center :end :space-between :space-around :stretch (by default) :layout-wrap-type ;; :wrap, :no-wrap :layout-padding-type ;; :simple, :multiple :layout-padding ;; {:p1 num :p2 num :p3 num :p4 num} number could be negative @@ -37,13 +37,13 @@ :start i/align-items-column-start :end i/align-items-column-end :center i/align-items-column-center - :strech i/align-items-column-strech + :stretch i/align-items-column-strech :baseline i/align-items-column-baseline) (case val :start i/align-items-row-start :end i/align-items-row-end :center i/align-items-row-center - :strech i/align-items-row-strech + :stretch i/align-items-row-strech :baseline i/align-items-row-baseline)) :justify-content (if is-col? (case val @@ -66,7 +66,7 @@ :center i/align-content-column-center :space-around i/align-content-column-around :space-between i/align-content-column-between - :strech nil) + :stretch nil) (case val :start i/align-content-row-start @@ -74,20 +74,20 @@ :center i/align-content-row-center :space-around i/align-content-row-around :space-between i/align-content-row-between - :strech nil)) + :stretch nil)) :align-self (if is-col? (case val :start i/align-self-column-top :end i/align-self-column-bottom :center i/align-self-column-center - :strech i/align-self-column-strech + :stretch i/align-self-column-strech :baseline i/align-self-column-baseline) (case val :start i/align-self-row-left :end i/align-self-row-right :center i/align-self-row-center - :strech i/align-self-row-strech + :stretch i/align-self-row-strech :baseline i/align-self-row-baseline)))) (mf/defc direction-btn @@ -129,7 +129,7 @@ [{:keys [is-col? align-items set-align] :as props}] [:div.align-items-style - (for [align [:start :center :end :strech]] + (for [align [:start :center :end :stretch]] [:button.align-start.tooltip {:class (dom/classnames :active (= align-items align) :tooltip-bottom-left (not= align :start) @@ -312,7 +312,7 @@ align-content (:layout-align-content values) set-align-content (fn [value] (if (= align-content value) - (st/emit! (dwsl/update-layout ids {:layout-align-content :strech})) + (st/emit! (dwsl/update-layout ids {:layout-align-content :stretch})) (st/emit! (dwsl/update-layout ids {:layout-align-content value})))) ;; Gap diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs index c01ea7ddb7..f36291ca21 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/layout_item.cljs @@ -26,7 +26,7 @@ :layout-item-min-h ;; num :layout-item-max-w ;; num :layout-item-min-w ;; num - :layout-item-align-self ;; :start :end :center :strech :baseline + :layout-item-align-self ;; :start :end :center :stretch :baseline ]) (mf/defc margin-section @@ -122,7 +122,7 @@ (mf/defc align-self-row [{:keys [is-col? align-self set-align-self] :as props}] - (let [dir-v [:start :center :end :strech :baseline]] + (let [dir-v [:start :center :end :stretch :baseline]] [:div.align-self-style (for [align dir-v] [:button.align-self.tooltip.tooltip-bottom