Skip to content

Add connectors that bind to a shape and follow it - #139

Merged
marcosqlbi merged 3 commits into
mainfrom
feature/connectors
Sep 17, 2026
Merged

marcosqlbi merged 3 commits into
mainfrom
feature/connectors

Conversation

@marcosqlbi

Copy link
Copy Markdown
Collaborator

Pull request 5 of the 1.6.0 design objects plan, for issue #131. It adds the
third thing the Insert row offers: a line, an arrow, or a curved arrow drawn by
dragging, which can bind to a shape or a container and then follows it.

Why it is built the way it is:

  • A connector is a board object like any other, and not a container. It
    carries its two ends and, for each, an optional anchor - the object it is tied
    to and where on that object's box, as a fraction each way. The fraction rather
    than the point is what is kept, so an endpoint follows a move, a scale, and a
    stretch without the file recording the same thing twice, and a board opens with
    its connectors where they were drawn without anything being worked out from
    what is around them.
  • One description of the geometry. Core.Geometry.ConnectorGeometry gives
    the path as a polyline, the arrowhead, the shortened line under it, and the
    box, so the renderer, the hit test, the area selection, the binding dots, and a
    later vector export cannot disagree about where the line is. A curve is one
    cubic whose control points leave each end along the outward normal of the side
    the anchor sits on, flattened to 32 segments.
  • Following happens where linked strokes are already carried. The group
    gesture collects the connectors bound to a selected object that are not
    themselves selected, recomputes them from their anchors against the new bounds,
    and puts them in the same ReplaceObjectsCommand, so one undo restores the
    shapes and the arrows together.
  • Deleting a shape frees its arrows rather than taking them. That is two
    changes to the document and one thing that happened, so CompositeCommand
    joins them into one step of the history.
  • An export area is never cut between a shape and its arrow.
    BoardPartitioner puts a connector in the unit of what it is bound to, and a
    connector bound at both ends merges those two units.

It affects the board format (a board with a connector is written as version 7,
as one with a shape or a label already is), AppSettings (a Connector block of
last-used colour, thickness, and kind - settings version stays 19), the property
bar (Colour and Thickness now apply to connectors, and a Line kind row appears
when everything selected is one), the Insert row and the optional toolbar flyout,
and the overlay picture in an editable export, which now includes connectors so
none of them vanishes from a deck or a PDF. Native cxnSp and PDF paths are
pull request 6, which is being built in parallel; the change to EditableSlide
here is the smallest one that keeps connectors visible, and nothing in
SQLBI.Whiteboard.Export is touched.

Decisions the plan did not settle

  • A free end of a curve leaves horizontally towards the other end. The plan
    says "horizontally when free"; for two ends at the same X that is a tie, and it
    is broken rightwards, which makes a vertical free curve hook round to point
    back at itself. It looks deliberate rather than broken, and every other case
    reads well, so it is left as the plan wrote it.
  • The binding reach is 16 screen pixels and the tap band is still 8. A drop
    is not a tap: the endpoint is already where the hand put it, and the only
    question is whether it meant the object. Decision 6 gives the 16; the hit test
    keeps BoardObject.HitBand.
  • With Ctrl the target still has to be under the pointer, but the nearest
    border point may be any distance away, so there is no reach test on that path.
    A shape answers with its own outline, everything else with its box.
  • A lone connector has no corner handle at all - not the drawn one, not the
    resize cursor, and not the gesture. Its box is a box around a line, so what it
    offers instead is its two ends.
  • Dragging a connector by its body detaches both ends, as the plan says, and
    that is recorded as part of the same move, so one undo puts the bindings back.
  • The Insert row now has two buttons labelled Arrow - the block arrow shape
    and the arrow connector - on either side of a separator. Both names come from
    the plan, and the tooltips say which is which.
  • The connector glyphs are hand-drawn on the 24-unit grid. Fluent has arrows,
    but none of them is a line between two things, and the shape glyphs beside them
    are hand-drawn for the same reason.
  • Under Mouse drawing off, a left drag still borrows Select, so a connector
    is drawn with a mouse only when mouse drawing is on. That is exactly how the
    shape tool behaves, and changing it is not this pull request's to make.

To try by hand

  • Draw one of each kind with the pen, with a finger under Finger drawing, and
    with the mouse; check that the live preview follows and that a tap without a
    drag makes nothing.
  • Drop an end near a corner and near a side midpoint of a shape, a picture, a
    text container, and a label, and watch the eight dots appear within about a
    finger's width. Hold Ctrl at release and check the end lands on the outline
    itself - on an ellipse and a diamond, where the outline and the box differ most.
  • Bind both ends, move and then resize one shape, and check the arrow follows and
    that one undo puts everything back.
  • Select the connector alone: drag each endpoint, drag the body, and check that
    the property bar offers colour, thickness, and the three kinds, and that
    applying one changes every selected connector at once.
  • Delete a shape that two arrows point at; they should stay where they were, and
    one undo should bring the shape and the bindings back.
  • Rubber band and lasso across a curve rather than across its box, under both
    Area selects settings.
  • Export a board of shapes joined by connectors to a deck and to a PDF and check
    nothing is missing and that no slide cuts between a shape and its arrow.

🤖 Generated with Claude Code

marcosqlbi and others added 3 commits September 17, 2026 13:27
The record, the curve and arrowhead math, binding points, following and
detaching, version 7, the export unit merge, and the Core smoke tests.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The connector tool and its three kinds, the live preview and binding dots,
endpoint dragging with Select, following and detaching through the gestures,
the Line kind row, and the overlay export.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Its box is a box around a line, so the handle and its cursor would offer a
resize the surface does not draw and the plan does not want.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@marcosqlbi
marcosqlbi merged commit 4d84797 into main Sep 17, 2026
5 checks passed
@marcosqlbi
marcosqlbi deleted the feature/connectors branch September 17, 2026 11:47
marcosqlbi added a commit that referenced this pull request Sep 17, 2026
)

Pull request 7 of the 1.6.0 plan in `docs/design-objects.md`: the
release cut. The five
features are on `main` — the grid (#134), selection by area (#135), text
labels (#136),
shapes and the Insert tab (#137), and connectors (#139) — and none of
them touched the
prose, so this is where a person is told what they got. **#138, the
native editable export,
must merge before this one**: the release notes and the guide both say
shapes and labels
leave as objects in a deck and a PDF, which is true once it lands.

`VersionPrefix` goes 1.5.2 → 1.6.0, so `CHANGELOG.md` gains the matching
section and the
**Release notes** check applies to this pull request.
`./scripts/release-notes.ps1 -Mode
Verify -Version 1.6.0` passes, and `dotnet build Whiteboard.sln -c
Release` is clean.

## What it affects

- **`CHANGELOG.md`** — one `## 1.6.0 - 17 September 2026` section with
three entries, which
is the shape of 1.5.0 (3), 1.5.1 (1) and 1.5.2 (2): the Insert tab with
shapes,
connectors and text, selection by area, and the grid. The toolbar
preference is one
sentence inside the first entry rather than a fourth entry, because it
is where somebody
meets it. The first entry also carries the one thing a person deciding
whether to upgrade
has to know: a board holding any of the new objects does not open in
1.5.x.
- **`README.md`** — three bullets in *Included in the application*,
seven rows in
*Controls*, the Preferences lists in the bullet and in the table, and
the containers
paragraph, which now says shapes and labels are containers and that a
shape is picked up
  by its outline.
- **`site/guide.html`** — a new *Shapes, connectors, and text* section
after *Text and
code*, a paragraph on area selection under *Containers*, one sentence on
the grid under
  *Navigation*, and the Insert tab named in the command-strip section.
- **`site/shortcuts.html`** — Insert, Lasso and Grid rows, the rubber
band and Ctrl-to-add,
and the Alt-mnemonic row extended with Alt+I, Edit L, View G, and Insert
T.
- **`site/index.html`** — two feature tiles, shapes/connectors/text and
select by area.
- **`docs/decisions.md`** — decision 31, why design objects are ordinary
board objects,
why a shape is taken by its outline, and why the grid is an application
preference. The
rest stays in `docs/design-objects.md`, whose status line is now shipped
in 1.6.0.
- **`TODO.md`** — the current version, which still said 1.3.0, and what
1.6.0 left out.

## Readings taken, since nobody could be asked

- **`site/compare.html` is untouched.** It has no row saying Whiteboard
lacks shapes, text,
a grid or multi-select; the nearest, *Ink and objects*, is a statement
about strokes
travelling with a container and is still true. The brief said to change
such cells and
  nothing else, so nothing else changed.
- **`site/faq.html` is untouched.** No answer on it became wrong.
- ***Architecture* in `README.md` is untouched.** The `Core` bullet
names no types — it
says "world geometry, camera math, retained board objects, commands, hit
testing" — so
there was no list for `ShapeGeometry`, `ConnectorGeometry` and
`RotatedRectangle` to join,
  and the brief said to leave it alone in that case.
- **Escape is an edited row, not a new one**, in both the README table
and the shortcut
  list: Escape already had one, and a second would contradict it.
- **`site/changelog.html` is untouched**, as it is generated from
`CHANGELOG.md` at
  deployment.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
@marcosqlbi marcosqlbi mentioned this pull request Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant