From 8d08180f56086f52db21b33c4be10fb89c55ac49 Mon Sep 17 00:00:00 2001 From: masarray Date: Mon, 13 Jul 2026 16:36:58 +0700 Subject: [PATCH 1/9] ci: add reviewed command and layout patch --- tools/apply_command_health_ui.py | 114 +++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 tools/apply_command_health_ui.py diff --git a/tools/apply_command_health_ui.py b/tools/apply_command_health_ui.py new file mode 100644 index 00000000..3e9750fc --- /dev/null +++ b/tools/apply_command_health_ui.py @@ -0,0 +1,114 @@ +from pathlib import Path +import re + +def read(p): return Path(p).read_text(encoding='utf-8') +def write(p,s): Path(p).write_bytes(s.replace('\r\n','\n').replace('\n','\r\n').encode('utf-8')) +def one(s,a,b,n): + c=s.count(a) + if c!=1: raise RuntimeError(f'{n}: {c}') + return s.replace(a,b,1) +def sub(s,p,r,n): + s,c=re.subn(p,r,s,count=1,flags=re.S) + if c!=1: raise RuntimeError(f'{n}: {c}') + return s + +# Stop the implicit DataGridRow style from binding MonitorPoint-only state on SignalDefinition rows. +p='App.xaml'; s=read(p) +s=sub(s,r'\s* - - - - - diff --git a/MainWindow.CommandPanelUx.cs b/MainWindow.CommandPanelUx.cs index 4589d1a6..8066c867 100644 --- a/MainWindow.CommandPanelUx.cs +++ b/MainWindow.CommandPanelUx.cs @@ -7,6 +7,7 @@ using System.Windows.Media; using System.Windows.Threading; using ArIED61850Tester.Models; +using ArIED61850Tester.Services; namespace ArIED61850Tester; @@ -31,7 +32,18 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur var testMode = values.ElementAtOrDefault(1) is true; var busy = values.ElementAtOrDefault(2) is true; var supportsOperate = values.ElementAtOrDefault(3) is true; - return (liveArmed || testMode) && supportsOperate && !busy; + var current = values.ElementAtOrDefault(4)?.ToString() ?? string.Empty; + var command = parameter?.ToString() ?? string.Empty; + return (liveArmed || testMode) && supportsOperate && !busy && !AlreadyActive(command, current); + } + + private static bool AlreadyActive(string command, string current) + { + if (string.IsNullOrWhiteSpace(command) || string.IsNullOrWhiteSpace(current) || current.Trim() == "-") return false; + if (Iec61850ValueFormatter.TryNormalizeDbpos(command, out var requested) && + Iec61850ValueFormatter.TryNormalizeDbpos(current, out var actual)) return requested == actual; + if (bool.TryParse(command, out var requestedBool) && bool.TryParse(current, out var actualBool)) return requestedBool == actualBool; + return command.Trim().Equals(current.Trim(), StringComparison.OrdinalIgnoreCase); } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) @@ -51,17 +63,10 @@ public object Convert(object value, Type targetType, object parameter, CultureIn return "Status only"; } - if (text.Contains("select before operate", StringComparison.OrdinalIgnoreCase) || - text.Contains("SBO", StringComparison.OrdinalIgnoreCase)) - { - return "SBO"; - } - - if (text.Contains("direct operate", StringComparison.OrdinalIgnoreCase) || - text.Contains("(DO)", StringComparison.OrdinalIgnoreCase)) - { - return "DO"; - } + if ((text.Contains("select before operate", StringComparison.OrdinalIgnoreCase) || text.Contains("SBO", StringComparison.OrdinalIgnoreCase)) && text.Contains("enhanced", StringComparison.OrdinalIgnoreCase)) return "SBO • Enhanced security"; + if (text.Contains("select before operate", StringComparison.OrdinalIgnoreCase) || text.Contains("SBO", StringComparison.OrdinalIgnoreCase)) return "SBO • Normal security"; + if ((text.Contains("direct operate", StringComparison.OrdinalIgnoreCase) || text.Contains("(DO)", StringComparison.OrdinalIgnoreCase)) && text.Contains("enhanced", StringComparison.OrdinalIgnoreCase)) return "Direct • Enhanced security"; + if (text.Contains("direct operate", StringComparison.OrdinalIgnoreCase) || text.Contains("(DO)", StringComparison.OrdinalIgnoreCase)) return "Direct • Normal security"; if (text.Contains("auto-detect", StringComparison.OrdinalIgnoreCase) || string.IsNullOrWhiteSpace(text)) @@ -105,7 +110,7 @@ private void InstallCommandPanelUx() _commandPanelUxTimer = new DispatcherTimer(DispatcherPriority.Background) { - Interval = TimeSpan.FromMilliseconds(500) + Interval = TimeSpan.FromMilliseconds(1500) }; _commandPanelUxTimer.Tick += CommandPanelUxTimer_Tick; _commandPanelUxTimer.Start(); @@ -210,12 +215,14 @@ private void ConfigureCommandPanelButton(Button button) var enabledBinding = new MultiBinding { Converter = CommandButtonEnabledConverter.Instance, + ConverterParameter = content, Mode = BindingMode.OneWay }; enabledBinding.Bindings.Add(new Binding(nameof(LiveControlArmed)) { Source = this }); enabledBinding.Bindings.Add(new Binding(nameof(CommandTestMode)) { Source = this }); enabledBinding.Bindings.Add(new Binding(nameof(SignalDefinition.ControlIsBusy))); enabledBinding.Bindings.Add(new Binding(nameof(SignalDefinition.ControlSupportsOperate))); + enabledBinding.Bindings.Add(new Binding(nameof(SignalDefinition.ControlCurrentValue))); BindingOperations.SetBinding(button, UIElement.IsEnabledProperty, enabledBinding); _configuredCommandButtons.Add(button, new Marker()); diff --git a/MainWindow.xaml b/MainWindow.xaml index 95dbd49c..dd34dc31 100644 --- a/MainWindow.xaml +++ b/MainWindow.xaml @@ -111,20 +111,17 @@ - + - - - - - - - + + + + @@ -136,13 +133,13 @@ - + - -