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>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ca0d4ceed0
commit
f54cd7423b
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace PolyTrader.Core.Modularity
|
||||
@@ -23,6 +24,9 @@ namespace PolyTrader.Core.Modularity
|
||||
/// <summary>Optionale Sortierreihenfolge.</summary>
|
||||
public int Order { get; init; } = 0;
|
||||
|
||||
/// <summary>Optionales Icon (16x16) für Menü/Buttons. Wird von der Shell/den Menüs genutzt.</summary>
|
||||
public System.Drawing.Image? Icon { get; init; }
|
||||
|
||||
/// <summary>Erzeugt das anzuzeigende Fenster (frische Instanz je Öffnung).</summary>
|
||||
public Func<Form> CreateForm { get; init; } = () => new Form();
|
||||
}
|
||||
@@ -30,9 +34,26 @@ namespace PolyTrader.Core.Modularity
|
||||
/// <summary>
|
||||
/// Wird der Shell beim Start übergeben; Core und Module registrieren hier ihre Ansichten.
|
||||
/// Die Shell (Launcher) öffnet die Fenster auf Anforderung und verwaltet den Offen-Status.
|
||||
/// Über die Navigations-Mitglieder kann JEDES Fenster (auch Modul-Fenster, die nur den Core
|
||||
/// kennen) das gemeinsame „Fenster"-Menü bauen (siehe <see cref="WindowMenu"/>).
|
||||
/// </summary>
|
||||
public interface IModuleUiHost
|
||||
{
|
||||
void RegisterView(ModuleView view);
|
||||
|
||||
/// <summary>Alle registrierten Ansichten (Core + Module).</summary>
|
||||
IReadOnlyList<ModuleView> Views { get; }
|
||||
|
||||
/// <summary>Ist das Fenster dieser View gerade offen?</summary>
|
||||
bool IsOpen(string viewId);
|
||||
|
||||
/// <summary>Öffnet die View bzw. holt ein bereits offenes Fenster in den Vordergrund (maximiert).</summary>
|
||||
void OpenView(string viewId);
|
||||
|
||||
/// <summary>Holt das Hauptfenster (Launcher) in den Vordergrund.</summary>
|
||||
void ActivateMain();
|
||||
|
||||
/// <summary>Feuert, wenn sich der Offen-Status irgendeiner View ändert.</summary>
|
||||
event Action? OpenStateChanged;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace PolyTrader.Core.Modularity
|
||||
{
|
||||
/// <summary>
|
||||
/// Baut das gemeinsame „Fenster"-Menü, das auf JEDEM PolyTrader-Fenster erscheint und das Wechseln
|
||||
/// zwischen allen Fenstern (Launcher + Core + Module) erlaubt. Da es nur den Core-Contract
|
||||
/// <see cref="IModuleUiHost"/> nutzt, funktioniert es auch aus Modul-Fenstern (die die App nicht kennen).
|
||||
///
|
||||
/// Der Menü-Container liegt im Designer jedes Fensters (ein <see cref="ToolStripMenuItem"/> „Fenster");
|
||||
/// die dynamische Liste (Offen-Status ändert sich) wird hier beim Aufklappen frisch gefüllt:
|
||||
/// offene Fenster sind angehakt, das aktuelle Fenster ist fett + angehakt markiert.
|
||||
/// </summary>
|
||||
public static class WindowMenu
|
||||
{
|
||||
/// <summary>Verdrahtet ein Designer-„Fenster"-Menüelement mit der Fensterliste (Neuaufbau beim Aufklappen).</summary>
|
||||
public static void Wire(ToolStripMenuItem fensterMenu, IModuleUiHost host, string? currentViewId)
|
||||
{
|
||||
fensterMenu.DropDownOpening += (_, _) => Populate(fensterMenu, host, currentViewId);
|
||||
Populate(fensterMenu, host, currentViewId);
|
||||
}
|
||||
|
||||
public static void Populate(ToolStripMenuItem fensterMenu, IModuleUiHost host, string? currentViewId)
|
||||
{
|
||||
fensterMenu.DropDownItems.Clear();
|
||||
|
||||
var launcher = new ToolStripMenuItem("Launcher") { Checked = currentViewId == null };
|
||||
if (currentViewId == null) launcher.Font = new Font(launcher.Font, FontStyle.Bold);
|
||||
launcher.Click += (_, _) => host.ActivateMain();
|
||||
fensterMenu.DropDownItems.Add(launcher);
|
||||
fensterMenu.DropDownItems.Add(new ToolStripSeparator());
|
||||
|
||||
foreach (var view in host.Views.OrderBy(v => v.Order).ThenBy(v => v.Title))
|
||||
{
|
||||
bool isCurrent = view.Id == currentViewId;
|
||||
var item = new ToolStripMenuItem(view.Title) { Image = view.Icon };
|
||||
item.Checked = isCurrent || host.IsOpen(view.Id);
|
||||
if (isCurrent) item.Font = new Font(item.Font, FontStyle.Bold);
|
||||
string id = view.Id;
|
||||
item.Click += (_, _) => host.OpenView(id);
|
||||
fensterMenu.DropDownItems.Add(item);
|
||||
}
|
||||
|
||||
fensterMenu.DropDownItems.Add(new ToolStripSeparator());
|
||||
var exit = new ToolStripMenuItem("Beenden");
|
||||
exit.Click += (_, _) => Application.Exit();
|
||||
fensterMenu.DropDownItems.Add(exit);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user