Phase 5-UI (Proof-of-Pattern): Launcher-Shell + erste extrahierte View (Terminal)

- Ui/LauncherForm: schlanke Startleiste, rendert Buttons dynamisch aus den
  registrierten Views (gruppiert) + Legacy-Button fuer das alte Tab-frm_main.
- Ui/ViewHostForm: generisches Host-Fenster fuer eine View (Control docked fill).
- Ui/ShellUiHost : IModuleUiHost: sammelt Views, oeffnet Einzelinstanz-Fenster.
- Ui/Views/TerminalView: erste designbare View (UserControl + Designer.cs);
  Terminal-Logik aus frm_main extrahiert; DI via Initialize(TerminalLogger)
  -> parameterloser Ctor bleibt fuer den VS-Designer nutzbar.
- Program.cs: startet jetzt LauncherForm (statt frm_main), registriert die
  Terminal-View; App bleibt via Legacy-Button voll bedienbar.
- Build 0 Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-02 10:47:14 +02:00
co-authored by Claude Opus 4.8
parent 26dd68a550
commit 3503bbb5d4
6 changed files with 409 additions and 2 deletions
+37
View File
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Windows.Forms;
using PolyTrader.Core.Modularity;
namespace PolyTraderSharp.Ui
{
/// <summary>
/// Sammelt die von Core-App und Modulen registrierten Views und öffnet sie als
/// eigenständige Host-Fenster (Einzelinstanz je View).
/// </summary>
public class ShellUiHost : IModuleUiHost
{
private readonly List<ModuleView> _views = new();
private readonly Dictionary<string, ViewHostForm> _open = new();
public IReadOnlyList<ModuleView> Views => _views;
public void RegisterView(ModuleView view) => _views.Add(view);
public void OpenView(ModuleView view)
{
if (_open.TryGetValue(view.Id, out var existing) && !existing.IsDisposed)
{
if (existing.WindowState == FormWindowState.Minimized)
existing.WindowState = FormWindowState.Normal;
existing.BringToFront();
existing.Activate();
return;
}
var host = new ViewHostForm(view);
host.FormClosed += (_, _) => _open.Remove(view.Id);
_open[view.Id] = host;
host.Show();
}
}
}