🐛 Fix some issues with grid

This commit is contained in:
alonso.torres 2023-09-29 15:43:22 +02:00
parent 7fd02022ac
commit a0c79fc038
5 changed files with 169 additions and 155 deletions

View file

@ -16,6 +16,7 @@
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.common.types.pages-list :as ctpl] [app.common.types.pages-list :as ctpl]
[app.common.types.shape-tree :as ctst] [app.common.types.shape-tree :as ctst]
[app.common.types.shape.layout :as ctl]
[app.common.uuid :as uuid])) [app.common.uuid :as uuid]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -265,7 +266,7 @@
(gpt/add orig-pos delta) (gpt/add orig-pos delta)
{:skip-components? true {:skip-components? true
:bottom-frames? true})) :bottom-frames? true}))
frame-ids-map (volatile! {}) ids-map (volatile! {})
update-new-shape update-new-shape
(fn [new-shape original-shape] (fn [new-shape original-shape]
@ -275,8 +276,7 @@
(when (nil? (:parent-id original-shape)) (when (nil? (:parent-id original-shape))
(vswap! unames conj new-name)) (vswap! unames conj new-name))
(when (= (:type original-shape) :frame) (vswap! ids-map assoc (:id original-shape) (:id new-shape))
(vswap! frame-ids-map assoc (:id original-shape) (:id new-shape)))
(cond-> new-shape (cond-> new-shape
:always :always
@ -307,24 +307,29 @@
(dissoc :component-root)))) (dissoc :component-root))))
[new-shape new-shapes _] [new-shape new-shapes _]
(ctst/clone-object component-shape (ctst/clone-object
nil component-shape
(if components-v2 (:objects component-page) (:objects component)) nil
update-new-shape (if components-v2 (:objects component-page) (:objects component))
(fn [object _] object) update-new-shape
force-id (fn [object _] object)
keep-ids?) force-id
keep-ids?)
;; If frame-id points to a shape inside the component, remap it to the ;; If frame-id points to a shape inside the component, remap it to the
;; corresponding new frame shape. If not, set it to the destination frame. ;; corresponding new frame shape. If not, set it to the destination frame.
;; Also fix empty parent-id. ;; Also fix empty parent-id.
remap-frame-id (fn [shape] remap-ids
(as-> shape $ (fn [shape]
(update $ :frame-id #(get @frame-ids-map % frame-id)) (as-> shape $
(update $ :parent-id #(or % (:frame-id $)))))] (update $ :frame-id #(get @ids-map % frame-id))
(update $ :parent-id #(or % (:frame-id $)))
(cond-> $
(ctl/grid-layout? shape)
(ctl/remap-grid-cells @ids-map))))]
[(remap-frame-id new-shape) [(remap-ids new-shape)
(map remap-frame-id new-shapes)]))) (map remap-ids new-shapes)])))
(defn get-top-instance (defn get-top-instance
"The case of having an instance that contains another instances. "The case of having an instance that contains another instances.

View file

@ -1177,3 +1177,15 @@
(for [r (range first-row (inc last-row)) (for [r (range first-row (inc last-row))
c (range first-column (inc last-column))] c (range first-column (inc last-column))]
[r c])))) [r c]))))
(defn remap-grid-cells
"Remaps the shapes inside the cells"
[shape ids-map]
(let [do-remap-cells
(fn [cell]
(-> cell
(update :shapes #(mapv ids-map %))))
shape
(-> shape
(update :layout-grid-cells update-vals do-remap-cells))]
shape))

View file

@ -330,17 +330,6 @@
(when selected (when selected
(rx/of (select-shape (:id selected)))))))) (rx/of (select-shape (:id selected))))))))
(defn remap-grid-cells
"Remaps the shapes inside the cells"
[shape ids-map]
(let [do-remap-cells
(fn [cell]
(-> cell
(update :shapes #(mapv ids-map %))))]
(update shape :layout-grid-cells update-vals do-remap-cells)))
;; --- Duplicate Shapes ;; --- Duplicate Shapes
(declare prepare-duplicate-shape-change) (declare prepare-duplicate-shape-change)
(declare prepare-duplicate-flows) (declare prepare-duplicate-flows)
@ -463,8 +452,7 @@
(d/update-when :interactions #(ctsi/remap-interactions % ids-map objects)) (d/update-when :interactions #(ctsi/remap-interactions % ids-map objects))
(cond-> (ctl/grid-layout? obj) (cond-> (ctl/grid-layout? obj)
(-> (ctl/check-deassigned-cells) (ctl/remap-grid-cells ids-map)))
(remap-grid-cells ids-map))))
new-obj (cond-> new-obj new-obj (cond-> new-obj
(not duplicating-component?) (not duplicating-component?)
@ -474,7 +462,7 @@
changes (-> (pcb/add-object changes new-obj {:ignore-touched (and duplicating-component? child?)}) changes (-> (pcb/add-object changes new-obj {:ignore-touched (and duplicating-component? child?)})
(pcb/amend-last-change #(assoc % :old-id (:id obj))) (pcb/amend-last-change #(assoc % :old-id (:id obj)))
(cond-> (ctl/grid-layout? objects (:parent-id obj)) (cond-> (ctl/grid-layout? objects (:parent-id obj))
(-> (pcb/update-shapes [(:parent-id obj)] ctl/assign-cells) (-> (pcb/update-shapes [(:parent-id obj)] (fn [shape] (-> shape ctl/assign-cells ctl/check-deassigned-cells)))
(pcb/reorder-grid-children [(:parent-id obj)])))) (pcb/reorder-grid-children [(:parent-id obj)]))))
changes (cond-> changes changes (cond-> changes

View file

@ -34,6 +34,9 @@
[cuerdas.core :as str] [cuerdas.core :as str]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
(def small-size-limit 60)
(def medium-size-limit 110)
(defn apply-to-point [result next-fn] (defn apply-to-point [result next-fn]
(conj result (next-fn (last result)))) (conj result (next-fn (last result))))
@ -630,6 +633,10 @@
[(:x text-p) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)] [(:x text-p) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)]
[(- (:x text-p) (max 0 (:size track-data))) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)]) [(- (:x text-p) (max 0 (:size track-data))) (- (:y text-p) (/ 36 zoom)) (max 0 (:size track-data)) (/ 36 zoom)])
trackwidth (* text-width zoom)
medium? (and (>= trackwidth small-size-limit) (< trackwidth medium-size-limit))
small? (< trackwidth small-size-limit)
track-before (get-in layout-data [track-list-prop (dec index)])] track-before (get-in layout-data [track-list-prop (dec index)])]
(mf/use-effect (mf/use-effect
@ -644,28 +651,29 @@
(dm/str (gmt/transform-in text-p (:transform shape))) (dm/str (gmt/transform-in text-p (:transform shape)))
(dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))} (dm/str (gmt/transform-in text-p (gmt/rotate (:transform shape) -90))))}
(when hovering? (when (and hovering? (not small?))
[:rect {:x (+ text-x (/ 5 zoom)) [:rect {:x (+ text-x (/ 18 zoom))
:y text-y :y text-y
:width (- text-width (/ 10 zoom)) :width (- text-width (/ 36 zoom))
:height (- text-height (/ 5 zoom)) :height (- text-height (/ 5 zoom))
:rx (/ 3 zoom) :rx (/ 3 zoom)
:fill "var(--color-distance)" :fill "var(--color-distance)"
:opacity 0.2}]) :opacity 0.2}])
[:foreignObject {:x text-x :y text-y :width text-width :height text-height} (when (not small?)
[:div {:class (css :grid-editor-wrapper)} [:foreignObject {:x text-x :y text-y :width text-width :height text-height}
[:input [:div {:class (css :grid-editor-wrapper)}
{:ref track-input-ref [:input
:style {} {:ref track-input-ref
:class (css :grid-editor-label) :style {}
:type "text" :class (css :grid-editor-label)
:default-value (format-size track-data) :type "text"
:data-default-value (format-size track-data) :default-value (format-size track-data)
:on-key-down handle-keydown-track-input :data-default-value (format-size track-data)
:on-blur handle-blur-track-input}] :on-key-down handle-keydown-track-input
(when hovering? :on-blur handle-blur-track-input}]
[:button {:class (css :grid-editor-button) (when (and hovering? (not medium?) (not small?))
:on-click handle-remove-track} i/trash])]]] [:button {:class (css :grid-editor-button)
:on-click handle-remove-track} i/trash])]])]
[:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))} [:g {:transform (when (= type :row) (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p)))}
[:& track-marker [:& track-marker
@ -782,106 +790,107 @@
(fn [] (fn []
#(st/emit! (dwge/stop-grid-layout-editing (:id shape))))) #(st/emit! (dwge/stop-grid-layout-editing (:id shape)))))
[:g.grid-editor {:pointer-events (when view-only "none") (when (and (not (:hidden shape)) (not (:blocked shape)))
:on-pointer-down handle-pointer-down} [:g.grid-editor {:pointer-events (when view-only "none")
[:g.cells :on-pointer-down handle-pointer-down}
(for [cell (ctl/get-cells shape {:sort? true})] [:g.cells
[:& grid-cell {:key (dm/str "cell-" (:id cell)) (for [cell (ctl/get-cells shape {:sort? true})]
:shape base-shape [:& grid-cell {:key (dm/str "cell-" (:id cell))
:layout-data layout-data :shape base-shape
:cell cell :layout-data layout-data
:cell cell
:zoom zoom
:hover? (contains? hover-cells (:id cell))
:selected? (contains? selected-cells (:id cell))}])]
(when-not view-only
[:*
[:& grid-editor-frame {:zoom zoom
:bounds bounds}]
(let [start-p (-> origin (gpt/add (hv width)))]
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
[:& plus-btn {:start-p start-p
:zoom zoom
:type :column
:on-click handle-add-column}]])
(let [start-p (-> origin (gpt/add (vv height)))]
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
[:& plus-btn {:start-p start-p
:zoom zoom
:type :row
:on-click handle-add-row}]])
(for [[idx column-data] (d/enumerate column-tracks)]
[:& track {:key (dm/str "column-track-" idx)
:shape shape
:zoom zoom :zoom zoom
:hover? (contains? hover-cells (:id cell)) :type :column
:selected? (contains? selected-cells (:id cell))}])] :index idx
(when-not view-only :layout-data layout-data
[:* :snap-pixel? snap-pixel?
[:& grid-editor-frame {:zoom zoom :track-data column-data
:bounds bounds}] :hovering? (contains? hover-columns idx)}])
(let [start-p (-> origin (gpt/add (hv width)))]
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))}
[:& plus-btn {:start-p start-p
:zoom zoom
:type :column
:on-click handle-add-column}]])
(let [start-p (-> origin (gpt/add (vv height)))] ;; Last track resize handler
[:g {:transform (dm/str (gmt/transform-in start-p (:transform shape)))} (when-not (empty? column-tracks)
[:& plus-btn {:start-p start-p (let [last-track (last column-tracks)
:zoom zoom start-p (:start-p last-track)
:type :row end-p (gpt/add start-p (hv (:size last-track)))
:on-click handle-add-row}]]) marker-p (-> (gpo/project-point bounds :h end-p)
(gpt/subtract (vv (/ 20 zoom))))]
[:g.track
[:& track-marker {:center marker-p
:index (count column-tracks)
:shape shape
:snap-pixel? snap-pixel?
:track-before (last column-tracks)
:type :column
:value (dm/str (inc (count column-tracks)))
:zoom zoom}]
[:& resize-track-handler
{:index (count column-tracks)
:last? true
:shape shape
:layout-data layout-data
:snap-pixel? snap-pixel?
:start-p end-p
:type :column
:track-before (last column-tracks)
:zoom zoom}]]))
(for [[idx column-data] (d/enumerate column-tracks)] (for [[idx row-data] (d/enumerate row-tracks)]
[:& track {:key (dm/str "column-track-" idx) [:& track {:index idx
:shape shape :key (dm/str "row-track-" idx)
:zoom zoom :layout-data layout-data
:type :column :shape shape
:index idx :snap-pixel? snap-pixel?
:layout-data layout-data :track-data row-data
:snap-pixel? snap-pixel? :type :row
:track-data column-data :zoom zoom
:hovering? (contains? hover-columns idx)}]) :hovering? (contains? hover-rows idx)}])
(when-not (empty? row-tracks)
;; Last track resize handler (let [last-track (last row-tracks)
(when-not (empty? column-tracks) start-p (:start-p last-track)
(let [last-track (last column-tracks) end-p (gpt/add start-p (vv (:size last-track)))
start-p (:start-p last-track) marker-p (-> (gpo/project-point bounds :v end-p)
end-p (gpt/add start-p (hv (:size last-track))) (gpt/subtract (hv (/ 20 zoom))))]
marker-p (-> (gpo/project-point bounds :h end-p) [:g.track
(gpt/subtract (vv (/ 20 zoom))))] [:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
[:g.track [:& track-marker {:center marker-p
[:& track-marker {:center marker-p :index (count row-tracks)
:index (count column-tracks) :shape shape
:shape shape :snap-pixel? snap-pixel?
:snap-pixel? snap-pixel? :track-before (last row-tracks)
:track-before (last column-tracks) :type :row
:type :column :value (dm/str (inc (count row-tracks)))
:value (dm/str (inc (count column-tracks))) :zoom zoom}]]
:zoom zoom}] [:& resize-track-handler
[:& resize-track-handler {:index (count row-tracks)
{:index (count column-tracks) :last? true
:last? true :shape shape
:shape shape :layout-data layout-data
:layout-data layout-data :start-p end-p
:snap-pixel? snap-pixel? :type :row
:start-p end-p :track-before (last row-tracks)
:type :column :snap-pixel? snap-pixel?
:track-before (last column-tracks) :zoom zoom}]]))])])))
:zoom zoom}]]))
(for [[idx row-data] (d/enumerate row-tracks)]
[:& track {:index idx
:key (dm/str "row-track-" idx)
:layout-data layout-data
:shape shape
:snap-pixel? snap-pixel?
:track-data row-data
:type :row
:zoom zoom
:hovering? (contains? hover-rows idx)}])
(when-not (empty? row-tracks)
(let [last-track (last row-tracks)
start-p (:start-p last-track)
end-p (gpt/add start-p (vv (:size last-track)))
marker-p (-> (gpo/project-point bounds :v end-p)
(gpt/subtract (hv (/ 20 zoom))))]
[:g.track
[:g {:transform (dm/fmt "rotate(-90 % %)" (:x marker-p) (:y marker-p))}
[:& track-marker {:center marker-p
:index (count row-tracks)
:shape shape
:snap-pixel? snap-pixel?
:track-before (last row-tracks)
:type :row
:value (dm/str (inc (count row-tracks)))
:zoom zoom}]]
[:& resize-track-handler
{:index (count row-tracks)
:last? true
:shape shape
:layout-data layout-data
:start-p end-p
:type :row
:track-before (last row-tracks)
:snap-pixel? snap-pixel?
:zoom zoom}]]))])]))

View file

@ -46,7 +46,7 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
position: absolute; position: absolute;
right: calc(10px / var(--zoom)); right: calc(20px / var(--zoom));
width: calc(20px / var(--zoom)); width: calc(20px / var(--zoom));
height: calc(20px / var(--zoom)); height: calc(20px / var(--zoom));
@ -80,12 +80,12 @@
.grid-cell-outline { .grid-cell-outline {
fill: transparent; fill: transparent;
stroke: var(--color-distance); stroke: var(--color-distance);
stroke-linecap: round; stroke-opacity: 0.5;
stroke-width: calc(2 / var(--zoom)); stroke-width: calc(1 / var(--zoom));
stroke-dasharray: 0 calc(8 / var(--zoom));
&.hover, &.hover,
&.selected { &.selected {
stroke-dasharray: initial; stroke-opacity: 1;
stroke-width: calc(2 / var(--zoom));
} }
} }