2025-01-01 17:49:48 +08:00
|
|
|
|
using Avalonia;
|
|
|
|
|
|
using Avalonia.Controls.Primitives;
|
|
|
|
|
|
using Avalonia.Input;
|
|
|
|
|
|
using Avalonia.Media;
|
|
|
|
|
|
using Serein.Library;
|
2025-01-04 22:25:42 +08:00
|
|
|
|
using Serein.Library.Api;
|
|
|
|
|
|
using Serein.Workbench.Avalonia.Api;
|
|
|
|
|
|
using Serein.Workbench.Avalonia.Extension;
|
2025-01-01 17:49:48 +08:00
|
|
|
|
using System;
|
2025-01-22 21:09:52 +08:00
|
|
|
|
using System.Diagnostics;
|
2025-01-01 17:49:48 +08:00
|
|
|
|
using Color = Avalonia.Media.Color;
|
|
|
|
|
|
using Point = Avalonia.Point;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Serein.Workbench.Avalonia.Custom.Views;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// <20><><EFBFBD>ӿ<EFBFBD><D3BF>Ƶ<EFBFBD>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class NodeJunctionView : TemplatedControl
|
|
|
|
|
|
{
|
2025-01-04 22:25:42 +08:00
|
|
|
|
|
|
|
|
|
|
public static readonly DirectProperty<NodeJunctionView, JunctionType> JunctionTypeProperty =
|
|
|
|
|
|
AvaloniaProperty.RegisterDirect<NodeJunctionView, JunctionType>(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<NodeJunctionView, NodeModelBase?> MyNodeProperty =
|
|
|
|
|
|
AvaloniaProperty.RegisterDirect<NodeJunctionView, NodeModelBase?>(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<NodeJunctionView, int> ArgIndexProperty =
|
|
|
|
|
|
AvaloniaProperty.RegisterDirect<NodeJunctionView, int>(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); }
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-01 17:49:48 +08:00
|
|
|
|
private readonly INodeOperationService nodeOperationService;
|
2025-01-04 22:25:42 +08:00
|
|
|
|
private readonly IFlowEnvironment flowEnvironment;
|
2025-01-01 17:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Render<65><72><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF><EFBFBD><EFBFBD>Ի<EFBFBD><D4BB><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
protected readonly StreamGeometry StreamGeometry = new StreamGeometry();
|
|
|
|
|
|
|
2025-01-04 22:25:42 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>
|
|
|
|
|
|
|
2025-01-01 17:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
public NodeJunctionView()
|
|
|
|
|
|
{
|
|
|
|
|
|
nodeOperationService = App.GetService<INodeOperationService>();
|
2025-01-04 22:25:42 +08:00
|
|
|
|
flowEnvironment = App.GetService<IFlowEnvironment>();
|
|
|
|
|
|
//this.PointerExited += NodeJunctionView_PointerExited;
|
|
|
|
|
|
this.PointerMoved += NodeJunctionView_PointerMoved;
|
2025-01-01 17:49:48 +08:00
|
|
|
|
this.PointerPressed += NodeJunctionView_PointerPressed;
|
|
|
|
|
|
this.PointerReleased += NodeJunctionView_PointerReleased;
|
|
|
|
|
|
}
|
2025-01-04 22:25:42 +08:00
|
|
|
|
|
2025-01-01 17:49:48 +08:00
|
|
|
|
|
2025-01-04 22:25:42 +08:00
|
|
|
|
public bool IsPreviewing { get; set; }
|
|
|
|
|
|
private Guid Guid = Guid.NewGuid();
|
|
|
|
|
|
|
|
|
|
|
|
private void NodeJunctionView_PointerMoved(object? sender, PointerEventArgs e)
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-22 21:09:52 +08:00
|
|
|
|
if (!nodeOperationService.ConnectingManage.IsCreateing)
|
2025-01-04 22:25:42 +08:00
|
|
|
|
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
|
|
|
|
|
|
{
|
2025-01-22 21:09:52 +08:00
|
|
|
|
var oldNj = nodeOperationService.ConnectingManage.CurrentJunction;
|
2025-01-04 22:25:42 +08:00
|
|
|
|
if (oldNj is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
oldNj.IsPreviewing = false;
|
|
|
|
|
|
oldNj.InvalidateVisual();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-04 22:25:42 +08:00
|
|
|
|
private void RefreshDisplay(NodeJunctionView junctionView)
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-22 21:09:52 +08:00
|
|
|
|
var oldNj = nodeOperationService.ConnectingManage.CurrentJunction;
|
2025-01-04 22:25:42 +08:00
|
|
|
|
if (oldNj is not null )
|
|
|
|
|
|
{
|
|
|
|
|
|
if (junctionView.Equals(oldNj))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
oldNj.IsPreviewing = false;
|
|
|
|
|
|
oldNj.InvalidateVisual();
|
|
|
|
|
|
}
|
2025-01-22 21:09:52 +08:00
|
|
|
|
nodeOperationService.ConnectingManage.CurrentJunction = junctionView;
|
|
|
|
|
|
if (!this.Equals(junctionView) && nodeOperationService.ConnectingManage.IsCanConnected())
|
2025-01-04 22:25:42 +08:00
|
|
|
|
{
|
2025-01-22 21:09:52 +08:00
|
|
|
|
Debug.WriteLine("ok");
|
|
|
|
|
|
nodeOperationService.ConnectingManage.TempLine?.ToEnd(junctionView);
|
2025-01-04 22:25:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
junctionView.IsPreviewing = true;
|
|
|
|
|
|
junctionView.InvalidateVisual();
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2025-01-04 22:25:42 +08:00
|
|
|
|
/// <20><><EFBFBD>Կ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2025-01-01 17:49:48 +08:00
|
|
|
|
/// </summary>
|
2025-01-04 22:25:42 +08:00
|
|
|
|
/// <param name="sender"></param>
|
2025-01-01 17:49:48 +08:00
|
|
|
|
/// <param name="e"></param>
|
2025-01-04 22:25:42 +08:00
|
|
|
|
private void NodeJunctionView_PointerPressed(object? sender, PointerPressedEventArgs e)
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-04 22:25:42 +08:00
|
|
|
|
nodeOperationService.TryCreateConnectionOnJunction(this); // <20><><EFBFBD>Կ<EFBFBD>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD>
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
2025-01-04 22:25:42 +08:00
|
|
|
|
private void NodeJunctionView_PointerReleased(object? sender, PointerReleasedEventArgs e)
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-04 22:25:42 +08:00
|
|
|
|
CheckJunvtion();
|
2025-01-22 21:09:52 +08:00
|
|
|
|
nodeOperationService.ConnectingManage.Reset();
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-21 18:26:01 +08:00
|
|
|
|
private async void CheckJunvtion()
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-22 21:09:52 +08:00
|
|
|
|
var myData = nodeOperationService.ConnectingManage;
|
2025-01-04 22:25:42 +08:00
|
|
|
|
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 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ù<EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
if (myData.Type == JunctionOfConnectionType.Invoke)
|
|
|
|
|
|
{
|
2025-03-21 18:26:01 +08:00
|
|
|
|
await flowEnvironment.ConnectInvokeNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
|
2025-01-04 22:25:42 +08:00
|
|
|
|
myData.StartJunction.JunctionType,
|
|
|
|
|
|
myData.CurrentJunction.JunctionType,
|
|
|
|
|
|
myData.ConnectionInvokeType);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-21 18:26:01 +08:00
|
|
|
|
await flowEnvironment.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
|
2025-01-04 22:25:42 +08:00
|
|
|
|
myData.StartJunction.JunctionType,
|
|
|
|
|
|
myData.CurrentJunction.JunctionType,
|
|
|
|
|
|
myData.ConnectionArgSourceType,
|
|
|
|
|
|
argIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-04 22:25:42 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-01-01 17:49:48 +08:00
|
|
|
|
#region <EFBFBD>ػ<EFBFBD>UI<EFBFBD>Ӿ<EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// <20>ؼ<EFBFBD><D8BC>ػ<EFBFBD><D8BB>¼<EFBFBD>
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="drawingContext"></param>
|
|
|
|
|
|
|
|
|
|
|
|
public override void Render(DrawingContext drawingContext)
|
|
|
|
|
|
{
|
|
|
|
|
|
double width = 44;
|
|
|
|
|
|
double height = 26;
|
|
|
|
|
|
var background = GetBackgrounp();
|
2025-01-04 22:25:42 +08:00
|
|
|
|
var pen = new Pen(Brushes.Transparent, 1);
|
|
|
|
|
|
//var pen = nodeOperationService.ConnectingData.IsCreateing ? new Pen(background, 1) : new Pen(Brushes.Black, 1);
|
2025-01-01 17:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ı<EFBFBD><C4B1><EFBFBD>
|
|
|
|
|
|
var connectorRect = new Rect(0, 0, width, height);
|
|
|
|
|
|
drawingContext.DrawRectangle(Brushes.Transparent, new Pen(), connectorRect);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double circleCenterX = width / 2 ; // <20><><EFBFBD><EFBFBD> X <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
double circleCenterY = height / 2 ; // <20><><EFBFBD><EFBFBD> Y <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
//_myCenterPoint = new Point(circleCenterX - Width / 2, circleCenterY); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>Բ<EFBFBD>εĴ<CEB5>С<EFBFBD><D0A1>λ<EFBFBD><CEBB>
|
|
|
|
|
|
var diameterCircle = width - 20;
|
|
|
|
|
|
Rect rect = new(4, 2, diameterCircle / 2, diameterCircle / 2);
|
|
|
|
|
|
var ellipse = new EllipseGeometry(rect);
|
|
|
|
|
|
drawingContext.DrawGeometry(background, pen, ellipse);
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>εļ<CEB5><C4BC><EFBFBD>
|
|
|
|
|
|
double triangleCenterX = width / 2 - 2; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> X <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
double triangleCenterY = height / 2 -5; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Y <20><><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2025-01-04 22:25:42 +08:00
|
|
|
|
drawingContext.DrawGeometry(background, pen, pathGeometry);
|
2025-01-01 17:49:48 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɫ
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
protected IBrush GetBackgrounp()
|
|
|
|
|
|
{
|
2025-01-22 21:09:52 +08:00
|
|
|
|
var myData = nodeOperationService.ConnectingManage;
|
2025-01-04 22:25:42 +08:00
|
|
|
|
if (IsPreviewing == false || !myData.IsCreateing )
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
|
|
|
|
|
return new SolidColorBrush(Color.Parse("#76ABEE"));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-04 22:25:42 +08:00
|
|
|
|
if (!myData.IsCanConnected())
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-04 22:25:42 +08:00
|
|
|
|
return new SolidColorBrush(Color.Parse("#FF0000"));
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-01-04 22:25:42 +08:00
|
|
|
|
if (myData.Type == JunctionOfConnectionType.Invoke)
|
2025-01-01 17:49:48 +08:00
|
|
|
|
{
|
2025-01-04 22:25:42 +08:00
|
|
|
|
return myData.ConnectionInvokeType.ToLineColor(); // <20><><EFBFBD><EFBFBD>
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-01-04 22:25:42 +08:00
|
|
|
|
return myData.ConnectionArgSourceType.ToLineColor(); // <20><><EFBFBD><EFBFBD>
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
2025-01-04 22:25:42 +08:00
|
|
|
|
|
2025-01-01 17:49:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|