diff --git a/PrepStep/Form1.cs b/PrepStep/Form1.cs
index 807588c..5c9b5d7 100644
--- a/PrepStep/Form1.cs
+++ b/PrepStep/Form1.cs
@@ -95,38 +95,27 @@ public partial class Form1 : Form
_lblFase.Font = new Font(Font, FontStyle.Bold);
headerPanel.Controls.Add(_lblFase);
- // Barra di navigazione come footer separato dal contenuto: linea sottile in cima e
- // sfondo bianco, invece dei bottoni appoggiati direttamente sul contenuto/sulla barra
- // di stato senza alcuna divisione visiva.
- // Padding destro = 16, lo stesso usato dai pannelli di ogni fase (Padding(16)): prima
- // era 12, quindi "Avanti" sporgeva 4px oltre il margine destro del contenuto sopra.
- var navContainer = new Panel { Dock = DockStyle.Bottom, Height = 64, BackColor = Color.White };
- var navSeparatore = new Panel
- {
- Dock = DockStyle.Top,
- Height = 1,
- BackColor = Color.FromArgb(220, 220, 220),
- };
- var navPanel = new FlowLayoutPanel
- {
- Dock = DockStyle.Fill,
- FlowDirection = FlowDirection.RightToLeft,
- Padding = new Padding(16, 14, 16, 14),
- };
+ // Floatbar di navigazione: card staccata dai bordi della finestra invece di un footer
+ // a tutta larghezza appoggiato direttamente sul contenuto/sulla barra di stato.
+ var (navContainer, navPanel) = UiStile.FloatBar();
_btnAvanti.Text = "Avanti ›";
UiStile.Primario(_btnAvanti);
- UiStile.Arrotonda(_btnAvanti);
- _btnAvanti.Click += (_, _) => VaiAllaFase(_faseAttuale + 1);
- navPanel.Controls.Add(_btnAvanti);
_btnIndietro.Text = "‹ Indietro";
_btnIndietro.Margin = new Padding(8, 0, 0, 0);
- UiStile.Secondario(_btnIndietro);
- UiStile.Arrotonda(_btnIndietro);
+ UiStile.SecondarioPieno(_btnIndietro);
+
+ // Dimensioni uguali decise PRIMA di arrotondare: se si arrotonda un bottone e solo dopo
+ // lo si ridimensiona, la Region calcolata sulla dimensione vecchia lascia un bordo
+ // "fantasma" finché non arriva un repaint completo della finestra.
+ UiStile.LarghezzaUguale(_btnAvanti, _btnIndietro);
+ UiStile.Arrotonda(_btnAvanti, 10);
+ UiStile.Arrotonda(_btnIndietro, 10);
+
+ _btnAvanti.Click += (_, _) => VaiAllaFase(_faseAttuale + 1);
+ navPanel.Controls.Add(_btnAvanti);
_btnIndietro.Click += (_, _) => VaiAllaFase(_faseAttuale - 1);
navPanel.Controls.Add(_btnIndietro);
- navContainer.Controls.Add(navPanel);
- navContainer.Controls.Add(navSeparatore);
var statusPanel = new Panel { Dock = DockStyle.Bottom, Height = 28, BackColor = SystemColors.ControlLight };
_lblStatus.Dock = DockStyle.Fill;
diff --git a/PrepStep/PrtMancantiForm.cs b/PrepStep/PrtMancantiForm.cs
index 29890ed..733c245 100644
--- a/PrepStep/PrtMancantiForm.cs
+++ b/PrepStep/PrtMancantiForm.cs
@@ -64,21 +64,17 @@ public class PrtMancantiForm : Form
grid.Rows[i].DefaultCellStyle.ForeColor = Color.DarkRed;
}
- var pannelloAzioni = new Panel { Dock = DockStyle.Bottom, Height = 50 };
- var flowAzioni = new FlowLayoutPanel
- {
- Dock = DockStyle.Fill,
- FlowDirection = FlowDirection.RightToLeft,
- Padding = new Padding(12, 8, 12, 8),
- };
+ var (pannelloAzioni, flowAzioni) = UiStile.FloatBar();
var btnChiudi = new Button { Text = "Chiudi" };
UiStile.Primario(btnChiudi);
+ UiStile.Arrotonda(btnChiudi, 10);
btnChiudi.Click += (_, _) => Close();
flowAzioni.Controls.Add(btnChiudi);
var btnApriCartella = new Button { Text = "Apri cartella raw", Margin = new Padding(8, 0, 0, 0) };
- UiStile.Secondario(btnApriCartella);
+ UiStile.SecondarioPieno(btnApriCartella);
+ UiStile.Arrotonda(btnApriCartella, 10);
btnApriCartella.Click += (_, _) =>
{
try { Process.Start("explorer.exe", cartellaRaw); }
@@ -90,8 +86,6 @@ public class PrtMancantiForm : Form
};
flowAzioni.Controls.Add(btnApriCartella);
- pannelloAzioni.Controls.Add(flowAzioni);
-
Controls.Add(grid);
Controls.Add(lblInfo);
Controls.Add(pannelloAzioni);
diff --git a/PrepStep/UiStile.cs b/PrepStep/UiStile.cs
index 1bc4314..af6387f 100644
--- a/PrepStep/UiStile.cs
+++ b/PrepStep/UiStile.cs
@@ -54,6 +54,21 @@ internal static class UiStile
b.Cursor = Cursors.Hand;
}
+ /// Come Secondario, ma pieno invece che a bordo: sulle card bianche delle floatbar
+ /// (vedi FloatBar) il bordo sottile di Secondario è quasi invisibile su sfondo bianco, e il
+ /// bottone risulterebbe visivamente diverso dal Primario pieno accanto — stessa costruzione
+ /// (nessun bordo, riempimento pieno), solo grigio chiaro invece che blu.
+ public static void SecondarioPieno(Button b)
+ {
+ DimensionamentoAutomatico(b);
+ b.FlatStyle = FlatStyle.Flat;
+ b.FlatAppearance.BorderSize = 0;
+ b.FlatAppearance.MouseOverBackColor = Color.FromArgb(230, 233, 237);
+ b.FlatAppearance.MouseDownBackColor = Color.FromArgb(213, 217, 222);
+ b.BackColor = Color.FromArgb(241, 243, 245);
+ b.Cursor = Cursors.Hand;
+ }
+
/// Arrotonda gli angoli del controllo (bottone o card). Si aggancia a SizeChanged
/// invece di calcolare la Region una volta sola: con AutoSize la dimensione finale si
/// conosce solo a layout avvenuto (dopo Text/Padding), non subito dopo la creazione del
@@ -105,4 +120,56 @@ internal static class UiStile
return card;
}
+ /// Barra di bottoni "flottante" (Avanti/Indietro, Apri cartella raw/Chiudi, ecc.):
+ /// una card bianca staccata su tutti e 4 i lati dal bordo della finestra — non un footer a
+ /// tutta larghezza — con angoli arrotondati e bordo sottile, sospesa sopra lo sfondo grigio
+ /// della pagina invece che ancorata al bordo. Lo sfondo del contenitore esterno deve
+ /// combaciare con quello di default della Form (nessun BackColor impostato altrove:
+ /// SystemColors.Control) perché il "distacco" si veda solo nel margine attorno alla card,
+ /// non in una fascia di colore diverso.
+ public static (Panel Contenitore, FlowLayoutPanel Bottoni) FloatBar()
+ {
+ // Altezza minima per non tagliare il contenuto: bottone (MinimumSize.Height = 32) +
+ // padding verticale della riga bottoni (12+12) + padding verticale del contenitore
+ // esterno (10+16) = 82, con un po' di margine in più.
+ var contenitore = new Panel
+ {
+ Dock = DockStyle.Bottom,
+ Height = 88,
+ BackColor = SystemColors.Control,
+ Padding = new Padding(16, 10, 16, 16),
+ };
+
+ var card = new Panel { Dock = DockStyle.Fill, BackColor = Color.White };
+ card.Paint += (_, e) =>
+ {
+ using var penna = new Pen(ColoreBordoCard);
+ e.Graphics.DrawRectangle(penna, 0, 0, card.Width - 1, card.Height - 1);
+ };
+ Arrotonda(card, 14);
+
+ var bottoni = new FlowLayoutPanel
+ {
+ Dock = DockStyle.Fill,
+ FlowDirection = FlowDirection.RightToLeft,
+ Padding = new Padding(16, 12, 16, 12),
+ };
+
+ card.Controls.Add(bottoni);
+ contenitore.Controls.Add(card);
+ return (contenitore, bottoni);
+ }
+
+ /// Forza le stesse dimensioni per due bottoni della stessa barra (es. Avanti/
+ /// Indietro): AutoSize li dimensiona in base al proprio testo, e con testi di lunghezza
+ /// diversa (o solo uno dei due in grassetto, come Primario/Secondario) risulterebbero
+ /// disallineati sia in larghezza che in altezza — un dettaglio che un designer non
+ /// lascerebbe passare. Va chiamato dopo aver impostato Text/Font su entrambi.
+ public static void LarghezzaUguale(params Button[] bottoni)
+ {
+ int larghezza = bottoni.Max(b => b.PreferredSize.Width);
+ int altezza = bottoni.Max(b => b.PreferredSize.Height);
+ foreach (var b in bottoni)
+ b.MinimumSize = new Size(larghezza, altezza);
+ }
}
diff --git a/docs/architettura.md b/docs/architettura.md
index 14ce54e..13159ba 100644
--- a/docs/architettura.md
+++ b/docs/architettura.md
@@ -211,9 +211,22 @@ completi".
per i secondari, blu pieno per l'azione principale di ogni fase), entrambi con
`AutoSize`+`Padding`+`MinimumSize` invece di una `Size` fissa in pixel indovinata a
mano (altrimenti il testo va a capo e si taglia in verticale se non ci sta nella
- larghezza scelta). `Arrotonda` applica angoli arrotondati via `Region` calcolata su
- `SizeChanged` (non una volta sola: con `AutoSize` la dimensione finale del bottone si
- conosce solo a layout avvenuto), usata sui bottoni "Avanti"/"Indietro" del wizard.
+ larghezza scelta). `SecondarioPieno` è la variante senza bordo (sfondo grigio chiaro
+ pieno) per i bottoni secondari sopra le card bianche di `Card`/`FloatBar`, dove il
+ bordo sottile di `Secondario` è troppo poco visibile su sfondo bianco. `Arrotonda`
+ applica angoli arrotondati a un `Control` qualsiasi (bottone o card) via `Region`
+ calcolata su `SizeChanged`, non una volta sola: con `AutoSize` la dimensione finale si
+ conosce solo a layout avvenuto — va chiamata dopo aver fissato le dimensioni finali del
+ controllo (es. dopo `LarghezzaUguale`), altrimenti la `Region` vecchia resta visibile
+ come bordo residuo finché non arriva un repaint completo. `Card` costruisce una card di
+ stato (sfondo/bordo distinti, angoli arrotondati), usata in fase 1 per il riepilogo
+ Database. `FloatBar` costruisce la barra di navigazione "flottante" in fondo alle
+ finestre (card bianca staccata su tutti e 4 i lati, non un footer a tutta larghezza):
+ usata per Avanti/Indietro nel wizard e per Chiudi/Apri cartella raw in
+ `PrtMancantiForm`. `LarghezzaUguale` forza la stessa larghezza e altezza tra due
+ bottoni della stessa barra (es. Avanti/Indietro, che altrimenti avrebbero dimensioni
+ diverse: testi di lunghezza diversa, e il font in grassetto di `Primario` richiede più
+ altezza di quello normale di `Secondario`/`SecondarioPieno`).
- **app.ico** — icona dell'app, referenziata da `` nel csproj (icona
dell'exe in Esplora risorse/taskbar) e riletta esplicitamente in `Form1.BuildUi()`
con `Icon.ExtractAssociatedIcon(Application.ExecutablePath)` per la titlebar, senza