Add shapes, the Insert tab, and an optional Insert button on the toolbar - #137
Merged
Merged
Conversation
ShapeBoardObject is a container selected by an eight-pixel band along its outline rather than by its interior, so what is drawn inside one stays reachable. ShapeGeometry answers for the outline once - as arcs for the renderer and as a polygon for the hit test and the area tests - so nothing derives it twice. A board that holds a shape is written as version 7; one with only frames stays 6 and one with neither stays 5, extending the rule frames set. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The surface draws a shape from the Core outline as one geometry, filled then stroked with the outline thickening with the zoom as ink does. The property bar's Color and Thickness rows now say which objects they apply to through named tests that the label and connector work extends by a line each, and a Fill row appears when everything selected is a shape. The editable export's overlay picture carries the shapes as well as the ink, and a writer that draws the ink itself still gets an overlay for them, so nothing disappears from a deck or a vector PDF before the native mapping lands. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
An Insert tab joins the strip between View and Help with the eight shapes and Alt+I. Picking one selects a shape tool: a drag draws the shape, Shift constrains it to a square, and a tap inserts one at 160 x 120. The new shape becomes the selection so the property bar can change it, and the tool stays for the next drag unless After inserting an object says to hand it back. Insert and Lasso on the toolbar, off by default, adds an Insert button beside Select with the same shapes in a flyout, and a chevron on Select offering Rectangle and Lasso that stays in step with the Edit row's toggle. Both are Collapsed when it is off, so the toolbar keeps the width it had. Select moves a shape by its outline band and resizes it freely from the corner handle, where Shift keeps the aspect - the opposite way round from a picture, which is the one difference a shape is allowed. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Text labels landed first, so this takes them in and puts the two side by side rather than in two places. - One Insert tab, one row: the eight shapes, a separator, then Text, which is the order the flyout shows and the order the connectors will be inserted into. The row is sticky, as main made it. - NeedsVersion7 covers labels and shapes; the archive keeps both cases and both sets of DTO fields. - The property bar's tests now read Color for a stroke, a shape, or a label, Thickness for a stroke or a shape, Fill for a shape, and Font for a label. A color change reaches shapes and strokes as one step and labels through their own path, which is also the one that changes the box being typed into. - The export overlay carries the ink, the labels, and the shapes, and the vector path still emits one for the design objects alone. - After inserting an object now governs the Text tool too: a committed label either leaves the tool for the next click or hands it back to Select, which is what decision 3 asks of every Insert tool. - The toolbar's Insert flyout ends with Text, and the Insert button reads as on for either tool. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 17, 2026
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 3 of the 1.6.0 plan in
docs/design-objects.md, closing #130. It adds theeight shapes, the Insert tab they come from, and the two Toolbar preferences that decide
where the Insert tools live and what happens after one has been drawn. It builds on #135,
which moved the per-type questions onto the records themselves — this adds a record and a
geometry and touches almost none of the window's switches.
Why it is shaped this way
A shape is taken hold of by its outline, never by its interior (decision 11). That is
the whole reason a shape can be a container: ink drawn inside one links to it and travels
with it, and a tap in the middle still reaches whatever is drawn there. The band is the
same eight screen pixels a frame's edge uses.
One description of the outline serves everybody.
Core.Geometry.ShapeGeometryreturnsa shape's outline as a start point and a list of line and arc steps. The surface hands the
arcs straight to WPF, so a circle stays a circle at any zoom; the hit test and the area
tests walk the same outline flattened to a polygon, sixty-four points to a full circle.
Nothing derives the geometry a second time, which is what stops the renderer and the hit
test disagreeing about where a shape's edge is — and it is what pull request 6 will read
to write native PowerPoint and PDF geometry.
The area asks the outline too. A rubber band over the empty corner of an ellipse's box
does not take the ellipse; one that crosses the curve does. A box test would have been
cheaper and would have felt wrong for exactly the shapes people draw around things.
Version 7 is asked for by the board that needs it.
NeedsVersion7is a one-linepredicate the label and connector work extends; a board with only frames still writes as 6
and one with neither as 5, so a board keeps opening in the release that can read it.
The two "applies when" tests in the property bar are named statics.
HasPrimaryColorand
HasThicknessare each one line for the text and connector pull requests to extend,rather than a predicate repeated at every row. Applying a color, a thickness, or a fill
replaces every selected stroke and shape as one step and becomes what the next shape is
drawn with.
Free resize is the one thing a shape does differently. Its corner handle takes the
width and the height the pointer is at, and Shift keeps the aspect — the opposite way round
from a picture, which is aspect-locked. It applies only when the selection is exactly one
shape; a set still scales as a set.
The editable export keeps the shapes visible. The overlay picture now carries the ink
and the shapes, and the vector PDF path — which draws the ink itself — still gets an
overlay for the shapes alone. Native shapes are pull request 6; until then nothing
disappears from a deck.
The toolbar's width
Measured from the XAML for the floating palette, at the default where the Eraser is not on
the bar. With the preference off both new controls are
Collapsedand contribute nothing,so the width is the 1.5.2 width to the pixel.
The compact pair grows by the Insert button (42) and the Select chevron (20); the dual pair
by 24, which is what the Insert button adds to the shared color column that sets the
palette's width. Both pairs were confirmed against a running copy: the measured deltas are
62 and 24 exactly. With the Eraser on the bar — that is, with finger or mouse drawing on —
the compact pair is 182 and 244.
Decisions the plan did not settle
a shape's first outline color and thickness are "the current pen's". Reading the pen's
setting at the moment a shape is drawn would make the same gesture produce different
shapes depending on which color was last chosen for ink, so
ShapeSettingsinsteadstarts at
InkPalettes.DefaultPen(vermillion, 4) and is last-used from then on, whichis what the settings table asks for.
side, a parallelogram slants by a quarter of its width, a block arrow's head starts at
three fifths and its shaft is half the height. Proportional rather than absolute, so a
shape dragged larger keeps the look it had when it was drawn.
dragged out of a rectangle should occupy that rectangle.
picking a tool is the start of drawing with it, and the row is where the next one comes
from. This branch had it closing on a pick and took main's answer instead.
for the Dual palette layout and says nothing about the chevron there; the dual palette's
widths are set by a shared column and a chevron would disturb it for one setting. Lasso
stays reachable from the Edit row in every layout.
outline shape set. Each is two nested contours filled even-odd on the same 24-unit grid,
including the Insert button's.
Decision 12 names a text container and a picture as the single-object cases and sends
everything else through the rasterizer only when more than one thing is selected. Worth a
look when the native export lands.
Taking in the text labels (#136)
origin/mainwas merged in after #136 landed, so the two sit side by side rather than intwo places:
order the flyout shows and the order the connectors will be inserted into.
NeedsVersion7covers labels and shapes; the archive keeps both cases and both sets ofDTO fields.
a stroke or a shape; Fill for a shape; Font for a label. A color reaches strokes and
shapes as one step, and labels through their own path — the one that also changes the box
being typed into while a label is open.
still emits one for the design objects alone.
shapes, but decision 3 is about every Insert tool, so a committed label either leaves the
tool for the next click or hands it back to Select.
tool.
Tests
Core harness: the outline of every kind at a known box; the band hitting the outline and
missing both the middle and the outside, and narrowing with the zoom; an area taking a
shape by its outline under both rules and refusing an empty corner of its box; a stroke
touching only a shape linking to it; the archive round trip with and without a fill, the
three versions, and an unknown kind normalizing to a rounded rectangle; the round trip and
normalization of both Toolbar settings and the shape defaults.
To try by hand
drawing. Only a mouse was driven here.
with a pen, which reaches them through the palette's own stylus path rather than through
mouse promotion.
height. It is what was dragged and Ctrl+Z removes it, but it is worth a look before the
connectors land on top of it.
🤖 Generated with Claude Code