0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-09 08:20:45 -05:00

🎉 Remember displacements when duplicating several shapes in a row

This commit is contained in:
Andrés Moya 2021-07-30 11:12:41 +02:00
parent 574387acac
commit 29cd8530a3
2 changed files with 56 additions and 5 deletions

View file

@ -9,6 +9,7 @@
- Use space + mouse drag to pan, instead of only space [Taiga #1800](https://tree.taiga.io/project/penpot/us/1800). - Use space + mouse drag to pan, instead of only space [Taiga #1800](https://tree.taiga.io/project/penpot/us/1800).
- Allow to zoom with ctrl + middle button [Taiga #1428](https://tree.taiga.io/project/penpot/us/1428). - Allow to zoom with ctrl + middle button [Taiga #1428](https://tree.taiga.io/project/penpot/us/1428).
- Auto placement of duplicated objects [Taiga #1386](https://tree.taiga.io/project/penpot/us/1386).
### :bug: Bugs fixed ### :bug: Bugs fixed
### :arrow_up: Deps updates ### :arrow_up: Deps updates

View file

@ -383,6 +383,53 @@
(into [fch] sch))) (into [fch] sch)))
(defn clear-memorize-duplicated
[]
(ptk/reify ::clear-memorize-duplicated
ptk/UpdateEvent
(update [_ state]
(d/dissoc-in state [:workspace-local :duplicated]))))
(defn memorize-duplicated
"When duplicate an object, remember the operation during the following seconds.
If the user moves the duplicated object, and then duplicates it again, check
the displacement and apply it to the third copy. This is useful for doing
grids or cascades of cloned objects."
[id-original id-duplicated]
(ptk/reify ::memorize-duplicated
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-local :duplicated] {:id-original id-original
:id-duplicated id-duplicated}))
ptk/WatchEvent
(watch [_ _ stream]
(let [stoper (rx/filter (ptk/type? ::memorize-duplicated) stream)]
(->> (rx/timer 10000) ;; This time may be adjusted after some user testing.
(rx/take-until stoper)
(rx/map clear-memorize-duplicated))))))
(defn calc-duplicate-delta
[obj state objects]
(let [{:keys [id-original id-duplicated]}
(get-in state [:workspace-local :duplicated])]
(if (and (not= id-original (:id obj))
(not= id-duplicated (:id obj)))
;; The default is leave normal shapes in place, but put
;; new frames to the right of the original.
(if (= (:type obj) :frame)
(gpt/point (+ (:width obj) 50) 0)
(gpt/point 0 0))
(let [obj-original (get objects id-original)
obj-duplicated (get objects id-duplicated)
distance (gpt/subtract (gpt/point obj-duplicated)
(gpt/point obj-original))
new-pos (gpt/add (gpt/point obj-duplicated) distance)
delta (gpt/subtract new-pos (gpt/point obj))]
delta))))
(def duplicate-selected (def duplicate-selected
(ptk/reify ::duplicate-selected (ptk/reify ::duplicate-selected
ptk/WatchEvent ptk/WatchEvent
@ -392,9 +439,7 @@
selected (wsh/lookup-selected state) selected (wsh/lookup-selected state)
delta (if (= (count selected) 1) delta (if (= (count selected) 1)
(let [obj (get objects (first selected))] (let [obj (get objects (first selected))]
(if (= (:type obj) :frame) (calc-duplicate-delta obj state objects))
(gpt/point (+ (:width obj) 50) 0)
(gpt/point 0 0)))
(gpt/point 0 0)) (gpt/point 0 0))
unames (dwc/retrieve-used-names objects) unames (dwc/retrieve-used-names objects)
@ -405,15 +450,20 @@
uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %)) uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %))
(reverse rchanges)) (reverse rchanges))
id-original (when (= (count selected) 1) (first selected))
selected (->> rchanges selected (->> rchanges
(filter #(selected (:old-id %))) (filter #(selected (:old-id %)))
(map #(get-in % [:obj :id])) (map #(get-in % [:obj :id]))
(into (d/ordered-set)))] (into (d/ordered-set)))
id-duplicated (when (= (count selected) 1) (first selected))]
(rx/of (dch/commit-changes {:redo-changes rchanges (rx/of (dch/commit-changes {:redo-changes rchanges
:undo-changes uchanges :undo-changes uchanges
:origin it}) :origin it})
(select-shapes selected)))))) (select-shapes selected)
(memorize-duplicated id-original id-duplicated))))))
(defn change-hover-state (defn change-hover-state
[id value] [id value]