mirror of
https://github.com/penpot/penpot.git
synced 2026-08-29 03:43:40 +08:00
coordinates and drawing mode
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1130,7 +1130,15 @@ for features 1–3, 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
|
||||
|
||||
Reference in New Issue
Block a user