From ba18d682f3f9e0910e81c764b13950cd26ac0f8e Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Mon, 21 Sep 2026 10:40:32 +0200 Subject: [PATCH] Fix overflowing/clipped UI text and give buttons a consistent flat style Instruction and status labels used AutoSize/fixed widths with no wrap constraint, so long Italian paragraphs and network paths ran past the window edge or got clipped instead of wrapping. Report dialogs had fixed-height labels that clipped multi-line text. ProgressForm's folder label could overflow its non-resizable dialog. - Labels now wrap responsively (TableLayoutPanel column at 100% + Dock=Top) instead of a fixed pixel cap, so they reflow when the window is resized. - Report dialog labels switched from fixed Height to AutoSize. - ProgressForm's folder label truncates with ellipsis + tooltip, matching the existing pattern used by the import status label. - Added ApplicationHighDpiMode=PerMonitorV2 to fix control proportions on scaled displays. - Added UiStile.cs: shared flat button style (primary/secondary), rounded corners for the wizard nav buttons, and AutoSize+padding on all buttons so button size always matches its text (fixes text getting clipped when a hardcoded Size was too narrow for the label). - Fase 5's drag&drop .asm list now fills available vertical space instead of a fixed 680x160 box. Co-Authored-By: Claude Sonnet 5 --- CadSearchGui/CadSearchGui.csproj | 1 + CadSearchGui/Form1.Designer.cs | 2 - CadSearchGui/Form1.cs | 134 +++++++++++++++----------- CadSearchGui/ProgressForm.cs | 10 +- CadSearchGui/PrtMancantiForm.cs | 4 +- CadSearchGui/ReportCompletezzaForm.cs | 3 +- CadSearchGui/ReportStepForm.cs | 4 +- CadSearchGui/UiStile.cs | 72 ++++++++++++++ 8 files changed, 166 insertions(+), 64 deletions(-) create mode 100644 CadSearchGui/UiStile.cs diff --git a/CadSearchGui/CadSearchGui.csproj b/CadSearchGui/CadSearchGui.csproj index e51919e..22997bf 100644 --- a/CadSearchGui/CadSearchGui.csproj +++ b/CadSearchGui/CadSearchGui.csproj @@ -6,6 +6,7 @@ enable true enable + PerMonitorV2 diff --git a/CadSearchGui/Form1.Designer.cs b/CadSearchGui/Form1.Designer.cs index f91b798..2819e0f 100644 --- a/CadSearchGui/Form1.Designer.cs +++ b/CadSearchGui/Form1.Designer.cs @@ -22,9 +22,7 @@ partial class Form1 AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(1000, 650); - MinimumSize = new Size(700, 400); Name = "Form1"; - Text = "CadSearch — ricerca archivio CAD"; ResumeLayout(false); } } diff --git a/CadSearchGui/Form1.cs b/CadSearchGui/Form1.cs index 1c7f444..77fee35 100644 --- a/CadSearchGui/Form1.cs +++ b/CadSearchGui/Form1.cs @@ -89,23 +89,23 @@ public partial class Form1 : Form var navPanel = new FlowLayoutPanel { Dock = DockStyle.Bottom, - Height = 48, + // I bottoni si auto-dimensionano al testo (UiStile): l'altezza qui deve stare + // comoda sopra al loro MinimumSize (32) più il padding, altrimenti vengono + // tagliati sul fondo della barra invece di restarci dentro. + Height = 56, FlowDirection = FlowDirection.RightToLeft, - Padding = new Padding(12, 8, 12, 8), + Padding = new Padding(12, 10, 12, 10), }; - _btnAvanti.Text = "Avanti >"; - _btnAvanti.Size = new Size(110, 32); - _btnAvanti.FlatStyle = FlatStyle.Flat; - _btnAvanti.FlatAppearance.BorderSize = 0; - _btnAvanti.BackColor = ColorePrimario; - _btnAvanti.ForeColor = Color.White; - _btnAvanti.Font = new Font(Font, FontStyle.Bold); + _btnAvanti.Text = "Avanti ›"; + UiStile.Primario(_btnAvanti); + UiStile.Arrotonda(_btnAvanti); _btnAvanti.Click += (_, _) => VaiAllaFase(_faseAttuale + 1); navPanel.Controls.Add(_btnAvanti); - _btnIndietro.Text = "< Indietro"; - _btnIndietro.Size = new Size(110, 32); + _btnIndietro.Text = "‹ Indietro"; _btnIndietro.Margin = new Padding(8, 0, 0, 0); + UiStile.Secondario(_btnIndietro); + UiStile.Arrotonda(_btnIndietro); _btnIndietro.Click += (_, _) => VaiAllaFase(_faseAttuale - 1); navPanel.Controls.Add(_btnIndietro); @@ -228,9 +228,13 @@ public partial class Form1 : Form ColumnCount = 1, Padding = new Padding(16), }; + // Colonna al 100%: le label sotto (Dock=Top) vanno a capo sulla larghezza reale della + // finestra invece che su un limite fisso in pixel, e si riadattano se viene ridimensionata. + contenuto.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); var lblIstruzioni = new Label { + Dock = DockStyle.Top, AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 0, 0, 12), @@ -240,9 +244,8 @@ public partial class Form1 : Form }; contenuto.Controls.Add(lblIstruzioni); + _lblDb.Dock = DockStyle.Top; _lblDb.AutoSize = true; - _lblDb.AutoEllipsis = true; - _lblDb.MaximumSize = new Size(900, 0); _lblDb.ForeColor = SystemColors.GrayText; _lblDb.Margin = new Padding(0, 0, 0, 4); contenuto.Controls.Add(_lblDb); @@ -255,13 +258,13 @@ public partial class Form1 : Form var bottoni = new FlowLayoutPanel { AutoSize = true, FlowDirection = FlowDirection.LeftToRight }; _btnApriDb.Text = "Apri DB..."; - _btnApriDb.Size = new Size(120, 32); _btnApriDb.Margin = new Padding(0, 0, 8, 0); + UiStile.Secondario(_btnApriDb); _btnApriDb.Click += (_, _) => ScegliDatabase(); bottoni.Controls.Add(_btnApriDb); _btnAggiorna.Text = "Aggiorna indice"; - _btnAggiorna.Size = new Size(120, 32); + UiStile.Secondario(_btnAggiorna); _btnAggiorna.Click += (_, _) => AggiornaIndice(); bottoni.Controls.Add(_btnAggiorna); @@ -269,6 +272,7 @@ public partial class Form1 : Form var lblManutenzione = new Label { + Dock = DockStyle.Top, AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 20, 0, 8), @@ -278,7 +282,7 @@ public partial class Form1 : Form contenuto.Controls.Add(lblManutenzione); _btnPulisci.Text = "Pulisci raw e step"; - _btnPulisci.Size = new Size(200, 30); + UiStile.Secondario(_btnPulisci); _btnPulisci.Click += (_, _) => PulisciRawEStep(); contenuto.Controls.Add(_btnPulisci); @@ -297,9 +301,11 @@ public partial class Form1 : Form ColumnCount = 1, Padding = new Padding(16), }; + contenuto.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); var lblIstruzioni = new Label { + Dock = DockStyle.Top, AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 0, 0, 8), @@ -312,22 +318,22 @@ public partial class Form1 : Form var btnSfoglia = new Button { Text = "Scegli file distinta...", - Size = new Size(220, 32), Margin = new Padding(0, 0, 0, 8), }; + UiStile.Secondario(btnSfoglia); btnSfoglia.Click += (_, _) => ScegliFileDistinta(); contenuto.Controls.Add(btnSfoglia); - _btnVerifica.Text = "Verifica presenza nel DB"; - _btnVerifica.Size = new Size(220, 32); + _btnVerifica.Text = "Verifica presenza"; _btnVerifica.Margin = new Padding(0, 0, 0, 8); + UiStile.Secondario(_btnVerifica); _btnVerifica.Click += (_, _) => VerificaCodiciNelDb(); contenuto.Controls.Add(_btnVerifica); + _lblImportStatus.Dock = DockStyle.Top; _lblImportStatus.AutoSize = false; _lblImportStatus.AutoEllipsis = true; _lblImportStatus.Height = 24; - _lblImportStatus.Width = 900; _lblImportStatus.ForeColor = SystemColors.GrayText; contenuto.Controls.Add(_lblImportStatus); @@ -370,9 +376,11 @@ public partial class Form1 : Form ColumnCount = 1, Padding = new Padding(16), }; + contenuto.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); var lblIstruzioni = new Label { + Dock = DockStyle.Top, AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 0, 0, 8), @@ -382,13 +390,8 @@ public partial class Form1 : Form contenuto.Controls.Add(lblIstruzioni); _btnCreaRaw.Text = "Crea cartella raw"; - _btnCreaRaw.Size = new Size(220, 36); _btnCreaRaw.Margin = new Padding(0, 0, 0, 12); - _btnCreaRaw.FlatStyle = FlatStyle.Flat; - _btnCreaRaw.FlatAppearance.BorderSize = 0; - _btnCreaRaw.BackColor = ColorePrimario; - _btnCreaRaw.ForeColor = Color.White; - _btnCreaRaw.Font = new Font(Font, FontStyle.Bold); + UiStile.Primario(_btnCreaRaw); _btnCreaRaw.Click += (_, _) => CreaCartellaRaw(); contenuto.Controls.Add(_btnCreaRaw); @@ -431,9 +434,11 @@ public partial class Form1 : Form ColumnCount = 1, Padding = new Padding(16), }; + contenuto.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); var lblIstruzioni = new Label { + Dock = DockStyle.Top, AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 0, 0, 12), @@ -445,7 +450,7 @@ public partial class Form1 : Form contenuto.Controls.Add(lblIstruzioni); _btnTrovaPrt.Text = "Trova componenti referenziati"; - _btnTrovaPrt.Size = new Size(220, 32); + UiStile.Secondario(_btnTrovaPrt); _btnTrovaPrt.Click += (_, _) => TrovaPrtReferenziati(); contenuto.Controls.Add(_btnTrovaPrt); @@ -456,17 +461,22 @@ public partial class Form1 : Form private Panel BuildFaseVerifica() { - var contenuto = new TableLayoutPanel + // Padding qui invece che su ogni sotto-pannello: si applica uniformemente a top/fill/bottom + // (il layout docked usa il DisplayRectangle del contenitore, già ridotto dal Padding). + var panel = new Panel { Padding = new Padding(16) }; + + var top = new TableLayoutPanel { Dock = DockStyle.Top, AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink, ColumnCount = 1, - Padding = new Padding(16), }; + top.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); var lblIstruzioniCompletezza = new Label { + Dock = DockStyle.Top, AutoSize = true, ForeColor = SystemColors.GrayText, Margin = new Padding(0, 0, 0, 8), @@ -474,13 +484,13 @@ public partial class Form1 : Form + "(ricorsivamente fino ai PRT) sono nell'indice. Nota: la scansione dei .asm " + "è euristica, quindi qualche falso 'incompleto' è possibile.", }; - contenuto.Controls.Add(lblIstruzioniCompletezza); + top.Controls.Add(lblIstruzioniCompletezza); _btnCompletezza.Text = "Verifica completezza assiemi"; - _btnCompletezza.Size = new Size(220, 32); - _btnCompletezza.Margin = new Padding(0, 0, 0, 8); + _btnCompletezza.Margin = new Padding(0, 0, 0, 12); + UiStile.Secondario(_btnCompletezza); _btnCompletezza.Click += (_, _) => VerificaCompletezzaAssiemi(); - contenuto.Controls.Add(_btnCompletezza); + top.Controls.Add(_btnCompletezza); var lblAnteprimaAsm = new Label { @@ -489,13 +499,43 @@ public partial class Form1 : Form Margin = new Padding(0, 0, 0, 4), Text = "File .asm della distinta trovati nell'indice (trascinali su Creo/Esplora risorse):", }; - contenuto.Controls.Add(lblAnteprimaAsm); + top.Controls.Add(lblAnteprimaAsm); + var bottom = new TableLayoutPanel + { + Dock = DockStyle.Bottom, + AutoSize = true, + AutoSizeMode = AutoSizeMode.GrowAndShrink, + ColumnCount = 1, + }; + bottom.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100)); + + var lblIstruzioniStep = new Label + { + Dock = DockStyle.Top, + AutoSize = true, + ForeColor = SystemColors.GrayText, + Margin = new Padding(12, 0, 0, 8), + Text = "Dopo aver esportato gli STEP con Creo, premi qui per confrontare i componenti " + + "della distinta (e i sotto-componenti trovati in fase 4) con i file .stp presenti " + + "in 'step', copiare quelli trovati in 'step_finali' e vedere quali mancano ancora.", + }; + bottom.Controls.Add(lblIstruzioniStep); + + _btnReport.Text = "Crea cartella step_finali"; + UiStile.Secondario(_btnReport); + _btnReport.Click += (_, _) => GeneraReportStep(); + bottom.Controls.Add(_btnReport); + + // Dock=Fill invece di una Size fissa: la lista occupa tutto lo spazio verticale + // rimasto tra le istruzioni sopra e sotto, così si vedono più file .asm senza scroll + // anche a finestra ingrandita, invece dei ~160px fissi di prima. _lstAnteprimaAsm.View = View.LargeIcon; _lstAnteprimaAsm.MultiSelect = true; _lstAnteprimaAsm.LargeImageList = new ImageList { ImageSize = new Size(32, 32) }; - _lstAnteprimaAsm.Size = new Size(680, 160); - _lstAnteprimaAsm.Margin = new Padding(0, 0, 0, 20); + _lstAnteprimaAsm.Dock = DockStyle.Fill; + _lstAnteprimaAsm.Margin = new Padding(0, 4, 0, 12); + _lstAnteprimaAsm.BorderStyle = BorderStyle.FixedSingle; _lstAnteprimaAsm.ItemDrag += (_, e) => { var percorsi = _lstAnteprimaAsm.SelectedItems.Cast() @@ -504,26 +544,10 @@ public partial class Form1 : Form if (percorsi.Length > 0) _lstAnteprimaAsm.DoDragDrop(new DataObject(DataFormats.FileDrop, percorsi), DragDropEffects.Copy); }; - contenuto.Controls.Add(_lstAnteprimaAsm); - var lblIstruzioniStep = new Label - { - AutoSize = true, - ForeColor = SystemColors.GrayText, - Margin = new Padding(0, 0, 0, 8), - Text = "Dopo aver esportato gli STEP con Creo, premi qui per confrontare i componenti " - + "della distinta (e i sotto-componenti trovati in fase 4) con i file .stp presenti " - + "in 'step', copiare quelli trovati in 'step_finali' e vedere quali mancano ancora.", - }; - contenuto.Controls.Add(lblIstruzioniStep); - - _btnReport.Text = "Crea cartella step_finali"; - _btnReport.Size = new Size(220, 32); - _btnReport.Click += (_, _) => GeneraReportStep(); - contenuto.Controls.Add(_btnReport); - - var panel = new Panel(); - panel.Controls.Add(contenuto); + panel.Controls.Add(_lstAnteprimaAsm); + panel.Controls.Add(bottom); + panel.Controls.Add(top); return panel; } diff --git a/CadSearchGui/ProgressForm.cs b/CadSearchGui/ProgressForm.cs index 7b445be..9b2bc1a 100644 --- a/CadSearchGui/ProgressForm.cs +++ b/CadSearchGui/ProgressForm.cs @@ -8,6 +8,7 @@ public sealed class ProgressForm : Form private readonly Label _lblDettaglio = new(); private readonly Label _lblEta = new(); private readonly Button _btnAnnulla = new(); + private readonly ToolTip _tipCartella = new(); public event EventHandler? Annullato; @@ -23,7 +24,12 @@ public sealed class ProgressForm : Form _lblCartella.Text = "Preparazione..."; _lblCartella.Location = new Point(16, 16); - _lblCartella.AutoSize = true; + // AutoSize=false + AutoEllipsis: un percorso lungo (share di rete) va troncato con "..." + // invece di sforare il bordo del dialog, che è FixedDialog e non si può allargare. + // Il testo completo resta disponibile nel tooltip (stesso pattern di Form1._lblImportStatus). + _lblCartella.AutoSize = false; + _lblCartella.AutoEllipsis = true; + _lblCartella.Size = new Size(428, 20); _lblCartella.Font = new Font(Font, FontStyle.Bold); _progressBar.Location = new Point(16, 44); @@ -46,6 +52,7 @@ public sealed class ProgressForm : Form _btnAnnulla.Text = "Annulla"; _btnAnnulla.Location = new Point(354, 152); _btnAnnulla.Size = new Size(90, 28); + UiStile.Secondario(_btnAnnulla); _btnAnnulla.Click += (_, e) => Annullato?.Invoke(this, e); Controls.AddRange(new Control[] @@ -57,6 +64,7 @@ public sealed class ProgressForm : Form public void Aggiorna(ScanProgress p) { _lblCartella.Text = $"Scansione {p.Cartella}..."; + _tipCartella.SetToolTip(_lblCartella, _lblCartella.Text); if (p.PrevistiTotali > 0) { diff --git a/CadSearchGui/PrtMancantiForm.cs b/CadSearchGui/PrtMancantiForm.cs index a881787..f8fbea0 100644 --- a/CadSearchGui/PrtMancantiForm.cs +++ b/CadSearchGui/PrtMancantiForm.cs @@ -19,8 +19,7 @@ public class PrtMancantiForm : Form var lblInfo = new Label { Dock = DockStyle.Top, - AutoSize = false, - Height = 44, + AutoSize = true, Padding = new Padding(12, 8, 12, 8), Text = $"Copiati in \"{cartellaRaw}\": {numPrt} PRT e {numAsm} sotto-assiemi trovati nell'indice." + (codiciNonTrovati.Count > 0 @@ -57,6 +56,7 @@ public class PrtMancantiForm : Form } var btnApriCartella = new Button { Text = "Apri cartella raw", Dock = DockStyle.Bottom, Height = 34 }; + UiStile.Secondario(btnApriCartella); btnApriCartella.Click += (_, _) => { try { Process.Start("explorer.exe", cartellaRaw); } diff --git a/CadSearchGui/ReportCompletezzaForm.cs b/CadSearchGui/ReportCompletezzaForm.cs index 2192c93..81842a1 100644 --- a/CadSearchGui/ReportCompletezzaForm.cs +++ b/CadSearchGui/ReportCompletezzaForm.cs @@ -18,8 +18,7 @@ public class ReportCompletezzaForm : Form var lblInfo = new Label { Dock = DockStyle.Top, - AutoSize = false, - Height = 48, + AutoSize = true, Padding = new Padding(12, 8, 12, 8), Text = $"{completi} completi, {incompleti} incompleti, {nonTrovati} non trovati nell'indice " + $"su {righe.Count} componenti. Nota: la scansione dei .asm è euristica, qualche " diff --git a/CadSearchGui/ReportStepForm.cs b/CadSearchGui/ReportStepForm.cs index 1f33800..fe76957 100644 --- a/CadSearchGui/ReportStepForm.cs +++ b/CadSearchGui/ReportStepForm.cs @@ -31,8 +31,7 @@ public class ReportStepForm : Form var lblInfo = new Label { Dock = DockStyle.Top, - AutoSize = false, - Height = 32, + AutoSize = true, Padding = new Padding(12, 8, 12, 8), Text = $"{creati} copiati, {stepMancanti} da esportare (CAD presente), " + $"{nonTrovati} non nell'indice, su {righe.Count} totali. In \"{cartellaStepFinali}\".", @@ -68,6 +67,7 @@ public class ReportStepForm : Form } var btnApriCartella = new Button { Text = "Apri cartella step_finali", Dock = DockStyle.Bottom, Height = 34 }; + UiStile.Secondario(btnApriCartella); btnApriCartella.Click += (_, _) => { try { Process.Start("explorer.exe", cartellaStepFinali); } diff --git a/CadSearchGui/UiStile.cs b/CadSearchGui/UiStile.cs new file mode 100644 index 0000000..402e14f --- /dev/null +++ b/CadSearchGui/UiStile.cs @@ -0,0 +1,72 @@ +using System.Drawing.Drawing2D; + +namespace CadSearchGui; + +/// Stile bottoni condiviso tra la form principale e i dialog secondari: piatto con +/// bordo sottile e hover, per un aspetto coerente sia per l'azione primaria di ogni fase +/// (blu pieno) sia per le azioni secondarie, al posto del bottone grigio di default. +internal static class UiStile +{ + // AutoSize+Padding invece di una Size fissa in pixel: il bottone si dimensiona sempre + // al proprio testo (a qualunque lunghezza/font), niente più testo che va a capo e viene + // tagliato in verticale quando non ci sta nella larghezza indovinata a mano. + private static void DimensionamentoAutomatico(Button b) + { + b.AutoSize = true; + b.AutoSizeMode = AutoSizeMode.GrowAndShrink; + b.Padding = new Padding(18, 4, 18, 4); + b.MinimumSize = new Size(0, 32); + } + + public static void Primario(Button b) + { + DimensionamentoAutomatico(b); + b.FlatStyle = FlatStyle.Flat; + b.FlatAppearance.BorderSize = 0; + b.FlatAppearance.MouseOverBackColor = Color.FromArgb(0, 84, 152); + b.FlatAppearance.MouseDownBackColor = Color.FromArgb(0, 70, 130); + b.BackColor = Color.FromArgb(0, 99, 177); + b.ForeColor = Color.White; + b.Font = new Font(b.Font, FontStyle.Bold); + b.Cursor = Cursors.Hand; + } + + public static void Secondario(Button b) + { + DimensionamentoAutomatico(b); + b.FlatStyle = FlatStyle.Flat; + b.FlatAppearance.BorderColor = Color.FromArgb(190, 195, 200); + b.FlatAppearance.BorderSize = 1; + b.FlatAppearance.MouseOverBackColor = Color.FromArgb(230, 238, 245); + b.FlatAppearance.MouseDownBackColor = Color.FromArgb(213, 226, 238); + b.BackColor = Color.White; + b.Cursor = Cursors.Hand; + } + + /// Arrotonda gli angoli del bottone. 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 controllo. + public static void Arrotonda(Button b, int raggio = 6) + { + b.SizeChanged += (_, _) => AggiornaRegione(b, raggio); + AggiornaRegione(b, raggio); + } + + private static void AggiornaRegione(Button b, int raggio) + { + if (b.Width <= 0 || b.Height <= 0) + return; + + int d = raggio * 2; + var rect = new Rectangle(Point.Empty, b.Size); + using var percorso = new GraphicsPath(); + percorso.AddArc(rect.X, rect.Y, d, d, 180, 90); + percorso.AddArc(rect.Right - d, rect.Y, d, d, 270, 90); + percorso.AddArc(rect.Right - d, rect.Bottom - d, d, d, 0, 90); + percorso.AddArc(rect.X, rect.Bottom - d, d, d, 90, 90); + percorso.CloseFigure(); + + b.Region?.Dispose(); + b.Region = new Region(percorso); + } +}