namespace IBKRTrader.UI; /// /// Verwaltet die eigenständigen Modul-Fenster des Launchers. /// Pro Modul-Key wird höchstens ein Fenster gehalten: erneutes Öffnen /// fokussiert das bestehende Fenster statt ein zweites zu erzeugen. /// /// Die tatsächlichen UI-Aktionen (Show/Focus) sind in überschreibbare /// Methoden gekapselt, damit die Tracking-Logik ohne Message-Loop testbar ist. /// public class WindowManager { private readonly Dictionary _open = new(StringComparer.OrdinalIgnoreCase); /// Öffnet das Fenster zum Key oder fokussiert ein bereits offenes. public Form OpenOrFocus(string key, Func
factory) { ArgumentException.ThrowIfNullOrWhiteSpace(key); ArgumentNullException.ThrowIfNull(factory); if (_open.TryGetValue(key, out var existing)) { if (!existing.IsDisposed) { Focus(existing); return existing; } _open.Remove(key); } var form = factory(); _open[key] = form; form.FormClosed += OnFormClosed; Present(form); return form; } /// True, wenn zum Key aktuell ein nicht-disposetes Fenster offen ist. public bool IsOpen(string key) => _open.TryGetValue(key, out var f) && !f.IsDisposed; /// Anzahl aktuell offener Fenster. public int OpenCount => _open.Values.Count(f => !f.IsDisposed); /// Schließt alle offenen Fenster (z. B. beim Beenden des Launchers). public void CloseAll() { foreach (var f in _open.Values.ToList()) { if (!f.IsDisposed) { f.FormClosed -= OnFormClosed; f.Close(); } } _open.Clear(); } // ─── Überschreibbare UI-Aktionen (für Tests) ────────────────────────────── /// Zeigt ein neu erzeugtes Fenster an. protected virtual void Present(Form form) => form.Show(); /// Bringt ein bestehendes Fenster in den Vordergrund. protected virtual void Focus(Form form) { if (form.WindowState == FormWindowState.Minimized) form.WindowState = FormWindowState.Normal; form.Activate(); form.BringToFront(); } private void OnFormClosed(object? sender, FormClosedEventArgs e) { if (sender is not Form f) return; f.FormClosed -= OnFormClosed; var entry = _open.FirstOrDefault(p => ReferenceEquals(p.Value, f)); if (entry.Key is not null) _open.Remove(entry.Key); } }