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

View file

@ -224,16 +224,25 @@
"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
children to find the target."
[objects position]
(let [frame-ids (all-frames-by-position objects position)
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))))))
([objects position]
(top-nested-frame objects position nil))
([objects position excluded]
(assert (or (nil? excluded) (set? excluded)))
(let [frame-ids (cond->> (all-frames-by-position objects position)
(some? excluded)
(remove excluded))
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
"Search the top nested frame in a list of ids"

View file

@ -16,6 +16,7 @@
[app.common.pages.helpers :as cph]
[app.common.spec :as us]
[app.common.types.modifiers :as ctm]
[app.common.types.shape.layout :as ctl]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.comments :as-alias dwcm]
[app.main.data.workspace.guides :as-alias dwg]
@ -144,12 +145,11 @@
(into {} (map #(vector % {:modifiers (get-modifier (get objects %))})) ids))
(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])))
layout? (get-in objects [target-frame :layout])
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
(fn [modif-tree [original-frame shapes]]

View file

@ -353,7 +353,7 @@
(declare start-move)
(declare start-move-duplicate)
(declare calculate-frame-for-move)
(declare move-shapes-to-frame)
(declare get-displacement)
(defn start-move-selected
@ -414,7 +414,6 @@
(rx/take 1)
(rx/map #(start-move from-position))))))
(defn- start-move
([from-position] (start-move from-position nil))
([from-position ids]
@ -436,13 +435,18 @@
zoom (get-in state [:workspace-local :zoom] 1)
focus (:workspace-focus-selected state)
fix-axis (fn [[position shift?]]
(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)))
exclude-frames (into #{}
(filter (partial cph/frame-shape? objects))
(cph/selected-with-children objects selected))
fix-axis
(fn [[position shift?]]
(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
(rx/with-latest-from ms/mouse-position-shift)
@ -456,33 +460,48 @@
(rx/switch-map
(fn [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)
(rx/of (finish-transform))
(rx/concat
(rx/merge
(->> position
;; We ask for the snap position but we continue even if the result is not available
(rx/with-latest vector snap-delta)
(let [move-stream
(->> position
;; We ask for the snap position but we continue even if the result is not available
(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
(rx/map snap/correct-snap-point)
;; 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
(fn [move-vector]
(let [position (gpt/add from-position move-vector)
target-frame (ctst/top-nested-frame objects position)]
(-> (dwm/create-modif-tree ids (ctm/move move-vector))
(dwm/build-change-frame-modifiers objects selected target-frame position)
(dwm/set-modifiers)))))
(rx/map
(fn [move-vector]
(let [position (gpt/add from-position move-vector)
target-frame (ctst/top-nested-frame objects position exclude-frames)
layout? (ctl/layout? objects target-frame)
drop-index (when layout? (gsl/get-drop-index target-frame objects position))]
[move-vector target-frame drop-index])))
(rx/take-until stopper)))
(rx/take-until stopper))]
(rx/of (dwu/start-undo-transaction)
(calculate-frame-for-move ids)
(dwm/apply-modifiers {:undo-transation? false})
(finish-transform)
(dwu/commit-undo-transaction)))))))))
(rx/merge
;; Temporary modifiers stream
(->> move-stream
(rx/map
(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})
@ -561,15 +580,13 @@
(rx/of (dwm/set-modifiers modif-tree)
(dwm/apply-modifiers))))))
(defn- calculate-frame-for-move
[ids]
(ptk/reify ::calculate-frame-for-move
(defn- move-shapes-to-frame
[ids frame-id drop-index]
(ptk/reify ::move-shapes-to-frame
ptk/WatchEvent
(watch [it state _]
(let [position @ms/mouse-position
page-id (:current-page-id state)
(let [page-id (:current-page-id state)
objects (wsh/lookup-page-objects state page-id)
frame-id (ctst/top-nested-frame objects position)
layout? (get-in objects [frame-id :layout])
lookup (d/getf objects)
@ -584,14 +601,12 @@
(remove #(and (= (:frame-id %) frame-id)
(not= (:parent-id %) frame-id))))
drop-index (when layout? (gsl/get-drop-index frame-id objects position))
changes
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects)
(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)
(dwc/expand-collapse frame-id)))))))