Add switcher

This commit is contained in:
2026-08-04 23:56:32 +02:00
parent ec07d91631
commit d9c1b79563
7 changed files with 143 additions and 36 deletions
@@ -2,13 +2,12 @@
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
namespace PamhagenSysCtrl.Helpers.Pipeline {
public class ConveyorBelt : INode {
public const double WIDTH = 35;
public const double WIDTH = 30;
public const double HEIGHT = 120;
public double CenterX { get; set; }
@@ -58,7 +57,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
_rect.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2);
_rect.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 2);
var d = 20;
var d = 15;
int n = (int)(HEIGHT / d) + 2;
_polyline = new Polyline() {
Points = [.. Enumerable.Range(0, n).SelectMany(i => new List<Point>() {
@@ -81,12 +80,12 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
Storyboard.SetTarget(slideUp, _polyline);
Storyboard.SetTargetProperty(slideUp, new PropertyPath(Canvas.TopProperty));
var clipCanvas = new Canvas() {
Width = WIDTH - 20,
Height = HEIGHT - 2,
Width = WIDTH - 15,
Height = HEIGHT - 8,
ClipToBounds = true,
};
clipCanvas.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 2 + 2);
clipCanvas.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2 + 10);
clipCanvas.SetValue(Canvas.TopProperty, CenterY - HEIGHT / 2 + 4);
clipCanvas.SetValue(Canvas.LeftProperty, CenterX - WIDTH / 2 + 7.5);
clipCanvas.Children.Add(_polyline);
canvas.Children.Add(_rect);
@@ -16,6 +16,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
public ISet<IEdge> Inputs { get; init; }
public ISet<IEdge> Outputs { get; init; }
public bool IsClickable { get; private set; }
public bool IsActive => CallbackActive();
public bool IsAnimationActive {
get => _animationActive;
@@ -33,12 +34,13 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
private Auger? _auger;
private TextBlock? _text;
public EncasedAuger(string label, double x, double y, Func<bool> cbActive, double angle = 0) {
public EncasedAuger(string label, double x, double y, Func<bool> cbActive, double angle = 0, bool clickable = true) {
CenterX = x;
CenterY = y;
Label = label;
Angle = angle;
CallbackActive = cbActive;
IsClickable = clickable;
Inputs = new HashSet<IEdge>();
Outputs = new HashSet<IEdge>();
}
@@ -84,6 +86,7 @@ namespace PamhagenSysCtrl.Helpers.Pipeline {
}
public void Update(bool isHovering, bool isPressed) {
isHovering = isHovering && IsClickable;
IsAnimationActive = IsActive;
_inner?.Fill =
IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Red :
@@ -0,0 +1,87 @@
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace PamhagenSysCtrl.Helpers.Pipeline {
public class Switcher : INode {
public const double WIDTH = 100;
public const double HEIGHT = 50;
public double CenterX { get; set; }
public double CenterY { get; set; }
public string Label { get; set; }
public ISet<IEdge> Inputs { get; init; }
public ISet<IEdge> Outputs { get; init; }
private Line? _main;
private Line? _shadow;
private RotateTransform? _mainTransform;
private RotateTransform? _shadowTransform;
protected Func<int> CallbackIsPosition;
protected Func<int> CallbackWantPosition;
public Switcher(string label, double x, double y, Func<int> cbIsPosition, Func<int> cbWantPosition) {
CenterX = x;
CenterY = y;
Label = label;
CallbackIsPosition = cbIsPosition;
CallbackWantPosition = cbWantPosition;
Inputs = new HashSet<IEdge>();
Outputs = new HashSet<IEdge>();
}
public void Draw(Canvas canvas) {
_mainTransform = new RotateTransform(0, CenterX, CenterY);
_shadowTransform = new RotateTransform(0, CenterX, CenterY);
_main = new Line() {
X1 = CenterX - WIDTH / 2, Y1 = CenterY,
X2 = CenterX + WIDTH / 2, Y2 = CenterY,
StrokeThickness = 5,
Stroke = Brushes.Black,
StrokeStartLineCap = PenLineCap.Square,
StrokeEndLineCap = PenLineCap.Square,
RenderTransform = _mainTransform,
};
_shadow = new Line() {
X1 = CenterX - WIDTH / 2, Y1 = CenterY,
X2 = CenterX + WIDTH / 2, Y2 = CenterY,
StrokeThickness = 5,
Stroke = Brushes.DarkGray,
StrokeStartLineCap = PenLineCap.Square,
StrokeEndLineCap = PenLineCap.Square,
RenderTransform = _shadowTransform,
};
canvas.Children.Add(_shadow);
canvas.Children.Add(_main);
}
public bool IsInside(double x, double y) {
return Math.Abs(x - CenterX) <= WIDTH / 2 && Math.Abs(y - CenterY) <= HEIGHT / 2;
}
public void Update(bool isHovering, bool isPressed) {
var isPos = CallbackIsPosition();
var wantPos = CallbackWantPosition();
if (isHovering && wantPos == isPos) wantPos = wantPos == 1 ? 2 : 1;
var target1 = isPos == 0 ? 0 : isPos == 1 ? 15 : -15;
var target2 = wantPos == 0 ? 0 : wantPos == 1 ? 15 : -15;
_mainTransform?.BeginAnimation(
RotateTransform.AngleProperty,
new DoubleAnimation {
From = _mainTransform.Angle,
To = target1,
Duration = TimeSpan.FromSeconds(Math.Abs(_mainTransform.Angle - target1) / 120.0)
});
_shadowTransform?.BeginAnimation(
RotateTransform.AngleProperty,
new DoubleAnimation {
From = _shadowTransform.Angle,
To = target2,
Duration = TimeSpan.FromSeconds(Math.Abs(_shadowTransform.Angle - target2) / 120.0)
});
}
}
}