🐛 Fix delete on curve handlers (#11896)

This commit is contained in:
Alonso Torres 2026-09-28 09:06:47 +02:00 committed by GitHub
parent 20c818661d
commit 2b8344d3a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 60 additions and 11 deletions

View File

@ -229,20 +229,35 @@
(update-path-content state (path/toggle-segment-curve content index))
state)))))
(defn remove-handler
"Collapses one handler onto its node, which becomes independent."
[index prefix]
(ptk/reify ::remove-handler
(defn remove-handlers
"Collapses handlers `[index prefix]` onto their nodes, which become
independent."
[handlers]
(ptk/reify ::remove-handlers
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)
content (st/get-path state :content)]
(if (some? content)
(-> (update-path-content state (path/collapse-handler content index prefix))
(update-in [:workspace-local :edit-path id :handler-types]
dissoc (helpers/handler-node-index index prefix)))
(if (and (some? content) (seq handlers))
(let [new-content (reduce (fn [content [index prefix]]
(path/collapse-handler content index prefix))
content
handlers)
nodes (map (fn [[index prefix]]
(helpers/handler-node-index index prefix))
handlers)]
(-> (update-path-content state new-content)
(update-in [:workspace-local :edit-path id :handler-types]
#(apply dissoc % nodes))
(update-in [:workspace-local :edit-path id :selection :handlers]
#(reduce disj (or % #{}) handlers))))
state)))))
(defn remove-handler
"Collapses one handler onto its node, which becomes independent."
[index prefix]
(remove-handlers #{[index prefix]}))
(defn merge-nodes []
(process-path-tool path/merge-nodes))
@ -287,7 +302,8 @@
(path/separate-nodes content points offset)))))
(defn delete-selected
"Heals selected nodes or opens selected segments."
"Heals selected nodes, opens selected segments or collapses selected
handlers."
[]
(ptk/reify ::delete-selected
ptk/WatchEvent
@ -296,17 +312,21 @@
content (st/get-path state :content)
selection (st/get-selection state id)
nodes (get selection :nodes #{})
segments (get selection :segments #{})]
segments (get selection :segments #{})
handlers (get selection :handlers #{})]
(rx/of
(cond
;; Node selection takes priority in mixed selections.
(seq nodes)
(process-path-tool (helpers/node-positions content nodes) path/remove-nodes)
;; Segment-only selection opens the path.
;; Segment selection opens the path.
(seq segments)
(separate-nodes)
(seq handlers)
(remove-handlers handlers)
:else
(remove-node)))))))

View File

@ -517,6 +517,35 @@
(t/is (< (nodes mixed) 4))
(t/is (= 1 (move-tos mixed))))))
(t/deftest delete-selected-collapses-selected-handlers
(let [id (random-uuid)
content (pth/selectable-path-content)
run (fn [handlers]
(let [state (pth/selectable-path-state
id content {:nodes #{} :segments #{} :handlers handlers})
events (atom [])]
(->> (ptk/watch (path.tools/delete-selected) state nil)
(rx/subs! #(swap! events conj %)))
(ptk/update (first @events) state)))
content-of (fn [st] (vec (get-in st [:workspace-drawing :object :content])))
selection-of (fn [st] (get-in st [:workspace-local :edit-path id :selection]))]
(t/testing "single handler collapses onto its node"
(let [state' (run #{[2 :c1]})
content' (content-of state')]
(t/is (= (gpt/point 10 0) (path/get-handler-point content' 2 :c1)))
(t/is (= (gpt/point 18 0) (path/get-handler-point content' 2 :c2)))
(t/is (= (gpt/point 8 0) (path/get-handler-point content' 1 :c2)))
(t/is (empty? (:handlers (selection-of state'))))))
(t/testing "multiple handlers collapse and flat curves become lines"
(let [state' (run #{[1 :c1] [1 :c2] [2 :c1]})
content' (content-of state')]
(t/is (= [:move-to :line-to :curve-to] (mapv :command content')))
(t/is (= (gpt/point 10 0) (path/get-handler-point content' 2 :c1)))
(t/is (= (gpt/point 18 0) (path/get-handler-point content' 2 :c2)))
(t/is (empty? (:handlers (selection-of state'))))))))
(t/deftest deleting-a-closed-seam-node-heals-its-adjacent-segments
(let [id (random-uuid)
content (path/content