Support for multi-track span in cells

This commit is contained in:
alonso.torres 2023-04-27 10:35:06 +02:00
parent 43d1f676ef
commit 0eff2e8887
9 changed files with 354 additions and 145 deletions

View file

@ -9,7 +9,7 @@
[potok.core :as ptk]))
(defn hover-grid-cell
[grid-id row column add-to-set]
[grid-id cell-id add-to-set]
(ptk/reify ::hover-grid-cell
ptk/UpdateEvent
(update [_ state]
@ -19,15 +19,15 @@
(fn [hover-set]
(let [hover-set (or hover-set #{})]
(if add-to-set
(conj hover-set [row column])
(disj hover-set [row column]))))))))
(conj hover-set cell-id)
(disj hover-set cell-id))))))))
(defn select-grid-cell
[grid-id row column]
[grid-id cell-id]
(ptk/reify ::select-grid-cell
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-grid-edition grid-id :selected] [row column]))))
(assoc-in state [:workspace-grid-edition grid-id :selected] cell-id))))
(defn remove-selection
[grid-id]

View file

@ -73,10 +73,10 @@
first-selected-shape (first selected-shapes)
shape-parent-frame (cph/get-frame objects (:frame-id first-selected-shape))
[grid-id {[row-selected col-selected] :selected}]
[grid-id {cell-id :selected}]
(d/seek (fn [[_ {:keys [selected]}]] (some? selected)) grid-edition)
grid-cell-selected? (and (some? grid-id) (some? row-selected) (some? col-selected))
grid-cell-selected? (and (some? grid-id) (some? cell-id))
on-change-tab
(fn [options-mode]
@ -96,8 +96,7 @@
[:& bool-options]
(cond
grid-cell-selected? [:& grid-cell/options {:shape (get objects grid-id)
:row row-selected
:column col-selected}]
:cell (get-in objects [grid-id :layout-grid-cells cell-id])}]
(d/not-empty? drawing) [:& shape-options {:shape (:object drawing)
:page-id page-id

View file

@ -447,7 +447,7 @@
(when expanded?
[:div.columns-info-wrapper
(for [[index column] (d/enumerate column-values)]
[:div.column-info
[:div.column-info {:key (dm/str index "-" (name type) "-" column)}
[:div.direction-grid-icon
(if is-col?
i/layout-rows

View file

@ -31,7 +31,7 @@
(mf/defc options
{::mf/wrap [mf/memo]}
[{:keys [_shape row column] :as props}]
[{:keys [_shape cell] :as props}]
(let [position-mode (mf/use-state :auto) ;; TODO this should come from shape
@ -51,10 +51,10 @@
#_(if (= align-self value)
(st/emit! (dwsl/update-layout-child ids {:layout-item-align-self nil}))
(st/emit! (dwsl/update-layout-child ids {:layout-item-align-self value}))))
column-start column
column-end (inc column)
row-start row
row-end (inc row)
column-start (:column cell)
column-end (+ (:column cell) (:column-span cell))
row-start (:row cell)
row-end (+ (:row cell) (:row-span cell))
on-change
(fn [_side _orientation _value]

View file

@ -203,6 +203,9 @@
show-pixel-grid? (and (contains? layout :show-pixel-grid)
(>= zoom 8))
show-text-editor? (and editing-shape (= :text (:type editing-shape)))
hover-grid? (and (some? @hover-top-frame-id) (ctl/grid-layout? objects @hover-top-frame-id))
show-grid-editor? (and editing-shape (ctl/grid-layout? editing-shape))
show-presence? page-id
show-prototypes? (= options-mode :prototype)
@ -586,8 +589,15 @@
{:id (first selected)
:zoom zoom}])
(when show-grid-editor?
;; TODO: Temporary showing on hover. Remove eventualy
(when (or show-grid-editor? hover-grid?)
[:& grid-layout/editor
{:zoom zoom
:objects base-objects
:shape (get base-objects edition)}])]]]))
:objects objects-modified
:shape (or (get objects-modified edition)
(gsh/transform-shape
(get base-objects @hover-top-frame-id)
(dm/get-in modifiers [@hover-top-frame-id :modifiers])))
:view-only (not show-grid-editor?)
}])
]]]))

View file

@ -11,9 +11,10 @@
[app.common.geom.point :as gpt]
[app.common.geom.shapes.grid-layout :as gsg]
[app.common.geom.shapes.points :as gpo]
[app.common.pages.helpers :as cph]
[app.common.types.modifiers :as ctm]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.grid-layout.editor :as dwge]
[app.main.data.workspace.modifiers :as dwm]
[app.main.data.workspace.shape-layout :as dwsl]
[app.main.refs :as refs]
[app.main.store :as st]
@ -145,8 +146,7 @@
(defn use-drag
[{:keys [on-drag-start on-drag-end on-drag-delta on-drag-position]}]
(let [
dragging-ref (mf/use-ref false)
(let [dragging-ref (mf/use-ref false)
start-pos-ref (mf/use-ref nil)
current-pos-ref (mf/use-ref nil)
@ -175,6 +175,7 @@
handle-pointer-move
(mf/use-callback
(mf/deps on-drag-delta on-drag-position)
(fn [event]
(when (mf/ref-val dragging-ref)
(let [start (mf/ref-val start-pos-ref)
@ -191,22 +192,67 @@
(mf/defc resize-cell-handler
{::mf/wrap-props false}
[props]
(let [x (unchecked-get props "x")
(let [shape (unchecked-get props "shape")
x (unchecked-get props "x")
y (unchecked-get props "y")
width (unchecked-get props "width")
height (unchecked-get props "height")
handler (unchecked-get props "handler")
{cell-id :id} (unchecked-get props "cell")
{:keys [row column row-span column-span]} (get-in shape [:layout-grid-cells cell-id])
direction (unchecked-get props "direction")
layout-data (unchecked-get props "layout-data")
cursor (if (= direction :row) (cur/scale-ns 0) (cur/scale-ew 0))
handle-drag-position
(mf/use-callback
(mf/deps shape row column row-span column-span)
(fn [position]
(prn ">>>" (gsg/get-position-grid-coord layout-data position))))
(let [[drag-row drag-column] (gsg/get-position-grid-coord layout-data position)
[new-row new-column new-row-span new-column-span]
(case handler
:top
(let [new-row (min (+ row (dec row-span)) drag-row)
new-row-span (+ (- row new-row) row-span)]
[new-row column new-row-span column-span])
:left
(let [new-column (min (+ column (dec column-span)) drag-column)
new-column-span (+ (- column new-column) column-span)]
[row new-column row-span new-column-span])
:bottom
(let [new-row-span (max 1 (inc (- drag-row row)))]
[row column new-row-span column-span])
:right
(let [new-column-span (max 1 (inc (- drag-column column)))]
[row column row-span new-column-span]))
shape
(-> (ctl/resize-cell-area shape row column new-row new-column new-row-span new-column-span)
(ctl/assign-cells))
modifiers
(-> (ctm/empty)
(ctm/change-property :layout-grid-rows (:layout-grid-rows shape))
(ctm/change-property :layout-grid-columns (:layout-grid-columns shape))
(ctm/change-property :layout-grid-cells (:layout-grid-cells shape)))]
(st/emit! (dwm/set-modifiers (dwm/create-modif-tree [(:id shape)] modifiers))))))
handle-drag-end
(mf/use-callback
(fn []
(st/emit! (dwm/apply-modifiers))))
{:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
(use-drag {:on-drag-position handle-drag-position})]
(use-drag {:on-drag-position handle-drag-position
;;:on-drag-start handle-drag-start
:on-drag-end handle-drag-end})]
[:rect
{:x x
:y y
@ -223,7 +269,8 @@
[props]
(let [shape (unchecked-get props "shape")
{:keys [origin row-tracks column-tracks layout-bounds] :as layout-data}
{: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")
@ -231,23 +278,23 @@
hover? (unchecked-get props "hover?")
selected? (unchecked-get props "selected?")
row (unchecked-get props "row")
column (unchecked-get props "column")
column-track (nth column-tracks (dec column) nil)
row-track (nth row-tracks (dec row) nil)
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 (:start-p column-track))
(gpt/to-vec origin (:start-p row-track))))
(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 (-> start-p
(gpt/add (hv (:size column-track)))
(gpt/add (vv (:size row-track))))
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))]
@ -259,10 +306,9 @@
:width cell-width
:height cell-height
:on-pointer-enter #(st/emit! (dwge/hover-grid-cell (:id shape) row column true))
:on-pointer-leave #(st/emit! (dwge/hover-grid-cell (:id shape) row column false))
:on-click #(st/emit! (dwge/select-grid-cell (:id shape) row column))
:on-pointer-enter #(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) true))
:on-pointer-leave #(st/emit! (dwge/hover-grid-cell (:id shape) (:id cell) false))
:on-click #(st/emit! (dwge/select-grid-cell (:id shape) (:id cell)))
:style {:fill "transparent"
:stroke "var(--color-distance)"
@ -274,14 +320,18 @@
(when selected?
(let [handlers
;; Handlers positions, size and cursor
[[(:x start-p) (+ (:y start-p) (/ -10 zoom)) cell-width (/ 20 zoom) :row]
[(+ (:x start-p) cell-width (/ -10 zoom)) (:y start-p) (/ 20 zoom) cell-height :column]
[(:x start-p) (+ (:y start-p) cell-height (/ -10 zoom)) cell-width (/ 20 zoom) :row]
[(+ (:x start-p) (/ -10 zoom)) (:y start-p) (/ 20 zoom) cell-height :column]]]
[[: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]]]
[:*
(for [[x y width height dir] handlers]
[:& resize-cell-handler {:x x
(for [[handler x y width height dir] handlers]
[:& resize-cell-handler {:key (dm/str "resize-" (d/name handler) "-" (:id cell))
:shape shape
:handler handler
:x x
:y y
:cell cell
:width width
:height height
:direction dir
@ -355,21 +405,28 @@
:style {:fill "transparent"}}]))
(mf/defc editor
{::mf/wrap-props false}
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[props]
(let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects")
zoom (unchecked-get props "zoom")
(let [shape (unchecked-get props "shape")
objects (unchecked-get props "objects")
zoom (unchecked-get props "zoom")
view-only (unchecked-get props "view-only")
bounds (:points shape)
;; We need to know the state unmodified so we can create the modifiers
shape-ref (mf/use-memo (mf/deps (:id shape)) #(refs/object-by-id (:id shape)))
base-shape (mf/deref shape-ref)
grid-edition-id-ref (mf/use-memo #(refs/workspace-grid-edition-id (:id shape)))
grid-edition (mf/deref grid-edition-id-ref)
hover-cells (:hover grid-edition)
selected-cells (:selected grid-edition)
children (->> (cph/get-immediate-children objects (:id shape))
children (->> (:shapes shape)
(map (d/getf objects))
(remove :hidden)
(map #(vector (gpo/parent-coords-bounds (:points %) (:points shape)) %)))
@ -400,22 +457,22 @@
(fn []
#(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
[:g.grid-editor
[:& grid-editor-frame {:zoom zoom
:bounds bounds}]
(let [start-p (-> origin (gpt/add (hv width)))]
[:& plus-btn {:start-p start-p
:zoom zoom
:type :column
:on-click handle-add-column}])
(let [start-p (-> origin (gpt/add (vv height)))]
[:& plus-btn {:start-p start-p
:zoom zoom
:type :row
:on-click handle-add-row}])
[:g.grid-editor {:pointer-events (when view-only "none")}
(when-not view-only
[:*
[:& grid-editor-frame {:zoom zoom
:bounds bounds}]
(let [start-p (-> origin (gpt/add (hv width)))]
[:& plus-btn {:start-p start-p
:zoom zoom
:type :column
:on-click handle-add-column}])
(let [start-p (-> origin (gpt/add (vv height)))]
[:& plus-btn {:start-p start-p
:zoom zoom
:type :row
:on-click handle-add-row}])])
(for [[idx column-data] (d/enumerate column-tracks)]
(let [start-p (:start-p column-data)
@ -427,7 +484,7 @@
text-p (-> start-p
(gpt/subtract (vv (/ 20 zoom)))
(gpt/add (hv (/ (:size column-data) 2))))]
[:*
[:* {:key (dm/str "column-" idx)}
[:& track-marker {:center marker-p
:value (dm/str (inc idx))
:zoom zoom}]
@ -454,12 +511,12 @@
marker-p (-> start-p
(gpt/subtract (hv (/ 20 zoom)))
(cond-> (not= idx 0)
(gpt/subtract (vv (/ layout-gap-row 2)))))
(gpt/subtract (vv (/ layout-gap-row 2)))))
text-p (-> start-p
(gpt/subtract (hv (/ 20 zoom)))
(gpt/add (vv (/ (:size row-data) 2))))]
[:*
[:* {:key (dm/str "row-" idx)}
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
[:& track-marker {:center marker-p
:value (dm/str (inc idx))
@ -483,11 +540,11 @@
:type :column
:zoom zoom}])]))
(for [[_ {:keys [column row]}] (:layout-grid-cells shape)]
[:& grid-cell {:shape shape
(for [[_ cell] (:layout-grid-cells shape)]
[:& grid-cell {:key (dm/str "cell-" (:id cell))
:shape base-shape
:layout-data layout-data
:row row
:column column
:cell cell
:zoom zoom
:hover? (contains? hover-cells [row column])
:selected? (= selected-cells [row column])}])]))
:hover? (contains? hover-cells (:id cell))
:selected? (= selected-cells (:id cell))}])]))