mirror of
https://github.com/penpot/penpot.git
synced 2026-03-12 21:36:39 +00:00
Merge pull request #6717 from penpot/alotor-grid-editor
✨ Support grid editor with wasm modifiers
This commit is contained in:
@@ -39,6 +39,43 @@
|
||||
(def ^:private xf:without-uuid-zero
|
||||
(remove #(= % uuid/zero)))
|
||||
|
||||
(def ^:private transform-attrs
|
||||
#{:selrect
|
||||
:points
|
||||
:x
|
||||
:y
|
||||
:r1
|
||||
:r2
|
||||
:r3
|
||||
:r4
|
||||
:shadow
|
||||
:blur
|
||||
:strokes
|
||||
:width
|
||||
:height
|
||||
:content
|
||||
:transform
|
||||
:transform-inverse
|
||||
:rotation
|
||||
:flip-x
|
||||
:flip-y
|
||||
:grow-type
|
||||
:position-data
|
||||
:layout-gap
|
||||
:layout-padding
|
||||
:layout-item-h-sizing
|
||||
:layout-item-max-h
|
||||
:layout-item-max-w
|
||||
:layout-item-min-h
|
||||
:layout-item-min-w
|
||||
:layout-item-v-sizing
|
||||
:layout-padding-type
|
||||
:layout-item-margin
|
||||
:layout-item-margin-type
|
||||
:layout-grid-cells
|
||||
:layout-grid-columns
|
||||
:layout-grid-rows})
|
||||
|
||||
;; -- temporary modifiers -------------------------------------------
|
||||
|
||||
;; During an interactive transformation of shapes (e.g. when resizing or rotating
|
||||
@@ -598,6 +635,18 @@
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [objects (dsh/lookup-page-objects state)
|
||||
|
||||
ignore-tree
|
||||
(calculate-ignore-tree modif-tree objects)
|
||||
|
||||
options
|
||||
(-> params
|
||||
(assoc :reg-objects? true)
|
||||
(assoc :ignore-tree ignore-tree)
|
||||
;; Attributes that can change in the transform. This
|
||||
;; way we don't have to check all the attributes
|
||||
(assoc :attrs transform-attrs))
|
||||
|
||||
geometry-entries (parse-geometry-modifiers modif-tree)
|
||||
|
||||
snap-pixel?
|
||||
@@ -627,7 +676,7 @@
|
||||
(clear-local-transform)
|
||||
(ptk/event ::dwg/move-frame-guides {:ids ids :transforms transforms})
|
||||
(ptk/event ::dwcm/move-frame-comment-threads transforms)
|
||||
(dwsh/update-shapes ids update-shape))))))
|
||||
(dwsh/update-shapes ids update-shape options))))))
|
||||
|
||||
(def ^:private
|
||||
xf-rotation-shape
|
||||
@@ -714,43 +763,6 @@
|
||||
|
||||
(assoc state :workspace-modifiers modif-tree)))))
|
||||
|
||||
(def ^:private transform-attrs
|
||||
#{:selrect
|
||||
:points
|
||||
:x
|
||||
:y
|
||||
:r1
|
||||
:r2
|
||||
:r3
|
||||
:r4
|
||||
:shadow
|
||||
:blur
|
||||
:strokes
|
||||
:width
|
||||
:height
|
||||
:content
|
||||
:transform
|
||||
:transform-inverse
|
||||
:rotation
|
||||
:flip-x
|
||||
:flip-y
|
||||
:grow-type
|
||||
:position-data
|
||||
:layout-gap
|
||||
:layout-padding
|
||||
:layout-item-h-sizing
|
||||
:layout-item-max-h
|
||||
:layout-item-max-w
|
||||
:layout-item-min-h
|
||||
:layout-item-min-w
|
||||
:layout-item-v-sizing
|
||||
:layout-padding-type
|
||||
:layout-item-margin
|
||||
:layout-item-margin-type
|
||||
:layout-grid-cells
|
||||
:layout-grid-columns
|
||||
:layout-grid-rows})
|
||||
|
||||
(defn apply-modifiers*
|
||||
"A lower-level version of apply-modifiers, that expects receive ready
|
||||
to use objects, object-modifiers and text-modifiers."
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
[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.features :as features]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.css-cursors :as cur]
|
||||
@@ -158,11 +159,13 @@
|
||||
(mf/deps on-drag-end)
|
||||
(fn [event]
|
||||
(let [raw-pt (mf/ref-val current-pos-ref)
|
||||
position (uwvv/point->viewport raw-pt)]
|
||||
position (uwvv/point->viewport raw-pt)
|
||||
start (mf/ref-val start-pos-ref)
|
||||
delta (gpt/to-vec start (dom/get-client-position event))]
|
||||
(dom/release-pointer event)
|
||||
(mf/set-ref-val! dragging-ref false)
|
||||
(mf/set-ref-val! start-pos-ref nil)
|
||||
(when on-drag-end (on-drag-end event position)))))
|
||||
(when on-drag-end (on-drag-end event position delta)))))
|
||||
|
||||
handle-pointer-move
|
||||
(mf/use-fn
|
||||
@@ -190,6 +193,9 @@
|
||||
height (unchecked-get props "height")
|
||||
handler (unchecked-get props "handler")
|
||||
|
||||
on-set-modifiers (unchecked-get props "on-set-modifiers")
|
||||
on-clear-modifiers (unchecked-get props "on-clear-modifiers")
|
||||
|
||||
objects (mf/deref refs/workspace-page-objects)
|
||||
{cell-id :id} (unchecked-get props "cell")
|
||||
{:keys [row column row-span column-span]} (get-in shape [:layout-grid-cells cell-id])
|
||||
@@ -197,10 +203,10 @@
|
||||
direction (unchecked-get props "direction")
|
||||
layout-data (unchecked-get props "layout-data")
|
||||
|
||||
handle-drag-position
|
||||
calculate-drag-modifiers
|
||||
(mf/use-fn
|
||||
(mf/deps shape row column row-span column-span)
|
||||
(fn [_ position]
|
||||
(fn [position]
|
||||
(let [[drag-row drag-column] (gsg/get-position-grid-coord layout-data position)
|
||||
|
||||
[new-row new-column new-row-span new-column-span]
|
||||
@@ -225,19 +231,34 @@
|
||||
|
||||
shape
|
||||
(-> (ctl/resize-cell-area shape row column new-row new-column new-row-span new-column-span)
|
||||
(ctl/assign-cells objects))
|
||||
(ctl/assign-cells objects))]
|
||||
(-> (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))))))
|
||||
|
||||
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-position
|
||||
(mf/use-fn
|
||||
(mf/deps calculate-drag-modifiers on-set-modifiers)
|
||||
(fn [_ position]
|
||||
(let [modifiers (calculate-drag-modifiers position)
|
||||
modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)]
|
||||
(if (features/active-feature? @st/state "render-wasm/v1")
|
||||
(do
|
||||
(when on-set-modifiers (on-set-modifiers modifiers))
|
||||
(st/emit! (dwm/set-wasm-modifiers modif-tree)))
|
||||
(st/emit! (dwm/set-modifiers modif-tree))))))
|
||||
|
||||
handle-drag-end
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(st/emit! (dwm/apply-modifiers))))
|
||||
(mf/deps calculate-drag-modifiers on-clear-modifiers)
|
||||
(fn [_ position]
|
||||
(if (features/active-feature? @st/state "render-wasm/v1")
|
||||
(let [modifiers (calculate-drag-modifiers position)
|
||||
modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)]
|
||||
(when on-clear-modifiers (on-clear-modifiers modifiers))
|
||||
(st/emit! (dwm/apply-wasm-modifiers modif-tree)))
|
||||
(st/emit! (dwm/apply-modifiers)))))
|
||||
|
||||
{:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
|
||||
(use-drag {:on-drag-position handle-drag-position
|
||||
@@ -291,9 +312,9 @@
|
||||
text]]))
|
||||
|
||||
(mf/defc grid-cell
|
||||
{::mf/memo #{:shape :cell :layout-data :zoom :hover? :selected?}
|
||||
{::mf/memo #{:shape :cell :layout-data :zoom :hover? :selected? :on-set-modifiers :on-clear-modifiers}
|
||||
::mf/props :obj}
|
||||
[{:keys [shape cell layout-data zoom hover? selected?]}]
|
||||
[{:keys [shape cell layout-data zoom hover? selected? on-set-modifiers on-clear-modifiers]}]
|
||||
(let [cell-bounds (gsg/cell-bounds layout-data cell)
|
||||
cell-origin (gpo/origin cell-bounds)
|
||||
cell-width (gpo/width-points cell-bounds)
|
||||
@@ -408,10 +429,12 @@
|
||||
:width width
|
||||
:height height
|
||||
:direction dir
|
||||
:layout-data layout-data}])]))]))
|
||||
:layout-data layout-data
|
||||
:on-set-modifiers on-set-modifiers
|
||||
:on-clear-modifiers on-clear-modifiers}])]))]))
|
||||
|
||||
(defn use-resize-track
|
||||
[type shape index track-before track-after zoom snap-pixel?]
|
||||
[type shape index track-before track-after zoom snap-pixel? on-set-modifiers on-clear-modifiers]
|
||||
|
||||
(let [start-size-before (mf/use-var nil)
|
||||
start-size-after (mf/use-var nil)
|
||||
@@ -433,13 +456,18 @@
|
||||
|
||||
modifiers
|
||||
(-> (ctm/empty)
|
||||
(ctm/change-property tracks-prop (get shape tracks-prop)))]
|
||||
(st/emit! (dwm/set-modifiers (dwm/create-modif-tree [(:id shape)] modifiers))))))
|
||||
(ctm/change-property tracks-prop (get shape tracks-prop)))
|
||||
|
||||
handle-drag-position
|
||||
modif-tree
|
||||
(dwm/create-modif-tree [(:id shape)] modifiers)]
|
||||
(if (features/active-feature? @st/state "render-wasm/v1")
|
||||
(st/emit! (dwm/set-wasm-modifiers modif-tree))
|
||||
(st/emit! (dwm/set-modifiers modif-tree))))))
|
||||
|
||||
calculate-modifiers
|
||||
(mf/use-fn
|
||||
(mf/deps shape track-before track-after)
|
||||
(fn [_ position]
|
||||
(fn [position]
|
||||
(let [[tracks-prop axis]
|
||||
(if (= :column type) [:layout-grid-columns :x] [:layout-grid-rows :y])
|
||||
|
||||
@@ -454,20 +482,34 @@
|
||||
(cond-> (some? track-before)
|
||||
(update-in [tracks-prop (dec index)] merge {:type :fixed :value new-size-before}))
|
||||
(cond-> (some? track-after)
|
||||
(update-in [tracks-prop index] merge {:type :fixed :value new-size-after})))
|
||||
(update-in [tracks-prop index] merge {:type :fixed :value new-size-after})))]
|
||||
(-> (ctm/empty)
|
||||
(ctm/change-property tracks-prop (get shape tracks-prop))))))
|
||||
|
||||
modifiers
|
||||
(-> (ctm/empty)
|
||||
(ctm/change-property tracks-prop (get shape tracks-prop)))]
|
||||
(st/emit! (dwm/set-modifiers (dwm/create-modif-tree [(:id shape)] modifiers))))))
|
||||
handle-drag-position
|
||||
(mf/use-fn
|
||||
(mf/deps calculate-modifiers on-set-modifiers)
|
||||
(fn [_ position]
|
||||
(let [modifiers (calculate-modifiers position)
|
||||
modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)]
|
||||
(if (features/active-feature? @st/state "render-wasm/v1")
|
||||
(do
|
||||
(when on-set-modifiers (on-set-modifiers modifiers))
|
||||
(st/emit! (dwm/set-wasm-modifiers modif-tree)))
|
||||
(st/emit! (dwm/set-modifiers modif-tree))))))
|
||||
|
||||
handle-drag-end
|
||||
(mf/use-fn
|
||||
(mf/deps track-before track-after)
|
||||
(fn []
|
||||
(mf/deps calculate-modifiers on-clear-modifiers)
|
||||
(fn [_ _ position]
|
||||
(if (features/active-feature? @st/state "render-wasm/v1")
|
||||
(let [modifiers (calculate-modifiers position)
|
||||
modif-tree (dwm/create-modif-tree [(:id shape)] modifiers)]
|
||||
(when on-clear-modifiers (on-clear-modifiers))
|
||||
(st/emit! (dwm/apply-wasm-modifiers modif-tree)))
|
||||
(st/emit! (dwm/apply-modifiers)))
|
||||
(reset! start-size-before nil)
|
||||
(reset! start-size-after nil)
|
||||
(st/emit! (dwm/apply-modifiers))))]
|
||||
(reset! start-size-after nil)))]
|
||||
|
||||
(use-drag {:on-drag-start handle-drag-start
|
||||
:on-drag-delta handle-drag-position
|
||||
@@ -485,6 +527,9 @@
|
||||
track-after (unchecked-get props "track-after")
|
||||
snap-pixel? (unchecked-get props "snap-pixel?")
|
||||
|
||||
on-set-modifiers (unchecked-get props "on-set-modifiers")
|
||||
on-clear-modifiers (unchecked-get props "on-clear-modifiers")
|
||||
|
||||
{:keys [column-total-size column-total-gap row-total-size row-total-gap] :as layout-data}
|
||||
(unchecked-get props "layout-data")
|
||||
|
||||
@@ -499,7 +544,7 @@
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
|
||||
{:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
|
||||
(use-resize-track type shape index track-before track-after zoom snap-pixel?)
|
||||
(use-resize-track type shape index track-before track-after zoom snap-pixel? on-set-modifiers on-clear-modifiers)
|
||||
|
||||
[width height]
|
||||
(if (= type :column)
|
||||
@@ -656,11 +701,14 @@
|
||||
track-after (unchecked-get props "track-after")
|
||||
snap-pixel? (unchecked-get props "snap-pixel?")
|
||||
|
||||
on-set-modifiers (unchecked-get props "on-set-modifiers")
|
||||
on-clear-modifiers (unchecked-get props "on-clear-modifiers")
|
||||
|
||||
text-x (:x center)
|
||||
text-y (:y center)
|
||||
|
||||
{:keys [handle-pointer-down handle-lost-pointer-capture handle-pointer-move]}
|
||||
(use-resize-track type shape index track-before track-after zoom snap-pixel?)]
|
||||
(use-resize-track type shape index track-before track-after zoom snap-pixel? on-set-modifiers on-clear-modifiers)]
|
||||
|
||||
[:g {:on-pointer-down handle-pointer-down
|
||||
:on-lost-pointer-capture handle-lost-pointer-capture
|
||||
@@ -699,6 +747,9 @@
|
||||
on-move-reorder-track (unchecked-get props "on-move-reorder-track")
|
||||
on-end-reorder-track (unchecked-get props "on-end-reorder-track")
|
||||
|
||||
on-set-modifiers (unchecked-get props "on-set-modifiers")
|
||||
on-clear-modifiers (unchecked-get props "on-clear-modifiers")
|
||||
|
||||
track-input-ref (mf/use-ref)
|
||||
[layout-gap-row layout-gap-col] (ctl/gaps shape)
|
||||
|
||||
@@ -876,7 +927,9 @@
|
||||
:track-before track-before
|
||||
:type type
|
||||
:value (dm/str (inc index))
|
||||
:zoom zoom}]]
|
||||
:zoom zoom
|
||||
:on-set-modifiers on-set-modifiers
|
||||
:on-clear-modifiers on-clear-modifiers}]]
|
||||
|
||||
[:& resize-track-handler
|
||||
{:index index
|
||||
@@ -888,7 +941,9 @@
|
||||
:track-after track-data
|
||||
:track-before track-before
|
||||
:type type
|
||||
:zoom zoom}]]))
|
||||
:zoom zoom
|
||||
:on-set-modifiers on-set-modifiers
|
||||
:on-clear-modifiers on-clear-modifiers}]]))
|
||||
|
||||
(mf/defc editor
|
||||
{::mf/memo true
|
||||
@@ -900,12 +955,18 @@
|
||||
zoom (unchecked-get props "zoom")
|
||||
view-only (unchecked-get props "view-only")
|
||||
|
||||
st-modif (mf/use-state nil)
|
||||
|
||||
shape
|
||||
(mf/use-memo
|
||||
(mf/deps modifiers base-shape)
|
||||
#(gsh/transform-shape
|
||||
base-shape
|
||||
(dm/get-in modifiers [(:id base-shape) :modifiers])))
|
||||
(mf/deps base-shape modifiers @st-modif)
|
||||
#(cond-> base-shape
|
||||
(some? modifiers)
|
||||
(gsh/transform-shape
|
||||
(dm/get-in modifiers [(:id base-shape) :modifiers]))
|
||||
|
||||
(some? @st-modif)
|
||||
(gsh/transform-shape @st-modif)))
|
||||
|
||||
snap-pixel? (mf/deref refs/snap-pixel?)
|
||||
|
||||
@@ -1032,7 +1093,17 @@
|
||||
|
||||
(mf/set-ref-val! target-tracks* nil)
|
||||
(reset! drop-track-type* nil)
|
||||
(reset! drop-track-target* nil)))]
|
||||
(reset! drop-track-target* nil)))
|
||||
|
||||
handle-set-modifiers
|
||||
(mf/use-fn
|
||||
(fn [modifier]
|
||||
(reset! st-modif modifier)))
|
||||
|
||||
handle-clear-modifiers
|
||||
(mf/use-fn
|
||||
(fn []
|
||||
(reset! st-modif nil)))]
|
||||
|
||||
(mf/with-effect []
|
||||
#(st/emit! (dwge/stop-grid-layout-editing (:id shape))))
|
||||
@@ -1048,7 +1119,9 @@
|
||||
:cell cell
|
||||
:zoom zoom
|
||||
:hover? (contains? hover-cells (:id cell))
|
||||
:selected? (contains? selected-cells (:id cell))}])]
|
||||
:selected? (contains? selected-cells (:id cell))
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}])]
|
||||
|
||||
(when-not ^boolean view-only
|
||||
[:*
|
||||
@@ -1085,7 +1158,9 @@
|
||||
:hovering? (contains? hover-columns idx)
|
||||
:on-start-reorder-track handle-start-reorder-track
|
||||
:on-move-reorder-track handle-move-reorder-track
|
||||
:on-end-reorder-track handle-end-reorder-track}]))
|
||||
:on-end-reorder-track handle-end-reorder-track
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}]))
|
||||
|
||||
;; Last track resize handler
|
||||
(when-not (empty? column-tracks)
|
||||
@@ -1102,7 +1177,9 @@
|
||||
:track-before (last column-tracks)
|
||||
:type :column
|
||||
:value (dm/str (inc (count column-tracks)))
|
||||
:zoom zoom}]
|
||||
:zoom zoom
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}]
|
||||
(let [drop? (and (= :column @drop-track-type*)
|
||||
(= (count column-tracks) @drop-track-target*))]
|
||||
[:& resize-track-handler
|
||||
@@ -1115,7 +1192,9 @@
|
||||
:start-p end-p
|
||||
:type :column
|
||||
:track-before (last column-tracks)
|
||||
:zoom zoom}])]))
|
||||
:zoom zoom
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}])]))
|
||||
|
||||
(for [[idx row-data] (d/enumerate row-tracks)]
|
||||
(let [drop? (and (= :row @drop-track-type*)
|
||||
@@ -1132,7 +1211,9 @@
|
||||
:hovering? (contains? hover-rows idx)
|
||||
:on-start-reorder-track handle-start-reorder-track
|
||||
:on-move-reorder-track handle-move-reorder-track
|
||||
:on-end-reorder-track handle-end-reorder-track}]))
|
||||
:on-end-reorder-track handle-end-reorder-track
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}]))
|
||||
(when-not (empty? row-tracks)
|
||||
(let [last-track (last row-tracks)
|
||||
start-p (:start-p last-track)
|
||||
@@ -1148,7 +1229,9 @@
|
||||
:track-before (last row-tracks)
|
||||
:type :row
|
||||
:value (dm/str (inc (count row-tracks)))
|
||||
:zoom zoom}]]
|
||||
:zoom zoom
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}]]
|
||||
(let [drop? (and (= :row @drop-track-type*)
|
||||
(= (count row-tracks) @drop-track-target*))]
|
||||
[:& resize-track-handler
|
||||
@@ -1161,4 +1244,6 @@
|
||||
:type :row
|
||||
:track-before (last row-tracks)
|
||||
:snap-pixel? snap-pixel?
|
||||
:zoom zoom}])]))])])))
|
||||
:zoom zoom
|
||||
:on-set-modifiers handle-set-modifiers
|
||||
:on-clear-modifiers handle-clear-modifiers}])]))])])))
|
||||
|
||||
@@ -457,7 +457,7 @@ pub extern "C" fn set_structure_modifiers() {
|
||||
let Some(shape) = state.shapes.get(&entry.id) else {
|
||||
continue;
|
||||
};
|
||||
for id in shape.all_children_with_self(&state.shapes) {
|
||||
for id in shape.all_children_with_self(&state.shapes, true) {
|
||||
state.scale_content.insert(id, entry.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,7 +412,7 @@ pub fn resize_matrix(
|
||||
parent_transform.post_translate(center);
|
||||
parent_transform.pre_translate(-center);
|
||||
|
||||
let parent_transform_inv = &parent_transform.invert().unwrap();
|
||||
let parent_transform_inv = &parent_transform.invert().unwrap_or_default();
|
||||
let origin = parent_transform_inv.map_point(child_bounds.nw);
|
||||
|
||||
let mut scale = Matrix::scale((scale_width, scale_height));
|
||||
|
||||
@@ -930,7 +930,8 @@ impl RenderState {
|
||||
let children_clip_bounds =
|
||||
node_render_state.get_children_clip_bounds(element, modifiers.get(&element.id));
|
||||
|
||||
let mut children_ids = modified_children_ids(element, structure.get(&element.id));
|
||||
let mut children_ids =
|
||||
modified_children_ids(element, structure.get(&element.id), false);
|
||||
|
||||
// Z-index ordering on Layouts
|
||||
if element.has_layout() {
|
||||
@@ -1020,7 +1021,7 @@ impl RenderState {
|
||||
let Some(root) = tree.get(&Uuid::nil()) else {
|
||||
return Err(String::from("Root shape not found"));
|
||||
};
|
||||
let root_ids = modified_children_ids(root, structure.get(&root.id));
|
||||
let root_ids = modified_children_ids(root, structure.get(&root.id), false);
|
||||
|
||||
// If we finish processing every node rendering is complete
|
||||
// let's check if there are more pending nodes
|
||||
@@ -1119,7 +1120,7 @@ impl RenderState {
|
||||
self.update_tile_for(&shape);
|
||||
} else {
|
||||
// We only need to rebuild tiles from the first level.
|
||||
let children = modified_children_ids(&shape, structure.get(&shape.id));
|
||||
let children = modified_children_ids(&shape, structure.get(&shape.id), false);
|
||||
for child_id in children.iter() {
|
||||
nodes.push(*child_id);
|
||||
}
|
||||
@@ -1149,7 +1150,7 @@ impl RenderState {
|
||||
self.update_tile_for(&shape);
|
||||
}
|
||||
|
||||
let children = modified_children_ids(&shape, structure.get(&shape.id));
|
||||
let children = modified_children_ids(&shape, structure.get(&shape.id), false);
|
||||
for child_id in children.iter() {
|
||||
nodes.push(*child_id);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use skia_safe::{self as skia};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::shapes::modifiers::common::GetBounds;
|
||||
|
||||
use crate::math::{Bounds, Matrix, Rect};
|
||||
use crate::shapes::modifiers::grid_layout::{calculate_tracks, create_cell_data};
|
||||
use crate::shapes::{modified_children_ids, Frame, Layout, Shape, StructureEntry, Type};
|
||||
@@ -22,7 +24,7 @@ pub fn render_overlay(
|
||||
return;
|
||||
};
|
||||
|
||||
let bounds = &HashMap::<Uuid, Bounds>::new();
|
||||
let bounds = &mut HashMap::<Uuid, Bounds>::new();
|
||||
|
||||
let shape = &mut shape.clone();
|
||||
if let Some(modifiers) = modifiers.get(&shape.id) {
|
||||
@@ -30,7 +32,19 @@ pub fn render_overlay(
|
||||
}
|
||||
|
||||
let layout_bounds = shape.bounds();
|
||||
let children = modified_children_ids(shape, structure.get(&shape.id));
|
||||
let children = modified_children_ids(shape, structure.get(&shape.id), false);
|
||||
|
||||
for child_id in children.iter() {
|
||||
let Some(child) = shapes.get(child_id) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(modifier) = modifiers.get(child_id) {
|
||||
let mut b = bounds.find(child);
|
||||
b.transform_mut(modifier);
|
||||
bounds.insert(*child_id, b);
|
||||
}
|
||||
}
|
||||
|
||||
let column_tracks = calculate_tracks(
|
||||
true,
|
||||
|
||||
@@ -728,7 +728,11 @@ impl Shape {
|
||||
self.children.first()
|
||||
}
|
||||
|
||||
pub fn children_ids(&self) -> IndexSet<Uuid> {
|
||||
pub fn children_ids(&self, include_hidden: bool) -> IndexSet<Uuid> {
|
||||
if include_hidden {
|
||||
return self.children.clone().into_iter().rev().collect();
|
||||
}
|
||||
|
||||
if let Type::Bool(_) = self.shape_type {
|
||||
IndexSet::<Uuid>::new()
|
||||
} else if let Type::Group(group) = self.shape_type {
|
||||
@@ -747,14 +751,22 @@ impl Shape {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_children_with_self(&self, shapes: &HashMap<Uuid, &mut Shape>) -> IndexSet<Uuid> {
|
||||
pub fn all_children_with_self(
|
||||
&self,
|
||||
shapes: &HashMap<Uuid, &mut Shape>,
|
||||
include_hidden: bool,
|
||||
) -> IndexSet<Uuid> {
|
||||
once(self.id)
|
||||
.chain(self.children_ids().into_iter().flat_map(|id| {
|
||||
shapes
|
||||
.get(&id)
|
||||
.map(|s| s.all_children_with_self(shapes))
|
||||
.unwrap_or_default()
|
||||
}))
|
||||
.chain(
|
||||
self.children_ids(include_hidden)
|
||||
.into_iter()
|
||||
.flat_map(|id| {
|
||||
shapes
|
||||
.get(&id)
|
||||
.map(|s| s.all_children_with_self(shapes, include_hidden))
|
||||
.unwrap_or_default()
|
||||
}),
|
||||
)
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -935,9 +947,11 @@ impl Shape {
|
||||
pub fn modified_children_ids(
|
||||
element: &Shape,
|
||||
structure: Option<&Vec<StructureEntry>>,
|
||||
include_hidden: bool,
|
||||
) -> IndexSet<Uuid> {
|
||||
if let Some(structure) = structure {
|
||||
let mut result: Vec<Uuid> = Vec::from_iter(element.children_ids().iter().copied());
|
||||
let mut result: Vec<Uuid> =
|
||||
Vec::from_iter(element.children_ids(include_hidden).iter().copied());
|
||||
let mut to_remove = HashSet::<&Uuid>::new();
|
||||
|
||||
for st in structure {
|
||||
@@ -960,7 +974,7 @@ pub fn modified_children_ids(
|
||||
|
||||
ret
|
||||
} else {
|
||||
element.children_ids()
|
||||
element.children_ids(include_hidden)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use std::collections::{HashMap, HashSet, VecDeque};
|
||||
mod common;
|
||||
pub mod common;
|
||||
mod constraints;
|
||||
mod flex_layout;
|
||||
pub mod grid_layout;
|
||||
@@ -25,7 +25,7 @@ fn propagate_children(
|
||||
structure: &HashMap<Uuid, Vec<StructureEntry>>,
|
||||
scale_content: &HashMap<Uuid, f32>,
|
||||
) -> VecDeque<Modifier> {
|
||||
let children_ids = modified_children_ids(shape, structure.get(&shape.id));
|
||||
let children_ids = modified_children_ids(shape, structure.get(&shape.id), true);
|
||||
|
||||
if children_ids.is_empty() || identitish(transform) {
|
||||
return VecDeque::new();
|
||||
@@ -95,7 +95,7 @@ fn calculate_group_bounds(
|
||||
let shape_bounds = bounds.find(shape);
|
||||
let mut result = Vec::<Point>::new();
|
||||
|
||||
let children_ids = modified_children_ids(shape, structure.get(&shape.id));
|
||||
let children_ids = modified_children_ids(shape, structure.get(&shape.id), true);
|
||||
for child_id in children_ids.iter() {
|
||||
let Some(child) = shapes.get(child_id) else {
|
||||
continue;
|
||||
@@ -115,22 +115,28 @@ fn set_pixel_precision(transform: &mut Matrix, bounds: &mut Bounds) {
|
||||
let x = bounds.min_x().round();
|
||||
let y = bounds.min_y().round();
|
||||
|
||||
let mut round_transform = Matrix::scale((
|
||||
bounds.width().round() / bounds.width(),
|
||||
bounds.height().round() / bounds.height(),
|
||||
));
|
||||
round_transform.post_concat(&tr);
|
||||
round_transform.pre_concat(&tr_inv);
|
||||
let scale_width = f32::max(0.01, bounds.width().round() / bounds.width());
|
||||
let scale_height = f32::max(0.01, bounds.height().round() / bounds.height());
|
||||
|
||||
transform.post_concat(&round_transform);
|
||||
bounds.transform_mut(&round_transform);
|
||||
if f32::is_finite(scale_width)
|
||||
&& f32::is_finite(scale_height)
|
||||
&& (!math::is_close_to(scale_width, 1.0) || !math::is_close_to(scale_height, 1.0))
|
||||
{
|
||||
let mut round_transform = Matrix::scale((scale_width, scale_height));
|
||||
round_transform.post_concat(&tr);
|
||||
round_transform.pre_concat(&tr_inv);
|
||||
transform.post_concat(&round_transform);
|
||||
bounds.transform_mut(&round_transform);
|
||||
}
|
||||
|
||||
let dx = x - bounds.min_x();
|
||||
let dy = y - bounds.min_y();
|
||||
|
||||
let round_transform = Matrix::translate((dx, dy));
|
||||
transform.post_concat(&round_transform);
|
||||
bounds.transform_mut(&round_transform);
|
||||
if f32::is_finite(dx) && f32::is_finite(dy) {
|
||||
let round_transform = Matrix::translate((dx, dy));
|
||||
transform.post_concat(&round_transform);
|
||||
bounds.transform_mut(&round_transform);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn propagate_modifiers(
|
||||
@@ -266,7 +272,7 @@ pub fn propagate_modifiers(
|
||||
}
|
||||
Type::Group(Group { masked: true }) => {
|
||||
let children_ids =
|
||||
modified_children_ids(shape, state.structure.get(&shape.id));
|
||||
modified_children_ids(shape, state.structure.get(&shape.id), true);
|
||||
if let Some(child) = shapes.get(&children_ids[0]) {
|
||||
let child_bounds = bounds.find(child);
|
||||
bounds.insert(shape.id, child_bounds);
|
||||
|
||||
@@ -11,26 +11,26 @@ pub fn calculate_resize(
|
||||
) -> Option<(f32, f32)> {
|
||||
let scale_width = match constraint_h {
|
||||
ConstraintH::Left | ConstraintH::Right | ConstraintH::Center => {
|
||||
parent_before.width() / parent_after.width()
|
||||
parent_before.width() / f32::max(0.01, parent_after.width())
|
||||
}
|
||||
ConstraintH::LeftRight => {
|
||||
let left = parent_before.left(child_before.nw);
|
||||
let right = parent_before.right(child_before.ne);
|
||||
let target_width = parent_after.width() - left - right;
|
||||
target_width / child_after.width()
|
||||
target_width / f32::max(0.01, child_after.width())
|
||||
}
|
||||
_ => 1.0,
|
||||
};
|
||||
|
||||
let scale_height = match constraint_v {
|
||||
ConstraintV::Top | ConstraintV::Bottom | ConstraintV::Center => {
|
||||
parent_before.height() / parent_after.height()
|
||||
parent_before.height() / f32::max(0.01, parent_after.height())
|
||||
}
|
||||
ConstraintV::TopBottom => {
|
||||
let top = parent_before.top(child_before.nw);
|
||||
let bottom = parent_before.bottom(child_before.sw);
|
||||
let target_height = parent_after.height() - top - bottom;
|
||||
target_height / child_after.height()
|
||||
target_height / f32::max(0.01, child_after.height())
|
||||
}
|
||||
_ => 1.0,
|
||||
};
|
||||
|
||||
@@ -184,7 +184,7 @@ fn initialize_tracks(
|
||||
) -> Vec<TrackData> {
|
||||
let mut tracks = Vec::<TrackData>::new();
|
||||
let mut current_track = TrackData::default();
|
||||
let mut children = modified_children_ids(shape, structure.get(&shape.id));
|
||||
let mut children = modified_children_ids(shape, structure.get(&shape.id), true);
|
||||
let mut first = true;
|
||||
|
||||
if flex_data.is_reverse() {
|
||||
@@ -269,7 +269,11 @@ fn initialize_tracks(
|
||||
// Resize main axis fill
|
||||
fn distribute_fill_main_space(layout_axis: &LayoutAxis, tracks: &mut [TrackData]) {
|
||||
for track in tracks.iter_mut() {
|
||||
let mut left_space = layout_axis.main_space() - track.main_size;
|
||||
let mut left_space = if layout_axis.is_auto_main {
|
||||
0.0
|
||||
} else {
|
||||
layout_axis.main_space() - track.main_size
|
||||
};
|
||||
let mut to_resize_children: Vec<&mut ChildAxis> = Vec::new();
|
||||
|
||||
for child in track.shapes.iter_mut() {
|
||||
@@ -299,7 +303,13 @@ fn distribute_fill_main_space(layout_axis: &LayoutAxis, tracks: &mut [TrackData]
|
||||
fn distribute_fill_across_space(layout_axis: &LayoutAxis, tracks: &mut [TrackData]) {
|
||||
let total_across_size = tracks.iter().map(|t| t.across_size).sum::<f32>()
|
||||
+ (tracks.len() - 1) as f32 * layout_axis.gap_across;
|
||||
let mut left_space = layout_axis.across_space() - total_across_size;
|
||||
|
||||
let mut left_space = if layout_axis.is_auto_across {
|
||||
0.0
|
||||
} else {
|
||||
layout_axis.across_space() - total_across_size
|
||||
};
|
||||
|
||||
let mut to_resize_tracks: Vec<&mut TrackData> = Vec::new();
|
||||
|
||||
for track in tracks.iter_mut() {
|
||||
@@ -411,7 +421,7 @@ fn calculate_track_positions(
|
||||
|
||||
for track in tracks.iter_mut() {
|
||||
track.anchor = next_anchor;
|
||||
next_anchor += layout_axis.across_v * real_gap;
|
||||
next_anchor += layout_axis.across_v * (track.across_size + real_gap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,13 +445,8 @@ fn calculate_track_data(
|
||||
structure,
|
||||
);
|
||||
|
||||
if !layout_axis.is_auto_main {
|
||||
distribute_fill_main_space(&layout_axis, &mut tracks);
|
||||
}
|
||||
|
||||
if !layout_axis.is_auto_across {
|
||||
distribute_fill_across_space(&layout_axis, &mut tracks);
|
||||
}
|
||||
distribute_fill_main_space(&layout_axis, &mut tracks);
|
||||
distribute_fill_across_space(&layout_axis, &mut tracks);
|
||||
|
||||
let total_across_size = tracks.iter().map(|t| t.across_size).sum::<f32>();
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ fn set_auto_base_size(
|
||||
(cell.row, cell.row_span)
|
||||
};
|
||||
|
||||
if prop_span != 1 || (prop as usize) >= tracks.len() {
|
||||
if prop_span != 1 || (prop as usize) > tracks.len() {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -634,7 +634,7 @@ pub fn reflow_grid_layout(
|
||||
) -> VecDeque<Modifier> {
|
||||
let mut result = VecDeque::new();
|
||||
let layout_bounds = bounds.find(shape);
|
||||
let children = modified_children_ids(shape, structure.get(&shape.id));
|
||||
let children = modified_children_ids(shape, structure.get(&shape.id), true);
|
||||
|
||||
let column_tracks = calculate_tracks(
|
||||
true,
|
||||
|
||||
Reference in New Issue
Block a user