using Avalonia; using Avalonia.Controls.Primitives; using Avalonia.Input; using Avalonia.Media; using Serein.Library; using Serein.Library.Api; using Serein.Workbench.Avalonia.Api; using Serein.Workbench.Avalonia.Extension; using System; using System.Diagnostics; using Color = Avalonia.Media.Color; using Point = Avalonia.Point; namespace Serein.Workbench.Avalonia.Custom.Views; /// /// 连接控制点 /// public class NodeJunctionView : TemplatedControl { public static readonly DirectProperty JunctionTypeProperty = AvaloniaProperty.RegisterDirect(nameof(JunctionType), o => o.JunctionType, (o, v) => o.JunctionType = v); private JunctionType junctionType; public JunctionType JunctionType { get { return junctionType; } set { SetAndRaise(JunctionTypeProperty, ref junctionType, value); } } public static readonly DirectProperty MyNodeProperty = AvaloniaProperty.RegisterDirect(nameof(MyNode), o => o.MyNode, (o, v) => o.MyNode = v); private NodeModelBase? myNode; public NodeModelBase? MyNode { get { return myNode; } set { SetAndRaise(MyNodeProperty, ref myNode, value); } } public static readonly DirectProperty ArgIndexProperty = AvaloniaProperty.RegisterDirect(nameof(ArgIndex), o => o.ArgIndex, (o, v) => o.ArgIndex = v); private int argIndex; public int ArgIndex { get { return argIndex; } set { SetAndRaise(ArgIndexProperty, ref argIndex, value); } } private readonly INodeOperationService nodeOperationService; private readonly IFlowEnvironment flowEnvironment; /// /// Render方法中控制自绘内容 /// protected readonly StreamGeometry StreamGeometry = new StreamGeometry(); #region 处理鼠标事件 public NodeJunctionView() { nodeOperationService = App.GetService(); flowEnvironment = App.GetService(); //this.PointerExited += NodeJunctionView_PointerExited; this.PointerMoved += NodeJunctionView_PointerMoved; this.PointerPressed += NodeJunctionView_PointerPressed; this.PointerReleased += NodeJunctionView_PointerReleased; } public bool IsPreviewing { get; set; } private Guid Guid = Guid.NewGuid(); private void NodeJunctionView_PointerMoved(object? sender, PointerEventArgs e) { if (!nodeOperationService.ConnectingManage.IsCreateing) return; if (nodeOperationService.MainCanvas is not InputElement inputElement) return; var currentPoint = e.GetPosition(nodeOperationService.MainCanvas); if (inputElement.InputHitTest(currentPoint) is NodeJunctionView junctionView) { RefreshDisplay(junctionView); } else { var oldNj = nodeOperationService.ConnectingManage.CurrentJunction; if (oldNj is not null) { oldNj.IsPreviewing = false; oldNj.InvalidateVisual(); } } } private void RefreshDisplay(NodeJunctionView junctionView) { var oldNj = nodeOperationService.ConnectingManage.CurrentJunction; if (oldNj is not null ) { if (junctionView.Equals(oldNj)) { return; } oldNj.IsPreviewing = false; oldNj.InvalidateVisual(); } nodeOperationService.ConnectingManage.CurrentJunction = junctionView; if (!this.Equals(junctionView) && nodeOperationService.ConnectingManage.IsCanConnected()) { Debug.WriteLine("ok"); nodeOperationService.ConnectingManage.TempLine?.ToEnd(junctionView); } junctionView.IsPreviewing = true; junctionView.InvalidateVisual(); } /// /// 尝试开始创建连接线 /// /// /// private void NodeJunctionView_PointerPressed(object? sender, PointerPressedEventArgs e) { nodeOperationService.TryCreateConnectionOnJunction(this); // 尝试开始创建 } private void NodeJunctionView_PointerReleased(object? sender, PointerReleasedEventArgs e) { CheckJunvtion(); nodeOperationService.ConnectingManage.Reset(); } private void CheckJunvtion() { var myData = nodeOperationService.ConnectingManage; if(myData.StartJunction is null || myData.CurrentJunction is null) { return; } if(myData.StartJunction.MyNode is null || myData.CurrentJunction.MyNode is null) { return; } if (!myData.IsCanConnected()) { return; } var canvas = nodeOperationService.MainCanvas; #region 方法调用关系创建 if (myData.Type == JunctionOfConnectionType.Invoke) { flowEnvironment.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid, myData.StartJunction.JunctionType, myData.CurrentJunction.JunctionType, myData.ConnectionInvokeType); } #endregion #region 参数来源关系创建 else if (myData.Type == JunctionOfConnectionType.Arg) { var argIndex = 0; if (myData.StartJunction.JunctionType == JunctionType.ArgData) { argIndex = myData.StartJunction.ArgIndex; } else if (myData.CurrentJunction.JunctionType == JunctionType.ArgData) { argIndex = myData.CurrentJunction.ArgIndex; } flowEnvironment.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid, myData.StartJunction.JunctionType, myData.CurrentJunction.JunctionType, myData.ConnectionArgSourceType, argIndex); } #endregion } #endregion #region 重绘UI视觉 /// /// 控件重绘事件 /// /// public override void Render(DrawingContext drawingContext) { double width = 44; double height = 26; var background = GetBackgrounp(); var pen = new Pen(Brushes.Transparent, 1); //var pen = nodeOperationService.ConnectingData.IsCreateing ? new Pen(background, 1) : new Pen(Brushes.Black, 1); // 输入连接器的背景 var connectorRect = new Rect(0, 0, width, height); drawingContext.DrawRectangle(Brushes.Transparent, new Pen(), connectorRect); double circleCenterX = width / 2 ; // 中心 X 坐标 double circleCenterY = height / 2 ; // 中心 Y 坐标 //_myCenterPoint = new Point(circleCenterX - Width / 2, circleCenterY); // 中心坐标 // 定义圆形的大小和位置 var diameterCircle = width - 20; Rect rect = new(4, 2, diameterCircle / 2, diameterCircle / 2); var ellipse = new EllipseGeometry(rect); drawingContext.DrawGeometry(background, pen, ellipse); // 定义三角形的间距 double triangleCenterX = width / 2 - 2; // 三角形中心 X 坐标 double triangleCenterY = height / 2 -5; // 三角形中心 Y 坐标 // 绘制三角形 var pathGeometry = new StreamGeometry(); using (var context = pathGeometry.Open()) { int t = 6; context.BeginFigure(new Point(triangleCenterX, triangleCenterY - t), true); context.LineTo(new Point(triangleCenterX + 8, triangleCenterY), true); context.LineTo(new Point(triangleCenterX, triangleCenterY + t), true); context.LineTo(new Point(triangleCenterX, triangleCenterY - t), true); } drawingContext.DrawGeometry(background, pen, pathGeometry); } /// /// 获取背景颜色 /// /// protected IBrush GetBackgrounp() { var myData = nodeOperationService.ConnectingManage; if (IsPreviewing == false || !myData.IsCreateing ) { return new SolidColorBrush(Color.Parse("#76ABEE")); } if (!myData.IsCanConnected()) { return new SolidColorBrush(Color.Parse("#FF0000")); } if (myData.Type == JunctionOfConnectionType.Invoke) { return myData.ConnectionInvokeType.ToLineColor(); // 调用 } else { return myData.ConnectionArgSourceType.ToLineColor(); // 参数 } } #endregion }