Fehler #87
Von Julius Haman vor 5 Tagen aktualisiert
## Ausgangslage In der Trainingsdetail-Seite zeigt die Karte "Pulszonen" „Pulszonen" das OxyPlot-Kreisdiagramm (300 × 230 px, `TrainingDetailView.xaml`, `oxy:PlotView` → `ZonePieModel`) mit der Zonenlegende rechts daneben. An den Tortenstücken stehen Prozentwerte **außen** mit Fehlerlinie Fühlerlinie (Tick). Bei den Segmenten oben (12 Uhr) und unten (6 Uhr) ist der Text oben bzw. unten angeschnitten und nicht vollständig lesbar; auch seitlich steht der Text dicht am Rand. ## Ursache * OxyPlot 2.2.0 `PieSeries` belegt `OutsideLabelFormat` im Konstruktor mit **`"{2:0} %"`** (Vorgabe, nicht `null`). Der Code setzt diese Eigenschaft nirgends - – die Außenbeschriftung entsteht also implizit und wurde so nie geplant. * `InsideLabelFormat = string.Empty` (TrainingDetailViewModel, `BuildZonePie`) betrifft ausschließlich Text **in** den Segmenten und ist für das Problem ohne Bedeutung (leerer String statt `null` lässt OxyPlot pro Segment trotzdem Text ausgeben). * OxyPlot berechnet den Radius als `min(PlotArea.Breite, PlotArea.Höhe) / 2`, die Torte füllt den Plotbereich also **randlos** - – im OxyPlot-Quellcode steht dazu `// todo: reduce available size due to the labels`. Tick (6 px radial + 8 px horizontal) und Text liegen damit außerhalb des sichtbaren Bereichs und werden vom festen 300 × 230-PlotView abgeschnitten. Betroffene Stelle: `ErControl.Core/ViewModels/TrainingDetailViewModel.cs`, Methode `BuildZonePie` (`new PieSeries { InsideLabelFormat = string.Empty, TrackerFormatString = ... }`). ## Lösungsvorschlag (umgesetzt) 1. Radius der Torte verkleinern: `PieSeries.Diameter = 0.9` (vorher 1,0, OxyPlot-Vorgabe), verkleinern (`PieSeries.Diameter`, ca. 0,9), damit oben und unten etwa 25–30 px Luft für Tick + Text bleibt. bleiben – PlotView-Größe und Layout (Karte neben der der Legende) bleiben unverändert. - Gemessen (echter WPF-Renderer, 300 × 230 px): PlotArea 8,0 … 221,6 / 8,0 … 292,0 → Ø Torte bei 0,9 = 190,8 px, Label-Rand oben/unten je 8-9 px. - Diameter 1,0 (vorher): nur 2 px Rand → Text oben/unten abgeschnitten. - Die ursprünglich geschätzten "25-30 px Luft" waren zu groß; für Tick (6 px) + Text (~8 px) reichen die gemessenen 8-9 px, solange kein Label über die PlotArea-Grenze hinausragt. 2. `OutsideLabelFormat` explizit auf `"{2:0} %"` setzen statt auf die OxyPlot-Vorgabe zu verlassen, verlassen, `InsideLabelFormat = null` statt leerem String. 3. Prüfen, ob das %-Format an der Torte (`"{2:0} %"`, ganzzahlig) und in der Legende zusammenpasst (Torte `"{2:0} %"` gerundet vs. Legende (`{percent:P1}`, eine Nachkommastelle): **bewusst so belassen** - abgestimmt und in Ordnung. `"{percent:P1}"` mit Nachkommastelle). Alternative (Außenbeschriftung (bitte entscheiden): Außenbeschriftung komplett abschalten, nur Legende): **entschieden, nicht abschalten umgesetzt** - (`OutsideLabelFormat = null`) und die Prozentwerte sollen weiterhin an nur in der Torte stehen, nur eben bewusst Legende zeigen – konfiguriert statt dann aber bewusst, nicht durch den einen OxyPlot-Zufall. ## Umsetzung * Commit `4c3ade6` - "#87 fix(trainingdetail): Prozentwerte an der Pulszonen-Torte nicht mehr abgeschnitten" (nur `TrainingDetailViewModel.cs` + `PulseZonePieSlice.cs`). * `dotnet build ErControl.slnx` = 0 Fehler, `dotnet test ErControl.Core.Tests` = 122/122 grün. * Layoutprüfung mit dem **echten WPF-Renderer** (offscreen `PlotView` → `RenderTargetBitmap`), Kantenabstände der Beschriftung in px (schlimmster Fall = Segment exakt um 12/6 Uhr): | Fall | Diameter 1,0 (vorher) | Diameter 0,9 (umgesetzt) | |---|---|---| | 50/50 (12 + 6 Uhr) | oben 2 / unten 2 → abgeschnitten | oben 9 / unten 8 | | 5 Zonen | oben 2 / unten 3 → abgeschnitten | oben 9 / unten 13 | | 1 %-Segment | links 2 → abgeschnitten | links 10 | | 100 %-Segment | links 2 → abgeschnitten | links 5 | | Dark-Skin | wie hell | wie hell (identisch) | * PlotArea ist im WPF-Pfad bereits **symmetrisch** (Torte mittig, Mitte y ≈ 114,8) - kein zusätzlicher Eingriff nötig. Die zuvor vermutete Asymmetrie war ein Artefakt des ImageSharp-Testharness, der für den leeren Titel ~55 px reserviert; der WPF-Renderer liefert bei `Title = null` `OxySize.Empty`. ## Abnahmekriterien * [x] [ ] Alle Prozentwerte an den Tortenstücken sind vollständig sichtbar, auch bei den Segmenten oben und unten und bei einem 100 %-Segment. * [x] [ ] Kein Abschneiden bei sehr kleinen Anteilen (z. B. 1-2 1–2 %). * [x] [ ] Klick-Tracker (`Zone: Wert (x,x %)`) und die Legende bleiben unverändert. * [x] [ ] Keine Layoutänderung an der Karte (300 × 230 px) und an der Trainingsdetailseite. * [x] [ ] Im Hell- und im Dark-Skin geprüft (Textfarbe folgt `PlotModel.TextColor`).