namespace PrepStep; public sealed class ProgressForm : Form { private readonly Label _lblCartella = new(); private readonly ProgressBar _progressBar = new(); private readonly Label _lblConteggio = new(); private readonly Label _lblDettaglio = new(); private readonly Label _lblEta = new(); private readonly Button _btnAnnulla = new(); private readonly ToolTip _tipCartella = new(); public event EventHandler? Annullato; public ProgressForm() { Text = "Aggiornamento indice in corso..."; FormBorderStyle = FormBorderStyle.FixedDialog; StartPosition = FormStartPosition.CenterParent; MinimizeBox = false; MaximizeBox = false; ControlBox = false; ClientSize = new Size(460, 190); _lblCartella.Text = "Preparazione..."; _lblCartella.Location = new Point(16, 16); // 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); _progressBar.Size = new Size(428, 24); _progressBar.Minimum = 0; _progressBar.Maximum = 1000; _progressBar.Style = ProgressBarStyle.Marquee; _lblConteggio.Location = new Point(16, 80); _lblConteggio.AutoSize = true; _lblDettaglio.Location = new Point(16, 104); _lblDettaglio.AutoSize = true; _lblDettaglio.ForeColor = SystemColors.GrayText; _lblEta.Location = new Point(16, 128); _lblEta.AutoSize = true; _lblEta.Font = new Font(Font, FontStyle.Bold); _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[] { _lblCartella, _progressBar, _lblConteggio, _lblDettaglio, _lblEta, _btnAnnulla }); } public void Aggiorna(ScanProgress p) { _lblCartella.Text = $"Scansione {p.Cartella}..."; _tipCartella.SetToolTip(_lblCartella, _lblCartella.Text); if (p.PrevistiTotali > 0) { _progressBar.Style = ProgressBarStyle.Continuous; double frazione = Math.Min(1.0, (double)p.FattiTotali / p.PrevistiTotali); _progressBar.Value = (int)(frazione * _progressBar.Maximum); } else { _progressBar.Style = ProgressBarStyle.Marquee; } _lblConteggio.Text = p.PrevistiTotali > 0 ? $"{p.FattiTotali:N0} / ~{p.PrevistiTotali:N0} file" : $"{p.FattiTotali:N0} file processati"; _lblDettaglio.Text = $"nuovi: {p.Nuovi:N0} aggiornati: {p.Aggiornati:N0} invariati: {p.Invariati:N0}" + (p.Rimossi > 0 ? $" rimossi: {p.Rimossi:N0}" : ""); _lblEta.Text = $"Trascorso: {FormatTempo(p.Trascorso)} — {StimaRimanente(p)}"; } private static string StimaRimanente(ScanProgress p) { if (p.PrevistiTotali <= 0 || p.FattiTotali <= 0) { return "stima non disponibile"; } double filePerSecondo = p.FattiTotali / Math.Max(p.Trascorso.TotalSeconds, 0.001); if (filePerSecondo <= 0) { return "stima non disponibile"; } long rimanenti = Math.Max(p.PrevistiTotali - p.FattiTotali, 0); var eta = TimeSpan.FromSeconds(rimanenti / filePerSecondo); return $"tempo rimanente stimato: {FormatTempo(eta)}"; } private static string FormatTempo(TimeSpan t) { if (t.TotalHours >= 1) { return $"{(int)t.TotalHours}h {t.Minutes}m {t.Seconds}s"; } if (t.TotalMinutes >= 1) { return $"{t.Minutes}m {t.Seconds}s"; } return $"{t.Seconds}s"; } }