diff --git a/common/src/app/common/geom/shapes/layout.cljc b/common/src/app/common/geom/shapes/layout.cljc index 41d219e16..3225a10ce 100644 --- a/common/src/app/common/geom/shapes/layout.cljc +++ b/common/src/app/common/geom/shapes/layout.cljc @@ -8,8 +8,7 @@ (:require [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] - [app.common.geom.shapes.rect :as gre] - [app.common.geom.shapes.transforms :as gtr])) + [app.common.geom.shapes.rect :as gre])) ;; :layout ;; true if active, false if not ;; :layout-dir ;; :right, :left, :top, :bottom @@ -66,20 +65,157 @@ (update :x + p3) (update :height - p1 p4)))) -(defn calc-layout-data - "Digest the layout data to pass it to the constrains" - [{:keys [layout-type layout-gap] :as shape} children modif-tree transformed-rect] +(defn calc-layout-lines + [{:keys [layout-gap layout-wrap-type] :as shape} children {:keys [width height] :as layout-bounds}] - (let [{:keys [x y width height]} (-> transformed-rect (add-padding shape)) - num-children (count children) + (let [wrap? (= layout-wrap-type :wrap) - [children-width children-height] - (->> children - (reduce (fn [[acc-width acc-height] shape] - [(+ acc-width (-> shape :points gre/points->rect :width)) - (+ acc-height (-> shape :points gre/points->rect :height))]) [0 0])) + reduce-fn + (fn [[{:keys [line-width line-height num-children] :as line-data} result] child] + (let [child-bounds (-> child :points gre/points->rect) + next-width (-> child-bounds :width) + next-height (-> child-bounds :height)] - layout-gap + (if (and (some? line-data) + (or (not wrap?) + (and (col? shape) (<= (+ line-width next-width (* layout-gap num-children)) width)) + (and (row? shape) (<= (+ line-height next-height (* layout-gap num-children)) height)))) + + [{:line-width (if (col? shape) (+ line-width next-width) (max line-width next-width)) + :line-height (if (row? shape) (+ line-height next-height) (max line-height next-height)) + :num-children (inc num-children)} + result] + + [{:line-width next-width + :line-height next-height + :num-children 1} + (cond-> result (some? line-data) (conj line-data))]))) + + [line-data layout-lines] (reduce reduce-fn [nil []] children)] + + (cond-> layout-lines (some? line-data) (conj line-data)))) + +(defn calc-layout-lines-position + [{:keys [layout-gap layout-type] :as shape} {:keys [x y width height]} layout-lines] + + (letfn [(get-base-line + [total-width total-height] + + (let [base-x + (cond + (and (row? shape) (h-center? shape)) + (+ x (/ (- width total-width) 2)) + + (and (row? shape) (h-end? shape)) + (+ x width (- total-width)) + + :else x) + + base-y + (cond + (and (col? shape) (v-center? shape)) + (+ y (/ (- height total-height) 2)) + + (and (col? shape) (v-end? shape)) + (+ y height (- total-height)) + + :else y)] + + [base-x base-y])) + + (get-start-line + [{:keys [line-width line-height num-children]} base-x base-y] + + (let [children-gap (* layout-gap (dec num-children)) + + start-x + (cond + (or (and (col? shape) (= :space-between layout-type)) + (and (col? shape) (= :space-around layout-type))) + x + + (and (col? shape) (h-center? shape)) + (- (+ x (/ width 2)) (/ (+ line-width children-gap) 2)) + + (and (col? shape) (h-end? shape)) + (- (+ x width) (+ line-width children-gap)) + + (and (row? shape) (h-center? shape)) + (+ base-x (/ line-width 2)) + + (and (row? shape) (h-end? shape)) + (+ base-x line-width) + + (row? shape) + base-x + + :else + x) + + start-y + (cond + (or (and (row? shape) (= :space-between layout-type)) + (and (row? shape) (= :space-around layout-type))) + y + + (and (row? shape) (v-center? shape)) + (- (+ y (/ height 2)) (/ (+ line-height children-gap) 2)) + + (and (row? shape) (v-end? shape)) + (- (+ y height) (+ line-height children-gap)) + + (and (col? shape) (v-center? shape)) + (+ base-y (/ line-height 2)) + + (and (col? shape) (v-end? shape)) + (+ base-y line-height) + + (col? shape) + base-y + + :else + y)] + [start-x start-y])) + + (get-next-line + [{:keys [line-width line-height]} base-x base-y] + (let [next-x (if (col? shape) base-x (+ base-x line-width layout-gap)) + next-y (if (row? shape) base-y (+ base-y line-height layout-gap))] + [next-x next-y])) + + (add-lines [[total-width total-height] {:keys [line-width line-height]}] + [(+ total-width line-width) + (+ total-height line-height)]) + + (add-starts [[result base-x base-y] layout-line] + (let [[start-x start-y] (get-start-line layout-line base-x base-y) + [next-x next-y] (get-next-line layout-line base-x base-y)] + [(conj result + (assoc layout-line + :start-x start-x + :start-y start-y)) + next-x + next-y]))] + + (let [[total-width total-height] + (->> layout-lines (reduce add-lines [0 0])) + + total-width (+ total-width (* layout-gap (dec (count layout-lines)))) + total-height (+ total-height (* layout-gap (dec (count layout-lines)))) + + [base-x base-y] + (get-base-line total-width total-height) + + [layout-lines _ _ _ _] + (reduce add-starts [[] base-x base-y] layout-lines)] + layout-lines))) + +(defn calc-layout-line-data + [{:keys [layout-type layout-gap] :as shape} + {:keys [width height] :as layout-bounds} + {:keys [num-children line-width line-height] :as line-data}] + + (let [layout-gap (cond (= :packed layout-type) layout-gap @@ -88,73 +224,47 @@ 0 (and (col? shape) (= :space-between layout-type)) - (/ (- width children-width) (dec num-children)) + (/ (- width line-width) (dec num-children)) (and (row? shape) (= :space-between layout-type)) - (/ (- height children-height) (dec num-children))) + (/ (- height line-height) (dec num-children))) - margin-x (if (and (col? shape) (= :space-around layout-type)) - (/ (- width children-width) (dec num-children) 2) - 0) + margin-x + (if (and (col? shape) (= :space-around layout-type)) + (/ (- width line-width) (inc num-children) ) + 0) - margin-y (if (and (row? shape) (= :space-around layout-type)) - (/ (- height children-height) (inc num-children)) - 0) + margin-y + (if (and (row? shape) (= :space-around layout-type)) + (/ (- height line-height) (inc num-children)) + 0)] - children-gap (* layout-gap (dec num-children)) + (assoc line-data + :layout-gap layout-gap + :margin-x margin-x + :margin-y margin-y))) - start-x - (cond - (or (and (col? shape) (= :space-between layout-type)) - (and (col? shape) (= :space-around layout-type))) - x - (and (row? shape) (h-center? shape)) - (+ x (/ width 2)) +(defn calc-layout-data + "Digest the layout data to pass it to the constrains" + [{:keys [layout-dir] :as shape} children layout-bounds] - (and (row? shape) (h-end? shape)) - (+ x width) + (let [reverse? (or (= :left layout-dir) (= :bottom layout-dir)) + layout-bounds (-> layout-bounds (add-padding shape)) + children (cond->> children reverse? reverse) + layout-lines + (->> (calc-layout-lines shape children layout-bounds) + (calc-layout-lines-position shape layout-bounds) + (map (partial calc-layout-line-data shape layout-bounds)))] - (and (col? shape) (h-center? shape)) - (- (+ x (/ width 2)) (/ (+ children-width children-gap) 2)) - - (and (col? shape) (h-end? shape)) - (- (+ x width) (+ children-width children-gap)) - - :else - x) - - start-y - (cond - (or (and (row? shape) (= :space-between layout-type)) - (and (row? shape) (= :space-around layout-type))) - y - - (and (col? shape) (v-center? shape)) - (+ y (/ height 2)) - - (and (col? shape) (v-end? shape)) - (+ y height) - - (and (row? shape) (v-center? shape)) - (- (+ y (/ height 2)) (/ (+ children-height children-gap) 2)) - - (and (row? shape) (v-end? shape)) - (- (+ y height) (+ children-height children-gap)) - - :else - y)] - - {:start-x start-x - :start-y start-y - :layout-gap layout-gap - :margin-x margin-x - :margin-y margin-y - :reverse? (or (= :left (:layout-dir shape)) (= :bottom (:layout-dir shape)))})) + {:layout-lines layout-lines + :reverse? reverse?})) (defn next-p "Calculates the position for the current shape given the layout-data context" - [shape {:keys [width height]} {:keys [start-x start-y layout-gap margin-x margin-y] :as layout-data}] + [shape + {:keys [width height]} + {:keys [start-x start-y layout-gap margin-x margin-y] :as layout-data}] (let [pos-x (cond diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index e3faaeec3..a9dffa037 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -165,13 +165,26 @@ modifiers (get-in modif-tree [id :modifiers]) transformed-rect (gtr/transform-selrect (:selrect shape) modifiers) - layout-data (gcl/calc-layout-data shape children modif-tree transformed-rect) - children (cond-> children (:reverse? layout-data) reverse) + layout-data (gcl/calc-layout-data shape children transformed-rect) + children (into [] (cond-> children (:reverse? layout-data) reverse)) - [_ modif-tree] - (reduce (partial set-layout-modifiers shape) [layout-data modif-tree] children)] + max-idx (dec (count children)) + layout-lines (:layout-lines layout-data)] - modif-tree))) + (loop [modif-tree modif-tree + layout-line (first layout-lines) + pending (rest layout-lines) + from-idx 0] + (if (and (some? layout-line) (<= from-idx max-idx)) + (let [to-idx (+ from-idx (:num-children layout-line)) + children (subvec children from-idx to-idx) + + [_ modif-tree] + (reduce (partial set-layout-modifiers shape) [layout-line modif-tree] children)] + + (recur modif-tree (first pending) (rest pending) to-idx)) + + modif-tree))))) (defn get-first-layout [id objects]