Add connectors that bind to a shape and follow it - #139
Merged
Merged
Conversation
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
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>
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
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.
Core.Geometry.ConnectorGeometrygivesthe 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.
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 theshapes and the arrows together.
changes to the document and one thing that happened, so
CompositeCommandjoins them into one step of the history.
BoardPartitionerputs a connector in the unit of what it is bound to, and aconnector 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(aConnectorblock oflast-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
cxnSpand PDF paths arepull request 6, which is being built in parallel; the change to
EditableSlidehere is the smallest one that keeps connectors visible, and nothing in
SQLBI.Whiteboard.Exportis touched.Decisions the plan did not settle
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.
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.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.
resize cursor, and not the gesture. Its box is a box around a line, so what it
offers instead is its two ends.
that is recorded as part of the same move, so one undo puts the bindings back.
and the arrow connector - on either side of a separator. Both names come from
the plan, and the tooltips say which is which.
but none of them is a line between two things, and the shape glyphs beside them
are hand-drawn for the same reason.
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
with the mouse; check that the live preview follows and that a tap without a
drag makes nothing.
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.
that one undo puts everything back.
the property bar offers colour, thickness, and the three kinds, and that
applying one changes every selected connector at once.
one undo should bring the shape and the bindings back.
Area selects settings.
nothing is missing and that no slide cuts between a shape and its arrow.
🤖 Generated with Claude Code