coordinates and drawing mode

This commit is contained in:
alonso.torres
2026-07-16 15:46:32 +02:00
parent acdadc2a76
commit d021d120fb
4 changed files with 73 additions and 4 deletions
@@ -507,13 +507,43 @@
(rx/empty))))))
(rx/empty))))))
(defn- enter-draw-from-selected-node
"Switching to draw mode with a single node selected and no line in progress
starts a new line from that node: it becomes the pending origin, and — unless
it is already the drawing tip — a move-to opens a new subpath there, so the
next click draws a segment from the selected point."
[state id]
(let [selection (dm/get-in state [:workspace-local :edit-path id :selection :nodes] #{})
last-point (dm/get-in state [:workspace-local :edit-path id :last-point])
content (st/get-path state :content)]
(if (and (nil? last-point)
(= 1 (count selection))
(some? content)
(helpers/node? content (first selection)))
(let [index (first selection)
pos (helpers/node-position content index)
last-idx (dec (count content))
tip? (and (= index last-idx)
(not= :close-path (:command (nth content index nil))))
state (assoc-in state [:workspace-local :edit-path id :last-point] pos)]
(if tip?
state
(update-in state (st/get-path-location state)
(fn [shape]
(-> shape
(update :content path/append-segment
{:command :move-to :params (select-keys pos [:x :y])})
(path/update-geometry))))))
state)))
(defn change-edit-mode
[mode]
(ptk/reify ::change-edit-mode
ptk/UpdateEvent
(update [_ state]
(if-let [id (dm/get-in state [:workspace-local :edition])]
(d/update-in-when state [:workspace-local :edit-path id] assoc :edit-mode mode)
(cond-> (d/update-in-when state [:workspace-local :edit-path id] assoc :edit-mode mode)
(= mode :draw) (enter-draw-from-selected-node id))
state))
ptk/WatchEvent
@@ -448,6 +448,37 @@
;; opposite (c1 of cmd2) mirrors it about the node (10,0): 2*10-6=14, 2*0-(-2)=2
(t/is (= (gpt/point 14 2) (path/get-handler-point content' 2 :c1)))))
(t/deftest change-to-draw-mode-starts-a-line-from-the-selected-node
(let [id (random-uuid)
content (path/content
[{:command :move-to :params {:x 0 :y 0}}
{:command :line-to :params {:x 10 :y 0}}
{:command :line-to :params {:x 20 :y 0}}])]
;; a middle node: opens a new subpath (move-to) at the node and makes it the
;; pending origin, so the next click draws a line from it
(let [state (selectable-path-state id content
{:nodes #{1} :segments #{} :handlers #{}})
state' (ptk/update (path.drawing/change-edit-mode :draw) state)
content' (get-in state' [:workspace-drawing :object :content])]
(t/is (= (gpt/point 10 0)
(get-in state' [:workspace-local :edit-path id :last-point])))
(t/is (= 4 (count content')))
(t/is (= :move-to (:command (nth content' 3))))
(t/is (= (gpt/point 10 0) (path.helpers/node-position content' 3))))
;; the drawing tip: just becomes the pending origin (extends), no new subpath
(let [state (selectable-path-state id content
{:nodes #{2} :segments #{} :handlers #{}})
state' (ptk/update (path.drawing/change-edit-mode :draw) state)
content' (get-in state' [:workspace-drawing :object :content])]
(t/is (= (gpt/point 20 0)
(get-in state' [:workspace-local :edit-path id :last-point])))
(t/is (= 3 (count content'))))
;; nothing selected: no pending line
(let [state (selectable-path-state id content
{:nodes #{} :segments #{} :handlers #{}})
state' (ptk/update (path.drawing/change-edit-mode :draw) state)]
(t/is (nil? (get-in state' [:workspace-local :edit-path id :last-point]))))))
(t/deftest set-selection-coordinate-translates-segments
;; feature 42: with a segment selected, editing a coordinate translates the
;; segment so its surrounding rectangle's top-left corner reaches the value
+2 -2
View File
@@ -8573,11 +8573,11 @@ msgstr "Handler behaviour"
#: src/app/main/ui/workspace/viewport/path_actions.cljs
msgid "workspace.path.actions.handler-mirror"
msgstr "Mirrored (equal length)"
msgstr "Equal"
#: src/app/main/ui/workspace/viewport/path_actions.cljs
msgid "workspace.path.actions.handler-aligned"
msgstr "Mirrored angle (independent length)"
msgstr "Aligned"
#: src/app/main/ui/workspace/viewport/path_actions.cljs
msgid "workspace.path.actions.handler-independent"
+9 -1
View File
@@ -1130,7 +1130,15 @@ for features 13, 8, 10, and 11 is complete.
- **Feature 42 — editable node coordinates in the right sidebar — DONE 2026-07-16 (§18).**
The selected node's x/y show in the right panel as fully-featured editable inputs (like a
shape's x/y); editing moves the node; multi-selection shows shared values or "mixed" and an
edit applies to all selected nodes (set-absolute-for-all). Live by-hand pass owed.
edit applies to all selected nodes (set-absolute-for-all). Extended same day to handlers and
segments (§18). Live by-hand pass owed.
- **Move→draw resumes from the selected node — DONE 2026-07-16.** Switching to draw mode
(`drawing/change-edit-mode :draw`) with a single node selected and no line in progress now
starts a line from that node: new `enter-draw-from-selected-node` (run in the UpdateEvent
before `start-draw-mode`) sets it as `:last-point`, appending a `move-to` to open a new
subpath there unless the node is already the drawing tip (then it just extends). Guarded on
exactly one selected node + nil `:last-point`, so the created-path / draw-loop-restart flows
are unaffected. Test `change-to-draw-mode-starts-a-line-from-the-selected-node`. By-hand owed.
- **Cursor sizing fix (2026-07-15):** the `draw-add`/`draw-node`/`draw-remove` badge
cursors rendered the pen smaller than `draw` (their SVGs pack pen+badge into the
16-unit viewBox at `scale(0.762)` vs `draw`'s `scale(0.941)`). Fixed by rendering the