Files
PolyTraderSharp/Ui/Views/TerminalView.cs
T
RichardandClaude Opus 4.8 0aedddabe8 UI: Terminal-Kopierfunktion (Kontextmenue) + Jobs-Toolstrip (via Designer)
- TerminalView: ContextMenuStrip (Kopieren/Alles auswaehlen/Alles kopieren/Terminal leeren)
  am rtbTerminal - macht das Kopieren entdeckbar (Ctrl+C funktioniert zusaetzlich nativ).
- JobsView: ToolStrip 'toolStripJobs' (docked Top) mit Starter-Button 'Aktualisieren'
  (dgvJobs.Refresh) - weitere Job-Steuerelemente folgen nach und nach.
Beide via Designer (.Designer.cs), Logik im Code-Behind. Build 0 Fehler, --smoke-ui ok.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-15 09:39:35 +02:00

129 lines
5.2 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.Concurrent;
using System.Windows.Forms;
using PolyTraderSharp.Services;
namespace PolyTraderSharp.Ui.Views
{
/// <summary>
/// Terminal-/Log-Ansicht. Designbar (siehe TerminalView.Designer.cs). Die Laufzeit-
/// Abhängigkeit (TerminalLogger) wird per <see cref="Initialize"/> injiziert, damit der
/// parameterlose Konstruktor für den VS-Designer nutzbar bleibt.
/// </summary>
public partial class TerminalView : Form
{
private TerminalLogger? _logger;
private readonly ConcurrentQueue<LogMessageEventArgs> _logQueue = new();
private readonly System.Windows.Forms.Timer _uiLogTimer = new() { Interval = 250 };
private bool _autoScroll = true;
private EventHandler<LogMessageEventArgs>? _logHandler;
public TerminalView()
{
InitializeComponent();
// Steuerelemente + statische Eigenschaften stammen aus dem Designer.
// Hier nur noch Verhalten verdrahten und einen sinnvollen Default wählen.
if (cbLogLevel.Items.Count > 0) cbLogLevel.SelectedIndex = 0;
btnAutoscroll.Click += (_, _) => ToggleAutoscroll();
_uiLogTimer.Tick += ProcessLogQueue;
// Kontextmenü: Text aus dem Terminal kopieren (Ctrl+C funktioniert zusätzlich nativ).
miCopy.Click += (_, _) => { if (rtbTerminal.SelectionLength > 0) rtbTerminal.Copy(); };
miSelectAll.Click += (_, _) => rtbTerminal.SelectAll();
miCopyAll.Click += (_, _) => CopyAllToClipboard();
miClear.Click += (_, _) => rtbTerminal.Clear();
}
private void CopyAllToClipboard()
{
try
{
if (!string.IsNullOrEmpty(rtbTerminal.Text))
Clipboard.SetText(rtbTerminal.Text);
}
catch { /* Zwischenablage kann kurzzeitig belegt sein bewusst ignorieren */ }
}
/// <summary>Verbindet die View mit dem Logger (Laufzeit-DI).</summary>
public void Initialize(TerminalLogger logger)
{
_logger = logger;
// Jüngste Historie vorladen, damit das Fenster beim Öffnen nicht leer ist.
foreach (var e in _logger.GetHistory(TimeSpan.FromMinutes(10)))
_logQueue.Enqueue(e);
_logHandler = (_, e) => _logQueue.Enqueue(e);
_logger.OnLogMessage += _logHandler;
_uiLogTimer.Start();
Disposed += OnDisposed;
}
private void OnDisposed(object? sender, EventArgs e)
{
_uiLogTimer.Stop();
if (_logger != null && _logHandler != null)
_logger.OnLogMessage -= _logHandler;
}
private void ToggleAutoscroll()
{
_autoScroll = !_autoScroll;
btnAutoscroll.BackColor = _autoScroll ? System.Drawing.Color.LightGreen : System.Drawing.Color.IndianRed;
btnAutoscroll.Text = _autoScroll ? "Stop Autoscroll" : "Start Autoscroll";
}
private void ProcessLogQueue(object? sender, EventArgs e)
{
if (_logQueue.IsEmpty || !IsHandleCreated) return;
string filter = cbLogLevel.SelectedItem?.ToString() ?? "Alle";
TimeZoneInfo berlinTz = TimeZoneInfo.FindSystemTimeZoneById("W. Europe Standard Time");
bool appended = false;
int count = 0;
const int maxProcess = 500;
rtbTerminal.SuspendLayout();
while (count < maxProcess && _logQueue.TryDequeue(out var logEvent))
{
count++;
if (filter != "Alle" && logEvent.Level.ToString() != filter) continue;
DateTime logTime = logEvent.Timestamp.Kind == DateTimeKind.Utc
? TimeZoneInfo.ConvertTimeFromUtc(logEvent.Timestamp, berlinTz)
: TimeZoneInfo.ConvertTime(logEvent.Timestamp, berlinTz);
string timeStr = $"[{logTime:HH:mm:ss}]";
System.Drawing.Color c = System.Drawing.Color.White;
if (logEvent.Level == LogLevel.Error) c = System.Drawing.Color.Red;
else if (logEvent.Level == LogLevel.Warning) c = System.Drawing.Color.Yellow;
else if (logEvent.Level == LogLevel.Trade) c = System.Drawing.Color.LightGreen;
else if (logEvent.Level == LogLevel.TradeReasoning) c = System.Drawing.Color.Orange;
rtbTerminal.SelectionStart = rtbTerminal.TextLength;
rtbTerminal.SelectionLength = 0;
rtbTerminal.SelectionColor = c;
rtbTerminal.AppendText($"{timeStr} [{logEvent.Level}] {logEvent.Message}\n");
appended = true;
}
if (appended)
{
if (rtbTerminal.TextLength > 80000)
{
rtbTerminal.Clear();
rtbTerminal.SelectionColor = System.Drawing.Color.LightPink;
rtbTerminal.AppendText($"[{DateTime.Now:HH:mm:ss}] [System] Terminal Auto-Clear (RAM Limit erreicht). Vollständige Logs im Ordner /Logs.\n");
}
if (_autoScroll) rtbTerminal.ScrollToCaret();
}
rtbTerminal.ResumeLayout();
}
}
}