chore: organize solution into module folders (Core/Server/Drivers/Client/Tooling)
Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
using System.ComponentModel;
|
||||
using System.Reflection;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using SkiaSharp;
|
||||
using Svg.Skia;
|
||||
using ZB.MOM.WW.OtOpcUa.Client.UI.ViewModels;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Client.UI.Views;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
LoadIcon();
|
||||
}
|
||||
|
||||
private void LoadIcon()
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
using var stream = assembly.GetManifestResourceStream("ZB.MOM.WW.OtOpcUa.Client.UI.Assets.app-icon.svg");
|
||||
if (stream == null) return;
|
||||
|
||||
using var svg = new SKSvg();
|
||||
svg.Load(stream);
|
||||
if (svg.Picture == null) return;
|
||||
|
||||
var size = 64;
|
||||
using var bitmap = new SKBitmap(size, size);
|
||||
using var canvas = new SKCanvas(bitmap);
|
||||
canvas.Clear(SKColors.Transparent);
|
||||
|
||||
var bounds = svg.Picture.CullRect;
|
||||
var scale = Math.Min(size / bounds.Width, size / bounds.Height);
|
||||
canvas.Translate((size - bounds.Width * scale) / 2, (size - bounds.Height * scale) / 2);
|
||||
canvas.Scale(scale);
|
||||
canvas.DrawPicture(svg.Picture);
|
||||
|
||||
using var image = SKImage.FromBitmap(bitmap);
|
||||
using var data = image.Encode(SKEncodedImageFormat.Png, 100);
|
||||
using var pngStream = new MemoryStream(data.ToArray());
|
||||
Icon = new WindowIcon(pngStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Icon loading is best-effort
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
var browseTreeView = this.FindControl<BrowseTreeView>("BrowseTreePanel");
|
||||
var treeView = browseTreeView?.FindControl<TreeView>("BrowseTree");
|
||||
if (treeView != null) treeView.SelectionChanged += OnTreeSelectionChanged;
|
||||
|
||||
var contextMenu = this.FindControl<ContextMenu>("TreeContextMenu");
|
||||
if (contextMenu != null) contextMenu.Opening += OnTreeContextMenuOpening;
|
||||
|
||||
var subscribeItem = this.FindControl<MenuItem>("SubscribeMenuItem");
|
||||
if (subscribeItem != null) subscribeItem.Click += OnSubscribeClicked;
|
||||
|
||||
var viewHistoryItem = this.FindControl<MenuItem>("ViewHistoryMenuItem");
|
||||
if (viewHistoryItem != null) viewHistoryItem.Click += OnViewHistoryClicked;
|
||||
|
||||
var monitorAlarmsItem = this.FindControl<MenuItem>("MonitorAlarmsMenuItem");
|
||||
if (monitorAlarmsItem != null) monitorAlarmsItem.Click += OnMonitorAlarmsClicked;
|
||||
|
||||
var browseCertPath = this.FindControl<Button>("BrowseCertPathButton");
|
||||
if (browseCertPath != null) browseCertPath.Click += OnBrowseCertPathClicked;
|
||||
}
|
||||
|
||||
private void OnTreeSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel vm || sender is not TreeView treeView) return;
|
||||
|
||||
vm.SelectedTreeNode = treeView.SelectedItem as TreeNodeViewModel;
|
||||
|
||||
vm.SelectedTreeNodes.Clear();
|
||||
foreach (var item in treeView.SelectedItems)
|
||||
if (item is TreeNodeViewModel node)
|
||||
vm.SelectedTreeNodes.Add(node);
|
||||
}
|
||||
|
||||
private void OnTreeContextMenuOpening(object? sender, CancelEventArgs e)
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel vm) return;
|
||||
|
||||
vm.UpdateHistoryEnabledForSelection();
|
||||
|
||||
var subscribeItem = this.FindControl<MenuItem>("SubscribeMenuItem");
|
||||
var viewHistoryItem = this.FindControl<MenuItem>("ViewHistoryMenuItem");
|
||||
var monitorAlarmsItem = this.FindControl<MenuItem>("MonitorAlarmsMenuItem");
|
||||
|
||||
if (subscribeItem != null)
|
||||
subscribeItem.IsEnabled = vm.IsConnected && vm.SelectedTreeNodes.Count > 0;
|
||||
if (viewHistoryItem != null)
|
||||
viewHistoryItem.IsEnabled = vm.IsHistoryEnabledForSelection;
|
||||
if (monitorAlarmsItem != null)
|
||||
monitorAlarmsItem.IsEnabled = vm.IsConnected && vm.SelectedTreeNodes.Count > 0;
|
||||
}
|
||||
|
||||
private async void OnSubscribeClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is MainWindowViewModel vm)
|
||||
await vm.SubscribeSelectedNodesCommand.ExecuteAsync(null);
|
||||
}
|
||||
|
||||
private void OnViewHistoryClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is MainWindowViewModel vm)
|
||||
vm.ViewHistoryForSelectedNodeCommand.Execute(null);
|
||||
}
|
||||
|
||||
private async void OnMonitorAlarmsClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is MainWindowViewModel vm)
|
||||
await vm.MonitorAlarmsForSelectedNodeCommand.ExecuteAsync(null);
|
||||
}
|
||||
|
||||
private async void OnBrowseCertPathClicked(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is not MainWindowViewModel vm) return;
|
||||
|
||||
var dialog = new OpenFolderDialog
|
||||
{
|
||||
Title = "Select Certificate Store Folder",
|
||||
Directory = vm.CertificateStorePath
|
||||
};
|
||||
|
||||
var result = await dialog.ShowAsync(this);
|
||||
if (!string.IsNullOrEmpty(result))
|
||||
vm.CertificateStorePath = result;
|
||||
}
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
if (DataContext is MainWindowViewModel vm)
|
||||
vm.SaveSettings();
|
||||
base.OnClosing(e);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user