Files
SmartReports/docs/superpowers/specs/2026-03-20-page1-header-restyle-design.md

177 lines
7.8 KiB
Markdown

# 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)