Files
kniip/.cursor/plans/vormenknop_d1b7f613.plan.md
T
2026-11-10 15:33:49 +01:00

85 lines
6.5 KiB
Markdown

---
name: Vormenknop
overview: Een nieuwe werkbalkknop "Vormen" naast Rechthoek en Ellips, met in de eigenschappenbalk een keuzelijst voor 11 vormen (driehoek, pijl, ster, wolk, ballon, hart, maan, druppel, ei, bliksemschicht, spiraal). Je tekent een vorm door een kader te slepen, net als bij een rechthoek.
todos:
- id: model
content: ToolKind.Shape, ShapeKind-enum, StyleSet.ShapeKind en StyleProps.ShapeKind in StyleSet.cs
status: completed
- id: geometries
content: "ShapeGeometries.cs: de 11 vormen in een eenheidsvierkant, plus IsOpen en Icon; ShapeIconConverter"
status: completed
- id: annotation
content: "FigureAnnotation.cs: Render met transform, HitTest (open/gesloten), spiegelen"
status: completed
- id: ui
content: Werkbalkknop, ShapeKindTemplate, ShapeGroup/ShapeKindCombo in EditorWindow.xaml
status: completed
- id: wiring
content: "EditorWindow.xaml.cs: CreateAnnotation, UpdatePropsPanel, ShapeKind_Changed, knopicoon, DefaultSplitOrder, sneltoets F, hinttekst"
status: completed
- id: verify
content: "Bouwen en handmatig testen: alle vormen tekenen, wisselen, Shift, grepen, spiegelen, kopiëren/plakken, export"
status: completed
isProject: false
---
# Vormenknop met 11 vormen
## Gedrag
- Er komt een nieuwe gereedschapsknop **Vormen** direct na Ellips. Rechthoek en Ellips blijven zoals ze zijn.
- In de eigenschappenbalk staat een keuzelijst **Vorm** (icoon plus naam): Driehoek, Pijl, Ster, Wolk, Ballon, Hart, Maan, Druppel, Ei, Bliksemschicht, Spiraal.
- Het icoon op de werkbalkknop toont de laatst gekozen vorm. De keuze wordt per gereedschap onthouden, net als de andere stijlinstellingen.
- Tekenen gaat door een kader te slepen; de vorm vult dat kader. Met Shift wordt het kader vierkant. Er zijn 8 formaatgrepen, net als bij een rechthoek.
- Eigenschappen: randkleur, vulkleur, dikte, stippellijn en schaduw. De spiraal is een open lijn en krijgt geen vulling.
- Bij een geselecteerde vorm kun je via de keuzelijst een andere vorm kiezen (met undo).
- Spiegelen (horizontaal en verticaal) werkt voor vormen, zodat de pijl, maan, bliksem, ballon en spiraal ook de andere kant op kunnen.
- Sneltoets **F** (figuur), want de meeste voor de hand liggende letters zijn al bezet.
- Aanname: **Ballon** is hier een tekstballon zonder tekst (afgeronde rechthoek met een staart linksonder) en **Wolk** een gedachtewolk zonder staart, als losse vorm. Voor een ballon of wolk met tekst blijft het tekstgereedschap bestaan.
## Technische aanpak
**1. Model** in [src/Kniip/Editor/StyleSet.cs](src/Kniip/Editor/StyleSet.cs)
- `ToolKind.Shape` achteraan toevoegen. Instellingen worden als tekst opgeslagen (`JsonStringEnumConverter`), dus de volgorde breekt niets.
- Nieuwe enum `ShapeKind { Triangle, BlockArrow, Star, Cloud, Balloon, Heart, Moon, Drop, Egg, Lightning, Spiral }`.
- `StyleSet.ShapeKind` (standaard `Triangle`) en vlag `StyleProps.ShapeKind`.
- `PropsFor(ToolKind.Shape)` = Stroke, Fill, Thickness, Dash, Shadow, ShapeKind. `DefaultFor` gebruikt de gewone standaard (rode rand, geen vulling).
**2. Geometrie** in een nieuw bestand `src/Kniip/Editor/Annotations/ShapeGeometries.cs`
- `Geometry For(ShapeKind kind)` bouwt elke vorm in een eenheidsvierkant (0..1), gecachet en bevroren, zoals [CursorGeometries.cs](src/Kniip/Editor/Annotations/CursorGeometries.cs):
- Driehoek, Pijl (blokpijl naar rechts), Ster (5 punten), Bliksemschicht: rechte polygonen.
- Hart, Druppel, Ei, Maan, Ballon: Bezier- en boogsegmenten in een `StreamGeometry`. De maan wordt een cirkel min een verschoven cirkel (`GeometryCombineMode.Exclude`).
- Wolk: een vereniging van cirkels, zoals `TextAnnotation` dat al doet.
- Spiraal: een open polyline langs een Archimedes-spiraal (ongeveer 3 omwentelingen).
- `bool IsOpen(ShapeKind)` geeft true voor Spiraal.
- `Geometry Icon(ShapeKind)` schaalt dezelfde vorm naar 20x20 voor de knop en de keuzelijst. Er komt een `ShapeIconConverter` naar het voorbeeld van [CursorIconConverter.cs](src/Kniip/Editor/CursorIconConverter.cs).
**3. Annotatie**: nieuw `src/Kniip/Editor/Annotations/FigureAnnotation.cs`, afgeleid van [RectAnnotation.cs](src/Kniip/Editor/Annotations/RectAnnotation.cs), zodat grepen, verplaatsen en Shift al werken.
- `Kind => ToolKind.Shape`. De vorm komt uit `Style.ShapeKind`, zodat wisselen via `ChangeStyle` meteen werkt.
- `Render`: de eenheidsgeometrie klonen met een `MatrixTransform` naar `Rect` (plus een spiegeling met `FlipX`/`FlipY`). De lijndikte schaalt daardoor niet mee. Tekenen gebeurt via `RenderHelpers.DrawWithShadow`, zonder vulling bij een open vorm.
- `HitTest`: `FillContains` voor gesloten vormen, `StrokeContains` met tolerantie voor de spiraal.
- `CanFlip => true`; `Flip` wisselt `FlipX` of `FlipY`.
**4. Editor** in [src/Kniip/Editor/EditorWindow.xaml](src/Kniip/Editor/EditorWindow.xaml) en [EditorWindow.xaml.cs](src/Kniip/Editor/EditorWindow.xaml.cs)
- XAML: een `RadioButton Tag="Shape" ItemId="Shape" Title="Vormen"` na Ellips, met een `Path x:Name="ShapeToolIcon"`. Daarnaast een `ShapeKindTemplate` (icoon via de converter, plus een label per waarde, net als `CursorKindTemplate`) en een `ShapeGroup` met `ShapeKindCombo` in de eigenschappenbalk.
- Code:
- `ShapeKindValues` als `ItemsSource`.
- `"Shape"` na `"Ellipse"` in `DefaultSplitOrder`. `MergeToolbarOrder` zet de nieuwe knop bij bestaande gebruikers automatisch na Ellips.
- `CreateAnnotation`: `ToolKind.Shape => new FigureAnnotation { Rect = new Rect(p, p), Style = style }`.
- `UpdatePropsPanel`: zichtbaarheid van `ShapeGroup` en selectie van `ShapeKindCombo`. De vulling wordt verborgen bij Spiraal.
- Handler `ShapeKind_Changed` roept `ChangeStyle("shape", s => s.ShapeKind = kind)` aan en werkt `ShapeToolIcon` bij. Bij het starten wordt het icoon ook gezet.
- Sneltoets `Key.F` en een hinttekst: "Sleep om de gekozen vorm te tekenen. Shift = gelijke breedte en hoogte. Kies een andere vorm in de balk eronder."
```mermaid
flowchart LR
ShapeKindCombo --> ChangeStyle --> StyleShapeKind["StyleSet.ShapeKind"]
StyleShapeKind --> ShapeGeometries
ShapeGeometries --> FigureAnnotation
ShapeGeometries --> ShapeIconConverter
ShapeIconConverter --> ShapeToolIcon
ShapeIconConverter --> ShapeKindTemplate
```
## Buiten scope
- Draaien van vormen. Een pijl omhoog of omlaag kan daardoor niet; links en rechts wel, via spiegelen.
- Tekst in een vorm. Daarvoor blijft het tekstgereedschap met ballon en wolk.
- Instelbare details per vorm, zoals het aantal punten van de ster, de dikte van de maan of het aantal windingen van de spiraal.