UI Slice 1b: Fenster-Menue auf ALLEN Fenstern (zentrale Shell-Injektion)
ShellUiHost injiziert das gemeinsame 'Fenster'-Menue beim Oeffnen zentral in jedes Fenster (nur wenn keins eigenes vorhanden ist, z.B. Launcher). Damit erscheint das Menue auf allen Core- und Modul-Fenstern ohne Achtfach-Designer-Duplikat, und jedes kuenftige Fenster bekommt es automatisch. Inhaltliche Controls bleiben designerbasiert; das Nav-Menue ist Shell-Chrome. Tests: +3 (WindowMenu.Populate: Inhalt Launcher/Views/Beenden, aktuelles Fenster fett+angehakt, offenes angehakt, Klick navigiert). 389 Tests gruen, --smoke-ui gruen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
f54cd7423b
commit
25f0d34042
@@ -28,6 +28,20 @@ namespace PolyTraderSharp.Ui
|
|||||||
/// <summary>Setzt das Hauptfenster (Launcher) – Ziel für <see cref="ActivateMain"/>.</summary>
|
/// <summary>Setzt das Hauptfenster (Launcher) – Ziel für <see cref="ActivateMain"/>.</summary>
|
||||||
public void SetMainWindow(Form main) => _mainWindow = main;
|
public void SetMainWindow(Form main) => _mainWindow = main;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fügt einem Fenster das gemeinsame „Fenster"-Menü hinzu (oberste Leiste). Als letztes
|
||||||
|
/// hinzugefügtes Top-Control belegt der MenuStrip die oberste Zeile über etwaigen ToolStrips.
|
||||||
|
/// </summary>
|
||||||
|
private void AttachWindowMenu(Form form, string currentViewId)
|
||||||
|
{
|
||||||
|
var menu = new MenuStrip { Dock = DockStyle.Top };
|
||||||
|
var fenster = new ToolStripMenuItem("Fenster");
|
||||||
|
menu.Items.Add(fenster);
|
||||||
|
PolyTrader.Core.Modularity.WindowMenu.Wire(fenster, this, currentViewId);
|
||||||
|
form.Controls.Add(menu);
|
||||||
|
form.MainMenuStrip = menu;
|
||||||
|
}
|
||||||
|
|
||||||
public void ActivateMain()
|
public void ActivateMain()
|
||||||
{
|
{
|
||||||
if (_mainWindow == null || _mainWindow.IsDisposed) return;
|
if (_mainWindow == null || _mainWindow.IsDisposed) return;
|
||||||
@@ -61,6 +75,12 @@ namespace PolyTraderSharp.Ui
|
|||||||
if (string.IsNullOrEmpty(form.Text) || form.Text == form.Name)
|
if (string.IsNullOrEmpty(form.Text) || form.Text == form.Name)
|
||||||
form.Text = view.Title;
|
form.Text = view.Title;
|
||||||
|
|
||||||
|
// Gemeinsames „Fenster"-Menü zentral in jedes Fenster injizieren (identische Shell-Chrome
|
||||||
|
// auf allen Fenstern; die inhaltlichen Controls bleiben designerbasiert). Nur, wenn das
|
||||||
|
// Fenster nicht bereits ein eigenes Menü mitbringt (z. B. der Launcher).
|
||||||
|
if (form.MainMenuStrip == null)
|
||||||
|
AttachWindowMenu(form, view.Id);
|
||||||
|
|
||||||
// Alle Fenster maximiert (Vorgabe): Full-HD-Ziel, skaliert auf größere Auflösungen.
|
// Alle Fenster maximiert (Vorgabe): Full-HD-Ziel, skaliert auf größere Auflösungen.
|
||||||
form.StartPosition = FormStartPosition.CenterScreen;
|
form.StartPosition = FormStartPosition.CenterScreen;
|
||||||
form.WindowState = FormWindowState.Maximized;
|
form.WindowState = FormWindowState.Maximized;
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using PolyTrader.Core.Modularity;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace PolyTrader.Tests
|
||||||
|
{
|
||||||
|
/// <summary>Sicherheitsnetz für das gemeinsame „Fenster"-Menü (Slice 1): Inhalt + Verhalten.</summary>
|
||||||
|
public class WindowMenuTests
|
||||||
|
{
|
||||||
|
private sealed class FakeUiHost : IModuleUiHost
|
||||||
|
{
|
||||||
|
public List<ModuleView> ViewList { get; } = new();
|
||||||
|
public HashSet<string> OpenIds { get; } = new();
|
||||||
|
public List<string> Opened { get; } = new();
|
||||||
|
public bool MainActivated { get; private set; }
|
||||||
|
|
||||||
|
public IReadOnlyList<ModuleView> Views => ViewList;
|
||||||
|
public bool IsOpen(string viewId) => OpenIds.Contains(viewId);
|
||||||
|
public void OpenView(string viewId) => Opened.Add(viewId);
|
||||||
|
public void ActivateMain() => MainActivated = true;
|
||||||
|
public void RegisterView(ModuleView view) => ViewList.Add(view);
|
||||||
|
public event Action? OpenStateChanged { add { } remove { } }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FakeUiHost Host()
|
||||||
|
{
|
||||||
|
var h = new FakeUiHost();
|
||||||
|
h.RegisterView(new ModuleView { Id = "core.dashboard", Title = "Dashboard", Order = 1 });
|
||||||
|
h.RegisterView(new ModuleView { Id = "core.terminal", Title = "Terminal / Logs", Order = 2 });
|
||||||
|
h.OpenIds.Add("core.terminal"); // Terminal ist offen
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Populate_lists_launcher_views_and_exit()
|
||||||
|
{
|
||||||
|
var host = Host();
|
||||||
|
var fenster = new ToolStripMenuItem("Fenster");
|
||||||
|
|
||||||
|
WindowMenu.Populate(fenster, host, currentViewId: "core.dashboard");
|
||||||
|
|
||||||
|
var texts = fenster.DropDownItems.OfType<ToolStripMenuItem>().Select(i => i.Text).ToList();
|
||||||
|
Assert.Equal("Launcher", texts[0]);
|
||||||
|
Assert.Contains("Dashboard", texts);
|
||||||
|
Assert.Contains("Terminal / Logs", texts);
|
||||||
|
Assert.Contains("Beenden", texts);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Current_view_is_bold_and_checked_open_view_is_checked()
|
||||||
|
{
|
||||||
|
var host = Host();
|
||||||
|
var fenster = new ToolStripMenuItem("Fenster");
|
||||||
|
|
||||||
|
WindowMenu.Populate(fenster, host, currentViewId: "core.dashboard");
|
||||||
|
|
||||||
|
var dashboard = fenster.DropDownItems.OfType<ToolStripMenuItem>().First(i => i.Text == "Dashboard");
|
||||||
|
var terminal = fenster.DropDownItems.OfType<ToolStripMenuItem>().First(i => i.Text == "Terminal / Logs");
|
||||||
|
|
||||||
|
Assert.True(dashboard.Checked); // aktuelles Fenster
|
||||||
|
Assert.True(dashboard.Font.Bold);
|
||||||
|
Assert.True(terminal.Checked); // offenes Fenster
|
||||||
|
Assert.False(terminal.Font.Bold);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Clicking_items_navigates()
|
||||||
|
{
|
||||||
|
var host = Host();
|
||||||
|
var fenster = new ToolStripMenuItem("Fenster");
|
||||||
|
WindowMenu.Populate(fenster, host, currentViewId: null);
|
||||||
|
|
||||||
|
var items = fenster.DropDownItems.OfType<ToolStripMenuItem>().ToList();
|
||||||
|
items.First(i => i.Text == "Launcher").PerformClick();
|
||||||
|
items.First(i => i.Text == "Terminal / Logs").PerformClick();
|
||||||
|
|
||||||
|
Assert.True(host.MainActivated);
|
||||||
|
Assert.Contains("core.terminal", host.Opened);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user