Commit Graph
10 Commits
Author SHA1 Message Date
dotCooCoo cde9a27b4f Objects on Path: the widgets flatten the group's path once per lookup
Finding where the Rotate All, Space, Move All and Select/Move widgets
go and testing whether the pointer is over one flattened the group's
path two to three times per widget. Starting a Space, Move All or
Select/Move drag flattened it five times, and one pointer move over the
group could flatten it eleven times. Each lookup now flattens the path
once and shares that measurement across the widgets:

- vectorcraft-doc makes `Measured` public with `stop` and `stops`, and
  adds `attachable`, which returns the path with its measurement.
- `Widgets::of` gives all four widgets for the canvas, `widget_at` gives
  the widget under the pointer, and `WidgetDrag::hit` gives the drag a
  press starts, each from one flattening. The Selection and Objects on
  Path tools and the canvas use them.
- A Space, Move All or Select/Move drag keeps its measurement and
  measures again only when the group's path changes.

Widget places, hits, cursors and drag results are unchanged. The new
`spine-count` feature of vectorcraft-doc exposes the flattening counter
to vectorcraft-tools' tests; it is enabled only as a dev-dependency and
leaves Cargo.lock unchanged.
2026-11-14 03:01:29 -08:00
dotCooCoo a1cbb852b3 Objects on Path: a Select/Move drag takes the place nearest the pointer on a path that turns back
The drag chose its place from the point of the path nearest the pointer, but counted each point as
farther by half its distance along the path from the last one. On an open path that turns back on
itself, the object then stayed at its place while the pointer was over another object's ring 10 pt
away. The drag now uses the point nearest the pointer. Where the path passes as near the pointer
more than once, as where it runs back over itself, the drag follows the part nearest along the path
to where it was.
2026-11-12 05:06:00 -08:00
dotCooCoo 2ee2ac6245 Objects on Path: the Select/Move widget chooses an object and drags it to another place along the path
With one Objects on Path group selected, the Selection and Objects on Path
tools show a ring on each object's attachment point. A click chooses that
object while the group stays selected; dragging a ring along the path moves
its object to the nearest object's place, and the objects between move one
place toward where it was, in one undo step. Hidden and locked objects have
no ring and keep their places. On a closed path the drag goes on round
across the first anchor, and Escape cancels it.

- object.objectsOnPath.selectMember {member} chooses an object.
- object.objectsOnPath.moveMember {member, target, group?} moves an object
  to another object's place; only the order along the path changes.

Docs: docs/mcp.md, docs/target-app-parity.md. Not yet: Detach.
2026-11-12 01:41:55 -08:00
dotCooCoo 634b9c7ff8 Objects on Path: the Move All widget slides every attached object along the path
With one Objects on Path group selected whose objects have room to move,
the Selection and Objects on Path tools show a diamond below the first
object. Dragging it moves every object along the path together, keeping
the distances between them (object.objectsOnPath.options with start),
in one undo step; Escape cancels it, and the first object's distance
along the path shows next to the pointer.

On an open path the widget shows only when the distance from the first
object to the last is shorter than the path, and the objects stop at its
ends; on a closed path they go on round across the first anchor. Where
Auto or a Space value the open path is too short for sets the distance,
the drag also sets spacing to the distance as drawn.
2026-11-11 14:55:46 -08:00
dotCooCoo 2b29a680f3 Objects on Path: the Space widget spaces the attached objects along the path
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.
2026-11-03 16:03:40 +07:00
dotCooCoo 8b8b0c371f Objects on Path: the Rotate All widget turns every attached object about its attachment point
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.
2026-11-02 12:04:07 +07:00
dotCooCoo 9ba55b3c03 Objects on Path: the tool's Rotate stays within -360 to 360
tool.setOption kept any finite rotate, while the Objects on Path Tool
Options dialog shows Rotate clamped to -360 to 360 and saves the value
it was given, so a rotate of 450 showed as 360 and the next attach used
450. The tool now clamps rotate to -360 to 360, and attach clamps the
saved rotate it falls back to the same way.
2026-11-01 04:53:41 +07:00
dotCooCoo af86b2c833 Objects on Path: double-clicking the tool opens its options
Double-clicking the Objects on Path tool opens Objects on Path Tool
Options: a nine-point Pivot grid, a Rotate field, Reset (the center and
0) and Save. Save sets the tool's options, which last across tool
switches and are saved with the preferences. The tool sends them with
each attach, and object.objectsOnPath.attach without pivot or rotate
uses them, so they apply to the objects attached next; groups attached
before keep theirs.
2026-11-01 04:53:41 +07:00
dotCooCoo 6041bb3c62 Objects on Path: clipping paths and parts of blends, envelopes and repeats stay in place
object.objectsOnPath.attach took a path inside a compound path, blend,
envelope, repeat or Intertwine group, or a clipping path, as the path
and put it into the new Objects on Path group, so it was no longer a
part of its container. As objects, a blend's key path, a repeat's
source art, an envelope's content and a clipping path were put into
the new group the same way.
The Objects on Path tool highlighted a blend's key path or a clipping
path and attached the selection to it.

objects_on_path::held now finds the container that holds an object.
The command refuses such a path or object with a reason, and the tool
does not highlight it or attach to it. A member of a compound path
given as an object still attaches as its whole compound path. The four
new messages have rows in every complete-message catalog.

Docs: docs/mcp.md (Objects on Path).
2026-10-21 16:46:13 +07:00
dotCooCoo 219253f163 Objects on Path: attach objects to a path and spread them along it
VectorCraft had no Objects on Path. A click with the Objects on Path
tool attaches the selected objects to the path clicked. The tool is in
Edit Toolbar's Modify section and the Blend tool's flyout, and Object ›
Objects on Path › Attach and the context menu with two or more objects
selected choose it. The objects and the path go into an Objects on
Path group with the path at its bottom.

- object.objectsOnPath.attach orders the objects column by column from
  left to right and top to bottom in each column. The first one sits
  on the path's first anchor, the last one sits on the end of an open
  path, and the rest are spread evenly by length; a closed path takes
  them all the way round. Each object's attachment point (Pivot, one
  of nine, default the center of its bounds without strokes) sits on
  the path, and the object is turned to the path there. An object that
  was rotated by an angle other than a multiple of 90° is first turned
  to the nearest multiple of 90°. Rotate tilts every object by that
  many degrees counter-clockwise. Symbol instances are measured by
  their art. Guides, compound paths, type, paths without length and
  graphs are refused with a reason.
- After every edit the objects go back on the path: editing the path
  moves them, an object moved on its own goes back, and objects moved
  into or out of the group in the Layers panel join the end of the
  path or leave it. Scaling, shearing or reflecting the whole group
  keeps each object's scale, shear or reflection, and the objects are
  spread evenly along the transformed path again. Undo takes the path
  and the objects back in one step, and a copied group stays live on
  its own path.
- object.objectsOnPath.options changes Pivot and Rotate, and
  object.objectsOnPath.expand leaves a plain group. Both act on the
  groups that `ids` names, or on the groups of the selection when
  `ids` is not given.
- The native file keeps the group live; SVG, PDF and the other exports
  write plain art. The tool highlights the path under the pointer, has
  a cursor entry, and Escape during a press cancels the click.

Part of #2545

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-19 21:51:32 +07:00