From 8bcb9e19762363a33b46b1e1798cb6391905f375 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 5 Oct 2022 22:16:48 +0200 Subject: [PATCH] :sparkles: Autofill vectors calculation --- common/src/app/common/geom/shapes/layout.cljc | 565 +++++++++------- .../app/common/geom/shapes/layout_new.cljc | 606 ------------------ .../src/app/common/geom/shapes/modifiers.cljc | 27 +- .../app/main/ui/workspace/shapes/frame.cljs | 5 +- 4 files changed, 363 insertions(+), 840 deletions(-) delete mode 100644 common/src/app/common/geom/shapes/layout_new.cljc diff --git a/common/src/app/common/geom/shapes/layout.cljc b/common/src/app/common/geom/shapes/layout.cljc index 73c08864a6..d0c616e85b 100644 --- a/common/src/app/common/geom/shapes/layout.cljc +++ b/common/src/app/common/geom/shapes/layout.cljc @@ -8,10 +8,10 @@ (:require [app.common.data :as d] [app.common.geom.point :as gpt] - [app.common.geom.shapes.rect :as gre])) + [app.common.geom.shapes.transforms :as gst])) ;; :layout ;; true if active, false if not -;; :layout-flex-dir ;; :row, :column, :reverse-row, :reverse-column +;; :layout-dir ;; :right, :left, :top, :bottom ;; :layout-gap ;; number could be negative ;; :layout-type ;; :packed, :space-between, :space-around ;; :layout-wrap-type ;; :wrap, :no-wrap @@ -21,12 +21,12 @@ ;; :layout-v-orientation ;; :left, :center, :right (defn col? - [{:keys [layout-flex-dir]}] - (or (= :column layout-flex-dir) (= :reverse-column layout-flex-dir))) + [{:keys [layout-dir]}] + (or (= :right layout-dir) (= :left layout-dir))) (defn row? - [{:keys [layout-flex-dir]}] - (or (= :row layout-flex-dir) (= :reverse-row layout-flex-dir))) + [{:keys [layout-dir]}] + (or (= :top layout-dir) (= :bottom layout-dir))) (defn h-start? [{:keys [layout-h-orientation]}] @@ -65,42 +65,128 @@ (update :x + p3) (update :height - p1 p4)))) +;; FUNCTIONS TO WORK WITH POINTS SQUARES + +(defn origin + [points] + (nth points 0)) + +(defn start-hv + "Horizontal vector from the origin with a magnitude `val`" + [[p0 p1 _ _] val] + (-> (gpt/to-vec p0 p1) + (gpt/unit) + (gpt/scale val))) + +(defn end-hv + "Horizontal vector from the oposite to the origin in the x axis with a magnitude `val`" + [[p0 p1 _ _] val] + (-> (gpt/to-vec p1 p0) + (gpt/unit) + (gpt/scale val))) + +(defn start-vv + "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" + [[p0 _ _ p3] val] + (-> (gpt/to-vec p0 p3) + (gpt/unit) + (gpt/scale val))) + +(defn end-vv + "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" + [[p0 _ _ p3] val] + (-> (gpt/to-vec p3 p0) + (gpt/unit) + (gpt/scale val))) + +;;(defn start-hp +;; [[p0 _ _ _ :as points] val] +;; (gpt/add p0 (start-hv points val))) +;; +;;(defn end-hp +;; "Horizontal Vector from the oposite to the origin in the x axis with a magnitude `val`" +;; [[_ p1 _ _ :as points] val] +;; (gpt/add p1 (end-hv points val))) +;; +;;(defn start-vp +;; "Vertical Vector from the oposite to the origin in the x axis with a magnitude `val`" +;; [[p0 _ _ _ :as points] val] +;; (gpt/add p0 (start-vv points val))) +;; +;;(defn end-vp +;; "Vertical Vector from the oposite to the origin in the x axis with a magnitude `val`" +;; [[_ _ p3 _ :as points] val] +;; (gpt/add p3 (end-vv points val))) + +(defn width-points + [[p0 p1 _ _]] + (gpt/length (gpt/to-vec p0 p1))) + +(defn height-points + [[p0 _ _ p3]] + (gpt/length (gpt/to-vec p0 p3))) + +(defn pad-points + [[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left] + (let [top-v (start-vv points pad-top) + right-v (end-hv points pad-right) + bottom-v (end-vv points pad-bottom) + left-v (start-hv points pad-left)] + + [(-> p0 (gpt/add left-v) (gpt/add top-v)) + (-> p1 (gpt/add right-v) (gpt/add top-v)) + (-> p2 (gpt/add right-v) (gpt/add bottom-v)) + (-> p3 (gpt/add left-v) (gpt/add bottom-v))])) + +;;;; + + (defn calc-layout-lines - [{:keys [layout-gap layout-wrap-type] :as shape} children {:keys [width height] :as layout-bounds}] + [{:keys [layout-gap layout-wrap-type] :as parent} children layout-bounds] (let [wrap? (= layout-wrap-type :wrap) + layout-width (width-points layout-bounds) + layout-height (height-points layout-bounds) reduce-fn (fn [[{:keys [line-width line-height num-children line-fill? child-fill? num-child-fill] :as line-data} result] child] - (let [child-bounds (-> child :points gre/points->rect) + (let [child-bounds (gst/parent-coords-points child parent) + child-width (width-points child-bounds) + child-height (height-points child-bounds) + + col? (col? parent) + row? (row? parent) cur-child-fill? - (or (and (col? shape) (= :fill (:layout-h-behavior child))) - (and (row? shape) (= :fill (:layout-v-behavior child)))) + (or (and col? (= :fill (:layout-h-behavior child))) + (and row? (= :fill (:layout-v-behavior child)))) cur-line-fill? - (or (and (row? shape) (= :fill (:layout-h-behavior child))) - (and (col? shape) (= :fill (:layout-v-behavior child)))) + (or (and row? (= :fill (:layout-h-behavior child))) + (and col? (= :fill (:layout-v-behavior child)))) ;; TODO LAYOUT: ADD MINWIDTH/HEIGHT - next-width (if (or (and (col? shape) cur-child-fill?) - (and (row? shape) cur-line-fill?)) + next-width (if (or (and col? cur-child-fill?) + (and row? cur-line-fill?)) 0 - (-> child-bounds :width)) + child-width) - next-height (if (or (and (row? shape) cur-child-fill?) - (and (col? shape) cur-line-fill?)) + next-height (if (or (and row? cur-child-fill?) + (and col? cur-line-fill?)) 0 - (-> child-bounds :height))] + child-height) + + next-total-width (+ line-width next-width (* layout-gap (dec num-children))) + next-total-height (+ line-height next-height (* layout-gap (dec num-children)))] (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)))) + (and col? (<= next-total-width layout-width)) + (and row? (<= next-total-height layout-height)))) ;; When :fill we add min width (0 by default) - [{: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)) + [{:line-width (if col? (+ line-width next-width) (max line-width next-width)) + :line-height (if row? (+ line-height next-height) (max line-height next-height)) :num-children (inc num-children) :child-fill? (or cur-child-fill? child-fill?) :line-fill? (or cur-line-fill? line-fill?) @@ -120,155 +206,148 @@ (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] :as layout-bounds} layout-lines] + [{:keys [layout-gap] :as parent} layout-bounds layout-lines] - (letfn [(get-base-line - [total-width total-height] + (let [layout-width (width-points layout-bounds) + layout-height (height-points layout-bounds) + row? (row? parent) + col? (col? parent) + h-center? (h-center? parent) + h-end? (h-end? parent) + v-center? (v-center? parent) + v-end? (v-end? parent)] - (let [base-x - (cond - (and (row? shape) (h-center? shape)) - (+ x (/ (- width total-width) 2)) + (letfn [;; short version to not repeat always with all arguments + (xv [val] + (start-hv layout-bounds val)) - (and (row? shape) (h-end? shape)) - (+ x width (- total-width)) + ;; short version to not repeat always with all arguments + (yv [val] + (start-vv layout-bounds val)) - :else x) + (get-base-line + [total-width total-height] - base-y - (cond - (and (col? shape) (v-center? shape)) - (+ y (/ (- height total-height) 2)) + (cond-> (origin layout-bounds) + (and row? h-center?) + (gpt/add (xv (/ (- layout-width total-width) 2))) - (and (col? shape) (v-end? shape)) - (+ y height (- total-height)) + (and row? h-end?) + (gpt/add (xv (- layout-width total-width))) - :else y)] + (and col? v-center?) + (gpt/add (yv (/ (- layout-height total-height) 2))) - [base-x base-y])) + (and col? v-end?) + (gpt/add (yv (- layout-height total-height))))) - (get-start-line - [{:keys [line-width line-height num-children child-fill?]} base-x base-y] + (get-start-line + [{:keys [line-width line-height num-children child-fill?]} base-p] - (let [children-gap (* layout-gap (dec num-children)) + (let [children-gap (* layout-gap (dec num-children)) - line-width (if (and (col? shape) child-fill?) (- width (* layout-gap num-children)) line-width) - line-height (if (and (row? shape) child-fill?) (- height (* layout-gap num-children)) line-height) + line-width (if (and col? child-fill?) + (- layout-width (* layout-gap (dec num-children))) + line-width) - start-x - (cond - ;;(and (col? shape) child-fill?) - ;;;; TODO LAYOUT: Start has to take into account max-width - ;;x + line-height (if (and row? child-fill?) + (- layout-height (* layout-gap (dec num-children))) + line-height) - (or (and (col? shape) (= :space-between layout-type)) - (and (col? shape) (= :space-around layout-type))) - x + start-p + (cond-> base-p + ;; X AXIS + (and col? h-center?) + (-> (gpt/add (xv (/ layout-width 2))) + (gpt/subtract (xv (/ (+ line-width children-gap) 2)))) - (and (col? shape) (h-center? shape)) - (- (+ x (/ width 2)) (/ (+ line-width children-gap) 2)) + (and col? h-end?) + (-> (gpt/add (xv layout-width)) + (gpt/subtract (xv (+ line-width children-gap)))) - (and (col? shape) (h-end? shape)) - (- (+ x width) (+ line-width children-gap)) + (and row? h-center?) + (gpt/add (xv (/ line-width 2))) - (and (row? shape) (h-center? shape)) - (+ base-x (/ line-width 2)) + (and row? h-end?) + (gpt/add (xv line-width)) - (and (row? shape) (h-end? shape)) - (+ base-x line-width) + ;; Y AXIS + (and row? v-center?) + (-> (gpt/add (yv (/ layout-height 2))) + (gpt/subtract (yv (/ (+ line-height children-gap) 2)))) - (row? shape) - base-x + (and row? v-end?) + (-> (gpt/add (yv layout-height)) + (gpt/subtract (yv (+ line-height children-gap)))) - :else - x) + (and col? v-center?) + (gpt/add (yv (/ line-height 2))) - start-y - (cond - ;;(and (row? shape) child-fill?) - ;;;; TODO LAYOUT: Start has to take into account max-width - ;;y - - (or (and (row? shape) (= :space-between layout-type)) - (and (row? shape) (= :space-around layout-type))) - y + (and col? v-end?) + (gpt/add (yv line-height)))] - (and (row? shape) (v-center? shape)) - (- (+ y (/ height 2)) (/ (+ line-height children-gap) 2)) + start-p)) - (and (row? shape) (v-end? shape)) - (- (+ y height) (+ line-height children-gap)) + (get-next-line + [{:keys [line-width line-height]} base-p] - (and (col? shape) (v-center? shape)) - (+ base-y (/ line-height 2)) + (cond-> base-p + row? + (gpt/add (xv (+ line-width layout-gap))) - (and (col? shape) (v-end? shape)) - (+ base-y line-height) + col? + (gpt/add (yv (+ line-height layout-gap))))) - (col? shape) - base-y + (add-lines [[total-width total-height] {:keys [line-width line-height]}] + [(+ total-width line-width) + (+ total-height line-height)]) - :else - y)] + (add-starts [[result base-p] layout-line] + (let [start-p (get-start-line layout-line base-p) + next-p (get-next-line layout-line base-p)] + [(conj result + (assoc layout-line :start-p start-p)) + next-p]))] - [start-x start-y])) + (let [[total-width total-height] (->> layout-lines (reduce add-lines [0 0])) - (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])) + total-width (+ total-width (* layout-gap (dec (count layout-lines)))) + total-height (+ total-height (* layout-gap (dec (count layout-lines)))) - (add-lines [[total-width total-height] {:keys [line-width line-height]}] - [(+ total-width line-width) - (+ total-height line-height)]) + vertical-fill-space (- layout-height total-height) + horizontal-fill-space (- layout-width total-width) + num-line-fill (count (->> layout-lines (filter :line-fill?))) - (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]))] + layout-lines + (->> layout-lines + (mapv #(cond-> % + (and col? (:line-fill? %)) + (update :line-height + (/ vertical-fill-space num-line-fill)) - (let [[total-width total-height] (->> layout-lines (reduce add-lines [0 0])) + (and row? (:line-fill? %)) + (update :line-width + (/ horizontal-fill-space num-line-fill))))) - total-width (+ total-width (* layout-gap (dec (count layout-lines)))) - total-height (+ total-height (* layout-gap (dec (count layout-lines)))) + total-height (if (and col? (> num-line-fill 0)) layout-height total-height) + total-width (if (and row? (> num-line-fill 0)) layout-width total-width) - vertical-fill-space (- height total-height) - horizontal-fill-space (- width total-width) - num-line-fill (count (->> layout-lines (filter :line-fill?))) + base-p (get-base-line total-width total-height) - layout-lines - (->> layout-lines - (mapv #(cond-> % - (and (col? shape) (:line-fill? %)) - (update :line-height + (/ vertical-fill-space num-line-fill)) - - (and (row? shape) (:line-fill? %)) - (update :line-width + (/ horizontal-fill-space num-line-fill))))) - - total-height (if (and (col? shape) (> num-line-fill 0)) height total-height) - total-width (if (and (row? shape) (> num-line-fill 0)) width total-width) - - [base-x base-y] - (get-base-line total-width total-height) - - [layout-lines _ _ _ _] - (reduce add-starts [[] base-x base-y] layout-lines)] - layout-lines))) + [layout-lines _ _ _ _] + (reduce add-starts [[] base-p] layout-lines)] + layout-lines)))) (defn calc-layout-line-data + "Calculates the baseline for a flex layout" [{:keys [layout-type layout-gap] :as shape} - {:keys [width height] :as layout-bounds} - {:keys [num-children line-width line-height] :as line-data}] + layout-bounds + {:keys [num-children line-width line-height child-fill?] :as line-data}] - (let [layout-gap + (let [width (width-points layout-bounds) + height (height-points layout-bounds) + + layout-gap (cond - (= :packed layout-type) + (or (= :packed layout-type) child-fill?) layout-gap (= :space-around layout-type) @@ -282,7 +361,7 @@ margin-x (if (and (col? shape) (= :space-around layout-type)) - (/ (- width line-width) (inc num-children) ) + (/ (- width line-width) (inc num-children)) 0) margin-y @@ -296,147 +375,199 @@ :margin-x margin-x :margin-y margin-y))) - -(defn calc-layout-data - "Digest the layout data to pass it to the constrains" - [{:keys [layout-flex-dir] :as shape} children layout-bounds] - - (let [reverse? (or (= :reverse-row layout-flex-dir) (= :reverse-column layout-flex-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)))] - - {: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}] + [parent + child-width child-height + {:keys [start-p layout-gap margin-x margin-y] :as layout-data}] - (let [pos-x - (cond - (and (row? shape) (h-center? shape)) - (- start-x (/ width 2)) + (let [row? (row? parent) + col? (col? parent) - (and (row? shape) (h-end? shape)) - (- start-x width) + layout-type (:layout-type parent) + space-around? (= :space-around layout-type) + space-between? (= :space-between layout-type) - :else - start-x) + stretch-h? (and row? (or space-around? space-between?)) + stretch-v? (and col? (or space-around? space-between?)) - pos-y - (cond - (and (col? shape) (v-center? shape)) - (- start-y (/ height 2)) + h-center? (and (h-center? parent) (not stretch-h?)) + h-end? (and (h-end? parent) (not stretch-h?)) + v-center? (and (v-center? parent) (not stretch-v?)) + v-end? (and (v-end? parent) (not stretch-v?)) + points (:points parent) - (and (col? shape) (v-end? shape)) - (- start-y height) + xv (partial start-hv points) + yv (partial start-vv points) - :else - start-y) + corner-p + (cond-> start-p + (and row? h-center?) + (gpt/add (xv (- (/ child-width 2)))) + (and row? h-end?) + (gpt/add (xv (- child-width))) - pos-x (cond-> pos-x (some? margin-x) (+ margin-x)) - pos-y (cond-> pos-y (some? margin-y) (+ margin-y)) + (and col? v-center? (not space-around?)) + (gpt/add (yv (- (/ child-height 2)))) - corner-p (gpt/point pos-x pos-y) + (and col? v-end? (not space-around?)) + (gpt/add (yv (- child-height))) - next-x - (if (col? shape) - (+ start-x width layout-gap) - start-x) + (some? margin-x) + (gpt/add (xv margin-x)) - next-y - (if (row? shape) - (+ start-y height layout-gap) - start-y) + (some? margin-y) + (gpt/add (yv margin-y))) - next-x (cond-> next-x (some? margin-x) (+ margin-x)) - next-y (cond-> next-y (some? margin-y) (+ margin-y)) + next-p + (cond-> start-p + col? + (gpt/add (xv (+ child-width layout-gap))) + row? + (gpt/add (yv (+ child-height layout-gap))) + + (some? margin-x) + (gpt/add (xv margin-x)) + + (some? margin-y) + (gpt/add (yv margin-y))) layout-data - (assoc layout-data :start-x next-x :start-y next-y)] + (assoc layout-data :start-p next-p)] + [corner-p layout-data])) (defn calc-fill-width-data - [child-bounds - {:keys [layout-gap] :as parent} + "Calculates the size and modifiers for the width of an auto-fill child" + [{:keys [layout-gap transform transform-inverse] :as parent} {:keys [layout-h-behavior] :as child} - {:keys [num-children line-width layout-bounds line-fill? child-fill?] :as layout-data}] + child-origin child-width + {:keys [num-children line-width line-fill? child-fill? layout-bounds] :as layout-data}] (cond (and (col? parent) (= :fill layout-h-behavior) child-fill?) - (let [fill-space (- (:width layout-bounds) line-width (* layout-gap num-children)) + (let [layout-width (width-points layout-bounds) + fill-space (- layout-width line-width (* layout-gap (dec num-children))) fill-width (/ fill-space (:num-child-fill layout-data)) - fill-scale (/ fill-width (:width child-bounds))] - {:bounds {:width fill-width} + fill-scale (/ fill-width child-width)] + {:width fill-width :modifiers [{:type :resize - :origin (gpt/point child-bounds) + :origin child-origin + :transform transform + :transform-inverse transform-inverse :vector (gpt/point fill-scale 1)}]}) (and (row? parent) (= :fill layout-h-behavior) line-fill?) - (let [fill-scale (/ line-width (:width child-bounds))] - {:bounds {:width line-width} + (let [fill-scale (/ line-width child-width)] + {:width line-width :modifiers [{:type :resize - :origin (gpt/point child-bounds) + :origin child-origin + :transform transform + :transform-inverse transform-inverse :vector (gpt/point fill-scale 1)}]}) )) (defn calc-fill-height-data - [child-bounds - {:keys [layout-gap] :as parent} + "Calculates the size and modifiers for the height of an auto-fill child" + [{:keys [layout-gap transform transform-inverse] :as parent} {:keys [layout-v-behavior] :as child} + child-origin child-height {:keys [num-children line-height layout-bounds line-fill? child-fill?] :as layout-data}] (cond (and (row? parent) (= :fill layout-v-behavior) child-fill?) - (let [fill-space (- (:height layout-bounds) line-height (* layout-gap num-children)) + (let [layout-height (height-points layout-bounds) + fill-space (- layout-height line-height (* layout-gap (dec num-children))) fill-height (/ fill-space (:num-child-fill layout-data)) - fill-scale (/ fill-height (:height child-bounds))] - {:bounds {:height fill-height} + fill-scale (/ fill-height child-height)] + {:height fill-height :modifiers [{:type :resize - :origin (gpt/point child-bounds) + :origin child-origin + :transform transform + :transform-inverse transform-inverse :vector (gpt/point 1 fill-scale)}]}) (and (col? parent) (= :fill layout-v-behavior) line-fill?) - (let [fill-scale (/ line-height (:height child-bounds))] - {:bounds {:height line-height} + (let [fill-scale (/ line-height child-height)] + {:height line-height :modifiers [{:type :resize - :origin (gpt/point child-bounds) + :origin child-origin + :transform transform + :transform-inverse transform-inverse :vector (gpt/point 1 fill-scale)}]}) )) +(defn normalize-child-modifiers + "Apply the modifiers and then normalized them against the parent coordinates" + [parent child modifiers transformed-parent] + + (let [transformed-child (gst/transform-shape child modifiers) + child-bb-before (gst/parent-coords-rect child parent) + child-bb-after (gst/parent-coords-rect transformed-child transformed-parent) + scale-x (/ (:width child-bb-before) (:width child-bb-after)) + scale-y (/ (:height child-bb-before) (:height child-bb-after))] + (-> modifiers + (update :v2 #(conj % + {:type :resize + :transform (:transform transformed-parent) + :transform-inverse (:transform-inverse transformed-parent) + :origin (-> transformed-parent :points (nth 0)) + :vector (gpt/point scale-x scale-y)}))))) + +(defn calc-layout-data + "Digest the layout data to pass it to the constrains" + [{:keys [layout-dir layout-padding layout-padding-type] :as parent} children] + + (let [;; Add padding to the bounds + {pad-top :p1 pad-right :p2 pad-bottom :p3 pad-left :p4} layout-padding + [pad-top pad-right pad-bottom pad-left] + (if (= layout-padding-type :multiple) + [pad-top pad-right pad-bottom pad-left] + [pad-top pad-top pad-top pad-top]) + + ;; Normalize the points to remove flips + points (gst/parent-coords-points parent parent) + + layout-bounds (pad-points points pad-top pad-right pad-bottom pad-left) + + ;; Reverse + reverse? (or (= :left layout-dir) (= :bottom layout-dir)) + children (cond->> children reverse? reverse) + + ;; Creates the layout lines information + layout-lines + (->> (calc-layout-lines parent children layout-bounds) + (calc-layout-lines-position parent layout-bounds) + (map (partial calc-layout-line-data parent layout-bounds)))] + + {:layout-lines layout-lines + :reverse? reverse?})) + (defn calc-layout-modifiers "Calculates the modifiers for the layout" - [parent child layout-data] - (let [transform (:transform parent) - child-bounds (-> child :points gre/points->selrect) + [parent child layout-line] + (let [child-bounds (gst/parent-coords-points child parent) - fill-width (calc-fill-width-data child-bounds parent child layout-data) - fill-height (calc-fill-height-data child-bounds parent child layout-data) + child-origin (origin child-bounds) + child-width (width-points child-bounds) + child-height (height-points child-bounds) - child-bounds (cond-> child-bounds - fill-width (merge (:bounds fill-width)) - fill-height (merge (:bounds fill-height))) + fill-width (calc-fill-width-data parent child child-origin child-width layout-line) + fill-height (calc-fill-height-data parent child child-origin child-height layout-line) - [corner-p layout-data] (next-p parent child-bounds layout-data) + child-width (or (:width fill-width) child-width) + child-height (or (:height fill-height) child-height) - delta-p - (-> corner-p - (gpt/subtract (gpt/point child-bounds)) - (cond-> (some? transform) (gpt/transform transform))) + [corner-p layout-line] (next-p parent child-width child-height layout-line) + + move-vec (gpt/to-vec child-origin corner-p) modifiers (-> [] (cond-> fill-width (d/concat-vec (:modifiers fill-width))) (cond-> fill-height (d/concat-vec (:modifiers fill-height))) - (conj {:type :move :vector delta-p}))] - - [modifiers layout-data])) + (conj {:type :move :vector move-vec}))] + [modifiers layout-line])) diff --git a/common/src/app/common/geom/shapes/layout_new.cljc b/common/src/app/common/geom/shapes/layout_new.cljc deleted file mode 100644 index a15d038702..0000000000 --- a/common/src/app/common/geom/shapes/layout_new.cljc +++ /dev/null @@ -1,606 +0,0 @@ -;; 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) UXBOX Labs SL - -(ns app.common.geom.shapes.layout-new - (:require - [app.common.data :as d] - [app.common.geom.point :as gpt] - [app.common.geom.shapes.rect :as gre] - [app.common.geom.shapes.transforms :as gst] - )) - -;; :layout ;; true if active, false if not -;; :layout-dir ;; :right, :left, :top, :bottom -;; :layout-gap ;; number could be negative -;; :layout-type ;; :packed, :space-between, :space-around -;; :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 -;; :layout-h-orientation ;; :top, :center, :bottom -;; :layout-v-orientation ;; :left, :center, :right - -(defn col? - [{:keys [layout-dir]}] - (or (= :right layout-dir) (= :left layout-dir))) - -(defn row? - [{:keys [layout-dir]}] - (or (= :top layout-dir) (= :bottom layout-dir))) - -(defn h-start? - [{:keys [layout-h-orientation]}] - (= layout-h-orientation :left)) - -(defn h-center? - [{:keys [layout-h-orientation]}] - (= layout-h-orientation :center)) - -(defn h-end? - [{:keys [layout-h-orientation]}] - (= layout-h-orientation :right)) - -(defn v-start? - [{:keys [layout-v-orientation]}] - (= layout-v-orientation :top)) - -(defn v-center? - [{:keys [layout-v-orientation]}] - (= layout-v-orientation :center)) - -(defn v-end? - [{:keys [layout-v-orientation]}] - (= layout-v-orientation :bottom)) - -(defn add-padding [transformed-rect {:keys [layout-padding-type layout-padding]}] - (let [{:keys [p1 p2 p3 p4]} layout-padding - [p1 p2 p3 p4] - (if (= layout-padding-type :multiple) - [p1 p2 p3 p4] - [p1 p1 p1 p1])] - - (-> transformed-rect - (update :y + p1) - (update :width - p2 p3) - (update :x + p3) - (update :height - p1 p4)))) - -;; FUNCTIONS TO WORK WITH POINTS SQUARES - -(defn origin - [points] - (nth points 0)) - -(defn start-hv - "Horizontal vector from the origin with a magnitude `val`" - [[p0 p1 p2 p3] val] - (-> (gpt/to-vec p0 p1) - (gpt/unit) - (gpt/scale val))) - -(defn end-hv - "Horizontal vector from the oposite to the origin in the x axis with a magnitude `val`" - [[p0 p1 p2 p3] val] - (-> (gpt/to-vec p1 p0) - (gpt/unit) - (gpt/scale val))) - -(defn start-vv - "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" - [[p0 p1 p2 p3] val] - (-> (gpt/to-vec p0 p3) - (gpt/unit) - (gpt/scale val))) - -(defn end-vv - "Vertical vector from the oposite to the origin in the x axis with a magnitude `val`" - [[p0 p1 p2 p3] val] - (-> (gpt/to-vec p3 p0) - (gpt/unit) - (gpt/scale val))) - -;;(defn start-hp -;; [[p0 _ _ _ :as points] val] -;; (gpt/add p0 (start-hv points val))) -;; -;;(defn end-hp -;; "Horizontal Vector from the oposite to the origin in the x axis with a magnitude `val`" -;; [[_ p1 _ _ :as points] val] -;; (gpt/add p1 (end-hv points val))) -;; -;;(defn start-vp -;; "Vertical Vector from the oposite to the origin in the x axis with a magnitude `val`" -;; [[p0 _ _ _ :as points] val] -;; (gpt/add p0 (start-vv points val))) -;; -;;(defn end-vp -;; "Vertical Vector from the oposite to the origin in the x axis with a magnitude `val`" -;; [[_ _ p3 _ :as points] val] -;; (gpt/add p3 (end-vv points val))) - -(defn width-points - [[p0 p1 p2 p3]] - (gpt/length (gpt/to-vec p0 p1))) - -(defn height-points - [[p0 p1 p2 p3]] - (gpt/length (gpt/to-vec p0 p3))) - -(defn pad-points - [[p0 p1 p2 p3 :as points] pad-top pad-right pad-bottom pad-left] - (let [top-v (start-vv points pad-top) - right-v (end-hv points pad-right) - bottom-v (end-vv points pad-bottom) - left-v (start-hv points pad-left)] - - [(-> p0 (gpt/add left-v) (gpt/add top-v)) - (-> p1 (gpt/add right-v) (gpt/add top-v)) - (-> p2 (gpt/add right-v) (gpt/add bottom-v)) - (-> p3 (gpt/add left-v) (gpt/add bottom-v))])) - -;;;; - - -(defn calc-layout-lines - [{:keys [layout-gap layout-wrap-type] :as parent} children layout-bounds] - - (let [wrap? (= layout-wrap-type :wrap) - layout-width (width-points layout-bounds) - layout-height (height-points layout-bounds) - - reduce-fn - (fn [[{:keys [line-width line-height num-children line-fill? child-fill? num-child-fill] :as line-data} result] child] - (let [child-bounds (gst/parent-coords-points child parent) - child-width (width-points child-bounds) - child-height (height-points child-bounds) - - col? (col? parent) - row? (row? parent) - - cur-child-fill? - (or (and col? (= :fill (:layout-h-behavior child))) - (and row? (= :fill (:layout-v-behavior child)))) - - cur-line-fill? - (or (and row? (= :fill (:layout-h-behavior child))) - (and col? (= :fill (:layout-v-behavior child)))) - - ;; TODO LAYOUT: ADD MINWIDTH/HEIGHT - next-width (if (or (and col? cur-child-fill?) - (and row? cur-line-fill?)) - 0 - child-width) - - next-height (if (or (and row? cur-child-fill?) - (and col? cur-line-fill?)) - 0 - child-height) - - next-total-width (+ line-width next-width (* layout-gap num-children)) - next-total-height (+ line-height next-height (* layout-gap num-children))] - - (if (and (some? line-data) - (or (not wrap?) - (and col? (<= next-total-width layout-width)) - (and row? (<= next-total-height layout-height)))) - - ;; When :fill we add min width (0 by default) - [{:line-width (if col? (+ line-width next-width) (max line-width next-width)) - :line-height (if row? (+ line-height next-height) (max line-height next-height)) - :num-children (inc num-children) - :child-fill? (or cur-child-fill? child-fill?) - :line-fill? (or cur-line-fill? line-fill?) - :num-child-fill (cond-> num-child-fill cur-child-fill? inc)} - result] - - [{:line-width next-width - :line-height next-height - :num-children 1 - :child-fill? cur-child-fill? - :line-fill? cur-line-fill? - :num-child-fill (if cur-child-fill? 1 0)} - (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 parent} layout-bounds layout-lines] - - (let [layout-width (width-points layout-bounds) - layout-height (height-points layout-bounds) - row? (row? parent) - col? (col? parent) - h-center? (h-center? parent) - h-end? (h-end? parent) - v-center? (v-center? parent) - v-end? (v-end? parent) - space-between? (= :space-between layout-type) - space-around? (= :space-around layout-type)] - - (letfn [(get-base-line - [total-width total-height] - - (cond-> (origin layout-bounds) - (and row? h-center?) - (gpt/add (start-hv layout-bounds (/ (- layout-width total-width) 2))) - - (and row? h-end?) - (gpt/add (start-hv layout-bounds (- layout-width total-width))) - - (and col? v-center?) - (gpt/add (start-vv layout-bounds (/ (- layout-height total-height) 2))) - - (and col? v-end?) - (gpt/add (start-vv layout-bounds (- layout-height total-height))) - )) - - (get-start-line - [{:keys [line-width line-height num-children child-fill?]} base-p] - - (let [children-gap (* layout-gap (dec num-children)) - - ;;line-width (if (and col? child-fill?) - ;; (- layout-width (* layout-gap num-children)) - ;; line-width) - ;; - ;;line-height (if (and row? child-fill?) - ;; (- layout-height (* layout-gap num-children)) - ;; line-height) - - - start-p - (cond-> base-p - ;; X AXIS - (and col? h-center? (not space-between?) (not space-around?)) - (-> (gpt/add (start-hv layout-bounds (/ layout-width 2))) - (gpt/subtract (start-hv layout-bounds (/ (+ line-width children-gap) 2)))) - - (and col? h-end? (not space-between?) (not space-around?)) - (-> (gpt/add (start-hv layout-bounds layout-width)) - (gpt/subtract (start-hv layout-bounds (+ line-width children-gap)))) - - (and row? h-center? (not space-between?) (not space-around?)) - (gpt/add (start-hv layout-bounds (/ line-width 2))) - - (and row? h-end? (not space-between?) (not space-around?)) - (gpt/add (start-hv layout-bounds line-width)) - - ;; Y AXIS - (and row? v-center? (not space-between?) (not space-around?)) - (-> (gpt/add (start-vv layout-bounds (/ layout-height 2))) - (gpt/subtract (start-vv layout-bounds (/ (+ line-height children-gap) 2)))) - - (and row? v-end? (not space-between?) (not space-around?)) - (-> (gpt/add (start-vv layout-bounds layout-height)) - (gpt/subtract (start-vv layout-bounds (+ line-height children-gap)))) - - (and col? v-center? (not space-between?) (not space-around?)) - (gpt/add (start-vv layout-bounds (/ line-height 2))) - - (and col? v-end? (not space-between?) (not space-around?)) - (gpt/add (start-vv layout-bounds line-height)) - - ) - - - ;;start-x - ;;(cond - ;; ;;(and (col? shape) child-fill?) - ;; ;; TODO LAYOUT: Start has to take into account max-width - ;; ;;x - ;; - ;; (or (and col? space-between?) (and col? space-around?)) - ;; x - ;; - ;; (and col? h-center?) - ;; (- (+ x (/ width 2)) (/ (+ line-width children-gap) 2)) - ;; - ;; (and col? h-end?) - ;; (- (+ x width) (+ line-width children-gap)) - ;; - ;; (and row? h-center?) - ;; (+ base-x (/ line-width 2)) - ;; - ;; (and row? h-end?) - ;; (+ base-x line-width) - ;; - ;; row? - ;; base-x - ;; - ;; :else - ;; x) - - ;;start-y - ;;(cond - ;; ;; (and (row? shape) child-fill?) - ;; ;; TODO LAYOUT: Start has to take into account max-width - ;; ;; y - ;; - ;; (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-p)) - - (get-next-line - [{:keys [line-width line-height]} base-p] - - (cond-> base-p - col? - (gpt/add (start-hv layout-bounds (+ line-width layout-gap))) - - row? - (gpt/add (start-vv layout-bounds (+ line-height layout-gap))) - ) - - #_(let [next-x (if col? base-x (+ base-x line-width layout-gap)) - next-y (if row? 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-p] layout-line] - (let [start-p (get-start-line layout-line base-p) - next-p (get-next-line layout-line base-p)] - [(conj result - (assoc layout-line :start-p start-p)) - next-p]))] - - (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)))) - - vertical-fill-space (- layout-height total-height) - horizontal-fill-space (- layout-width total-width) - num-line-fill (count (->> layout-lines (filter :line-fill?))) - - layout-lines - (->> layout-lines - (mapv #(cond-> % - (and col? (:line-fill? %)) - (update :line-height + (/ vertical-fill-space num-line-fill)) - - (and row? (:line-fill? %)) - (update :line-width + (/ horizontal-fill-space num-line-fill))))) - - total-height (if (and col? (> num-line-fill 0)) layout-height total-height) - total-width (if (and row? (> num-line-fill 0)) layout-width total-width) - - base-p (get-base-line total-width total-height) - - [layout-lines _ _ _ _] - (reduce add-starts [[] base-p] 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 - - (= :space-around layout-type) - 0 - - (and (col? shape) (= :space-between layout-type)) - (/ (- width line-width) (dec num-children)) - - (and (row? shape) (= :space-between layout-type)) - (/ (- height line-height) (dec num-children))) - - 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 line-height) (inc num-children)) - 0)] - - (assoc line-data - :layout-bounds layout-bounds - :layout-gap layout-gap - :margin-x margin-x - :margin-y margin-y))) - -(defn next-p - "Calculates the position for the current shape given the layout-data context" - [parent - child-bounds - {:keys [start-p layout-gap margin-x margin-y] :as layout-data}] - - (let [width (width-points child-bounds) - height (height-points child-bounds) - - row? (row? parent) - col? (col? parent) - h-center? (h-center? parent) - h-end? (h-end? parent) - v-center? (v-center? parent) - v-end? (v-end? parent) - points (:points parent) - - corner-p - (cond-> start-p - (and row? h-center?) - (gpt/add (start-hv points (- (/ width 2)))) - - (and row? h-end?) - (gpt/add (start-hv points (- width))) - - (and col? v-center?) - (gpt/add (start-vv points (- (/ height 2)))) - - (and col? v-end?) - (gpt/add (start-vv points (- height))) - - (some? margin-x) - (gpt/add (start-hv points margin-x)) - - (some? margin-y) - (gpt/add (start-vv points margin-y))) - - next-p - (cond-> start-p - col? - (gpt/add (start-hv points (+ width layout-gap))) - - row? - (gpt/add (start-vv points (+ height layout-gap))) - - (some? margin-x) - (gpt/add (start-hv points margin-x)) - - (some? margin-y) - (gpt/add (start-vv points margin-y))) - - layout-data - (assoc layout-data :start-p next-p)] - - [corner-p layout-data])) - -(defn calc-fill-width-data - [child-bounds - {:keys [layout-gap] :as parent} - {:keys [layout-h-behavior] :as child} - {:keys [num-children line-width layout-bounds line-fill? child-fill?] :as layout-data}] - - (cond - (and (col? parent) (= :fill layout-h-behavior) child-fill?) - (let [fill-space (- (:width layout-bounds) line-width (* layout-gap num-children)) - fill-width (/ fill-space (:num-child-fill layout-data)) - fill-scale (/ fill-width (:width child-bounds))] - {:bounds {:width fill-width} - :modifiers [{:type :resize - :origin (gpt/point child-bounds) - :vector (gpt/point fill-scale 1)}]}) - - (and (row? parent) (= :fill layout-h-behavior) line-fill?) - (let [fill-scale (/ line-width (:width child-bounds))] - {:bounds {:width line-width} - :modifiers [{:type :resize - :origin (gpt/point child-bounds) - :vector (gpt/point fill-scale 1)}]}) - )) - -(defn calc-fill-height-data - [child-bounds - {:keys [layout-gap] :as parent} - {:keys [layout-v-behavior] :as child} - {:keys [num-children line-height layout-bounds line-fill? child-fill?] :as layout-data}] - - (cond - (and (row? parent) (= :fill layout-v-behavior) child-fill?) - (let [fill-space (- (:height layout-bounds) line-height (* layout-gap num-children)) - fill-height (/ fill-space (:num-child-fill layout-data)) - fill-scale (/ fill-height (:height child-bounds))] - {:bounds {:height fill-height} - :modifiers [{:type :resize - :origin (gpt/point child-bounds) - :vector (gpt/point 1 fill-scale)}]}) - - (and (col? parent) (= :fill layout-v-behavior) line-fill?) - (let [fill-scale (/ line-height (:height child-bounds))] - {:bounds {:height line-height} - :modifiers [{:type :resize - :origin (gpt/point child-bounds) - :vector (gpt/point 1 fill-scale)}]}) - )) - -(defn normalize-child-modifiers - "Apply the modifiers and then normalized them against the parent coordinates" - [parent child modifiers transformed-parent] - - (let [transformed-child (gst/transform-shape child modifiers) - child-bb-before (gst/parent-coords-rect child parent) - child-bb-after (gst/parent-coords-rect transformed-child transformed-parent) - scale-x (/ (:width child-bb-before) (:width child-bb-after)) - scale-y (/ (:height child-bb-before) (:height child-bb-after))] - (-> modifiers - (update :v2 #(conj % - {:type :resize - :transform (:transform transformed-parent) - :transform-inverse (:transform-inverse transformed-parent) - :origin (-> transformed-parent :points (nth 0)) - :vector (gpt/point scale-x scale-y)}))))) - -(defn calc-layout-data - "Digest the layout data to pass it to the constrains" - [{:keys [layout-dir points layout-padding layout-padding-type] :as parent} children] - - (let [;; Add padding to the bounds - {pad-top :p1 pad-right :p2 pad-bottom :p3 pad-left :p4} layout-padding - [pad-top pad-right pad-bottom pad-left] - (if (= layout-padding-type :multiple) - [pad-top pad-right pad-bottom pad-left] - [pad-top pad-top pad-top pad-top]) - layout-bounds (-> points (pad-points pad-top pad-right pad-bottom pad-left)) - - ;; Reverse - reverse? (or (= :left layout-dir) (= :bottom layout-dir)) - children (cond->> children reverse? reverse) - - ;; Creates the layout lines information - layout-lines - (->> (calc-layout-lines parent children layout-bounds) - (calc-layout-lines-position parent layout-bounds) - (map (partial calc-layout-line-data parent layout-bounds)))] - - {:layout-lines layout-lines - :reverse? reverse?})) - -(defn calc-layout-modifiers - "Calculates the modifiers for the layout" - [parent child layout-line] - (let [child-bounds (gst/parent-coords-points child parent) - - ;;fill-width (calc-fill-width-data child-bounds parent child layout-line) - ;;fill-height (calc-fill-height-data child-bounds parent child layout-line) - - ;;child-bounds (cond-> child-bounds - ;; fill-width (merge (:bounds fill-width)) - ;; fill-height (merge (:bounds fill-height))) - - - [corner-p layout-line] (next-p parent child-bounds layout-line) - - move-vec (gpt/to-vec (origin child-bounds) corner-p) - - modifiers - (-> [] - #_(cond-> fill-width (d/concat-vec (:modifiers fill-width))) - #_(cond-> fill-height (d/concat-vec (:modifiers fill-height))) - (conj {:type :move :vector move-vec}))] - - [modifiers layout-line])) - diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index fc987dfc9a..7eaf9fb5af 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -11,8 +11,7 @@ [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.constraints :as gct] - [app.common.geom.shapes.layout :as gclo] - [app.common.geom.shapes.layout-new :as gcln] + [app.common.geom.shapes.layout :as gcl] [app.common.geom.shapes.rect :as gpr] [app.common.geom.shapes.transforms :as gtr] [app.common.math :as mth] @@ -142,7 +141,7 @@ (letfn [(normalize-child [transformed-parent _snap-pixel? modif-tree child] (let [modifiers (get-in modif-tree [(:id parent) :modifiers]) - child-modifiers (gcln/normalize-child-modifiers parent child modifiers transformed-parent)] + child-modifiers (gcl/normalize-child-modifiers parent child modifiers transformed-parent)] (cond-> modif-tree (not (ctm/empty-modifiers? child-modifiers)) (update-in [(:id child) :modifiers :v2] d/concat-vec (:v2 child-modifiers))))) @@ -153,12 +152,12 @@ (some? modifiers) (gtr/transform-shape modifiers) - (and (nil? modifiers) (group? child)) + (and (some? modifiers) (group? child)) (gtr/apply-group-modifiers objects modif-tree)))) (set-layout-modifiers [parent [layout-line modif-tree] child] (let [[modifiers layout-line] - (gcln/calc-layout-modifiers parent child layout-line) + (gcl/calc-layout-modifiers parent child layout-line) modif-tree (cond-> modif-tree @@ -175,7 +174,7 @@ children (->> children (map (partial apply-modifiers modif-tree))) - layout-data (gcln/calc-layout-data transformed-parent children) + layout-data (gcl/calc-layout-data transformed-parent children) children (into [] (cond-> children (:reverse? layout-data) reverse)) @@ -325,12 +324,13 @@ :else (recur (:parent-id current)))))) -#_(defn modif->js - [modif-tree objects] - (clj->js (into {} - (map (fn [[k v]] - [(get-in objects [k :name]) v])) - modif-tree))) +;;#?(:cljs +;; (defn modif->js +;; [modif-tree objects] +;; (clj->js (into {} +;; (map (fn [[k v]] +;; [(get-in objects [k :name]) v])) +;; modif-tree)))) (defn set-objects-modifiers [ids objects get-modifier ignore-constraints snap-pixel?] @@ -367,5 +367,6 @@ modif-tree))] - ;;(.log js/console ">result" (modif->js modif-tree objects)) + ;; #?(:cljs + ;; (.log js/console ">result" (modif->js modif-tree objects))) modif-tree)) diff --git a/frontend/src/app/main/ui/workspace/shapes/frame.cljs b/frontend/src/app/main/ui/workspace/shapes/frame.cljs index 07b57d1564..1de768035e 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame.cljs @@ -24,10 +24,7 @@ [app.main.ui.workspace.shapes.frame.node-store :as fns] [app.main.ui.workspace.shapes.frame.thumbnail-render :as ftr] [beicon.core :as rx] - [rumext.v2 :as mf] - - [app.common.geom.shapes.layout :as gsl] - [app.common.geom.point :as gpt])) + [rumext.v2 :as mf])) (defn frame-shape-factory [shape-wrapper]