using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace PamhagenSysCtrl.Helpers.Pipeline { public class ConveyorBelt : INode { public const double WIDTH = 6; public const double HEIGHT = 24; public double CenterX { get; set; } public double CenterY { get; set; } public string Label { get; set; } public ISet Inputs { get; init; } public ISet Outputs { get; init; } public bool IsActive => CallbackActive(); public bool IsAnimationActive { get => !(_storyboard?.GetIsPaused() ?? true); set { if (_storyboard == null) return; if (value && _storyboard.GetIsPaused()) { _storyboard.Resume(); } else if (!value && !_storyboard.GetIsPaused()) { _storyboard.Pause(); } } } protected Func CallbackActive; private Rectangle? _rect; private Polyline? _polyline; private DoubleAnimation? _slideUp; private Canvas? _clipCanvas; private Storyboard? _storyboard; public ConveyorBelt(string label, double x, double y, Func cbActive) { CenterX = x; CenterY = y; Label = label; CallbackActive = cbActive; Inputs = new HashSet(); Outputs = new HashSet(); } public void Draw(Canvas canvas) { _rect = new Rectangle() { Stroke = Brushes.Black, Fill = Brushes.WhiteSmoke, StrokeLineJoin = PenLineJoin.Round, }; _polyline = new Polyline() { Fill = Brushes.Transparent, Stroke = Brushes.Black, StrokeThickness = 2, }; _polyline.SetValue(Canvas.TopProperty, 0.0); _slideUp = new DoubleAnimation { From = 0, Duration = new Duration(TimeSpan.FromSeconds(1)), RepeatBehavior = RepeatBehavior.Forever, }; _storyboard = new Storyboard(); _storyboard.Children.Add(_slideUp); Storyboard.SetTarget(_slideUp, _polyline); Storyboard.SetTargetProperty(_slideUp, new PropertyPath(Canvas.TopProperty)); _clipCanvas = new Canvas() { ClipToBounds = true, }; _clipCanvas.Children.Add(_polyline); canvas.Children.Add(_rect); canvas.Children.Add(_clipCanvas); _storyboard.Begin(); _storyboard.Pause(); } public void Scale(double scale) { var border = Graph.ToBorder(scale); _rect?.Width = WIDTH * scale; _rect?.Height = HEIGHT * scale; _rect?.StrokeThickness = border; _rect?.SetValue(Canvas.LeftProperty, (CenterX - WIDTH / 2) * scale); _rect?.SetValue(Canvas.TopProperty, (CenterY - HEIGHT / 2) * scale); var d = 3 * scale; int n = (int)(HEIGHT * scale / d) + 2; _polyline?.Points = [.. Enumerable.Range(0, n).SelectMany(i => new List() { new(-WIDTH * scale, i * d), new(WIDTH * scale, i * d), new(-WIDTH * scale, i * d) })]; _polyline?.StrokeThickness = border; _slideUp?.To = -d; _clipCanvas?.Width = (WIDTH - 2.2) * scale - border * 2; _clipCanvas?.Height = (HEIGHT - 0.8) * scale - border * 2; _clipCanvas?.SetValue(Canvas.LeftProperty, (CenterX - WIDTH / 2 + 1.1) * scale + border); _clipCanvas?.SetValue(Canvas.TopProperty, (CenterY - HEIGHT / 2 + 0.4) * scale + border); } 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) { IsAnimationActive = IsActive; _rect?.Fill = IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Red : IsAnimationActive && isHovering ? PamhagenBrushes.Red : !IsAnimationActive && isHovering && isPressed ? PamhagenBrushes.Green : !IsAnimationActive && isHovering ? PamhagenBrushes.Green : IsAnimationActive ? PamhagenBrushes.Green : Brushes.WhiteSmoke; } } }