diff --git a/StarterNG/Views/Depot/CouplerLook.cs b/StarterNG/Views/Depot/CouplerLook.cs
index 5b733de..b81ffcf 100644
--- a/StarterNG/Views/Depot/CouplerLook.cs
+++ b/StarterNG/Views/Depot/CouplerLook.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Avalonia.Media;
+using Material.Icons;
using StarterNG.Classes;
namespace StarterNG.Views;
@@ -26,14 +27,21 @@ public enum CouplerState
NoEndSignals
}
-/// How a coupler is drawn on the consist strip, so its state reads at a glance.
+///
+/// How a coupler is drawn on the consist strip, so its state reads at a glance:
+/// an icon and a bar under it that ties the two cards, both in the state's colour.
+/// Green is left out - on the strip it means selected or turned round.
+///
public static class CouplerLook
{
- private static readonly IBrush Dim = new SolidColorBrush(Color.Parse("#808080"));
- private static readonly IBrush Green = new SolidColorBrush(Color.Parse("#41C400"));
- private static readonly IBrush Blue = new SolidColorBrush(Color.Parse("#4AA3FF"));
- private static readonly IBrush Red = new SolidColorBrush(Color.Parse("#E5484D"));
- private static readonly IBrush Amber = new SolidColorBrush(Color.Parse("#E0A030"));
+ private static readonly IBrush Steel = Solid("#C3CBD3");
+ private static readonly IBrush Dim = Solid("#6B737B");
+ private static readonly IBrush Sky = Solid("#4FB8FF");
+ private static readonly IBrush Violet = Solid("#B08CFF");
+ private static readonly IBrush Red = Solid("#FF5A5A");
+ private static readonly IBrush Amber = Solid("#F0A030");
+
+ private static IBrush Solid(string color) => new SolidColorBrush(Color.Parse(color));
public static CouplerState StateOf(Coupling coupling, bool trailing)
{
@@ -47,26 +55,31 @@ public static class CouplerLook
return (flags & Coupling.ControlMU) != 0 ? CouplerState.MultipleUnit : CouplerState.Coupled;
}
- // Box drawing and a plain disc: Windows draws no colour emoji for these.
- public static string Glyph(CouplerState state) => state switch
+ public static MaterialIconKind Icon(CouplerState state) => state switch
{
- CouplerState.Free => "╎",
- CouplerState.Permanent => "═",
- CouplerState.EndSignals => "●",
- _ => "≣"
+ CouplerState.Free => MaterialIconKind.LinkVariantOff,
+ CouplerState.Permanent => MaterialIconKind.LinkLock,
+ CouplerState.EndSignals => MaterialIconKind.RecordCircle,
+ CouplerState.NoEndSignals => MaterialIconKind.AlertCircleOutline,
+ _ => MaterialIconKind.LinkVariant
};
- /// The colour of the glyph; null keeps the ordinary text colour.
- public static IBrush? Brush(CouplerState state) => state switch
+ public static IBrush Brush(CouplerState state) => state switch
{
CouplerState.Free => Dim,
- CouplerState.MultipleUnit => Green,
- CouplerState.Permanent => Blue,
+ CouplerState.MultipleUnit => Sky,
+ CouplerState.Permanent => Violet,
CouplerState.EndSignals => Red,
CouplerState.NoEndSignals => Amber,
- _ => null
+ _ => Steel
};
+ /// The bar under the icon: none at the back, broken where nothing is coupled.
+ public static bool HasBar(CouplerState state) => state is not (CouplerState.EndSignals or CouplerState.NoEndSignals);
+
+ /// Thicker where the vehicles do not part in shunting.
+ public static double BarThickness(CouplerState state) => state == CouplerState.Permanent ? 5 : 3;
+
/// What the coupler connects, by the names the coupler editor uses.
public static IReadOnlyList Connections(Coupling coupling) =>
Enumerable.Range(0, CouplingBits.BitKeys.Length)
diff --git a/StarterNG/Views/Depot/VehicleCards.cs b/StarterNG/Views/Depot/VehicleCards.cs
index 08a0dd5..a43d2cc 100644
--- a/StarterNG/Views/Depot/VehicleCards.cs
+++ b/StarterNG/Views/Depot/VehicleCards.cs
@@ -2,7 +2,9 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia;
+using Avalonia.Collections;
using Avalonia.Controls;
+using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Media;
@@ -413,36 +415,34 @@ public sealed class VehicleCards
public Control BuildCoupler(ConsistItem item, bool trailing = false)
{
var coupling = Consist.TailCar(item).Coupling;
- var glyph = new TextBlock
+ var icon = new MaterialIcon { Width = 18, Height = 18, HorizontalAlignment = HorizontalAlignment.Center };
+ var bar = new Line
{
- FontSize = 18,
- VerticalAlignment = VerticalAlignment.Center,
- HorizontalAlignment = HorizontalAlignment.Center
+ StartPoint = new Point(0, 0),
+ EndPoint = new Point(22, 0),
+ HorizontalAlignment = HorizontalAlignment.Center,
+ StrokeLineCap = PenLineCap.Round
};
var coupler = new Button
{
- Padding = new Thickness(4, 6, 4, 6),
+ Padding = new Thickness(3, 6, 3, 6),
MinWidth = 0,
Cursor = _hand,
VerticalAlignment = VerticalAlignment.Center,
- Content = glyph
+ Content = new StackPanel { Spacing = 4, Children = { icon, bar } }
};
coupler.Classes.Add("Basic");
void Restyle()
{
var state = CouplerLook.StateOf(coupling, trailing);
- glyph.Text = CouplerLook.Glyph(state);
- if (CouplerLook.Brush(state) is { } brush)
- {
- glyph.Foreground = brush;
- glyph.Opacity = 1;
- }
- else
- {
- glyph.ClearValue(TextBlock.ForegroundProperty);
- glyph.Opacity = 0.7;
- }
+ var brush = CouplerLook.Brush(state);
+ icon.Kind = CouplerLook.Icon(state);
+ icon.Foreground = brush;
+ bar.Opacity = CouplerLook.HasBar(state) ? 1 : 0; // kept in the layout, so every icon sits level
+ bar.Stroke = brush;
+ bar.StrokeThickness = CouplerLook.BarThickness(state);
+ bar.StrokeDashArray = state == CouplerState.Free ? new AvaloniaList { 1.5, 1.5 } : null;
ToolTip.SetTip(coupler, CouplerLook.Describe(coupling, trailing));
}