Phase 5-UI: Views sind echte Forms + Launcher-Offen-Status

- ModuleView liefert jetzt ein Form (CreateForm statt CreateControl); die 4 Views
  (Terminal, Settings, Jobs, Dashboard) von UserControl auf Form umgestellt
  (im Designer als Fenster bearbeitbar). ViewHostForm entfernt.
- ShellUiHost verwaltet offene Forms: Einzelinstanz, bereits offenes Fenster wird
  in den Vordergrund geholt, OpenStateChanged-Event.
- LauncherForm: Fenster-Buttons an View-IDs gebunden; offene Fenster werden am
  Button markiert (Checked), erneuter Klick holt das Fenster nach vorn.
- Build 0 Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-03 09:19:13 +02:00
co-authored by Claude Opus 4.8
parent ff1db2aea0
commit ad5ba34b56
18 changed files with 242 additions and 102 deletions
+4 -12
View File
@@ -138,9 +138,7 @@ internal static class Program
Title = "Terminal", Title = "Terminal",
Group = "Core", Group = "Core",
Order = 10, Order = 10,
PreferredWidth = 1000, CreateForm = () =>
PreferredHeight = 650,
CreateControl = () =>
{ {
var view = new PolyTraderSharp.Ui.Views.TerminalView(); var view = new PolyTraderSharp.Ui.Views.TerminalView();
view.Initialize(viewServices.GetRequiredService<TerminalLogger>()); view.Initialize(viewServices.GetRequiredService<TerminalLogger>());
@@ -153,9 +151,7 @@ internal static class Program
Title = "Server Settings", Title = "Server Settings",
Group = "Core", Group = "Core",
Order = 20, Order = 20,
PreferredWidth = 720, CreateForm = () =>
PreferredHeight = 720,
CreateControl = () =>
{ {
var view = new PolyTraderSharp.Ui.Views.SettingsView(); var view = new PolyTraderSharp.Ui.Views.SettingsView();
view.Initialize( view.Initialize(
@@ -171,9 +167,7 @@ internal static class Program
Title = "Server Jobs", Title = "Server Jobs",
Group = "Core", Group = "Core",
Order = 30, Order = 30,
PreferredWidth = 1000, CreateForm = () =>
PreferredHeight = 500,
CreateControl = () =>
{ {
var view = new PolyTraderSharp.Ui.Views.JobsView(); var view = new PolyTraderSharp.Ui.Views.JobsView();
view.Initialize(viewServices.GetRequiredService<JobManager>()); view.Initialize(viewServices.GetRequiredService<JobManager>());
@@ -186,9 +180,7 @@ internal static class Program
Title = "Dashboard", Title = "Dashboard",
Group = "Core", Group = "Core",
Order = 5, Order = 5,
PreferredWidth = 1200, CreateForm = () =>
PreferredHeight = 650,
CreateControl = () =>
{ {
var view = new PolyTraderSharp.Ui.Views.DashboardView(); var view = new PolyTraderSharp.Ui.Views.DashboardView();
view.Initialize( view.Initialize(
+10
View File
@@ -100,6 +100,16 @@ namespace PolyTraderSharp.Properties {
} }
} }
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap dashboard {
get {
object obj = ResourceManager.GetObject("dashboard", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary> /// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary> /// </summary>
+10 -7
View File
@@ -118,20 +118,26 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="system_time" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\system_time.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="diskette" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="diskette" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\diskette.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\diskette.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="money" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="money" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\money.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\money.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="traffic_lights_green" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\traffic_lights_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="money_add" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="money_add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\money_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\money_add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="token_quantifier" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="token_quantifier" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\token_quantifier.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\token_quantifier.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="traffic_lights_green" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="error_log" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\traffic_lights_green.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\error_log.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="cancel" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="cancel" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\cancel.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\cancel.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
@@ -145,9 +151,6 @@
<data name="coins_in_hand" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="coins_in_hand" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\coins_in_hand.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\coins_in_hand.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="error_log" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\error_log.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="add" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="add" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\add.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
@@ -172,7 +175,7 @@
<data name="money_dollar" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="money_dollar" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\money_dollar.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\money_dollar.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
<data name="system_time" type="System.Resources.ResXFileRef, System.Windows.Forms"> <data name="dashboard" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\system_time.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value> <value>..\Resources\dashboard.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data> </data>
</root> </root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+15 -11
View File
@@ -22,10 +22,10 @@ namespace PolyTraderSharp.Ui
miLegacy = new ToolStripMenuItem(); miLegacy = new ToolStripMenuItem();
miBeenden = new ToolStripMenuItem(); miBeenden = new ToolStripMenuItem();
toolstrip_windows = new ToolStrip(); toolstrip_windows = new ToolStrip();
btn_dashboard = new ToolStripButton();
btn_settings = new ToolStripButton(); btn_settings = new ToolStripButton();
btn_terminal = new ToolStripButton(); btn_terminal = new ToolStripButton();
btn_jobs = new ToolStripButton(); btn_jobs = new ToolStripButton();
btn_dashboard = new ToolStripButton();
toolstrip_quickbar = new ToolStrip(); toolstrip_quickbar = new ToolStrip();
btn_liveTrading = new ToolStripButton(); btn_liveTrading = new ToolStripButton();
btn_demoTrading = new ToolStripButton(); btn_demoTrading = new ToolStripButton();
@@ -72,13 +72,23 @@ namespace PolyTraderSharp.Ui
// //
toolstrip_windows.AutoSize = false; toolstrip_windows.AutoSize = false;
toolstrip_windows.ImageScalingSize = new Size(64, 64); toolstrip_windows.ImageScalingSize = new Size(64, 64);
toolstrip_windows.Items.AddRange(new ToolStripItem[] { btn_settings, btn_terminal, btn_jobs, btn_dashboard }); toolstrip_windows.Items.AddRange(new ToolStripItem[] { btn_dashboard, btn_settings, btn_terminal, btn_jobs });
toolstrip_windows.Location = new Point(0, 35); toolstrip_windows.Location = new Point(0, 35);
toolstrip_windows.Name = "toolstrip_windows"; toolstrip_windows.Name = "toolstrip_windows";
toolstrip_windows.Size = new Size(2599, 70); toolstrip_windows.Size = new Size(2599, 70);
toolstrip_windows.TabIndex = 3; toolstrip_windows.TabIndex = 3;
toolstrip_windows.Text = "toolStrip1"; toolstrip_windows.Text = "toolStrip1";
// //
// btn_dashboard
//
btn_dashboard.Image = Properties.Resources.dashboard;
btn_dashboard.ImageScaling = ToolStripItemImageScaling.None;
btn_dashboard.Name = "btn_dashboard";
btn_dashboard.Overflow = ToolStripItemOverflow.Never;
btn_dashboard.Size = new Size(104, 65);
btn_dashboard.Text = "Dashboard";
btn_dashboard.TextImageRelation = TextImageRelation.ImageAboveText;
//
// btn_settings // btn_settings
// //
btn_settings.BackColor = SystemColors.Control; btn_settings.BackColor = SystemColors.Control;
@@ -108,13 +118,6 @@ namespace PolyTraderSharp.Ui
btn_jobs.Text = "Server Jobs"; btn_jobs.Text = "Server Jobs";
btn_jobs.TextImageRelation = TextImageRelation.ImageAboveText; btn_jobs.TextImageRelation = TextImageRelation.ImageAboveText;
// //
// btn_dashboard
//
btn_dashboard.DisplayStyle = ToolStripItemDisplayStyle.Text;
btn_dashboard.Name = "btn_dashboard";
btn_dashboard.Size = new Size(110, 65);
btn_dashboard.Text = "Dashboard";
//
// toolstrip_quickbar // toolstrip_quickbar
// //
toolstrip_quickbar.ImageScalingSize = new Size(24, 24); toolstrip_quickbar.ImageScalingSize = new Size(24, 24);
@@ -144,7 +147,7 @@ namespace PolyTraderSharp.Ui
statusStrip_info.BackColor = Color.Gainsboro; statusStrip_info.BackColor = Color.Gainsboro;
statusStrip_info.ImageScalingSize = new Size(24, 24); statusStrip_info.ImageScalingSize = new Size(24, 24);
statusStrip_info.Items.AddRange(new ToolStripItem[] { lbl_trading, lbl_modules, lbl_ratelimit }); statusStrip_info.Items.AddRange(new ToolStripItem[] { lbl_trading, lbl_modules, lbl_ratelimit });
statusStrip_info.Location = new Point(0, 133); statusStrip_info.Location = new Point(0, 140);
statusStrip_info.Name = "statusStrip_info"; statusStrip_info.Name = "statusStrip_info";
statusStrip_info.Size = new Size(2599, 32); statusStrip_info.Size = new Size(2599, 32);
statusStrip_info.TabIndex = 5; statusStrip_info.TabIndex = 5;
@@ -172,11 +175,12 @@ namespace PolyTraderSharp.Ui
// //
AutoScaleDimensions = new SizeF(10F, 25F); AutoScaleDimensions = new SizeF(10F, 25F);
AutoScaleMode = AutoScaleMode.Font; AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(2599, 165); ClientSize = new Size(2599, 172);
Controls.Add(statusStrip_info); Controls.Add(statusStrip_info);
Controls.Add(toolstrip_quickbar); Controls.Add(toolstrip_quickbar);
Controls.Add(toolstrip_windows); Controls.Add(toolstrip_windows);
Controls.Add(menuStrip); Controls.Add(menuStrip);
FormBorderStyle = FormBorderStyle.FixedSingle;
MainMenuStrip = menuStrip; MainMenuStrip = menuStrip;
Margin = new Padding(4, 5, 4, 5); Margin = new Padding(4, 5, 4, 5);
Name = "LauncherForm"; Name = "LauncherForm";
+28 -15
View File
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -19,6 +20,7 @@ namespace PolyTraderSharp.Ui
private readonly IServiceProvider _services; private readonly IServiceProvider _services;
private readonly TradingState _state; private readonly TradingState _state;
private readonly System.Windows.Forms.Timer _statusTimer = new() { Interval = 1000 }; private readonly System.Windows.Forms.Timer _statusTimer = new() { Interval = 1000 };
private readonly Dictionary<string, ToolStripButton> _viewButtons;
private frm_main? _legacyForm; private frm_main? _legacyForm;
public LauncherForm(ShellUiHost uiHost, IServiceProvider services) public LauncherForm(ShellUiHost uiHost, IServiceProvider services)
@@ -29,19 +31,40 @@ namespace PolyTraderSharp.Ui
InitializeComponent(); InitializeComponent();
btn_settings.Click += (_, _) => OpenView("core.settings"); // Fenster-Buttons an stabile View-IDs binden (Views werden per DI registriert).
btn_terminal.Click += (_, _) => OpenView("core.terminal"); _viewButtons = new Dictionary<string, ToolStripButton>
btn_jobs.Click += (_, _) => OpenView("core.jobs"); {
btn_dashboard.Click += (_, _) => OpenView("core.dashboard"); ["core.dashboard"] = btn_dashboard,
["core.settings"] = btn_settings,
["core.terminal"] = btn_terminal,
["core.jobs"] = btn_jobs,
};
foreach (var (id, btn) in _viewButtons)
{
var viewId = id;
btn.Click += (_, _) => _uiHost.OpenView(viewId);
}
btn_liveTrading.Click += (_, _) => CycleLiveTrading(); btn_liveTrading.Click += (_, _) => CycleLiveTrading();
btn_demoTrading.Click += (_, _) => CycleDemoTrading(); btn_demoTrading.Click += (_, _) => CycleDemoTrading();
miLegacy.Click += (_, _) => OpenLegacy(); miLegacy.Click += (_, _) => OpenLegacy();
miBeenden.Click += (_, _) => Close(); miBeenden.Click += (_, _) => Close();
// Offen-Status der Fenster spiegeln (Button „checked", wenn Fenster offen).
_uiHost.OpenStateChanged += UpdateWindowButtonStates;
_statusTimer.Tick += (_, _) => UpdateStatus(); _statusTimer.Tick += (_, _) => UpdateStatus();
_statusTimer.Start(); _statusTimer.Start();
UpdateStatus(); UpdateStatus();
UpdateTradingToggles(); UpdateTradingToggles();
UpdateWindowButtonStates();
}
private void UpdateWindowButtonStates()
{
if (IsDisposed) return;
foreach (var (id, btn) in _viewButtons)
btn.Checked = _uiHost.IsOpen(id);
} }
private void CycleLiveTrading() private void CycleLiveTrading()
@@ -91,17 +114,6 @@ namespace PolyTraderSharp.Ui
} }
} }
/// <summary>Öffnet die Ansicht mit der angegebenen ID (bzw. fokussiert das offene Fenster).</summary>
private void OpenView(string viewId)
{
var view = _uiHost.Views.FirstOrDefault(v => v.Id == viewId);
if (view != null)
_uiHost.OpenView(view);
else
MessageBox.Show($"Ansicht '{viewId}' ist (noch) nicht registriert.", "Hinweis",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void UpdateStatus() private void UpdateStatus()
{ {
string trading = _state.GlobalTradingPaused string trading = _state.GlobalTradingPaused
@@ -116,6 +128,7 @@ namespace PolyTraderSharp.Ui
// Toggle-Buttons mit externem State synchron halten (z.B. Änderungen aus der Legacy-UI). // Toggle-Buttons mit externem State synchron halten (z.B. Änderungen aus der Legacy-UI).
UpdateTradingToggles(); UpdateTradingToggles();
UpdateWindowButtonStates();
} }
private void OpenLegacy() private void OpenLegacy()
+32 -7
View File
@@ -1,22 +1,38 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using PolyTrader.Core.Modularity; using PolyTrader.Core.Modularity;
namespace PolyTraderSharp.Ui namespace PolyTraderSharp.Ui
{ {
/// <summary> /// <summary>
/// Sammelt die von Core-App und Modulen registrierten Views und öffnet sie als /// Verwaltet die registrierten Fenster-Views: öffnet sie als eigenständige Forms,
/// eigenständige Host-Fenster (Einzelinstanz je View). /// 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> /// </summary>
public class ShellUiHost : IModuleUiHost public class ShellUiHost : IModuleUiHost
{ {
private readonly List<ModuleView> _views = new(); private readonly List<ModuleView> _views = new();
private readonly Dictionary<string, ViewHostForm> _open = new(); private readonly Dictionary<string, Form> _open = new();
/// <summary>Wird ausgelöst, wenn sich der Offen-Status irgendeiner View ändert.</summary>
public event Action? OpenStateChanged;
public IReadOnlyList<ModuleView> Views => _views; public IReadOnlyList<ModuleView> Views => _views;
public void RegisterView(ModuleView view) => _views.Add(view); public void RegisterView(ModuleView view) => _views.Add(view);
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) public void OpenView(ModuleView view)
{ {
if (_open.TryGetValue(view.Id, out var existing) && !existing.IsDisposed) if (_open.TryGetValue(view.Id, out var existing) && !existing.IsDisposed)
@@ -28,10 +44,19 @@ namespace PolyTraderSharp.Ui
return; return;
} }
var host = new ViewHostForm(view); var form = view.CreateForm();
host.FormClosed += (_, _) => _open.Remove(view.Id); if (string.IsNullOrEmpty(form.Text) || form.Text == form.Name)
_open[view.Id] = host; form.Text = view.Title;
host.Show();
_open[view.Id] = form;
form.FormClosed += (_, _) =>
{
_open.Remove(view.Id);
OpenStateChanged?.Invoke();
};
form.Show();
OpenStateChanged?.Invoke();
} }
} }
} }
-28
View File
@@ -1,28 +0,0 @@
using System.Windows.Forms;
using PolyTrader.Core.Modularity;
namespace PolyTraderSharp.Ui
{
/// <summary>
/// Generisches Host-Fenster für genau eine <see cref="ModuleView"/>. Erzeugt das
/// (designbare) Control der View und dockt es formfüllend. Die Shell öffnet je View
/// höchstens eine Instanz (siehe <see cref="ShellUiHost"/>).
/// </summary>
public class ViewHostForm : Form
{
public string ViewId { get; }
public ViewHostForm(ModuleView view)
{
ViewId = view.Id;
Text = view.Title;
Width = view.PreferredWidth;
Height = view.PreferredHeight;
StartPosition = FormStartPosition.CenterScreen;
var control = view.CreateControl();
control.Dock = DockStyle.Fill;
Controls.Add(control);
}
}
}
+2 -1
View File
@@ -173,8 +173,9 @@ namespace PolyTraderSharp.Ui.Views
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.dgvTrades); this.Controls.Add(this.dgvTrades);
this.Controls.Add(this.pnlTop); this.Controls.Add(this.pnlTop);
this.ClientSize = new System.Drawing.Size(1200, 650);
this.Name = "DashboardView"; this.Name = "DashboardView";
this.Size = new System.Drawing.Size(1100, 600); this.Text = "Dashboard";
this.pnlTop.ResumeLayout(false); this.pnlTop.ResumeLayout(false);
this.pnlTop.PerformLayout(); this.pnlTop.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.dgvTrades)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.dgvTrades)).EndInit();
+1 -1
View File
@@ -11,7 +11,7 @@ namespace PolyTraderSharp.Ui.Views
/// generischen Core-Trade-Log (ITradeLogRepository) und eine Kurzauswertung. /// generischen Core-Trade-Log (ITradeLogRepository) und eine Kurzauswertung.
/// Designbar (DashboardView.Designer.cs). /// Designbar (DashboardView.Designer.cs).
/// </summary> /// </summary>
public partial class DashboardView : UserControl public partial class DashboardView : Form
{ {
private ITradeLogRepository? _tradeLog; private ITradeLogRepository? _tradeLog;
private TradingState? _state; private TradingState? _state;
+2 -1
View File
@@ -109,8 +109,9 @@ namespace PolyTraderSharp.Ui.Views
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.dgvJobs); this.Controls.Add(this.dgvJobs);
this.ClientSize = new System.Drawing.Size(1000, 500);
this.Name = "JobsView"; this.Name = "JobsView";
this.Size = new System.Drawing.Size(900, 500); this.Text = "Server Jobs";
((System.ComponentModel.ISupportInitialize)(this.dgvJobs)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.dgvJobs)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
} }
+1 -1
View File
@@ -10,7 +10,7 @@ namespace PolyTraderSharp.Ui.Views
/// Verhalten wie der bisherige Jobs-Tab: „Run Now" löst den ManualTrigger aus, /// Verhalten wie der bisherige Jobs-Tab: „Run Now" löst den ManualTrigger aus,
/// „Aktiv" schaltet den Job über die Bindung. /// „Aktiv" schaltet den Job über die Bindung.
/// </summary> /// </summary>
public partial class JobsView : UserControl public partial class JobsView : Form
{ {
public JobsView() public JobsView()
{ {
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+2 -1
View File
@@ -66,8 +66,9 @@ namespace PolyTraderSharp.Ui.Views
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.propertyGrid); this.Controls.Add(this.propertyGrid);
this.Controls.Add(this.pnlTop); this.Controls.Add(this.pnlTop);
this.ClientSize = new System.Drawing.Size(720, 720);
this.Name = "SettingsView"; this.Name = "SettingsView";
this.Size = new System.Drawing.Size(700, 600); this.Text = "Server Settings";
this.pnlTop.ResumeLayout(false); this.pnlTop.ResumeLayout(false);
this.ResumeLayout(false); this.ResumeLayout(false);
} }
+1 -1
View File
@@ -10,7 +10,7 @@ namespace PolyTraderSharp.Ui.Views
/// Designbar (siehe SettingsView.Designer.cs); Laufzeit-Abhängigkeiten via Initialize. /// Designbar (siehe SettingsView.Designer.cs); Laufzeit-Abhängigkeiten via Initialize.
/// Verhalten entspricht dem bisherigen Settings-Tab (Speichern -> XML + Services neu laden). /// Verhalten entspricht dem bisherigen Settings-Tab (Speichern -> XML + Services neu laden).
/// </summary> /// </summary>
public partial class SettingsView : UserControl public partial class SettingsView : Form
{ {
private const string SettingsPath = "server_settings.xml"; private const string SettingsPath = "server_settings.xml";
+2 -1
View File
@@ -90,8 +90,9 @@ namespace PolyTraderSharp.Ui.Views
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.rtbTerminal); this.Controls.Add(this.rtbTerminal);
this.Controls.Add(this.pnlTop); this.Controls.Add(this.pnlTop);
this.ClientSize = new System.Drawing.Size(1000, 650);
this.Name = "TerminalView"; this.Name = "TerminalView";
this.Size = new System.Drawing.Size(900, 500); this.Text = "Terminal / Logs";
this.pnlTop.ResumeLayout(false); this.pnlTop.ResumeLayout(false);
this.pnlTop.PerformLayout(); this.pnlTop.PerformLayout();
this.ResumeLayout(false); this.ResumeLayout(false);
+1 -1
View File
@@ -10,7 +10,7 @@ namespace PolyTraderSharp.Ui.Views
/// Abhängigkeit (TerminalLogger) wird per <see cref="Initialize"/> injiziert, damit der /// Abhängigkeit (TerminalLogger) wird per <see cref="Initialize"/> injiziert, damit der
/// parameterlose Konstruktor für den VS-Designer nutzbar bleibt. /// parameterlose Konstruktor für den VS-Designer nutzbar bleibt.
/// </summary> /// </summary>
public partial class TerminalView : UserControl public partial class TerminalView : Form
{ {
private TerminalLogger? _logger; private TerminalLogger? _logger;
private readonly ConcurrentQueue<LogMessageEventArgs> _logQueue = new(); private readonly ConcurrentQueue<LogMessageEventArgs> _logQueue = new();
+11 -14
View File
@@ -4,35 +4,32 @@ using System.Windows.Forms;
namespace PolyTrader.Core.Modularity namespace PolyTrader.Core.Modularity
{ {
/// <summary> /// <summary>
/// Eine vom Core oder einem Modul beigesteuerte UI-Ansicht. Die Shell entscheidet, /// Eine vom Core oder einem Modul beigesteuerte Fenster-Ansicht. Die eigentliche UI ist
/// wie sie präsentiert wird (aktuell: eigenständiges Host-Fenster über den Launcher). /// ein designbares <see cref="Form"/>, das über <see cref="CreateForm"/> erzeugt wird
/// Die eigentliche UI ist ein designbares <see cref="Control"/> (i.d.R. ein UserControl), /// (mit DI-Abhängigkeiten). Die Shell zeigt je View höchstens eine Instanz und holt ein
/// das über <see cref="CreateControl"/> erzeugt wird (mit DI-Abhängigkeiten). /// bereits offenes Fenster wieder in den Vordergrund.
/// </summary> /// </summary>
public sealed class ModuleView public sealed class ModuleView
{ {
/// <summary>Stabile ID für Einzelinstanz-Handling (nur ein Fenster je View).</summary> /// <summary>Stabile ID für Einzelinstanz-Handling (nur ein Fenster je View).</summary>
public string Id { get; init; } = Guid.NewGuid().ToString(); public string Id { get; init; } = Guid.NewGuid().ToString();
/// <summary>Titel für Launcher-Eintrag und Fenstertitel.</summary> /// <summary>Titel (Fallback-Fenstertitel, falls das Form keinen eigenen setzt).</summary>
public string Title { get; init; } = "View"; public string Title { get; init; } = "Fenster";
/// <summary>Optionale Gruppierung im Launcher (z.B. "Core", "CopyTrading").</summary> /// <summary>Optionale Gruppierung (z.B. "Core", "CopyTrading").</summary>
public string? Group { get; init; } public string? Group { get; init; }
/// <summary>Optionale Sortierreihenfolge im Launcher.</summary> /// <summary>Optionale Sortierreihenfolge.</summary>
public int Order { get; init; } = 0; public int Order { get; init; } = 0;
/// <summary>Erzeugt das anzuzeigende Control (frische Instanz je Fensteröffnung).</summary> /// <summary>Erzeugt das anzuzeigende Fenster (frische Instanz je Öffnung).</summary>
public Func<Control> CreateControl { get; init; } = () => new Control(); public Func<Form> CreateForm { get; init; } = () => new Form();
public int PreferredWidth { get; init; } = 900;
public int PreferredHeight { get; init; } = 600;
} }
/// <summary> /// <summary>
/// Wird der Shell beim Start übergeben; Core und Module registrieren hier ihre Ansichten. /// Wird der Shell beim Start übergeben; Core und Module registrieren hier ihre Ansichten.
/// Der Launcher rendert daraus seine Einträge und öffnet je View ein Host-Fenster. /// Die Shell (Launcher) öffnet die Fenster auf Anforderung und verwaltet den Offen-Status.
/// </summary> /// </summary>
public interface IModuleUiHost public interface IModuleUiHost
{ {