Preferences > Smart Guides gets Snap to Last Location (`snapToLastLocation`,
off by default). With it and Smart Guides on, a selection moved by dragging
with the Selection, Group Selection or Direct Selection tool, Shift too, goes
back to where the move began while the move is within Snapping Tolerance,
labeled "last location". An Alt copy is not pulled back onto its original.
Source: https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/smart-guides-options.html
The distance, the label and the copy rule are VectorCraft's own.
The `Tool` implementation's `busy`, `pointer`, `key`, `claims_key`, `overlays`
and `cursor` in shape.rs, and `pointer` and `cursor` in select.rs, are the ones
this pull request edits; each now has a doc comment, so the docstring coverage
of the functions the diff touches is complete.
The Selection tool's cursor now checks the ruler guides before a selected
object's centre point, as a press does. Tests: a ruler guide under the centre
point keeps the pointer and drags; on a box too thin for its centre to clear the
handles the handles take both; a shape-tool move from the centre snaps and shows
the hollow arrow; and Alt pressed mid-drag copies the shape through the engine.
The Selection tool's cursor now checks the bounding-box handles before a
selected object's centre point, as a press does (on a thin box the centre lies
within a handle's reach). The shape tools' tests cover a Live Corners widget
that lands on another selected shape's centre (the widget rounds), Alt pressed
mid-drag (the preview copies and the copy cursor shows), and the engine tests
check the copy's place and both gestures' Undo and Redo. The cursor catalog says
which arrow a drag of the selection shows.
- The Selection tool takes a Shift-press on a selected object's centre point
too: a Shift-drag moves the selection held to 45° steps, and a Shift-click
there takes the object out of the selection, as a Shift-press on the object
does.
- One rotate zone for the Selection tool and the shape tools
(`select::rotate_zone`): a press on a bounding-box handle is not a turn, so
the shape tools' zone matches the Selection tool's classification exactly.
- The shape tools' hover cursor follows the press order (corner and pie widgets,
then the centre point, then the rotate zone), and a move of the selection
shows the Selection tool's feedback: SelectionCopy with Alt, ArrowHollow while
it snaps.
- Engine-level tests for the whole gesture (`crates/engine/src/tests/shapetools.rs`):
repeated previews and one undo step, Alt copy, Escape then release, a turn
about the centre, the corner widget still rounding, and an unfilled shape
moved by the Selection tool.
- docs: evidence in target-app-parity.md's Shapes bullet and the M2 milestone,
and the Move cursor's entry names the copy and snap cursors.
A shape just drawn keeps its bounding box with the Rectangle, Rounded Rectangle,
Ellipse, Polygon and Star tools, but its centre point (Attributes › Show Center)
did nothing and the box's handles only drew: a press anywhere started a new
shape, and with the Selection tool a press on the centre of an unfilled shape
started a marquee.
- The Selection tool now takes a press on a selected object's centre point as
the start of a move (held by that point, so it snaps and Alt copies), as
Direct Selection has since #4891. A click there still makes the object the
key object of a multi-selection.
- The shape tools take it too, and take a press in the rotate zone just outside
a bounding-box corner (the Selection tool's own zone and cursor) as the start
of a rotation about the box's centre. Live Corners widgets keep the corners
themselves, so a press on a corner still rounds it; every other press still
draws a new shape. Escape cancels, as for the Selection tool's drags.
`hit_center` moves from direct.rs to select.rs, shared by the three tools.
Hovering looks up the bounds of every selected object, and each lookup
went through the memo key check, which compares the whole selection. That
made a hover quadratic in the selection: 1.5 s at 50,000 selected paths.
The walk now checks the key once and shares it across its lookups.
Part of #1280.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With one Objects on Path group of two or more objects selected, the
Selection and Objects on Path tools show a square Space widget beyond the
last object, ahead along the path. Dragging it moves the last object
along the path, around its bends, as far as the pointer moves along it,
and the objects between follow evenly while the first one stays. With
Alt (Option on macOS) the objects spread from both ends toward or away
from the center of an open path, or of the first anchor of a closed one.
The distance between the objects shows next to the pointer in the
document's units; the drag is one undo step, and Escape cancels it.
- object.objectsOnPath.options takes spacing (points, or "auto", the
default even spread) and start (points from the first anchor). A
spacing the path has no room for is drawn smaller and kept, so a
longer path brings it back. Older files read as Auto.
- Moving the group, Pivot, Rotate, path edits, copies and saving keep
the Space. Scaling, rotating or shearing the group keeps the first
and last objects where the transform takes them on the new path, live
shapes included; a value that cannot be kept that way scales with the
path's length.
- The Rotate All widget follows the first object when Space moves it.
Behavior: https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rearrange-and-edit-objects-on-a-path.html
and https://helpx.adobe.com/illustrator/using/objects-on-path.html.
Escape also clears state that earlier clicks set up, so taking Escape for a
dropped press lost it in five tools. Each now drops only the press:
- Blend: the object picked first and the blend being added to are put
back as they were at the press.
- Dimension: a dropped click picks nothing, and the points or lines picked
before stay; a dropped drag is canceled as before.
- Width: the drag ends and the width points selected at the press are
selected again.
- Gradient: a dropped click on a freeform gradient leaves the line being
drawn open.
- Selection: with the pointer loaded with text, a dropped press threads
nothing and the text stays loaded; a dropped press on a port loads none.
While a symbol with Enable Guides for 9-Slice Scaling on is edited in
symbol editing mode, the canvas draws its two horizontal and two vertical
guides as dotted lines across its art, with any tool and with ruler guides
hidden. With the Selection tool the pointer near a guide shows the Move
cursor, and dragging the guide sets it through `symbol.options`'s
`nineSliceGuides` as one undo step; Escape during the drag puts it back.
A guide within 4 screen pixels takes the press before the art and the
bounding box. A dragged guide stays within the art's box and stops short
of the opposite guide; positions outside the art are not supported yet.
The snap targets of a Shift-drag that starts on a highlighted Global Edit
match are gathered when the drag begins, for the selection with the match
added, before the first preview moves it. The first preview is now snapped
to the grid or to points, and later previews snap from the original
position.
A Shift-press on a highlighted object of the Global Edit waits for the release
to leave it out of the edit. A drag from it now selects it when the drag starts
and moves it with the selection, as a Shift-drag from an unselected object did.
The snap targets are gathered after the object joins the selection.
A match that sits inside a selected object is no longer highlighted, and a
Shift-click on it with the Selection tool deselects that object as before
instead of leaving the match out of the Global Edit.
While Global Edit is on, a Shift-click (not a Shift-drag) with the
Selection tool on a highlighted match, or on an object inside a matched
group, leaves that match out: it is no longer highlighted and later
edits leave it as it is. The object the edit started from stays in, and
Global Edit ends when fewer than two matches are left. Leaving a match
out is not an undo step.
- New command `select.globalEditExclude {id}` returns `{active, count,
ids}`; the Selection tool calls it on the release of a Shift-click.
- `ToolContext::global_edit` gives the tools the Global Edit's objects.
- Label and messages in the i18n catalogs; docs/mcp.md,
docs/ui-parity.md and docs/target-app-parity.md updated.
Source: https://helpx.adobe.com/ph_fil/illustrator/how-to/global-editing-sensei.html
A double-click on a Radial, Grid or Mirror Repeat with the Selection
tool enters isolation mode on it. There its source art is selected and
edited as usual (a double-click on type in it switches to the Type tool
on that text) and every copy follows, the repeat keeping its settings.
With one Objects on Path group selected, the Selection and Objects on
Path tools show a round handle beyond the top of the group's first
object, joined by a line to its attachment point. Dragging it adds the
angle the pointer turns about that point to the group's Rotate, previewed
while dragging and kept as one undo step on release
(object.objectsOnPath.options). Shift turns in 15 degree steps, Escape
cancels the drag, and the pointer shows the rotate cursor over the
handle.
Docs: docs/target-app-parity.md, docs/mcp.md.
Cmd/Ctrl held with the Pen lends the last-used selection tool (Direct
Selection until one is chosen), which already moved anchors, straight
segments and curves of the path being drawn, one undo step each, and
handed the path back to the Pen.
With the Selection tool used last, the lent tool hit-tested the
bounding box even though the canvas hides it while anchors are selected
on their own, as the end anchor of a path being drawn is. Over the
path it showed a resize pointer, and the drag scaled the path by a
handle nobody could see: a flat path did nothing at all.
The Selection tool's handles now take the pointer only while the box is
shown (View > Show Bounding Box, no anchors selected on their own), so
the lent Selection tool moves the path being drawn.
Tests: select::tests::hidden_box_handles_take_no_press_while_anchors_are_selected,
tests::draw2::pen_cmd_drag_edits_anchors_and_segments_and_goes_on_drawing.
Holding backquote while dragging with the Selection tool (move, bounding-box
scale or rotate) or the Rotate, Reflect, Scale or Shear tool applies the drag
to the selected objects' pattern fills and strokes and leaves their geometry
in place. The key state at release decides the result: the key may be pressed
after the mouse button goes down, and releasing it before the button comes up
commits an ordinary transform. Objects without pattern paint do not move.
PointerEvent gains a `backquote` flag (false when absent). The desktop canvas
reads it from the held key on every pointer event, and `ui.pointer` and the
`pointer_gesture` tool accept it per event or as a default for the gesture.
An image in a clipping mask, picked in the Layers panel, shows its
whole frame, but a press on the part the mask hides hit nothing: the
Selection, Direct Selection and Group Selection tools started a marquee
there, which dropped the selection, so the image could be dragged only
by the part that shows.
Such a press now grabs the selection by that art, as a press on its
visible part does: a drag moves the selected object (the image, not its
clip group) and a click keeps it selected. With nothing of it selected
there, or with Shift, a press there starts a marquee as before.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EjfPR4a1jPek7r3nyFFNYv
While an opacity mask or a pattern is edited, a press on a selected Shaper
original shape now moves it when it is not the first selected object or
shares the selection with shapes of another Shaper Group. An object in
front of the Shaper Group at the pointer is selected instead.
While an opacity mask or a pattern was edited, a Shaper double-click
selected a Shaper Group's original shape without isolating the group's
original shapes. A Selection tool press on that shape then selected and
moved the whole Shaper Group over the art the group shows, and started
a marquee over a part of the shape the group does not show.
A press on the selected original shape now holds it for a move, and
the pointer shows the move cursor over it.
Escape during a Selection tool move or Alt-drag copy, a bounding-box
scale or rotation, a marquee, or a drag of a corner widget, a pie widget
or the brackets of type on a path did nothing, and the release then
applied the drag. Only a ruler guide, mirror axis or grid repeat drag
and the loaded text took Escape.
Escape in any of these drags now cancels it, the way Direct Selection
cancels its drags: the art returns to its state at the press, an
Alt-drag leaves no copy, no undo step is added, and the release does
nothing.
Outside a drag Escape works as before.
Docs: docs/mcp.md, docs/target-app-parity.md.
With the Selection tool, a single selected grid repeat shows a handle below the grid (rows), one right of it (columns), one past its bottom-right corner (both) and sliders between its first two columns and rows (horizontal and vertical spacing), as the public Set grid repeat options page describes. Each drag previews object.repeat.options and commits as one Repeat Options undo step; Escape cancels, and a drag that ends where it began leaves no step. Bounding-box handles keep priority where they overlap, and the controls hide with the edges or the bounding box. Before, a drag there scaled the source or started a marquee.
Part of #2691.
A Selection tool press within reach of an anchor or the centre grabs the
object by that point, but the drag threshold was measured from that point
instead of from the press. A press 3-6 px from it was already past the
threshold, so the first pointer wobble started a move and jumped the
object by the offset. The threshold now counts from where the pointer
went down; a real drag still moves the object by the grabbed point.
One rule for the hover's context (PR review follow-ups): the target is
recomputed where the pointer is, or cleared, whenever what lies under it
can change while Alt is held.
- The tool hovers only where the pointer is on the canvas itself
(`on_canvas`): under a floating panel, a menu, a popup or a dialog
its hover ends (Tool::hover_ended), as when the pointer leaves the
canvas or a pan, zoom or view-rotation press starts.
- The canvas keeps the hover's context: its rect, the view's centre,
zoom and rotation, and the active document's id and revision (which
moves with every edit, undo and selection change). When it changes
under a still pointer, a tool that asks (Tool::wants_rehover; the
Selection tool after an Alt hover) is hovered again at the pointer,
so wheel, gesture, key or command scrolling and zooming, tab
switches, edits and undos re-measure.
- Coming back onto the canvas re-hovers the tool.
canvas::tests::distance_guides_follow_what_lies_under_a_still_pointer:
a floating window over the pointer (fails without the on_canvas filter),
a 150 pt scroll that leaves empty artboard under it (fails without the
re-hover), a square made under it. select::tests::distance_guides_need_
alt_a_selection_and_smart_guides checks wants_rehover.
An Alt+Space pan press went to Drag::Pan and never reached the tool, so the Distance Guides stayed through the pan until the pointer left the canvas (PR review follow-up). One rule now covers all three cases: the tool's hover ends (Tool::hover_ended, renamed from pointer_left; Session::tool_hover_ended) when the pointer leaves the canvas with no press the tool holds, and when a press starts any drag that doesn't reach the tool (pan, middle-button pan, zoom box or scrub, view rotation, touch gesture). canvas::tests::distance_guides_go_when_the_hover_ends asserts they go at an Alt+Space press and stay gone panning out over a panel.
Leaving the canvas (for a panel, or out of the window) sent the tool no
hover event, so the Selection tool kept its Alt-hover target and went
on drawing the measurements (PR review finding).
- Tool::pointer_left: the pointer left the canvas with no button held;
the Selection tool drops its Distance Guides target and its Smart
Guides hover label. Session::tool_pointer_left reaches it.
- The canvas remembers whether the pointer was over it last frame: on
leaving with no drag it calls tool_pointer_left; on coming back it
re-hovers the tool even after a single jump egui doesn't count as
moving, so the guides show again.
Tests: canvas::tests::distance_guides_go_when_the_pointer_leaves_the_
canvas (fails before: the label stayed over a panel with Alt held),
select::tests::distance_guides_need_alt_a_selection_and_smart_guides
(pointer_left clears them).
Distance Guides, from the public "Use Distance Guides for accurate
placement" and "Smart Guides options" (Invoke Distance Guides) pages:
with Smart Guides on, something selected and the Selection tool,
holding Alt/Option over another object shows the horizontal and
vertical distances between the selection and it, and over an empty
part of an artboard the selection's distances from the artboard's left,
right, top and bottom edges.
- guides::distance_guides measures the selection's bounds to a box: on
an axis on which they lie apart, the gap between their facing edges;
otherwise the offsets of both pairs of matching edges. Each line runs
across the middle of the overlap on the other axis (else the
selection's middle), with a dashed line out to the target's edge when
it passes beside it. An artboard is always measured edge to edge.
Labels are in the General unit, in the smart guide colour.
- The Selection tool keeps what its Alt hover points at and draws the
guides while idle; letting Alt go (the canvas re-hovers on a modifier
change), a press or moving off clears them.
- Overlay::Distance: the line with end ticks and its length in a pill;
the canvas draws it.
- Preferences › Smart Guides › Invoke Distance Guides (`distanceGuides`,
on by default), with i18n rows; View › Smart Guides gates it too.
- Hover only, as the pages describe: nothing while moving or nudging.
Tests: select::tests::alt_over_* (gap and edges beside and below,
artboard edges in pt and mm), distance_guides_need_alt_a_selection_and_
smart_guides, tests_prefs::invoke_distance_guides_measures_the_selection_
to_the_object_under_alt, canvas::tests::alt_over_another_object_draws_
the_distance_guide_label (frame test of the drawn label and line).
Cause: with Snap to Point, the point of a moved selection that snaps to a
ruler guide is the grabbed point (#1534). Away from an anchor or center
that was the raw pressed spot (select.rs: `grab` fell back to `p`;
direct.rs: a straight segment's `grab: p`, MoveObject's `start`). A press
on a stroke or within the pick tolerance of an edge lies a few pixels
beside the path, so the pressed spot landed on the guide, "align" showed,
and the path stopped that far beside it: 0.096 pt at 3,891% and 0.0099 pt
at 28,757% in the #3701 screenshots, visible only when zoomed in.
Change: `guides::hold_on_path` finds the nearest point of the path (on a
straight segment exactly on its line). `select::hold_point` uses it for a
press on the stroke or outline, or within 6 px of it. The Selection tool
(`State::Moving::hold`), Direct and Group Selection moves
(`State::MoveObject::hold`) and Direct Selection's straight-segment drag
(`grab`) snap that point. The move delta still runs from the press, so
nothing jumps. A press in the middle of a fill still snaps the pressed
spot, as Snap to Point is documented to.
Verification: tests_prefs::a_move_held_by_a_paths_stroke_lands_the_path_on_a_ruler_guide
and tests_prefs::a_straight_segment_dragged_by_direct_selection_lands_on_a_ruler_guide
fail without the change (edge 0.0257 pt and anchors -0.0052 pt off the
guide) and pass with it (|gap| < 1e-9 pt). A headless egui/wgpu render at
3,891% and 28,757% puts the guide, the selection outline and the centre of
the 1 pt stroke band in the same pixel column. cargo xtask ci: all 10
steps passed; 9429 tests passed, 0 failed.
Store corner radii as fractions of each corner's max so rounding scales with the shape; expose via Corners dialog and object.setLiveShape relativeRadii.
Co-authored-by: Cursor <cursoragent@cursor.com>
Illustrator links type in an area or along a path (https://helpx.adobe.com/illustrator/using/manage-text-area.html); until now only area type threaded here. Type on a path that overflows ends its line where its text stops fitting, so a story flows on from it, and its red out port, just past its end bracket, loads the Selection tool with the text as area type's does. A new frame threaded from it at a point is type on a path of its shape.