docs: add spec for page1 header restyle and label fixes
This commit is contained in:
176
docs/superpowers/specs/2026-03-20-page1-header-restyle-design.md
Normal file
176
docs/superpowers/specs/2026-03-20-page1-header-restyle-design.md
Normal file
@@ -0,0 +1,176 @@
|
||||
# Design Spec: Page 1 Header Restyle & Label Fixes
|
||||
|
||||
**Date:** 2026-03-20
|
||||
**Status:** Approved
|
||||
**Scope:** `AnagraficaSectionRenderer.cs`, `EventiSectionRenderer.cs`, `PdfTheme.cs`
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Piccolo insieme di modifiche visive e testuali alla pagina 1 del report PDF e alla sezione eventi, senza alterare la struttura generale del report.
|
||||
|
||||
---
|
||||
|
||||
## 1. Nuovo layout header Pagina 1 (`AnagraficaSectionRenderer.DrawTitle`)
|
||||
|
||||
### Layout approvato
|
||||
|
||||
```
|
||||
Scheda Prodotto XS1234567890 ← centrato, blu bold, font grande
|
||||
──────────────────────────────────────────────── ← linea separatrice AccentBlue (2pt)
|
||||
[TIPOLOGIA / Cert. Bonus Cap] [DATA / 18/03/26] [BID / 98.50] [ASK / 99.20]
|
||||
```
|
||||
|
||||
### Specifiche riquadri (riga inferiore)
|
||||
|
||||
Tutti i box hanno la **stessa altezza** (28pt) e la **stessa struttura a due righe**:
|
||||
- Riga 1: label piccola (9pt, uppercase, bold, colore accent), altezza 11pt
|
||||
- Riga 2: valore (13pt bold, colore accent scuro), altezza 17pt
|
||||
|
||||
Il padding interno è 5pt verticale, 10pt orizzontale (dopo il bordo sinistro da 4pt).
|
||||
|
||||
| Box | Larghezza | Sfondo | Bordo sinistro | Colore label | Colore valore |
|
||||
|-----|-----------|--------|----------------|--------------|---------------|
|
||||
| Tipologia | `PageW - 3*6 - 84 - 70 - 70` | `PdfTheme.BoxLightBlueBg` | `PdfTheme.AccentBlue` 4pt | `PdfTheme.AccentBlue` | `PdfTheme.AccentBlueDark` |
|
||||
| Data | 84pt fisso | `PdfTheme.BoxGrayBg` | `PdfTheme.BoxGrayAccent` 4pt | `PdfTheme.BoxGrayLabel` | `PdfTheme.BoxGrayValue` |
|
||||
| Bid | 70pt fisso | `PdfTheme.BoxLightBlueBg` | `PdfTheme.AccentBlue` 4pt | `PdfTheme.AccentBlue` | `PdfTheme.AccentBlueDark` |
|
||||
| Ask | 70pt fisso | `PdfTheme.BoxLightBlueBg` | `PdfTheme.AccentBlue` 4pt | `PdfTheme.AccentBlue` | `PdfTheme.AccentBlueDark` |
|
||||
|
||||
Gap tra box: 6pt.
|
||||
|
||||
### Nuove costanti da aggiungere a `PdfTheme.cs`
|
||||
|
||||
```csharp
|
||||
public static readonly Color AccentBlueDark = Color.FromArgb(255, 13, 71, 161); // #0D47A1
|
||||
public static readonly Color BoxLightBlueBg = Color.FromArgb(255,235,242,251); // #EBF2FB
|
||||
public static readonly Color BoxGrayBg = Color.FromArgb(255,245,245,245); // #F5F5F5
|
||||
public static readonly Color BoxGrayAccent = Color.FromArgb(255,136,136,136); // #888888
|
||||
public static readonly Color BoxGrayLabel = Color.FromArgb(255,102,102,102); // #666666
|
||||
public static readonly Color BoxGrayValue = Color.FromArgb(255, 51, 51, 51); // #333333
|
||||
|
||||
// Brush corrispondenti
|
||||
public static readonly PdfBrush BoxLightBlueBgBrush = new PdfSolidBrush(BoxLightBlueBg);
|
||||
public static readonly PdfBrush BoxGrayBgBrush = new PdfSolidBrush(BoxGrayBg);
|
||||
public static readonly PdfBrush BoxGrayAccentBrush = new PdfSolidBrush(BoxGrayAccent);
|
||||
public static readonly PdfBrush BoxGrayLabelBrush = new PdfSolidBrush(BoxGrayLabel);
|
||||
public static readonly PdfBrush BoxGrayValueBrush = new PdfSolidBrush(BoxGrayValue);
|
||||
public static readonly PdfBrush AccentBlueDarkBrush = new PdfSolidBrush(AccentBlueDark);
|
||||
```
|
||||
|
||||
### Font per i box
|
||||
|
||||
Riusare i font esistenti in `PdfTheme`:
|
||||
- Label: `PdfTheme.Small` (9pt) — già esistente
|
||||
- Valore Bid/Ask/Data: `PdfTheme.Bold` (stesso usato altrove)
|
||||
- Valore Tipologia: nuovo font `PdfTheme.BoldSmall` (11pt bold) — aggiungere se non esistente, altrimenti usare font bold a 11pt inline
|
||||
|
||||
### Implementazione PDF (Syncfusion) — helper `DrawInfoBox`
|
||||
|
||||
Creare un metodo privato in `AnagraficaSectionRenderer`:
|
||||
|
||||
```csharp
|
||||
private void DrawInfoBox(PdfGraphics g, float x, float y, float w, float boxH,
|
||||
string label, string value,
|
||||
PdfBrush bgBrush, PdfBrush accentBrush, PdfBrush labelBrush, PdfBrush valueBrush,
|
||||
PdfFont valueFont)
|
||||
{
|
||||
// Sfondo
|
||||
g.DrawRectangle(bgBrush, new RectangleF(x, y, w, boxH));
|
||||
// Bordo sinistro 4pt
|
||||
g.DrawRectangle(accentBrush, new RectangleF(x, y, 4f, boxH));
|
||||
// Label (riga 1) — parte dopo il bordo + padding
|
||||
float innerX = x + 4f + 6f;
|
||||
float innerW = w - 4f - 6f - 4f;
|
||||
g.DrawString(label, PdfTheme.Small, labelBrush,
|
||||
new RectangleF(innerX, y + 4f, innerW, 11f));
|
||||
// Valore (riga 2)
|
||||
g.DrawString(value, valueFont, valueBrush,
|
||||
new RectangleF(innerX, y + 14f, innerW, 14f));
|
||||
}
|
||||
```
|
||||
|
||||
**Nota Syncfusion:** `RectangleF` non supporta named arguments — usare sempre la forma posizionale `new RectangleF(x, y, w, h)`.
|
||||
|
||||
### Gestione casi nulli / vuoti
|
||||
|
||||
- **Bid e Ask**: se `string.IsNullOrEmpty(info.Bid) || string.IsNullOrEmpty(info.Ask)`, i box Bid e Ask **non vengono disegnati**; la larghezza liberata viene assorbita dal box Tipologia. Il box Data viene comunque disegnato se `LastPriceDate` non è vuoto.
|
||||
- **Data**: se `string.IsNullOrEmpty(info.LastPriceDate)`, il box Data viene omesso.
|
||||
- **Tipologia**: se `string.IsNullOrEmpty(info.Categoria)`, il box Tipologia viene omesso; in quel caso i box rimanenti (Data/Bid/Ask) si dispongono da sinistra normalmente.
|
||||
|
||||
### Troncamento testo Tipologia
|
||||
|
||||
Il box Tipologia usa `RectangleF` con larghezza calcolata. Syncfusion tronca automaticamente il testo che eccede la `RectangleF` — nessuna logica extra necessaria. Il font 11pt consente fino a ~45 caratteri nella larghezza tipica (~290pt). Per tipologie più lunghe il testo viene tagliato dal renderer PDF senza errori.
|
||||
|
||||
### Rimozione logica precedente
|
||||
|
||||
Il vecchio `DrawTitle` disegnava:
|
||||
- Titolo a sinistra in `w * 0.65f` + Bid/Ask come stringa a destra in `w * 0.35f`
|
||||
- Tipologia come riga di testo grigio `Regular` sotto il titolo
|
||||
|
||||
Tutta la logica di `DrawTitle` viene riscritta. Il metodo `DrawTitle` torna `float y` (la nuova y dopo il titolo + linea + box row).
|
||||
|
||||
---
|
||||
|
||||
## 2. Rinomina colonne Tabella Sottostanti (`AnagraficaSectionRenderer.DrawSottostanti`)
|
||||
|
||||
Modifica solo le stringhe nell'array degli header:
|
||||
|
||||
| Vecchio | Nuovo |
|
||||
|---------|-------|
|
||||
| `"Barr.K"` | `"Barriera Capitale"` |
|
||||
| `"Buffer K"` | `"Buffer Capitale"` |
|
||||
| `"Trig.CPN"` | `"Trigger Cedola"` |
|
||||
| `"Buf.CPN"` | `"Buffer Cedola"` |
|
||||
|
||||
Le altre colonne (`Nome`, `Strike`, `Last`, `% Perf.`, `Trig.AC`) rimangono invariate. Le larghezze colonna possono richiedere un piccolo aggiustamento se i nuovi header non entrano — da verificare a runtime.
|
||||
|
||||
---
|
||||
|
||||
## 3. Rinomina colonna Tabella Eventi (`EventiSectionRenderer`)
|
||||
|
||||
| Vecchio | Nuovo |
|
||||
|---------|-------|
|
||||
| `"Trigger CPN"` | `"Trigger Cedola"` |
|
||||
|
||||
La colonna è alla posizione 4 (0-indexed), larghezza corrente 52pt. "Trigger Cedola" a font Small ha larghezza simile a "Trigger CPN" — la larghezza 52pt è sufficiente, non richiede modifica. Da verificare visivamente dopo il build.
|
||||
|
||||
---
|
||||
|
||||
## 4. Fix footer branding (`PdfTheme.DrawFooter`)
|
||||
|
||||
### Situazione attuale
|
||||
|
||||
Il codice esistente già usa `"Powered by "` (con spazio finale) come testo di prefisso, e calcola la X del link tramite `MeasureString`. Il bug visivo è che `PdfStandardFont.MeasureString` può restituire una larghezza che esclude il trailing space, causando sovrapposizione tra "by" e il link "Smart Roots".
|
||||
|
||||
### Fix
|
||||
|
||||
Aggiungere un offset fisso di **2pt** alla X del link, dopo il valore restituito da `MeasureString`:
|
||||
|
||||
```csharp
|
||||
// PRIMA:
|
||||
float prefixWidth = prefixFont.MeasureString(prefixText).Width;
|
||||
webLink.DrawTextWebLink(g, new PointF(prefixWidth, footerY));
|
||||
|
||||
// DOPO:
|
||||
float prefixWidth = prefixFont.MeasureString(prefixText).Width + 2f;
|
||||
webLink.DrawTextWebLink(g, new PointF(prefixWidth, footerY));
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files modificati
|
||||
|
||||
| File | Modifica |
|
||||
|------|----------|
|
||||
| `CertReports.Syncfusion/Helpers/PdfTheme.cs` | Nuove costanti colore/brush, fix footer offset +2pt |
|
||||
| `CertReports.Syncfusion/Services/Implementations/AnagraficaSectionRenderer.cs` | Riscrittura `DrawTitle`, helper `DrawInfoBox`, rinomina colonne sottostanti |
|
||||
| `CertReports.Syncfusion/Services/Implementations/EventiSectionRenderer.cs` | Rinomina colonna "Trigger CPN" → "Trigger Cedola" |
|
||||
|
||||
---
|
||||
|
||||
## Non in scope
|
||||
|
||||
- Modifiche al grafico, agli scenari, o ad altre sezioni del report
|
||||
- Modifiche al DB o alle stored procedure
|
||||
- Modifiche al layout delle sezioni A, B del report (Caratteristiche, Analisi)
|
||||
Reference in New Issue
Block a user