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 9247f20bf..7f0d5ee5b 100644 --- a/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/modifiers.cljc @@ -63,8 +63,7 @@ {:height target-height :modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)}))) -(defn layout-child-modifiers - "Calculates the modifiers for the layout" +(defn fill-modifiers [parent parent-bounds child child-bounds layout-line] (let [child-origin (gpo/origin child-bounds) child-width (gpo/width-points child-bounds) @@ -83,15 +82,27 @@ (calc-fill-height-data parent transform transform-inverse child child-origin child-height layout-line)) child-width (or (:width fill-width) child-width) - child-height (or (:height fill-height) child-height) + child-height (or (:height fill-height) child-height)] + + [child-width + child-height + (-> (ctm/empty) + (cond-> fill-width (ctm/add-modifiers (:modifiers fill-width))) + (cond-> fill-height (ctm/add-modifiers (:modifiers fill-height))))])) + +(defn layout-child-modifiers + "Calculates the modifiers for the layout" + [parent parent-bounds child child-bounds layout-line] + (let [child-origin (gpo/origin child-bounds) + + [child-width child-height fill-modifiers] + (fill-modifiers parent parent-bounds child child-bounds 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) modifiers (-> (ctm/empty) - (cond-> fill-width (ctm/add-modifiers (:modifiers fill-width))) - (cond-> fill-height (ctm/add-modifiers (:modifiers fill-height))) + (ctm/add-modifiers fill-modifiers) (ctm/move move-vec))] [modifiers layout-line])) diff --git a/common/src/app/common/geom/shapes/grid_layout.cljc b/common/src/app/common/geom/shapes/grid_layout.cljc index cb28f3ab7..8483b8dde 100644 --- a/common/src/app/common/geom/shapes/grid_layout.cljc +++ b/common/src/app/common/geom/shapes/grid_layout.cljc @@ -15,3 +15,4 @@ (dm/export glp/child-modifiers) (dm/export glp/get-position-grid-coord) (dm/export glp/get-drop-cell) +(dm/export glp/cell-bounds) diff --git a/common/src/app/common/geom/shapes/grid_layout/positions.cljc b/common/src/app/common/geom/shapes/grid_layout/positions.cljc index 3dcdeba33..30d5de604 100644 --- a/common/src/app/common/geom/shapes/grid_layout/positions.cljc +++ b/common/src/app/common/geom/shapes/grid_layout/positions.cljc @@ -7,19 +7,108 @@ (ns app.common.geom.shapes.grid-layout.positions (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.grid-layout.layout-data :as ld] [app.common.geom.shapes.points :as gpo] + [app.common.geom.shapes.transforms :as gtr] [app.common.math :as mth] [app.common.pages.helpers :as cph] - [app.common.types.modifiers :as ctm])) + [app.common.types.modifiers :as ctm] + [app.common.types.shape.layout :as ctl])) + +(defn cell-bounds + [{:keys [origin row-tracks column-tracks layout-bounds column-gap row-gap] :as layout-data} {:keys [row column row-span column-span] :as cell}] + + (let [hv #(gpo/start-hv layout-bounds %) + vv #(gpo/start-vv layout-bounds %) + + span-column-tracks (subvec column-tracks (dec column) (+ (dec column) column-span)) + span-row-tracks (subvec row-tracks (dec row) (+ (dec row) row-span)) + + p1 + (gpt/add + origin + (gpt/add + (gpt/to-vec origin (dm/get-in span-column-tracks [0 :start-p])) + (gpt/to-vec origin (dm/get-in span-row-tracks [0 :start-p])))) + + p2 + (as-> p1 $ + (reduce (fn [p track] (gpt/add p (hv (:size track)))) $ span-column-tracks) + (gpt/add $ (hv (* column-gap (dec (count span-column-tracks)))))) + + p3 + (as-> p2 $ + (reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks) + (gpt/add $ (vv (* row-gap (dec (count span-row-tracks)))))) + + p4 + (as-> p1 $ + (reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks) + (gpt/add $ (vv (* row-gap (dec (count span-row-tracks))))))] + [p1 p2 p3 p4])) + +(defn calc-fill-width-data + "Calculates the size and modifiers for the width of an auto-fill child" + [_parent + transform + transform-inverse + _child + child-origin child-width + cell-bounds] + + (let [target-width (max (gpo/width-points cell-bounds) 0.01) + fill-scale (/ target-width child-width)] + {:width target-width + :modifiers (ctm/resize-modifiers (gpt/point fill-scale 1) child-origin transform transform-inverse)})) + +(defn calc-fill-height-data + "Calculates the size and modifiers for the height of an auto-fill child" + [_parent + transform transform-inverse + _child + child-origin child-height + cell-bounds] + (let [target-height (max (gpo/height-points cell-bounds) 0.01) + fill-scale (/ target-height child-height)] + {:height target-height + :modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)})) + +(defn fill-modifiers + [parent parent-bounds child child-bounds layout-data cell-data] + (let [child-origin (gpo/origin child-bounds) + child-width (gpo/width-points child-bounds) + child-height (gpo/height-points child-bounds) + + cell-bounds (cell-bounds layout-data cell-data) + + [_ transform transform-inverse] + (when (or (ctl/fill-width? child) (ctl/fill-height? child)) + (gtr/calculate-geometry @parent-bounds)) + + fill-width + (when (ctl/fill-width? child) + (calc-fill-width-data parent transform transform-inverse child child-origin child-width cell-bounds)) + + fill-height + (when (ctl/fill-height? child) + (calc-fill-height-data parent transform transform-inverse child child-origin child-height cell-bounds))] + + (-> (ctm/empty) + (cond-> fill-width (ctm/add-modifiers (:modifiers fill-width))) + (cond-> fill-height (ctm/add-modifiers (:modifiers fill-height)))))) (defn child-modifiers - [_parent _transformed-parent-bounds _child child-bounds cell-data] - (ctm/move-modifiers - (gpt/subtract (:start-p cell-data) (gpo/origin child-bounds)))) + [parent parent-bounds child child-bounds layout-data cell-data] + + (let [fill-modifiers (fill-modifiers parent parent-bounds child child-bounds layout-data cell-data) + position-delta (gpt/subtract (:start-p cell-data) (gpo/origin child-bounds))] + (-> (ctm/empty) + (ctm/add-modifiers fill-modifiers) + (ctm/move position-delta)))) (defn line-value diff --git a/common/src/app/common/geom/shapes/modifiers.cljc b/common/src/app/common/geom/shapes/modifiers.cljc index 37dd7019a..9d3df9ed4 100644 --- a/common/src/app/common/geom/shapes/modifiers.cljc +++ b/common/src/app/common/geom/shapes/modifiers.cljc @@ -205,8 +205,10 @@ (gpo/parent-coords-bounds @transformed-parent-bounds)) child]) - (set-child-modifiers [modif-tree cell-data [child-bounds child]] - (let [modifiers (gcgl/child-modifiers parent transformed-parent-bounds child child-bounds cell-data) + (set-child-modifiers [modif-tree grid-data cell-data [child-bounds child]] + (let [modifiers + (gcgl/child-modifiers parent transformed-parent-bounds child child-bounds grid-data cell-data) + modif-tree (cond-> modif-tree (d/not-empty? modifiers) @@ -224,7 +226,7 @@ (let [cell-data (gcgl/get-cell-data grid-data @transformed-parent-bounds bound+child) modif-tree (cond-> modif-tree (some? cell-data) - (set-child-modifiers cell-data bound+child))] + (set-child-modifiers grid-data cell-data bound+child))] (recur modif-tree (first pending) (rest pending))) modif-tree))))) diff --git a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs index 185af68f9..b446f1b7b 100644 --- a/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/grid_layout_editor.cljs @@ -271,45 +271,26 @@ (mf/defc grid-cell {::mf/wrap-props false} [props] - (let [shape (unchecked-get props "shape") + (let [shape (unchecked-get props "shape") + cell (unchecked-get props "cell") + layout-data (unchecked-get props "layout-data") + zoom (unchecked-get props "zoom") + hover? (unchecked-get props "hover?") + selected? (unchecked-get props "selected?") - {:keys [row column row-span column-span] :as cell} (unchecked-get props "cell") - {:keys [origin row-tracks column-tracks layout-bounds column-gap row-gap] :as layout-data} - (unchecked-get props "layout-data") - zoom (unchecked-get props "zoom") - - hover? (unchecked-get props "hover?") - selected? (unchecked-get props "selected?") - - span-column-tracks (subvec column-tracks (dec column) (+ (dec column) column-span)) - span-row-tracks (subvec row-tracks (dec row) (+ (dec row) row-span)) - - hv #(gpo/start-hv layout-bounds %) - vv #(gpo/start-vv layout-bounds %) - - start-p (gpt/add origin - (gpt/add - (gpt/to-vec origin (dm/get-in span-column-tracks [0 :start-p])) - (gpt/to-vec origin (dm/get-in span-row-tracks [0 :start-p])))) - - end-p - (as-> start-p $ - (reduce (fn [p track] (gpt/add p (hv (:size track)))) $ span-column-tracks) - (reduce (fn [p track] (gpt/add p (vv (:size track)))) $ span-row-tracks) - (gpt/add $ (hv (* column-gap (dec (count span-column-tracks))))) - (gpt/add $ (vv (* row-gap (dec (count span-row-tracks)))))) - - cell-width (- (:x end-p) (:x start-p)) - cell-height (- (:y end-p) (:y start-p))] + cell-bounds (gsg/cell-bounds layout-data cell) + cell-origin (gpo/origin cell-bounds) + cell-width (gpo/width-points cell-bounds) + cell-height (gpo/height-points cell-bounds)] [:g.cell-editor [:rect {:class (dom/classnames (css :grid-cell-outline) true (css :hover) hover? (css :selected) selected?) - :x (:x start-p) - :y (:y start-p) + :x (:x cell-origin) + :y (:y cell-origin) :width cell-width :height cell-height @@ -320,10 +301,10 @@ (when selected? (let [handlers ;; Handlers positions, size and cursor - [[:top (:x start-p) (+ (:y start-p) (/ -10 zoom)) cell-width (/ 20 zoom) :row] - [:right (+ (:x start-p) cell-width (/ -10 zoom)) (:y start-p) (/ 20 zoom) cell-height :column] - [:bottom (:x start-p) (+ (:y start-p) cell-height (/ -10 zoom)) cell-width (/ 20 zoom) :row] - [:left (+ (:x start-p) (/ -10 zoom)) (:y start-p) (/ 20 zoom) cell-height :column]]] + [[:top (:x cell-origin) (+ (:y cell-origin) (/ -10 zoom)) cell-width (/ 20 zoom) :row] + [:right (+ (:x cell-origin) cell-width (/ -10 zoom)) (:y cell-origin) (/ 20 zoom) cell-height :column] + [:bottom (:x cell-origin) (+ (:y cell-origin) cell-height (/ -10 zoom)) cell-width (/ 20 zoom) :row] + [:left (+ (:x cell-origin) (/ -10 zoom)) (:y cell-origin) (/ 20 zoom) cell-height :column]]] [:* (for [[handler x y width height dir] handlers] [:& resize-cell-handler {:key (dm/str "resize-" (d/name handler) "-" (:id cell)) @@ -366,7 +347,6 @@ (reset! start-size-after (:size track-after)) (let [tracks-prop (if (= :column type) :layout-grid-columns :layout-grid-rows) - shape (-> shape (cond-> (some? track-before) @@ -387,7 +367,8 @@ (if (= :column type) [:layout-grid-columns :x] [:layout-grid-rows :y]) precision (if snap-pixel? mth/round identity) - delta (get position axis) + delta (/ (get position axis) zoom) + shape (-> shape (cond-> (some? track-before) @@ -439,7 +420,7 @@ :style {:fill "transparent"}}])) (mf/defc track - {::mf/wrap [mf/memo] + {::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "zoom" "index" "type" "track-data" "layout-data"]))] ::mf/wrap-props false} [props] (let [shape (unchecked-get props "shape") @@ -485,7 +466,7 @@ value (-> target dom/get-input-value str/upper) value-int (d/parse-integer value) - [type value] + [track-type value] (cond (str/ends-with? value "%") [:percent value-int] @@ -498,10 +479,10 @@ (or (= value "AUTO") (= "" value)) [:auto nil])] - (if (some? type) - (do (dom/set-value! target (format-size {:type type :value value})) - (dom/set-data! target "default-value" (format-size {:type type :value value})) - (st/emit! (dwsl/change-layout-track [(:id shape)] type index {:type type :value value}))) + + (if (some? track-type) + (do (st/emit! (dwsl/change-layout-track [(:id shape)] type index {:type track-type :value value})) + (dom/set-data! target "default-value" (format-size {:type type :value value}))) (obj/set! target "value" (dom/get-attribute target "data-default-value")))))) handle-keydown-track-input @@ -659,6 +640,26 @@ :layout-data layout-data :track-data row-data}]) + (let [last-track (last row-tracks) + start-p (:start-p (last row-tracks)) + marker-p (-> start-p + (gpt/subtract (hv (/ 20 zoom))) + (gpt/add (vv (:size last-track))))] + [:g.track + [:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))} + [:& track-marker {:center marker-p + :value (dm/str (inc (count row-tracks))) + :zoom zoom}]] + [:& resize-track-handler + {:index (count row-tracks) + :shape shape + :layout-data layout-data + :start-p (-> start-p + (gpt/add (vv (:size last-track)))) + :type :row + :track-before (last row-tracks) + :zoom zoom}]]) + (for [[_ cell] (:layout-grid-cells shape)] [:& grid-cell {:key (dm/str "cell-" (:id cell)) :shape base-shape