0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 23:18:48 -05:00

Fix problems moving frames

This commit is contained in:
alonso.torres 2022-11-03 17:44:10 +01:00
parent 7caf4b9136
commit c86d88834e
4 changed files with 77 additions and 54 deletions

View file

@ -29,7 +29,7 @@
(defn frame-shape? (defn frame-shape?
([objects id] ([objects id]
(= (get-in objects [id :type]) id)) (frame-shape? (get objects id)))
([{:keys [type]}] ([{:keys [type]}]
(= type :frame))) (= type :frame)))
@ -467,7 +467,6 @@
(defn selected-with-children (defn selected-with-children
[objects selected] [objects selected]
(into selected (into selected
(mapcat #(get-children-ids objects %)) (mapcat #(get-children-ids objects %))
selected)) selected))

View file

@ -224,16 +224,25 @@
"Search for the top nested frame for positioning shapes when moving or creating. "Search for the top nested frame for positioning shapes when moving or creating.
Looks for all the frames in a position and then goes in depth between the top-most and its Looks for all the frames in a position and then goes in depth between the top-most and its
children to find the target." children to find the target."
[objects position] ([objects position]
(let [frame-ids (all-frames-by-position objects position) (top-nested-frame objects position nil))
frame-set (set frame-ids)]
(loop [current-id (first frame-ids)] ([objects position excluded]
(let [current-shape (get objects current-id) (assert (or (nil? excluded) (set? excluded)))
child-frame-id (d/seek #(contains? frame-set %)
(-> (:shapes current-shape) reverse))] (let [frame-ids (cond->> (all-frames-by-position objects position)
(if (nil? child-frame-id) (some? excluded)
(or current-id uuid/zero) (remove excluded))
(recur child-frame-id))))))
frame-set (set frame-ids)]
(loop [current-id (first frame-ids)]
(let [current-shape (get objects current-id)
child-frame-id (d/seek #(contains? frame-set %)
(-> (:shapes current-shape) reverse))]
(if (nil? child-frame-id)
(or current-id uuid/zero)
(recur child-frame-id)))))))
(defn top-nested-frame-ids (defn top-nested-frame-ids
"Search the top nested frame in a list of ids" "Search the top nested frame in a list of ids"

View file

@ -16,6 +16,7 @@
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.modifiers :as ctm] [app.common.types.modifiers :as ctm]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.changes :as dch] [app.main.data.workspace.changes :as dch]
[app.main.data.workspace.comments :as-alias dwcm] [app.main.data.workspace.comments :as-alias dwcm]
[app.main.data.workspace.guides :as-alias dwg] [app.main.data.workspace.guides :as-alias dwg]
@ -144,12 +145,11 @@
(into {} (map #(vector % {:modifiers (get-modifier (get objects %))})) ids)) (into {} (map #(vector % {:modifiers (get-modifier (get objects %))})) ids))
(defn build-change-frame-modifiers (defn build-change-frame-modifiers
[modif-tree objects selected target-frame position] [modif-tree objects selected target-frame drop-index]
(let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id]))) (let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id])))
layout? (get-in objects [target-frame :layout])
child-set (set (get-in objects [target-frame :shapes])) child-set (set (get-in objects [target-frame :shapes]))
drop-index (when layout? (gsl/get-drop-index target-frame objects position)) layout? (ctl/layout? objects target-frame)
update-frame-modifiers update-frame-modifiers
(fn [modif-tree [original-frame shapes]] (fn [modif-tree [original-frame shapes]]

View file

@ -353,7 +353,7 @@
(declare start-move) (declare start-move)
(declare start-move-duplicate) (declare start-move-duplicate)
(declare calculate-frame-for-move) (declare move-shapes-to-frame)
(declare get-displacement) (declare get-displacement)
(defn start-move-selected (defn start-move-selected
@ -414,7 +414,6 @@
(rx/take 1) (rx/take 1)
(rx/map #(start-move from-position)))))) (rx/map #(start-move from-position))))))
(defn- start-move (defn- start-move
([from-position] (start-move from-position nil)) ([from-position] (start-move from-position nil))
([from-position ids] ([from-position ids]
@ -436,13 +435,18 @@
zoom (get-in state [:workspace-local :zoom] 1) zoom (get-in state [:workspace-local :zoom] 1)
focus (:workspace-focus-selected state) focus (:workspace-focus-selected state)
fix-axis (fn [[position shift?]] exclude-frames (into #{}
(let [delta (gpt/to-vec from-position position)] (filter (partial cph/frame-shape? objects))
(if shift? (cph/selected-with-children objects selected))
(if (> (mth/abs (:x delta)) (mth/abs (:y delta)))
(gpt/point (:x delta) 0) fix-axis
(gpt/point 0 (:y delta))) (fn [[position shift?]]
delta))) (let [delta (gpt/to-vec from-position position)]
(if shift?
(if (> (mth/abs (:x delta)) (mth/abs (:y delta)))
(gpt/point (:x delta) 0)
(gpt/point 0 (:y delta)))
delta)))
position (->> ms/mouse-position position (->> ms/mouse-position
(rx/with-latest-from ms/mouse-position-shift) (rx/with-latest-from ms/mouse-position-shift)
@ -456,33 +460,48 @@
(rx/switch-map (rx/switch-map
(fn [pos] (fn [pos]
(->> (snap/closest-snap-move page-id shapes objects layout zoom focus pos) (->> (snap/closest-snap-move page-id shapes objects layout zoom focus pos)
(rx/map #(vector pos %)))))))] (rx/map #(vector pos %)))))))
drop-frame (atom nil)]
(if (empty? shapes) (if (empty? shapes)
(rx/of (finish-transform)) (rx/of (finish-transform))
(rx/concat (let [move-stream
(rx/merge (->> position
(->> position ;; We ask for the snap position but we continue even if the result is not available
;; We ask for the snap position but we continue even if the result is not available (rx/with-latest vector snap-delta)
(rx/with-latest vector snap-delta)
;; We try to use the previous snap so we don't have to wait for the result of the new ;; We try to use the previous snap so we don't have to wait for the result of the new
(rx/map snap/correct-snap-point) (rx/map snap/correct-snap-point)
(rx/map (rx/map
(fn [move-vector] (fn [move-vector]
(let [position (gpt/add from-position move-vector) (let [position (gpt/add from-position move-vector)
target-frame (ctst/top-nested-frame objects position)] target-frame (ctst/top-nested-frame objects position exclude-frames)
(-> (dwm/create-modif-tree ids (ctm/move move-vector)) layout? (ctl/layout? objects target-frame)
(dwm/build-change-frame-modifiers objects selected target-frame position) drop-index (when layout? (gsl/get-drop-index target-frame objects position))]
(dwm/set-modifiers))))) [move-vector target-frame drop-index])))
(rx/take-until stopper))) (rx/take-until stopper))]
(rx/of (dwu/start-undo-transaction) (rx/merge
(calculate-frame-for-move ids) ;; Temporary modifiers stream
(dwm/apply-modifiers {:undo-transation? false}) (->> move-stream
(finish-transform) (rx/map
(dwu/commit-undo-transaction))))))))) (fn [[move-vector target-frame drop-index]]
(-> (dwm/create-modif-tree ids (ctm/move move-vector))
(dwm/build-change-frame-modifiers objects selected target-frame drop-index)
(dwm/set-modifiers)))))
;; Last event will write the modifiers creating the changes
(->> move-stream
(rx/last)
(rx/mapcat
(fn [[move-vector target-frame drop-index]]
(rx/of (dwu/start-undo-transaction)
(move-shapes-to-frame ids target-frame drop-index)
(dwm/apply-modifiers {:undo-transation? false})
(finish-transform)
(dwu/commit-undo-transaction)))))))))))))
(s/def ::direction #{:up :down :right :left}) (s/def ::direction #{:up :down :right :left})
@ -561,15 +580,13 @@
(rx/of (dwm/set-modifiers modif-tree) (rx/of (dwm/set-modifiers modif-tree)
(dwm/apply-modifiers)))))) (dwm/apply-modifiers))))))
(defn- calculate-frame-for-move (defn- move-shapes-to-frame
[ids] [ids frame-id drop-index]
(ptk/reify ::calculate-frame-for-move (ptk/reify ::move-shapes-to-frame
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [position @ms/mouse-position (let [page-id (:current-page-id state)
page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id) objects (wsh/lookup-page-objects state page-id)
frame-id (ctst/top-nested-frame objects position)
layout? (get-in objects [frame-id :layout]) layout? (get-in objects [frame-id :layout])
lookup (d/getf objects) lookup (d/getf objects)
@ -584,14 +601,12 @@
(remove #(and (= (:frame-id %) frame-id) (remove #(and (= (:frame-id %) frame-id)
(not= (:parent-id %) frame-id)))) (not= (:parent-id %) frame-id))))
drop-index (when layout? (gsl/get-drop-index frame-id objects position))
changes changes
(-> (pcb/empty-changes it page-id) (-> (pcb/empty-changes it page-id)
(pcb/with-objects objects) (pcb/with-objects objects)
(pcb/change-parent frame-id moving-shapes drop-index))] (pcb/change-parent frame-id moving-shapes drop-index))]
(when-not (empty? changes) (when (and (some? frame-id) (not (empty? changes)))
(rx/of (dch/commit-changes changes) (rx/of (dch/commit-changes changes)
(dwc/expand-collapse frame-id))))))) (dwc/expand-collapse frame-id)))))))