Phase 5-UI: Launcher auf Toolstrip-Modell + SettingsView (Designer-first)

- LauncherForm: lstView-Ansatz entfernt (lstViews/colName/pnlBottom/btnOpen raus).
  Fenster werden ueber toolstrip_windows-Buttons geoeffnet/fokussiert:
  btn_settings -> Settings, btn_terminal -> Terminal (Bindung per stabiler View-ID).
- statusStrip_info: Live-Status (Trading, Modul-Anzahl, API WSS/Polling) via 1s-Timer.
- toolstrip_quickbar bleibt fuer Schnellaktionen (Trading an/aus) reserviert.
- Neue SettingsView (UserControl + Designer): ServerSettings-PropertyGrid +
  Speichern/Neu laden; Verhalten wie bisheriger Settings-Tab. In Program.cs registriert.
- Build 0 Fehler.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-07-02 11:44:47 +02:00
co-authored by Claude Opus 4.8
parent 1781d71983
commit f112668147
9 changed files with 378 additions and 147 deletions
+18
View File
@@ -143,6 +143,24 @@ internal static class Program
return view;
}
});
uiHost.RegisterView(new PolyTrader.Core.Modularity.ModuleView
{
Id = "core.settings",
Title = "Server Settings",
Group = "Core",
Order = 20,
PreferredWidth = 720,
PreferredHeight = 720,
CreateControl = () =>
{
var view = new PolyTraderSharp.Ui.Views.SettingsView();
view.Initialize(
viewServices.GetRequiredService<ThreemaService>(),
viewServices.GetRequiredService<MullvadVpnService>(),
viewServices.GetRequiredService<TerminalLogger>());
return view;
}
});
// TODO Phase 5-UI: registrierte IPolyTraderModule durchlaufen und module.RegisterUi(uiHost) aufrufen.
var launcher = AppHost.Services.GetRequiredService<PolyTraderSharp.Ui.LauncherForm>();
+17 -9
View File
@@ -1,11 +1,9 @@
using MongoDB.Driver;
using PolyTraderSharp.Extensions;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
@@ -18,10 +16,10 @@ namespace PolyTraderSharp.Properties {
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "18.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@@ -35,7 +33,7 @@ namespace PolyTraderSharp.Properties {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
@@ -49,7 +47,7 @@ namespace PolyTraderSharp.Properties {
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
@@ -172,6 +170,16 @@ namespace PolyTraderSharp.Properties {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap setting_tools {
get {
object obj = ResourceManager.GetObject("setting_tools", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
+5 -2
View File
@@ -118,6 +118,9 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="stop" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\stop.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">
<value>..\Resources\diskette.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
@@ -163,7 +166,7 @@
<data name="accept_button" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\accept_button.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="stop" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\stop.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="setting_tools" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\setting_tools.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+119 -77
View File
@@ -17,102 +17,140 @@ namespace PolyTraderSharp.Ui
private void InitializeComponent()
{
this.menuStrip = new System.Windows.Forms.MenuStrip();
this.miDatei = new System.Windows.Forms.ToolStripMenuItem();
this.miLegacy = new System.Windows.Forms.ToolStripMenuItem();
this.miBeenden = new System.Windows.Forms.ToolStripMenuItem();
this.lstViews = new System.Windows.Forms.ListView();
this.colName = new System.Windows.Forms.ColumnHeader();
this.pnlBottom = new System.Windows.Forms.Panel();
this.btnOpen = new System.Windows.Forms.Button();
this.menuStrip.SuspendLayout();
this.pnlBottom.SuspendLayout();
this.SuspendLayout();
menuStrip = new MenuStrip();
miDatei = new ToolStripMenuItem();
miLegacy = new ToolStripMenuItem();
miBeenden = new ToolStripMenuItem();
toolstrip_windows = new ToolStrip();
btn_settings = new ToolStripButton();
btn_terminal = new ToolStripButton();
toolstrip_quickbar = new ToolStrip();
statusStrip_info = new StatusStrip();
lbl_trading = new ToolStripStatusLabel();
lbl_modules = new ToolStripStatusLabel();
lbl_ratelimit = new ToolStripStatusLabel();
menuStrip.SuspendLayout();
toolstrip_windows.SuspendLayout();
statusStrip_info.SuspendLayout();
SuspendLayout();
//
// menuStrip
//
this.menuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miDatei});
this.menuStrip.Location = new System.Drawing.Point(0, 0);
this.menuStrip.Name = "menuStrip";
this.menuStrip.Size = new System.Drawing.Size(360, 24);
this.menuStrip.TabIndex = 0;
menuStrip.ImageScalingSize = new Size(24, 24);
menuStrip.Items.AddRange(new ToolStripItem[] { miDatei });
menuStrip.Location = new Point(0, 0);
menuStrip.Name = "menuStrip";
menuStrip.Padding = new Padding(9, 3, 0, 3);
menuStrip.Size = new Size(2599, 35);
menuStrip.TabIndex = 0;
//
// miDatei
//
this.miDatei.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.miLegacy,
this.miBeenden});
this.miDatei.Name = "miDatei";
this.miDatei.Text = "Datei";
miDatei.DropDownItems.AddRange(new ToolStripItem[] { miLegacy, miBeenden });
miDatei.Name = "miDatei";
miDatei.Size = new Size(69, 29);
miDatei.Text = "Datei";
//
// miLegacy
//
this.miLegacy.Name = "miLegacy";
this.miLegacy.Text = "Legacy-UI (alte Tabs)";
miLegacy.Name = "miLegacy";
miLegacy.Size = new Size(275, 34);
miLegacy.Text = "Legacy-UI (alte Tabs)";
//
// miBeenden
//
this.miBeenden.Name = "miBeenden";
this.miBeenden.Text = "Beenden";
miBeenden.Name = "miBeenden";
miBeenden.Size = new Size(275, 34);
miBeenden.Text = "Beenden";
//
// lstViews
// toolstrip_windows
//
this.lstViews.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.colName});
this.lstViews.Dock = System.Windows.Forms.DockStyle.Fill;
this.lstViews.FullRowSelect = true;
this.lstViews.HideSelection = false;
this.lstViews.Location = new System.Drawing.Point(0, 24);
this.lstViews.MultiSelect = false;
this.lstViews.Name = "lstViews";
this.lstViews.Size = new System.Drawing.Size(360, 420);
this.lstViews.TabIndex = 1;
this.lstViews.UseCompatibleStateImageBehavior = false;
this.lstViews.View = System.Windows.Forms.View.Details;
toolstrip_windows.AutoSize = false;
toolstrip_windows.ImageScalingSize = new Size(64, 64);
toolstrip_windows.Items.AddRange(new ToolStripItem[] { btn_settings, btn_terminal });
toolstrip_windows.Location = new Point(0, 35);
toolstrip_windows.Name = "toolstrip_windows";
toolstrip_windows.Size = new Size(2599, 70);
toolstrip_windows.TabIndex = 3;
toolstrip_windows.Text = "toolStrip1";
//
// colName
// btn_settings
//
this.colName.Text = "Ansicht";
this.colName.Width = 330;
btn_settings.BackColor = SystemColors.Control;
btn_settings.Image = Properties.Resources.setting_tools;
btn_settings.ImageScaling = ToolStripItemImageScaling.None;
btn_settings.ImageTransparentColor = Color.Magenta;
btn_settings.Name = "btn_settings";
btn_settings.Size = new Size(112, 65);
btn_settings.Text = "Settings";
btn_settings.TextImageRelation = TextImageRelation.ImageAboveText;
//
// pnlBottom
// btn_terminal
//
this.pnlBottom.Controls.Add(this.btnOpen);
this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnlBottom.Location = new System.Drawing.Point(0, 444);
this.pnlBottom.Name = "pnlBottom";
this.pnlBottom.Size = new System.Drawing.Size(360, 44);
this.pnlBottom.TabIndex = 2;
btn_terminal.DisplayStyle = ToolStripItemDisplayStyle.Text;
btn_terminal.Name = "btn_terminal";
btn_terminal.Size = new Size(112, 65);
btn_terminal.Text = "Terminal";
//
// btnOpen
// toolstrip_quickbar
//
this.btnOpen.Location = new System.Drawing.Point(12, 8);
this.btnOpen.Name = "btnOpen";
this.btnOpen.Size = new System.Drawing.Size(336, 30);
this.btnOpen.TabIndex = 0;
this.btnOpen.Text = "Öffnen";
this.btnOpen.UseVisualStyleBackColor = true;
toolstrip_quickbar.ImageScalingSize = new Size(24, 24);
toolstrip_quickbar.Location = new Point(0, 105);
toolstrip_quickbar.Name = "toolstrip_quickbar";
toolstrip_quickbar.Size = new Size(2599, 25);
toolstrip_quickbar.TabIndex = 4;
toolstrip_quickbar.Text = "toolStrip2";
//
// statusStrip_info
//
statusStrip_info.ImageScalingSize = new Size(24, 24);
statusStrip_info.Items.AddRange(new ToolStripItem[] { lbl_trading, lbl_modules, lbl_ratelimit });
statusStrip_info.Location = new Point(0, 924);
statusStrip_info.Name = "statusStrip_info";
statusStrip_info.Size = new Size(2599, 22);
statusStrip_info.TabIndex = 5;
statusStrip_info.Text = "statusStrip1";
//
// lbl_trading
//
lbl_trading.Name = "lbl_trading";
lbl_trading.Size = new Size(100, 16);
lbl_trading.Text = "Trading: —";
//
// lbl_modules
//
lbl_modules.Name = "lbl_modules";
lbl_modules.Size = new Size(90, 16);
lbl_modules.Text = "Module: —";
//
// lbl_ratelimit
//
lbl_ratelimit.Name = "lbl_ratelimit";
lbl_ratelimit.Size = new Size(80, 16);
lbl_ratelimit.Text = "API: —";
//
// LauncherForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(360, 488);
this.Controls.Add(this.lstViews);
this.Controls.Add(this.pnlBottom);
this.Controls.Add(this.menuStrip);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MainMenuStrip = this.menuStrip;
this.MaximizeBox = false;
this.Name = "LauncherForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "PolyTrader";
this.menuStrip.ResumeLayout(false);
this.menuStrip.PerformLayout();
this.pnlBottom.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
AutoScaleDimensions = new SizeF(10F, 25F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(2599, 946);
Controls.Add(statusStrip_info);
Controls.Add(toolstrip_quickbar);
Controls.Add(toolstrip_windows);
Controls.Add(menuStrip);
MainMenuStrip = menuStrip;
Margin = new Padding(4, 5, 4, 5);
Name = "LauncherForm";
StartPosition = FormStartPosition.CenterScreen;
Text = "PolyTrader";
menuStrip.ResumeLayout(false);
menuStrip.PerformLayout();
toolstrip_windows.ResumeLayout(false);
toolstrip_windows.PerformLayout();
statusStrip_info.ResumeLayout(false);
statusStrip_info.PerformLayout();
ResumeLayout(false);
PerformLayout();
}
#endregion
@@ -121,9 +159,13 @@ namespace PolyTraderSharp.Ui
private System.Windows.Forms.ToolStripMenuItem miDatei;
private System.Windows.Forms.ToolStripMenuItem miLegacy;
private System.Windows.Forms.ToolStripMenuItem miBeenden;
private System.Windows.Forms.ListView lstViews;
private System.Windows.Forms.ColumnHeader colName;
private System.Windows.Forms.Panel pnlBottom;
private System.Windows.Forms.Button btnOpen;
private ToolStrip toolstrip_windows;
private ToolStripButton btn_settings;
private ToolStripButton btn_terminal;
private ToolStrip toolstrip_quickbar;
private StatusStrip statusStrip_info;
private ToolStripStatusLabel lbl_trading;
private ToolStripStatusLabel lbl_modules;
private ToolStripStatusLabel lbl_ratelimit;
}
}
+34 -32
View File
@@ -7,58 +7,60 @@ using PolyTrader.Core.Modularity;
namespace PolyTraderSharp.Ui
{
/// <summary>
/// Schlanke „Startleiste" der PolyTrader.App. Das Layout (ListView, Menü, Button) liegt
/// im Designer (LauncherForm.Designer.cs). Zur Laufzeit werden ausschließlich die
/// Listeneinträge (Daten) aus den registrierten Views befüllt — keine Steuerelemente.
/// Kennt selbst kein Modul.
/// „Startleiste" der PolyTrader.App. Fenster werden über die im Designer platzierten
/// Buttons in <c>toolstrip_windows</c> geöffnet bzw. in den Vordergrund geholt.
/// <c>toolstrip_quickbar</c> ist für Schnellaktionen (z.B. Trading an/aus) reserviert,
/// <c>statusStrip_info</c> zeigt Kernkennzahlen. Der Launcher kennt selbst kein Modul
/// Buttons werden per stabiler View-ID an registrierte Views gebunden.
/// </summary>
public partial class LauncherForm : Form
{
private readonly ShellUiHost _uiHost;
private readonly IServiceProvider _services;
private readonly TradingState _state;
private readonly System.Windows.Forms.Timer _statusTimer = new() { Interval = 1000 };
private frm_main? _legacyForm;
public LauncherForm(ShellUiHost uiHost, IServiceProvider services)
{
_uiHost = uiHost;
_services = services;
_state = services.GetRequiredService<TradingState>();
InitializeComponent();
PopulateViews();
lstViews.DoubleClick += (_, _) => OpenSelected();
btnOpen.Click += (_, _) => OpenSelected();
btn_settings.Click += (_, _) => OpenView("core.settings");
btn_terminal.Click += (_, _) => OpenView("core.terminal");
miLegacy.Click += (_, _) => OpenLegacy();
miBeenden.Click += (_, _) => Close();
_statusTimer.Tick += (_, _) => UpdateStatus();
_statusTimer.Start();
UpdateStatus();
}
private void PopulateViews()
/// <summary>Öffnet die Ansicht mit der angegebenen ID (bzw. fokussiert das offene Fenster).</summary>
private void OpenView(string viewId)
{
lstViews.BeginUpdate();
lstViews.Groups.Clear();
lstViews.Items.Clear();
foreach (var group in _uiHost.Views
.GroupBy(v => string.IsNullOrEmpty(v.Group) ? "Allgemein" : v.Group!)
.OrderBy(g => g.Key))
{
var lvGroup = new ListViewGroup(group.Key) { Header = group.Key };
lstViews.Groups.Add(lvGroup);
foreach (var view in group.OrderBy(v => v.Order).ThenBy(v => v.Title))
{
lstViews.Items.Add(new ListViewItem(view.Title, lvGroup) { Tag = view });
}
}
lstViews.EndUpdate();
}
private void OpenSelected()
{
if (lstViews.SelectedItems.Count == 0) return;
if (lstViews.SelectedItems[0].Tag is ModuleView view)
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()
{
string trading = _state.GlobalTradingPaused
? "Pausiert"
: $"Live={_state.LiveTradingMode} / Demo={_state.DemoTradingMode}";
lbl_trading.Text = $"Trading: {trading}";
int moduleCount = _services.GetServices<IPolyTraderModule>().Count();
lbl_modules.Text = $"Module: {moduleCount}";
lbl_ratelimit.Text = $"API: {(_state.IsAlchemyHealthy ? "WSS aktiv" : "Polling")}";
}
private void OpenLegacy()
+42 -27
View File
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
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
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>
@@ -26,36 +26,36 @@
<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
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
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
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
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
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
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
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@@ -117,4 +117,19 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>585, 0</value>
</metadata>
<metadata name="toolstrip_windows.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>733, 0</value>
</metadata>
<metadata name="toolstrip_quickbar.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>376, 0</value>
</metadata>
<metadata name="statusStrip_info.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>944, 0</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>25</value>
</metadata>
</root>
+82
View File
@@ -0,0 +1,82 @@
namespace PolyTraderSharp.Ui.Views
{
partial class SettingsView
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Komponenten-Designer generierter Code
private void InitializeComponent()
{
this.pnlTop = new System.Windows.Forms.Panel();
this.btnReload = new System.Windows.Forms.Button();
this.btnSave = new System.Windows.Forms.Button();
this.propertyGrid = new System.Windows.Forms.PropertyGrid();
this.pnlTop.SuspendLayout();
this.SuspendLayout();
//
// pnlTop
//
this.pnlTop.Controls.Add(this.btnReload);
this.pnlTop.Controls.Add(this.btnSave);
this.pnlTop.Dock = System.Windows.Forms.DockStyle.Top;
this.pnlTop.Location = new System.Drawing.Point(0, 0);
this.pnlTop.Name = "pnlTop";
this.pnlTop.Size = new System.Drawing.Size(700, 44);
this.pnlTop.TabIndex = 0;
//
// btnReload
//
this.btnReload.Location = new System.Drawing.Point(140, 8);
this.btnReload.Name = "btnReload";
this.btnReload.Size = new System.Drawing.Size(120, 28);
this.btnReload.TabIndex = 1;
this.btnReload.Text = "Neu laden";
this.btnReload.UseVisualStyleBackColor = true;
//
// btnSave
//
this.btnSave.Location = new System.Drawing.Point(12, 8);
this.btnSave.Name = "btnSave";
this.btnSave.Size = new System.Drawing.Size(120, 28);
this.btnSave.TabIndex = 0;
this.btnSave.Text = "Speichern";
this.btnSave.UseVisualStyleBackColor = true;
//
// propertyGrid
//
this.propertyGrid.Dock = System.Windows.Forms.DockStyle.Fill;
this.propertyGrid.Location = new System.Drawing.Point(0, 44);
this.propertyGrid.Name = "propertyGrid";
this.propertyGrid.Size = new System.Drawing.Size(700, 556);
this.propertyGrid.TabIndex = 1;
//
// SettingsView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.propertyGrid);
this.Controls.Add(this.pnlTop);
this.Name = "SettingsView";
this.Size = new System.Drawing.Size(700, 600);
this.pnlTop.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel pnlTop;
private System.Windows.Forms.Button btnSave;
private System.Windows.Forms.Button btnReload;
private System.Windows.Forms.PropertyGrid propertyGrid;
}
}
+61
View File
@@ -0,0 +1,61 @@
using System;
using System.Windows.Forms;
using PolyTraderSharp.Models;
using PolyTraderSharp.Services;
namespace PolyTraderSharp.Ui.Views
{
/// <summary>
/// Core-Settings-Ansicht: bearbeitet die ServerSettings über ein PropertyGrid.
/// Designbar (siehe SettingsView.Designer.cs); Laufzeit-Abhängigkeiten via Initialize.
/// Verhalten entspricht dem bisherigen Settings-Tab (Speichern -> XML + Services neu laden).
/// </summary>
public partial class SettingsView : UserControl
{
private const string SettingsPath = "server_settings.xml";
private ServerSettings _settings = new();
private ThreemaService? _threema;
private MullvadVpnService? _vpn;
private TerminalLogger? _logger;
public SettingsView()
{
InitializeComponent();
btnSave.Click += (_, _) => Save();
btnReload.Click += (_, _) => Reload();
}
public void Initialize(ThreemaService threema, MullvadVpnService vpn, TerminalLogger logger)
{
_threema = threema;
_vpn = vpn;
_logger = logger;
Reload();
}
private void Reload()
{
_settings = ServerSettings.Load(SettingsPath);
propertyGrid.SelectedObject = _settings;
}
private void Save()
{
try
{
_settings.Save(SettingsPath);
_threema?.ReloadSettings();
_vpn?.ReloadSettings();
_logger?.Info("Server-Einstellungen gespeichert und Services neu geladen.");
MessageBox.Show("Server-Einstellungen gespeichert.", "Erfolg",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"Fehler beim Speichern: {ex.Message}", "Fehler",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}