-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathMainWindow.ExplorerSignalGrid.cs
More file actions
171 lines (145 loc) · 6.87 KB
/
Copy pathMainWindow.ExplorerSignalGrid.cs
File metadata and controls
171 lines (145 loc) · 6.87 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
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Threading;
using ArIED61850Tester.Models;
using WpfToolTip = System.Windows.Controls.ToolTip;
namespace ArIED61850Tester;
public partial class MainWindow
{
private void QueueExplorerSignalGridLayout()
{
Dispatcher.BeginInvoke(
DispatcherPriority.Loaded,
new Action(ConfigureExplorerSignalGridForCompactFit));
}
private void ConfigureExplorerSignalGridForCompactFit()
{
var signalGrid = FindExplorerVisualChildren<DataGrid>(MainTabs)
.FirstOrDefault(grid =>
{
if (grid.Columns.Count != 6)
return false;
var headers = grid.Columns
.Select(column => column.Header?.ToString() ?? string.Empty)
.ToArray();
return headers.SequenceEqual(new[]
{
"Signal",
"IEC Telegram",
"Value",
"Quality",
"IED Timestamp",
"Acquisition"
});
});
if (signalGrid == null)
return;
ScrollViewer.SetHorizontalScrollBarVisibility(signalGrid, ScrollBarVisibility.Disabled);
signalGrid.CanUserResizeColumns = false;
signalGrid.FrozenColumnCount = 0;
var weights = new[] { 1.00, 1.55, 0.82, 0.68, 1.15, 1.05 };
var minimums = new[] { 90d, 140d, 80d, 70d, 135d, 115d };
for (var index = 0; index < signalGrid.Columns.Count; index++)
{
signalGrid.Columns[index].MinWidth = minimums[index];
signalGrid.Columns[index].Width = new DataGridLength(weights[index], DataGridLengthUnitType.Star);
}
ConfigureExplorerTimestampPresentation(signalGrid);
}
private static void ConfigureExplorerTimestampPresentation(DataGrid signalGrid)
{
if (signalGrid.Columns.Count <= 4 || signalGrid.Columns[4] is not DataGridTextColumn timestampColumn)
return;
// Display only is rounded to nearest millisecond. The monitor point keeps the
// original full-resolution timestamp for evidence, search and hover detail.
timestampColumn.Binding = new Binding(nameof(Iec61850MonitorPoint.DeviceTimestamp))
{
Converter = ExplorerTimestampMillisecondsConverter.Instance,
Mode = BindingMode.OneWay
};
var timestampTextStyle = new Style(typeof(TextBlock), timestampColumn.ElementStyle);
timestampTextStyle.Setters.Add(new Setter(
FrameworkElement.ToolTipProperty,
new Binding(nameof(Iec61850MonitorPoint.DeviceTimestamp))
{
Converter = ExplorerTimestampFullPrecisionToolTipConverter.Instance,
Mode = BindingMode.OneWay
}));
timestampTextStyle.Setters.Add(new Setter(ToolTipService.ShowDurationProperty, 30000));
timestampTextStyle.Setters.Add(new Setter(TextBlock.TextTrimmingProperty, TextTrimming.CharacterEllipsis));
timestampColumn.ElementStyle = timestampTextStyle;
// Scope the premium tooltip styling to this live-value DataGrid so unrelated
// application tooltips retain their established appearance.
signalGrid.Resources[typeof(WpfToolTip)] = BuildExplorerTimestampToolTipStyle();
}
private static Style BuildExplorerTimestampToolTipStyle()
{
var style = new Style(typeof(WpfToolTip));
style.Setters.Add(new Setter(Control.ForegroundProperty, Brushes.White));
style.Setters.Add(new Setter(Control.FontSizeProperty, 11.4));
style.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.Medium));
style.Setters.Add(new Setter(WpfToolTip.PlacementProperty, PlacementMode.Mouse));
style.Setters.Add(new Setter(WpfToolTip.HorizontalOffsetProperty, 10d));
style.Setters.Add(new Setter(WpfToolTip.VerticalOffsetProperty, 12d));
var template = new ControlTemplate(typeof(WpfToolTip));
var chrome = new FrameworkElementFactory(typeof(Border));
chrome.SetValue(Border.BackgroundProperty, new SolidColorBrush(Color.FromRgb(35, 49, 59)));
chrome.SetValue(Border.BorderBrushProperty, new SolidColorBrush(Color.FromRgb(91, 111, 123)));
chrome.SetValue(Border.BorderThicknessProperty, new Thickness(1));
chrome.SetValue(Border.CornerRadiusProperty, new CornerRadius(8));
chrome.SetValue(Border.PaddingProperty, new Thickness(11, 8, 11, 8));
chrome.SetValue(Border.EffectProperty, new DropShadowEffect
{
BlurRadius = 16,
ShadowDepth = 4,
Opacity = 0.20,
Color = Color.FromRgb(15, 23, 42)
});
var content = new FrameworkElementFactory(typeof(ContentPresenter));
content.SetValue(ContentPresenter.RecognizesAccessKeyProperty, false);
chrome.AppendChild(content);
template.VisualTree = chrome;
style.Setters.Add(new Setter(Control.TemplateProperty, template));
return style;
}
private static IEnumerable<T> FindExplorerVisualChildren<T>(DependencyObject? root)
where T : DependencyObject
{
if (root == null)
yield break;
for (var index = 0; index < VisualTreeHelper.GetChildrenCount(root); index++)
{
var child = VisualTreeHelper.GetChild(root, index);
if (child is T typed)
yield return typed;
foreach (var descendant in FindExplorerVisualChildren<T>(child))
yield return descendant;
}
}
}
internal sealed class ExplorerTimestampMillisecondsConverter : IValueConverter
{
public static ExplorerTimestampMillisecondsConverter Instance { get; } = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
=> Iec61850TimestampPresentation.FormatMilliseconds(value as string);
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> throw new NotSupportedException();
}
internal sealed class ExplorerTimestampFullPrecisionToolTipConverter : IValueConverter
{
public static ExplorerTimestampFullPrecisionToolTipConverter Instance { get; } = new();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var text = (value as string)?.Trim();
return string.IsNullOrWhiteSpace(text) || text == "-"
? "IED TIMESTAMP · FULL PRECISION\nNo timestamp available"
: $"IED TIMESTAMP · FULL PRECISION\n{text}";
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
=> throw new NotSupportedException();
}