poe2-bot/src/Automata.Ui/Views/MainWindow.axaml.cs
2026-03-02 16:23:23 -05:00

171 lines
5.7 KiB
C#

using System.Collections.Specialized;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media;
using Automata.Core;
using Automata.Ui.ViewModels;
namespace Automata.Ui.Views;
public partial class MainWindow : Window
{
private ConfigStore? _store;
private static readonly IBrush TimeBrush = new SolidColorBrush(Color.Parse("#484f58"));
private static readonly IBrush InfoBrush = new SolidColorBrush(Color.Parse("#58a6ff"));
private static readonly IBrush WarnBrush = new SolidColorBrush(Color.Parse("#d29922"));
private static readonly IBrush ErrorBrush = new SolidColorBrush(Color.Parse("#f85149"));
private static readonly IBrush DebugBrush = new SolidColorBrush(Color.Parse("#8b949e"));
private static readonly IBrush DefaultBrush = new SolidColorBrush(Color.Parse("#e6edf3"));
public MainWindow()
{
InitializeComponent();
}
public void SetConfigStore(ConfigStore store)
{
_store = store;
var s = store.Settings;
if (s.WindowWidth.HasValue && s.WindowHeight.HasValue)
{
Width = s.WindowWidth.Value;
Height = s.WindowHeight.Value;
}
if (s.WindowX.HasValue && s.WindowY.HasValue)
{
Position = new PixelPoint((int)s.WindowX.Value, (int)s.WindowY.Value);
WindowStartupLocation = WindowStartupLocation.Manual;
}
else
{
WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
}
protected override void OnDataContextChanged(EventArgs e)
{
base.OnDataContextChanged(e);
if (DataContext is MainWindowViewModel vm)
{
vm.Logs.CollectionChanged += (_, args) =>
{
var block = this.FindControl<SelectableTextBlock>("LogBlock");
var scroll = this.FindControl<ScrollViewer>("LogScroll");
if (block == null) return;
if (args.Action == NotifyCollectionChangedAction.Add && args.NewItems != null)
{
foreach (LogEntry entry in args.NewItems)
AppendLogEntry(block, entry);
}
else if (args.Action == NotifyCollectionChangedAction.Remove)
{
// Rebuild when old entries trimmed
RebuildLog(block, vm);
}
scroll?.ScrollToEnd();
};
}
}
private static void AppendLogEntry(SelectableTextBlock block, LogEntry entry)
{
if (block.Inlines?.Count > 0)
block.Inlines.Add(new Run("\n"));
block.Inlines ??= [];
block.Inlines.Add(new Run(entry.Time + " ") { Foreground = TimeBrush });
block.Inlines.Add(new Run(entry.Message) { Foreground = LevelBrush(entry.Level) });
}
private static void RebuildLog(SelectableTextBlock block, MainWindowViewModel vm)
{
block.Inlines?.Clear();
block.Inlines ??= [];
for (var i = 0; i < vm.Logs.Count; i++)
{
if (i > 0) block.Inlines.Add(new Run("\n"));
var entry = vm.Logs[i];
block.Inlines.Add(new Run(entry.Time + " ") { Foreground = TimeBrush });
block.Inlines.Add(new Run(entry.Message) { Foreground = LevelBrush(entry.Level) });
}
}
private static IBrush LevelBrush(string level) => level switch
{
"INFO" => InfoBrush,
"WARN" or "WARNING" => WarnBrush,
"ERROR" => ErrorBrush,
"DEBUG" => DebugBrush,
_ => DefaultBrush,
};
public void CurrencyImage_PointerPressed(object? sender, PointerPressedEventArgs e)
{
if (sender is not Control grid) return;
if (DataContext is not MainWindowViewModel mainVm) return;
var settingsVm = mainVm.SettingsVm;
if (settingsVm?.CurrencyTabImage == null) return;
// Viewbox puts us in image-pixel space — coords are already image pixels
var pos = e.GetPosition(grid);
settingsVm.OnCurrencyImageClick((int)pos.X, (int)pos.Y);
UpdateHoverMarker(settingsVm.SelectedCurrency);
}
public void CurrencyItem_PointerEntered(object? sender, PointerEventArgs e)
{
if (sender is Control { DataContext: CurrencyPositionViewModel vm })
UpdateHoverMarker(vm);
}
public void CurrencyItem_PointerExited(object? sender, PointerEventArgs e)
{
var marker = this.FindControl<Ellipse>("HoverMarker");
if (marker != null) marker.IsVisible = false;
}
private void UpdateHoverMarker(CurrencyPositionViewModel? vm)
{
var marker = this.FindControl<Ellipse>("HoverMarker");
if (marker == null) return;
if (vm == null || !vm.IsPositioned)
{
marker.IsVisible = false;
return;
}
// Canvas is in image-pixel space thanks to Viewbox
Canvas.SetLeft(marker, vm.X - marker.Width / 2);
Canvas.SetTop(marker, vm.Y - marker.Height / 2);
marker.IsVisible = true;
}
public void BrowserRow_PointerPressed(object? sender, PointerPressedEventArgs e)
{
if (sender is not Control { DataContext: FieldRowViewModel row }) return;
if (!row.IsPointer) return;
if (DataContext is not MainWindowViewModel mainVm) return;
mainVm.BrowserVm?.NavigateToPointer(row);
}
protected override void OnClosing(WindowClosingEventArgs e)
{
if (_store != null)
{
_store.UpdateSettings(s =>
{
s.WindowX = Position.X;
s.WindowY = Position.Y;
s.WindowWidth = Width;
s.WindowHeight = Height;
});
}
base.OnClosing(e);
}
}