Files
PolyTraderSharp/Ui/ShellUiHost.cs
T
RichardandClaude Opus 4.8 f54cd7423b UI Slice 1a: Shell-Fundament + Launcher-Buttons statisch + Fenster-Menue + maximiert
- IModuleUiHost (Core) um Navigation erweitert: Views/IsOpen/OpenView/ActivateMain/OpenStateChanged
  + optionales Icon je ModuleView. So kann JEDES Fenster (auch Modul-Fenster, die nur Core kennen)
  das gemeinsame Fenster-Menue bauen.
- WindowMenu (Core): baut das 'Fenster'-Dropdown (Launcher + alle Views + Beenden), haakt offene
  Fenster an, markiert das aktuelle fett; Neuaufbau beim Aufklappen.
- ShellUiHost: SetMainWindow/ActivateMain; oeffnet ALLE Fenster jetzt MAXIMIERT (Vorgabe).
- Launcher: alle Modul-/Core-Buttons STATISCH im Designer (btn_copytrading/-resolutionfarming/
  -supervisor ergaenzt), an View-IDs gebunden; fehlt eine View -> Button deaktiviert. Dynamischer
  Laufzeit-Anhang ENTFERNT -> kein doppelter Accounting-Button mehr; leerer btn_accounting_Click raus.
  Datei/Beenden -> Fenster-Menue (WindowMenu). Launcher startet maximiert (Sizable, MinSize 1280x720).

Build 0 Fehler, --smoke-ui alle 6 Views + Launcher gruen. Fenster-Menue auf den uebrigen Fenstern folgt (1b).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-20 18:30:30 +02:00

80 lines
2.8 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using PolyTrader.Core.Modularity;
namespace PolyTraderSharp.Ui
{
/// <summary>
/// Verwaltet die registrierten Fenster-Views: öffnet sie als eigenständige Forms,
/// hält je View höchstens eine Instanz offen und holt ein bereits offenes Fenster
/// wieder in den Vordergrund. Meldet Änderungen am Offen-Status (für die
/// Button-Markierung im Launcher).
/// </summary>
public class ShellUiHost : IModuleUiHost
{
private readonly List<ModuleView> _views = new();
private readonly Dictionary<string, Form> _open = new();
private Form? _mainWindow;
/// <summary>Wird ausgelöst, wenn sich der Offen-Status irgendeiner View ändert.</summary>
public event Action? OpenStateChanged;
public IReadOnlyList<ModuleView> Views => _views;
public void RegisterView(ModuleView view) => _views.Add(view);
/// <summary>Setzt das Hauptfenster (Launcher) Ziel für <see cref="ActivateMain"/>.</summary>
public void SetMainWindow(Form main) => _mainWindow = main;
public void ActivateMain()
{
if (_mainWindow == null || _mainWindow.IsDisposed) return;
if (_mainWindow.WindowState == FormWindowState.Minimized)
_mainWindow.WindowState = FormWindowState.Maximized;
_mainWindow.BringToFront();
_mainWindow.Activate();
}
public bool IsOpen(string viewId) =>
_open.TryGetValue(viewId, out var form) && !form.IsDisposed;
public void OpenView(string viewId)
{
var view = _views.FirstOrDefault(v => v.Id == viewId);
if (view != null) OpenView(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 form = view.CreateForm();
if (string.IsNullOrEmpty(form.Text) || form.Text == form.Name)
form.Text = view.Title;
// Alle Fenster maximiert (Vorgabe): Full-HD-Ziel, skaliert auf größere Auflösungen.
form.StartPosition = FormStartPosition.CenterScreen;
form.WindowState = FormWindowState.Maximized;
_open[view.Id] = form;
form.FormClosed += (_, _) =>
{
_open.Remove(view.Id);
OpenStateChanged?.Invoke();
};
form.Show();
OpenStateChanged?.Invoke();
}
}
}