diff --git a/PamhagenSysCtrl/Helpers/PamhagenBrushes.cs b/PamhagenSysCtrl/Helpers/PamhagenBrushes.cs new file mode 100644 index 0000000..c72c2c7 --- /dev/null +++ b/PamhagenSysCtrl/Helpers/PamhagenBrushes.cs @@ -0,0 +1,43 @@ +using System.Windows.Media; + +namespace PamhagenSysCtrl.Helpers { + public class PamhagenBrushes { + + public const double TRANSITION = 1.0 / 4096; + + public static readonly SolidColorBrush Green = new SolidColorBrush(Color.FromRgb(0x20, 0xE0, 0x20)); + public static readonly SolidColorBrush DimOrange = new SolidColorBrush(Color.FromRgb(0xFF, 0xC0, 0x80)); + public static readonly SolidColorBrush Yellow = new SolidColorBrush(Color.FromRgb(0xFF, 0xE0, 0x10)); + public static readonly SolidColorBrush Red = new SolidColorBrush(Color.FromRgb(0xFF, 0x20, 0x20)); + + public static Brush ForFillState(FillState state, Color background) { + return state switch { + FillState.Empty => GetEmpty(background), + FillState.Filled => GetFilled(background), + FillState.Half => GetHalf(background), + FillState.Full => GetFull(background), + _ => GetEmpty(background), + }; + } + + public static Brush ForFillState(FillState state, SolidColorBrush background) { + return ForFillState(state, background.Color); + } + + public static Brush GetEmpty(Color background) { + return new SolidColorBrush(background); + } + + public static Brush GetFilled(Color background) { + return new LinearGradientBrush(background, Green.Color, new(0.5, 0.875 - TRANSITION), new(0.5, 0.875 + TRANSITION)); + } + + public static Brush GetHalf(Color background) { + return new LinearGradientBrush(background, Green.Color, new(0.5, 0.5 - TRANSITION), new(0.5, 0.5 + TRANSITION)); + } + + public static Brush GetFull(Color background) { + return new LinearGradientBrush(background, Red.Color, new(0.5, 0.0625 - TRANSITION), new(0.5, 0.0625 + TRANSITION)); + } + } +} diff --git a/PamhagenSysCtrl/Helpers/PamhagenGraph.cs b/PamhagenSysCtrl/Helpers/PamhagenGraph.cs index ad3fc6a..3950c60 100644 --- a/PamhagenSysCtrl/Helpers/PamhagenGraph.cs +++ b/PamhagenSysCtrl/Helpers/PamhagenGraph.cs @@ -35,8 +35,8 @@ namespace PamhagenSysCtrl.Helpers { var rebler = new Rebler("Rebler", (mw1X + mw2X) / 2, 100); Nodes.Add(rebler); - MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelA1 != FillState.Empty); - MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelA1 != FillState.Empty); + MW1 = new Trough("MW1", mw1X, mpY - 70, () => App.Plant?.FillLevelA1 ?? FillState.Unknown); + MW2 = new Trough("MW2", mw2X, mpY - 70, () => App.Plant?.FillLevelA1 ?? FillState.Unknown); var mp1 = new Pump("MP1", mw1X, mpY); var mp2 = new Pump("MP2", mw2X, mpY); var x1 = new PipeJoin(mw1X, mpY + 40); @@ -314,8 +314,8 @@ namespace PamhagenSysCtrl.Helpers { var prY = 680; var pr1X = 750; var pr2X = 900; - var press1 = new Press("Presse 1", pr1X, prY, 200000, () => App.Plant?.FillLevelPress1 == FillState.Full); - var press2 = new Press("Presse 2", pr2X, prY, 150000, () => App.Plant?.FillLevelPress1 == FillState.Full); + var press1 = new Press("Presse 1", pr1X, prY, 200000, () => App.Plant?.FillLevelPress1 ?? FillState.Unknown); + var press2 = new Press("Presse 2", pr2X, prY, 150000, () => App.Plant?.FillLevelPress1 ?? FillState.Unknown); var v50 = CreateValve(50, pr1X - 45, prY - 100); var v51 = CreateValve(51, pr1X - 15, prY - 100); var v52 = CreateValve(52, pr1X + 15, prY - 100); @@ -357,7 +357,7 @@ namespace PamhagenSysCtrl.Helpers { } protected static Tank CreateTank(int n, double x, double y, int capacity) { - return new($"Tank {n}", x, y, capacity, () => App.Plant?.TankFillLevels[n - 1] != FillState.Empty, () => App.Plant?.TankFillLevels[n - 1] != FillState.Full); + return new($"Tank {n}", x, y, capacity, () => App.Plant?.TankFillLevels[n - 1] ?? FillState.Unknown); } public void TraverseSubgraph(INode start, HashSet? visited = null, Action? edgeAction = null, Action? valveAction = null) { diff --git a/PamhagenSysCtrl/Helpers/Pipeline/HeatExchanger.cs b/PamhagenSysCtrl/Helpers/Pipeline/HeatExchanger.cs index 2b5446f..89f3a29 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/HeatExchanger.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/HeatExchanger.cs @@ -54,8 +54,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { return Math.Abs(x - CenterX) <= WIDTH / 2 && Math.Abs(y - CenterY) <= HEIGHT / 2; } - public void Update(bool isHovering, bool isPresed) { - _rect?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; + public void Update(bool isHovering, bool isPressed) { + _rect?.Fill = + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke; } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Press.cs b/PamhagenSysCtrl/Helpers/Pipeline/Press.cs index a1a9c0a..22aa93e 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Press.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Press.cs @@ -15,23 +15,24 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public ISet Inputs { get; set; } public ISet Outputs { get; set; } - protected Func CallbackIsFull; - public double TopY => CenterY - DIAMETER / 2; - public bool IsFull => CallbackIsFull(); + public FillState FillState => CallbackFillState(); + public bool IsFull => FillState == FillState.Full; public int? CapacityLiters { get; set; } + protected Func CallbackFillState; + private Shape? _circle; private TextBlock? _text; - public Press(string label, double x, double y, int capacityLiters, Func cbFull) { + public Press(string label, double x, double y, int capacityLiters, Func cbFillState) { CenterX = x; CenterY = y; Label = label; CapacityLiters = capacityLiters; - CallbackIsFull = cbFull; + CallbackFillState = cbFillState; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -64,7 +65,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { - _circle?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; + _circle?.Fill = PamhagenBrushes.ForFillState(FillState, + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke + ); } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs b/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs index 50f78d6..8c1b75f 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Rebler.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Windows; +using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; @@ -39,8 +38,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { Stroke = Brushes.Black, StrokeThickness = 2, }; - var hx = CenterX + WIDTH / 2 - 10; + var left = CenterX - WIDTH / 2; + var right = CenterX + WIDTH / 2; var top = CenterY - HEIGHT / 2; + var bottom = CenterY + HEIGHT / 2; + var hx = right - 10; var h = 15; var w = 25; _hopperOuter = new Polygon() { @@ -51,6 +53,14 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { Points = [new(hx - w + 2, top - h), new(hx, top + 26), new(hx + w - 2, top - h)], Fill = Brushes.WhiteSmoke, }; + _bottomOuter = new Polygon() { + Points = [new(left + 20, bottom), new(right - 20, bottom), new(right - 15, bottom + 10), new(left + 15, bottom + 10)], + Fill = Brushes.Black, + }; + _bottomInner = new Polygon() { + Points = [new(left + 20 + 2, bottom), new(right - 20 - 2, bottom), new(right - 15 - 2, bottom + 10), new(left + 15 + 2, bottom + 10)], + Fill = Brushes.WhiteSmoke, + }; _text = new() { Text = Label, FontSize = 12, @@ -63,8 +73,10 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { _text.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2); _text.SetValue(Canvas.TopProperty, CenterY - 8); canvas.Children.Add(_hopperOuter); + canvas.Children.Add(_bottomOuter); canvas.Children.Add(_rect); canvas.Children.Add(_hopperInner); + canvas.Children.Add(_bottomInner); canvas.Children.Add(_text); } @@ -73,9 +85,18 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { - _rect?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; - _hopperInner?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; - _bottomInner?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; + _rect?.Fill = + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke; + _hopperInner?.Fill = + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke; + _bottomInner?.Fill = + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke; } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Tank.cs b/PamhagenSysCtrl/Helpers/Pipeline/Tank.cs index 1810445..e45c10a 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Tank.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Tank.cs @@ -14,27 +14,26 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public double TopY => CenterY - HEIGHT / 2; public double BottomY => CenterY + HEIGHT / 2; public string Label { get; set; } - public bool IsFull => CallbackIsFull(); - public bool IsFilled => CallbackIsFilled(); + public FillState FillState => CallbackFillState(); + public bool IsFull => FillState == FillState.Full; + public bool IsFilled => FillState != FillState.Empty; public ISet Inputs { get; init; } public ISet Outputs { get; init; } public int? CapacityLiters { get; set; } - protected Func CallbackIsFilled; - protected Func CallbackIsFull; + protected Func CallbackFillState; private Shape? _rect; private TextBlock? _text; - public Tank(string label, double x, double y, int capacityLiters, Func cbFilled, Func cbFull) { + public Tank(string label, double x, double y, int capacityLiters, Func cbFillState) { CenterX = x; CenterY = y; Label = label; CapacityLiters = capacityLiters; - CallbackIsFilled = cbFilled; - CallbackIsFull = cbFull; + CallbackFillState = cbFillState; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -67,7 +66,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { - _rect?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; + _rect?.Fill = PamhagenBrushes.ForFillState(FillState, + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke + ); } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Trough.cs b/PamhagenSysCtrl/Helpers/Pipeline/Trough.cs index 8ca1cd8..b2cdc35 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Trough.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Trough.cs @@ -13,21 +13,22 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public double CenterY { get; set; } public double BottomY => CenterY + HEIGHT / 2; public string Label { get; set; } - public bool IsFilled => CallbackIsFilled(); + public FillState FillState => CallbackFillState(); + public bool IsFilled => FillState != FillState.Empty; public ISet Inputs { get; init; } public ISet Outputs { get; init; } - protected Func CallbackIsFilled; + protected Func CallbackFillState; private Shape? _inner; private Shape? _outer; private TextBlock? _text; - public Trough(string label, double x, double y, Func cbFilled) { + public Trough(string label, double x, double y, Func cbFillState) { CenterX = x; CenterY = y; Label = label; - CallbackIsFilled = cbFilled; + CallbackFillState = cbFillState; Inputs = new HashSet(); Outputs = new HashSet(); } @@ -45,7 +46,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { }; _text = new() { Text = Label, - FontSize = 12, + FontSize = 14, Width = WIDTH, TextAlignment = TextAlignment.Center, VerticalAlignment = VerticalAlignment.Center, @@ -55,7 +56,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { _inner.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2 + 2); _inner.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 2); _text.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2); - _text.SetValue(Canvas.TopProperty, CenterY - 8); + _text.SetValue(Canvas.TopProperty, CenterY - 10); canvas.Children.Add(_outer); canvas.Children.Add(_inner); canvas.Children.Add(_text); @@ -66,7 +67,11 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { } public void Update(bool isHovering, bool isPressed) { - _inner?.Fill = isHovering ? Brushes.LightGray : Brushes.WhiteSmoke; + _inner?.Fill = PamhagenBrushes.ForFillState(FillState, + isHovering && isPressed ? Brushes.DarkGray : + isHovering ? Brushes.LightGray : + Brushes.WhiteSmoke + ); } } } diff --git a/PamhagenSysCtrl/Helpers/Pipeline/Valve.cs b/PamhagenSysCtrl/Helpers/Pipeline/Valve.cs index 2c44812..40c44ee 100644 --- a/PamhagenSysCtrl/Helpers/Pipeline/Valve.cs +++ b/PamhagenSysCtrl/Helpers/Pipeline/Valve.cs @@ -66,10 +66,10 @@ namespace PamhagenSysCtrl.Helpers.Pipeline { public void Update(bool isHovering, bool isPressed) { _circle?.Fill = - IsLocked && !WantOpen && !IsOpen ? Brushes.Orange : - IsLocked && !WantOpen && IsOpen ? Brushes.Red : - IsLocked && WantOpen && !IsOpen ? Brushes.Yellow : - IsLocked && WantOpen && IsOpen ? Brushes.Green : + IsLocked && !WantOpen && !IsOpen ? PamhagenBrushes.DimOrange : + IsLocked && !WantOpen && IsOpen ? PamhagenBrushes.Red : + IsLocked && WantOpen && !IsOpen ? PamhagenBrushes.Yellow : + IsLocked && WantOpen && IsOpen ? PamhagenBrushes.Green : Highlight ?? (isHovering ? Brushes.LightGray : Brushes.DarkGray); } } diff --git a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml index 23ecc20..32f432c 100644 --- a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml +++ b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml @@ -5,8 +5,9 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:PamhagenSysCtrl.Windows" Title="Schema - Anlagensteuerung Pamhagen" Height="800" Width="1600" MinWidth="1500" MinHeight="800"> - - + + diff --git a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs index cc008dc..c5163b0 100644 --- a/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs +++ b/PamhagenSysCtrl/Windows/PlantSchemeWindow.xaml.cs @@ -47,14 +47,14 @@ namespace PamhagenSysCtrl.Windows { Graph.AddPath(path); _lastSource = null; } - } else if (c is ISource source) { - _lastSource = source; - _path = []; } else if (_lastSource != null) { var path = Graph.GetPath([_lastSource, .. _path, c], (n) => n is not ISink && (n is not Valve v || !v.IsLocked)); if (path != null) { _path.Add(c); } + } else if (c is ISource source) { + _lastSource = source; + _path = []; } else { _lastSource = null; } @@ -67,7 +67,7 @@ namespace PamhagenSysCtrl.Windows { e.Highlight = null; } foreach (var p in Graph.SelectedPaths) { - Graph.ColorPipesAdjacientToPath(p, Brushes.Green, Brushes.Orange); + Graph.ColorPipesAdjacientToPath(p, PamhagenBrushes.Green, PamhagenBrushes.DimOrange); } var hover = Graph.GetHover(pos.X, pos.Y); if (_lastSource != null && (hover.Count > 0 || _path.Count > 0)) { @@ -78,16 +78,16 @@ namespace PamhagenSysCtrl.Windows { if (points.Count >= 2) { var res = Graph.GetPath(points, (n) => n is not ISink && (n is not Valve v || !v.IsLocked)); if (res is Path path) { - Graph.ColorPipesAdjacientToPath(path, Brushes.Green, Brushes.Orange); + Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Green, PamhagenBrushes.DimOrange); } } } else if (_lastSource == null && hover.Count > 0 && Graph.SelectedPaths.Any(p => p.Start == hover.First())) { var path = Graph.SelectedPaths.First(p => p.Start == hover.First()); - Graph.ColorPipesAdjacientToPath(path, Brushes.Red, null); + Graph.ColorPipesAdjacientToPath(path, PamhagenBrushes.Red, null); } if (_lastSource != null) { foreach (var edge in _lastSource.Outputs) { - edge.Highlight = Brushes.Green; + edge.Highlight = PamhagenBrushes.Green; } } Graph.Update(hover, down);