-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAssignSignalsToModbusWindow.xaml.cs
More file actions
176 lines (156 loc) · 6.26 KB
/
Copy pathAssignSignalsToModbusWindow.xaml.cs
File metadata and controls
176 lines (156 loc) · 6.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using Ari61850Bridge.Models;
namespace Ari61850Bridge;
public partial class AssignSignalsToModbusWindow : Window, INotifyPropertyChanged
{
private RelayEndpointView? _selectedRelay;
private string _searchText = string.Empty;
public ObservableCollection<RelayEndpointView> Relays { get; }
public ObservableCollection<AssignmentSignalRow> Rows { get; } = new();
public ICollectionView RowsView { get; }
public IReadOnlyList<SignalDefinition> SelectedSignals { get; private set; } = Array.Empty<SignalDefinition>();
public event PropertyChangedEventHandler? PropertyChanged;
public RelayEndpointView? SelectedRelay
{
get => _selectedRelay;
set
{
if (ReferenceEquals(_selectedRelay, value)) return;
_selectedRelay = value;
Raise();
RebuildRows();
}
}
public string SearchText
{
get => _searchText;
set
{
if (_searchText == value) return;
_searchText = value;
Raise();
RowsView.Refresh();
Raise(nameof(SelectionSummary));
}
}
public string SelectionSummary => $"{Rows.Count(r => r.IsChecked && r.CanAssign)} selected · {Rows.Count(r => r.IsAlreadyAssigned)} already assigned · {RowsView.Cast<object>().Count()} visible";
public AssignSignalsToModbusWindow(IEnumerable<RelayEndpointView> relays, RelayEndpointView? selectedRelay)
{
Relays = new ObservableCollection<RelayEndpointView>(relays.Where(r => r.Signals.Any(s => s.IsSelected && s.CanPublishToRuntime)));
RowsView = CollectionViewSource.GetDefaultView(Rows);
RowsView.Filter = FilterRow;
DataContext = this;
InitializeComponent();
SelectedRelay = Relays.FirstOrDefault(r => ReferenceEquals(r, selectedRelay)) ?? Relays.FirstOrDefault();
}
private void RebuildRows()
{
Rows.Clear();
if (SelectedRelay != null)
{
var assigned = SelectedRelay.ModbusBindings
.Select(b => b.IecReference)
.ToHashSet(StringComparer.OrdinalIgnoreCase);
foreach (var signal in SelectedRelay.Signals
.Where(s => s.IsSelected && s.CanPublishToRuntime)
.OrderBy(s => s.SortPriority)
.ThenBy(s => s.ObjectReference))
{
var row = new AssignmentSignalRow(signal, assigned.Contains(signal.ObjectReference));
row.PropertyChanged += (_, e) =>
{
if (e.PropertyName == nameof(AssignmentSignalRow.IsChecked))
Raise(nameof(SelectionSummary));
};
Rows.Add(row);
}
}
RowsView.Refresh();
Raise(nameof(SelectionSummary));
}
private bool FilterRow(object item)
{
if (item is not AssignmentSignalRow row) return false;
var text = SearchText.Trim();
if (string.IsNullOrWhiteSpace(text)) return true;
var haystack = $"{row.Signal.Name} {row.Signal.ObjectReference} {row.Signal.LogicalNode} {row.Signal.DataType} {row.Signal.Category} {row.Signal.Value} {row.Signal.Quality}";
return text.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.All(token => haystack.Contains(token, StringComparison.OrdinalIgnoreCase));
}
private void SignalsGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var source = e.OriginalSource as DependencyObject;
if (FindVisualParent<CheckBox>(source) != null || FindVisualParent<DataGridColumnHeader>(source) != null)
return;
var row = FindVisualParent<DataGridRow>(source);
if (row?.Item is not AssignmentSignalRow item || !item.CanAssign) return;
item.IsChecked = !item.IsChecked;
row.IsSelected = true;
e.Handled = true;
}
private void AssignmentCheckBox_Click(object sender, RoutedEventArgs e)
{
Raise(nameof(SelectionSummary));
e.Handled = true;
}
private void ClearSearch_Click(object sender, RoutedEventArgs e) => SearchText = string.Empty;
private void Assign_Click(object sender, RoutedEventArgs e)
{
if (SelectedRelay == null) return;
SelectedSignals = Rows.Where(r => r.IsChecked && r.CanAssign).Select(r => r.Signal).ToList();
if (SelectedSignals.Count == 0)
{
MessageBox.Show(this, "Select at least one unassigned Explorer signal.", "Nothing selected", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
DialogResult = true;
Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
private static T? FindVisualParent<T>(DependencyObject? child) where T : DependencyObject
{
while (child != null)
{
if (child is T typed) return typed;
child = VisualTreeHelper.GetParent(child);
}
return null;
}
private void Raise([CallerMemberName] string? name = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
public sealed class AssignmentSignalRow : INotifyPropertyChanged
{
private bool _isChecked;
public SignalDefinition Signal { get; }
public bool IsAlreadyAssigned { get; }
public bool CanAssign => !IsAlreadyAssigned;
public string AssignmentStatus => IsAlreadyAssigned ? "Assigned" : "Available";
public bool IsChecked
{
get => _isChecked;
set
{
if (!CanAssign || _isChecked == value) return;
_isChecked = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsChecked)));
}
}
public AssignmentSignalRow(SignalDefinition signal, bool isAlreadyAssigned)
{
Signal = signal;
IsAlreadyAssigned = isAlreadyAssigned;
}
public event PropertyChangedEventHandler? PropertyChanged;
}