Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion App.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,11 @@
<Geometry x:Key="LucidePlus">M12,5 V19 M5,12 H19</Geometry>
<!-- Exact operator-supplied filled SVG contours (native WPF geometry, shared and static).
Negative Y is intentional: source SVG viewBox is 0 -960 960 960. -->
<!-- Operator-supplied wireless contour is identical for Explorer and GOOSE. -->
<!-- Operator-supplied glyphs. Wireless geometry remains GOOSE-specific. -->
<Geometry x:Key="OperatorIecTopologyIcon">M600-160v-80H440v-200h-80v80H80v-240h280v80h80v-200h160v-80h280v240H600v-80h-80v320h80v-80h280v240H600Zm80-80h120v-80H680v80ZM160-440h120v-80H160v80Zm520-200h120v-80H680v80Zm0 400v-80 80ZM280-440v-80 80Zm400-200v-80 80Z</Geometry>
<Geometry x:Key="OperatorDiagnosticsIcon">M80-600v-120q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v220h-80v-220H160v120H80Zm200 320q-11 0-21-5.5T244-302l-69-138H80v-80h120q11 0 21 5.5t15 16.5l44 88 124-248q5-10 15-15t21-5q11 0 21 5t15 15l67 134q-18 11-34.5 23T478-474l-38-76-124 248q-5 11-15 16.5t-21 5.5Zm147 120H160q-33 0-56.5-23.5T80-240v-120h80v120h243q3 21 9 41t15 39Zm53-320Zm58.5 341.5Q480-197 480-280t58.5-141.5Q597-480 680-480t141.5 58.5Q880-363 880-280t-58.5 141.5Q763-80 680-80t-141.5-58.5ZM688-260l91-91-28-28-91 91 28 28Z</Geometry>
<Geometry x:Key="OperatorCommandDockPowerIcon">M451.5-491.5Q440-503 440-520v-320q0-17 11.5-28.5T480-880q17 0 28.5 11.5T520-840v320q0 17-11.5 28.5T480-480q-17 0-28.5-11.5Zm-112 343q-65.5-28.5-114-77t-77-114Q120-405 120-480q0-61 20-118.5T198-704q11-14 28-13.5t30 13.5q11 11 10 27t-11 30q-27 36-41 79t-14 88q0 117 81.5 198.5T480-200q117 0 198.5-81.5T760-480q0-46-13.5-89.5T704-649q-10-13-11-28.5t10-26.5q12-12 29-12.5t28 12.5q39 48 59.5 105T840-480q0 75-28.5 140.5t-77 114q-48.5 48.5-114 77T480-120q-75 0-140.5-28.5Z</Geometry>
<!-- GOOSE wireless indicator remains unchanged. -->
<Geometry x:Key="OperatorIecWirelessIcon">M280-200q-33 0-56.5-23.5T200-280v-400q0-33 23.5-56.5T280-760h400q33 0 56.5 23.5T760-680v400q0 33-23.5 56.5T680-200H280Zm0 80h400q66 0 113-47t47-113v-400q0-66-47-113t-113-47H280q-66 0-113 47t-47 113v400q0 66 47 113t113 47Zm11-379-55-55q42-51 108.5-78.5T480-660q67 0 134 27.5T723-554l-55 55q-35-38-83.5-59.5T480-580q-56 0-104.5 21.5T291-499Zm114 114-57-57q26-28 60.5-43t72.5-15q38 0 71.5 15t59.5 43l-56 57q-14-15-34.5-25T480-420q-21 0-41 10t-34 25Zm46.5 93.5Q440-303 440-320t11.5-28.5Q463-360 480-360t28.5 11.5Q520-337 520-320t-11.5 28.5Q497-280 480-280t-28.5-11.5ZM480-480Z</Geometry>
<Geometry x:Key="OperatorLiveMonitorIcon">M308.5-411.5Q320-423 320-440t-11.5-28.5Q297-480 280-480t-28.5 11.5Q240-457 240-440t11.5 28.5Q263-400 280-400t28.5-11.5Zm0-160Q320-583 320-600t-11.5-28.5Q297-640 280-640t-28.5 11.5Q240-617 240-600t11.5 28.5Q263-560 280-560t28.5-11.5ZM360-400h360v-80H360v80Zm0-160h360v-80H360v80Zm-40 440v-80H160q-33 0-56.5-23.5T80-280v-480q0-33 23.5-56.5T160-840h640q33 0 56.5 23.5T880-760v480q0 33-23.5 56.5T800-200H640v80H320ZM160-280h640v-480H160v480Zm0 0v-480 480Z</Geometry>
<Geometry x:Key="OperatorIedBrowserIcon">M600-120v-120H440v-400h-80v120H80v-320h280v120h240v-120h280v320H600v-120h-80v320h80v-120h280v320H600ZM160-760v160-160Zm520 400v160-160Zm0-400v160-160Zm0 160h120v-160H680v160Zm0 400h120v-160H680v160ZM160-600h120v-160H160v160Z</Geometry>
Expand Down
6 changes: 3 additions & 3 deletions MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
<Button x:Name="NavExplorerButton" Grid.Column="0" Tag="0" Click="NavButton_Click" Style="{StaticResource SegmentedNavButton}" ToolTip="IEC 61850 Explorer">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Viewbox Width="15" Height="15" Margin="0,0,5,0" IsHitTestVisible="False">
<Path Data="{StaticResource OperatorIecWirelessIcon}" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Stretch="Uniform"/>
<Path Data="{StaticResource OperatorIecTopologyIcon}" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Stretch="Uniform"/>
</Viewbox>
<TextBlock Text="IEC 61850 Explorer" VerticalAlignment="Center"/>
</StackPanel>
Expand Down Expand Up @@ -152,7 +152,7 @@
<Button x:Name="NavDiagnosticsButton" Grid.Column="5" Tag="5" Click="NavButton_Click" Style="{StaticResource SegmentedNavButton}">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<Viewbox Width="15" Height="15" Margin="0,0,5,0" IsHitTestVisible="False">
<Path Data="{StaticResource MaterialDiagnosticsIcon}" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Stretch="Uniform"/>
<Path Data="{StaticResource OperatorDiagnosticsIcon}" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Stretch="Uniform"/>
</Viewbox>
<TextBlock Text="Diagnostics" VerticalAlignment="Center"/>
<Border Visibility="{Binding DiagnosticsAlertVisibility}"
Expand Down Expand Up @@ -681,7 +681,7 @@
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
<Border Width="28" Height="28" CornerRadius="9" Background="#E7F0FF" BorderBrush="#C9DBF7" BorderThickness="1" Margin="0,0,9,0">
<Viewbox Width="15" Height="15" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Data="{StaticResource MaterialTuneIcon}" Style="{StaticResource MaterialIconGlyph}"/>
<Path Data="{StaticResource OperatorCommandDockPowerIcon}" Style="{StaticResource MaterialIconGlyph}"/>
</Viewbox>
</Border>
<TextBlock Text="IED Command Panel" FontSize="13.6" FontWeight="SemiBold" Foreground="{StaticResource Ink}" VerticalAlignment="Center"/>
Expand Down
32 changes: 30 additions & 2 deletions tests/ARSAS.Tests/MaterialIconConsistencyTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ public sealed class MaterialIconConsistencyTests
private static readonly XNamespace X = "http://schemas.microsoft.com/winfx/2006/xaml";

[Theory]
[InlineData("NavExplorerButton", "0", "OperatorIecWirelessIcon")]
[InlineData("NavExplorerButton", "0", "OperatorIecTopologyIcon")]
[InlineData("NavLiveButton", "1", "OperatorLiveMonitorIcon")]
[InlineData("NavEventsButton", "2", "OperatorEventLogIcon")]
[InlineData("NavAlarmButton", "3", "OperatorAlarmIcon")]
[InlineData("NavGooseButton", "4", "OperatorIecWirelessIcon")]
[InlineData("NavDiagnosticsButton", "5", "MaterialDiagnosticsIcon")]
[InlineData("NavDiagnosticsButton", "5", "OperatorDiagnosticsIcon")]
[InlineData("NavNativeFatButton", "6", "OperatorFatIcon")]
[InlineData("NavIedBrowserButton", "7", "OperatorIedBrowserIcon")]
public void EveryNavigationDestinationOwnsOneGlyphAndSameClickHandler(
Expand All @@ -44,6 +44,34 @@ public void EveryNavigationDestinationOwnsOneGlyphAndSameClickHandler(
Assert.NotEmpty(button.Descendants(P + "TextBlock"));
}

[Fact]
public void SelectedOperatorPathsBindToExactlyOneNavigationAndCommandGlyph()
{
var app = XDocument.Load(Find("App.xaml"));
var xaml = XDocument.Load(Find("MainWindow.xaml"));
foreach (var (key, prefix) in new[]
{
("OperatorIecTopologyIcon", "M600-160v-80"),
("OperatorDiagnosticsIcon", "M80-600v-120"),
("OperatorCommandDockPowerIcon", "M451.5-491.5")
})
{
var entry = Assert.Single(app.Descendants(P + "Geometry"), g =>
(string?)g.Attribute(X + "Key") == key);
Assert.StartsWith(prefix, entry.Value);
Assert.False(Geometry.Parse(entry.Value).Bounds.IsEmpty);
}
var command = Assert.Single(xaml.Descendants(P + "Expander"),
x => (string?)x.Attribute(X + "Name") == "CommandPanelExpander");
Assert.Equal("{StaticResource OperatorCommandDockPowerIcon}",
(string?)Assert.Single(command.Element(P + "Expander.Header")!
.Descendants(P + "Path")).Attribute("Data"));
var goose = Assert.Single(xaml.Descendants(P + "Button"), b =>
(string?)b.Attribute(X + "Name") == "NavGooseButton");
Assert.Contains(goose.Descendants(P + "Path"), g =>
(string?)g.Attribute("Data") == "{StaticResource OperatorIecWirelessIcon}");
}

[Fact]
public void OfficialMaterialGeometryRegistryIsValidAndEveryKeyIsUnique()
{
Expand Down
Loading