2024-08-06 16:09:46 +08:00
|
|
|
|
using Microsoft.Win32;
|
|
|
|
|
|
using Newtonsoft.Json.Linq;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
using Serein.Library;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
using Serein.Library.Api;
|
2024-09-12 20:32:54 +08:00
|
|
|
|
using Serein.Library.Utils;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
using Serein.Library.Utils.SereinExpression;
|
2024-09-27 23:47:25 +08:00
|
|
|
|
using Serein.NodeFlow.Tool;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
using Serein.Workbench.Extension;
|
2024-10-24 23:32:43 +08:00
|
|
|
|
using Serein.Workbench.Node;
|
2024-10-15 21:56:09 +08:00
|
|
|
|
using Serein.Workbench.Node.View;
|
|
|
|
|
|
using Serein.Workbench.Node.ViewModel;
|
|
|
|
|
|
using Serein.Workbench.Themes;
|
2024-10-24 23:32:43 +08:00
|
|
|
|
using System;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
using System.IO;
|
2024-11-02 16:48:40 +08:00
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
using System.Runtime.InteropServices;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Controls;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
using System.Windows.Controls.Primitives;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
using System.Windows.Input;
|
|
|
|
|
|
using System.Windows.Media;
|
|
|
|
|
|
using System.Windows.Media.Animation;
|
|
|
|
|
|
using System.Windows.Shapes;
|
2024-09-07 15:56:34 +08:00
|
|
|
|
using DataObject = System.Windows.DataObject;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
2024-10-15 21:56:09 +08:00
|
|
|
|
namespace Serein.Workbench
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-06 09:13:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 拖拽创建节点类型
|
|
|
|
|
|
/// </summary>
|
2024-08-05 10:11:58 +08:00
|
|
|
|
public static class MouseNodeType
|
|
|
|
|
|
{
|
2024-10-15 21:56:09 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建来自DLL的节点
|
|
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
public static string CreateDllNodeInCanvas { get; } = nameof(CreateDllNodeInCanvas);
|
2024-10-15 21:56:09 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建基础节点
|
|
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
public static string CreateBaseNodeInCanvas { get; } = nameof(CreateBaseNodeInCanvas);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Interaction logic for MainWindow.xaml,第一次用git,不太懂
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public partial class MainWindow : Window
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 全局捕获Console输出事件,打印在这个窗体里面
|
|
|
|
|
|
/// </summary>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private readonly LogWindow LogOutWindow = new LogWindow();
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// 流程接口
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private IFlowEnvironment EnvDecorator { get; }
|
2024-09-16 21:38:34 +08:00
|
|
|
|
private MainWindowViewModel ViewModel { get; set; }
|
2024-09-09 16:42:01 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 存储所有与节点有关的控件
|
2024-09-22 14:10:13 +08:00
|
|
|
|
/// 任何情景下都尽量避免直接操作 ViewModel 中的 NodeModel 节点,
|
|
|
|
|
|
/// 而是应该调用 FlowEnvironment 提供接口进行操作,
|
|
|
|
|
|
/// 因为 Workbench 应该更加关注UI视觉效果,而非直接干扰流程环境运行的逻辑。
|
|
|
|
|
|
/// 之所以暴露 NodeModel 属性,因为有些场景下不可避免的需要直接获取节点的属性。
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-16 21:38:34 +08:00
|
|
|
|
private Dictionary<string, NodeControlBase> NodeControls { get; } = [];
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-22 14:10:13 +08:00
|
|
|
|
/// 存储所有的连接。考虑集成在运行环境中。
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-10-23 19:22:27 +08:00
|
|
|
|
private List<ConnectionControl> Connections { get; } = [];
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 起始节点
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
//private NodeControlBase StartNodeControl{ get; set; }
|
|
|
|
|
|
|
2024-09-12 20:32:54 +08:00
|
|
|
|
#region 与画布相关的字段
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
2024-09-12 20:32:54 +08:00
|
|
|
|
/// <summary>
|
2024-09-18 16:45:41 +08:00
|
|
|
|
/// 标记是否正在尝试选取控件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private bool IsSelectControl;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 标记是否正在进行连接操作
|
|
|
|
|
|
/// </summary>
|
2024-10-27 00:54:10 +08:00
|
|
|
|
//private bool IsConnecting;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 标记是否正在拖动控件
|
2024-09-12 20:32:54 +08:00
|
|
|
|
/// </summary>
|
2024-09-18 16:45:41 +08:00
|
|
|
|
private bool IsControlDragging;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 标记是否正在拖动画布
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private bool IsCanvasDragging;
|
2024-09-21 10:06:44 +08:00
|
|
|
|
private bool IsSelectDragging;
|
2024-09-12 20:32:54 +08:00
|
|
|
|
|
2024-09-16 21:38:34 +08:00
|
|
|
|
/// <summary>
|
2024-09-18 16:45:41 +08:00
|
|
|
|
/// 当前选取的控件
|
2024-09-16 21:38:34 +08:00
|
|
|
|
/// </summary>
|
2024-09-18 16:45:41 +08:00
|
|
|
|
private readonly List<NodeControlBase> selectNodeControls = [];
|
2024-09-16 21:38:34 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-20 10:50:32 +08:00
|
|
|
|
/// 记录开始拖动节点控件时的鼠标位置
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-20 10:50:32 +08:00
|
|
|
|
private Point startControlDragPoint;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 记录移动画布开始时的鼠标位置
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Point startCanvasDragPoint;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 记录开始选取节点控件时的鼠标位置
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private Point startSelectControolPoint;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 记录开始连接的文本块
|
|
|
|
|
|
/// </summary>
|
2024-10-27 00:54:10 +08:00
|
|
|
|
//private NodeControlBase? startConnectNodeControl;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当前正在绘制的连接线
|
|
|
|
|
|
/// </summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
//private Line? currentLine;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当前正在绘制的真假分支属性
|
|
|
|
|
|
/// </summary>
|
2024-10-27 00:54:10 +08:00
|
|
|
|
//private ConnectionInvokeType currentConnectionType;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-09 16:42:01 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 组合变换容器
|
|
|
|
|
|
/// </summary>
|
2024-09-30 22:20:02 +08:00
|
|
|
|
private readonly TransformGroup canvasTransformGroup;
|
2024-09-09 16:42:01 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 缩放画布
|
|
|
|
|
|
/// </summary>
|
2024-09-30 22:20:02 +08:00
|
|
|
|
private readonly ScaleTransform scaleTransform;
|
2024-09-09 16:42:01 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 平移画布
|
|
|
|
|
|
/// </summary>
|
2024-09-30 22:20:02 +08:00
|
|
|
|
private readonly TranslateTransform translateTransform;
|
2024-09-12 20:32:54 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
public MainWindow()
|
|
|
|
|
|
{
|
2024-09-16 21:38:34 +08:00
|
|
|
|
ViewModel = new MainWindowViewModel(this);
|
2024-10-27 00:54:10 +08:00
|
|
|
|
this.DataContext = ViewModel;
|
|
|
|
|
|
InitializeComponent();
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator = ViewModel.FlowEnvironment;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
ViewObjectViewer.FlowEnvironment = EnvDecorator;
|
|
|
|
|
|
IOCObjectViewer.FlowEnvironment = EnvDecorator;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
IOCObjectViewer.SelectObj += ViewObjectViewer.LoadObjectInformation;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
#region 缩放平移容器
|
2024-09-30 22:20:02 +08:00
|
|
|
|
canvasTransformGroup = new TransformGroup();
|
|
|
|
|
|
scaleTransform = new ScaleTransform();
|
|
|
|
|
|
translateTransform = new TranslateTransform();
|
|
|
|
|
|
canvasTransformGroup.Children.Add(scaleTransform);
|
|
|
|
|
|
canvasTransformGroup.Children.Add(translateTransform);
|
|
|
|
|
|
FlowChartCanvas.RenderTransform = canvasTransformGroup;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
#endregion
|
2024-09-30 22:20:02 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
InitFlowEnvironmentEvent(); // 配置环境事件
|
2024-09-30 22:20:02 +08:00
|
|
|
|
|
|
|
|
|
|
if (App.FlowProjectData is not null)
|
2024-09-25 22:20:23 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.LoadProject(new FlowEnvInfo { Project = App.FlowProjectData }, App.FileDataPath); // 加载项目
|
2024-09-25 22:20:23 +08:00
|
|
|
|
}
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 初始化环境事件
|
|
|
|
|
|
/// </summary>
|
2024-09-22 17:37:32 +08:00
|
|
|
|
private void InitFlowEnvironmentEvent()
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.OnDllLoad += FlowEnvironment_DllLoadEvent;
|
|
|
|
|
|
EnvDecorator.OnProjectLoaded += FlowEnvironment_OnProjectLoaded;
|
|
|
|
|
|
EnvDecorator.OnStartNodeChange += FlowEnvironment_StartNodeChangeEvent;
|
|
|
|
|
|
EnvDecorator.OnNodeConnectChange += FlowEnvironment_NodeConnectChangeEvemt;
|
|
|
|
|
|
EnvDecorator.OnNodeCreate += FlowEnvironment_NodeCreateEvent;
|
2024-10-20 21:59:42 +08:00
|
|
|
|
EnvDecorator.OnNodeRemove += FlowEnvironment_NodeRemoteEvent;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.OnFlowRunComplete += FlowEnvironment_OnFlowRunComplete;
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.OnMonitorObjectChange += FlowEnvironment_OnMonitorObjectChange;
|
|
|
|
|
|
EnvDecorator.OnNodeInterruptStateChange += FlowEnvironment_OnNodeInterruptStateChange;
|
|
|
|
|
|
EnvDecorator.OnInterruptTrigger += FlowEnvironment_OnInterruptTrigger;
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.OnIOCMembersChanged += FlowEnvironment_OnIOCMembersChanged;
|
|
|
|
|
|
|
|
|
|
|
|
EnvDecorator.OnNodeLocated += FlowEnvironment_OnNodeLocate;
|
|
|
|
|
|
EnvDecorator.OnNodeMoved += FlowEnvironment_OnNodeMoved;
|
|
|
|
|
|
EnvDecorator.OnEnvOut += FlowEnvironment_OnEnvOut;
|
|
|
|
|
|
this.EnvDecorator.SetConsoleOut(); // 设置输出
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 移除环境事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void ResetFlowEnvironmentEvent()
|
2024-09-24 22:39:43 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.OnDllLoad -= FlowEnvironment_DllLoadEvent;
|
|
|
|
|
|
EnvDecorator.OnProjectLoaded -= FlowEnvironment_OnProjectLoaded;
|
|
|
|
|
|
EnvDecorator.OnStartNodeChange -= FlowEnvironment_StartNodeChangeEvent;
|
|
|
|
|
|
EnvDecorator.OnNodeConnectChange -= FlowEnvironment_NodeConnectChangeEvemt;
|
|
|
|
|
|
EnvDecorator.OnNodeCreate -= FlowEnvironment_NodeCreateEvent;
|
2024-10-20 21:59:42 +08:00
|
|
|
|
EnvDecorator.OnNodeRemove -= FlowEnvironment_NodeRemoteEvent;
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.OnFlowRunComplete -= FlowEnvironment_OnFlowRunComplete;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
EnvDecorator.OnMonitorObjectChange -= FlowEnvironment_OnMonitorObjectChange;
|
|
|
|
|
|
EnvDecorator.OnNodeInterruptStateChange -= FlowEnvironment_OnNodeInterruptStateChange;
|
|
|
|
|
|
EnvDecorator.OnInterruptTrigger -= FlowEnvironment_OnInterruptTrigger;
|
|
|
|
|
|
|
|
|
|
|
|
EnvDecorator.OnIOCMembersChanged -= FlowEnvironment_OnIOCMembersChanged;
|
|
|
|
|
|
EnvDecorator.OnNodeLocated -= FlowEnvironment_OnNodeLocate;
|
|
|
|
|
|
EnvDecorator.OnNodeMoved -= FlowEnvironment_OnNodeMoved;
|
|
|
|
|
|
|
|
|
|
|
|
EnvDecorator.OnEnvOut -= FlowEnvironment_OnEnvOut;
|
|
|
|
|
|
|
2024-09-24 22:39:43 +08:00
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
|
|
|
|
|
#region 窗体加载方法
|
2024-09-17 14:20:27 +08:00
|
|
|
|
private void Window_Loaded(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
LogOutWindow.Close();
|
2024-08-05 10:11:58 +08:00
|
|
|
|
System.Windows.Application.Current.Shutdown();
|
|
|
|
|
|
}
|
2024-09-17 14:20:27 +08:00
|
|
|
|
private void Window_ContentRendered(object sender, EventArgs e)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
Console.WriteLine("load project...");
|
2024-09-24 22:39:43 +08:00
|
|
|
|
var project = App.FlowProjectData;
|
2024-09-25 22:20:23 +08:00
|
|
|
|
if (project is null)
|
2024-09-24 22:39:43 +08:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
InitializeCanvas(project.Basic.Canvas.Width, project.Basic.Canvas.Height);// 设置画布大小
|
2024-11-02 16:48:40 +08:00
|
|
|
|
//foreach (var connection in Connections)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// connection.RefreshLine(); // 窗体完成加载后试图刷新所有连接线
|
|
|
|
|
|
//}
|
|
|
|
|
|
Console.WriteLine($"运行环境当前工作目录:{System.IO.Directory.GetCurrentDirectory()}");
|
|
|
|
|
|
|
2024-09-24 22:39:43 +08:00
|
|
|
|
var canvasData = project.Basic.Canvas;
|
2024-09-30 22:20:02 +08:00
|
|
|
|
if (canvasData is not null)
|
2024-09-20 17:11:31 +08:00
|
|
|
|
{
|
|
|
|
|
|
scaleTransform.ScaleX = 1;
|
|
|
|
|
|
scaleTransform.ScaleY = 1;
|
|
|
|
|
|
translateTransform.X = 0;
|
|
|
|
|
|
translateTransform.Y = 0;
|
|
|
|
|
|
scaleTransform.ScaleX = canvasData.ScaleX;
|
|
|
|
|
|
scaleTransform.ScaleY = canvasData.ScaleY;
|
|
|
|
|
|
translateTransform.X += canvasData.ViewX;
|
|
|
|
|
|
translateTransform.Y += canvasData.ViewY;
|
|
|
|
|
|
// 应用变换组
|
|
|
|
|
|
FlowChartCanvas.RenderTransform = canvasTransformGroup;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-02 16:48:40 +08:00
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}
|
2024-11-02 16:48:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-17 14:20:27 +08:00
|
|
|
|
#endregion
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
#region 运行环境事件
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 环境内容输出
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="value"></param>
|
|
|
|
|
|
private void FlowEnvironment_OnEnvOut(string value)
|
|
|
|
|
|
{
|
|
|
|
|
|
LogOutWindow.AppendText(value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加载完成
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
2024-09-17 14:20:27 +08:00
|
|
|
|
private void FlowEnvironment_OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 运行完成
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
|
private void FlowEnvironment_OnFlowRunComplete(FlowEventArgs eventArgs)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-26 21:00:17 +08:00
|
|
|
|
Console.WriteLine("-------运行完成---------\r\n");
|
2024-10-20 12:10:57 +08:00
|
|
|
|
this.Dispatcher.Invoke(() =>
|
|
|
|
|
|
{
|
|
|
|
|
|
IOCObjectViewer.ClearObjItem();
|
|
|
|
|
|
});
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 加载了DLL文件,dll内容
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-30 02:45:49 +08:00
|
|
|
|
private void FlowEnvironment_DllLoadEvent(LoadDllEventArgs eventArgs)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-11-03 18:28:16 +08:00
|
|
|
|
NodeLibraryInfo nodeLibraryInfo = eventArgs.NodeLibraryInfo;
|
2024-10-20 21:59:42 +08:00
|
|
|
|
List<MethodDetailsInfo> methodDetailss = eventArgs.MethodDetailss;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-11-03 18:28:16 +08:00
|
|
|
|
var dllControl = new DllControl(nodeLibraryInfo);
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
foreach (var methodDetailsInfo in methodDetailss)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!EnumHelper.TryConvertEnum<Library.NodeType>(methodDetailsInfo.NodeType, out var nodeType))
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
switch (nodeType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case Library.NodeType.Action:
|
|
|
|
|
|
dllControl.AddAction(methodDetailsInfo); // 添加动作类型到控件
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Library.NodeType.Flipflop:
|
|
|
|
|
|
dllControl.AddFlipflop(methodDetailsInfo); // 添加触发器方法到控件
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
|
menu.Items.Add(CreateMenuItem("卸载", (s, e) =>
|
|
|
|
|
|
{
|
2024-11-03 23:51:18 +08:00
|
|
|
|
if (this.EnvDecorator.UnloadLibrary(nodeLibraryInfo.AssemblyName))
|
2024-10-20 21:59:42 +08:00
|
|
|
|
{
|
|
|
|
|
|
DllStackPanel.Children.Remove(dllControl);
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
else
|
2024-09-30 02:45:49 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
Console.WriteLine("卸载失败");
|
|
|
|
|
|
}
|
|
|
|
|
|
}));
|
2024-09-30 02:45:49 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
dllControl.ContextMenu = menu;
|
|
|
|
|
|
|
|
|
|
|
|
DllStackPanel.Children.Add(dllControl); // 将控件添加到界面上显示
|
2024-09-30 02:45:49 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 节点连接关系变更
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-10-15 10:55:41 +08:00
|
|
|
|
/// <param name="eventArgs"></param>
|
2024-11-04 23:30:52 +08:00
|
|
|
|
private void FlowEnvironment_NodeConnectChangeEvemt(NodeConnectChangeEventArgs eventArgs)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-26 21:00:17 +08:00
|
|
|
|
string fromNodeGuid = eventArgs.FromNodeGuid;
|
|
|
|
|
|
string toNodeGuid = eventArgs.ToNodeGuid;
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (!TryGetControl(fromNodeGuid, out var fromNodeControl)
|
|
|
|
|
|
|| !TryGetControl(toNodeGuid, out var toNodeControl))
|
2024-09-27 23:47:25 +08:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (eventArgs.JunctionOfConnectionType == JunctionOfConnectionType.Invoke)
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
ConnectionInvokeType connectionType = eventArgs.ConnectionInvokeType;
|
2024-10-28 15:21:08 +08:00
|
|
|
|
#region 创建/删除节点之间的调用关系
|
|
|
|
|
|
#region 创建连接
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接
|
2024-09-26 21:00:17 +08:00
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("非预期的情况");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
JunctionControlBase startJunction = IFormJunction.NextStepJunction;
|
|
|
|
|
|
JunctionControlBase endJunction = IToJunction.ExecuteJunction;
|
|
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
// 添加连接
|
|
|
|
|
|
var connection = new ConnectionControl(
|
2024-10-28 15:21:08 +08:00
|
|
|
|
FlowChartCanvas,
|
2024-10-24 23:32:43 +08:00
|
|
|
|
connectionType,
|
|
|
|
|
|
startJunction,
|
2024-11-04 23:30:52 +08:00
|
|
|
|
endJunction
|
2024-10-24 23:32:43 +08:00
|
|
|
|
);
|
|
|
|
|
|
|
2024-11-04 23:30:52 +08:00
|
|
|
|
//() => EnvDecorator.RemoveConnectInvokeAsync(fromNodeGuid, toNodeGuid, connectionType)
|
|
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (toNodeControl is FlipflopNodeControl flipflopControl
|
|
|
|
|
|
&& flipflopControl?.ViewModel?.NodeModel is NodeModelBase nodeModel) // 某个节点连接到了触发器,尝试从全局触发器视图中移除该触发器
|
|
|
|
|
|
{
|
|
|
|
|
|
NodeTreeViewer.RemoteGlobalFlipFlop(nodeModel); // 从全局触发器树树视图中移除
|
|
|
|
|
|
}
|
2024-11-04 23:30:52 +08:00
|
|
|
|
//connection.RefreshLine(); // 添加贝塞尔曲线显示
|
2024-10-24 23:32:43 +08:00
|
|
|
|
Connections.Add(connection);
|
|
|
|
|
|
fromNodeControl.AddCnnection(connection);
|
|
|
|
|
|
toNodeControl.AddCnnection(connection);
|
2024-10-27 00:54:10 +08:00
|
|
|
|
EndConnection(); // 环境触发了创建节点连接事件
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
2024-10-28 15:21:08 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
#region 移除连接
|
2024-10-24 23:32:43 +08:00
|
|
|
|
else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remote) // 移除连接
|
|
|
|
|
|
{
|
|
|
|
|
|
// 需要移除连接
|
2024-10-28 15:21:08 +08:00
|
|
|
|
var removeConnections = Connections.Where(c =>
|
|
|
|
|
|
c.Start.MyNode.Guid.Equals(fromNodeGuid)
|
|
|
|
|
|
&& c.End.MyNode.Guid.Equals(toNodeGuid)
|
|
|
|
|
|
&& (c.Start.JunctionType.ToConnectyionType() == JunctionOfConnectionType.Invoke
|
|
|
|
|
|
|| c.End.JunctionType.ToConnectyionType() == JunctionOfConnectionType.Invoke))
|
2024-10-24 23:32:43 +08:00
|
|
|
|
.ToList();
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
foreach (var connection in removeConnections)
|
|
|
|
|
|
{
|
|
|
|
|
|
Connections.Remove(connection);
|
2024-11-04 23:30:52 +08:00
|
|
|
|
fromNodeControl.RemoveConnection(connection); // 移除连接
|
|
|
|
|
|
toNodeControl.RemoveConnection(connection); // 移除连接
|
2024-10-28 15:21:08 +08:00
|
|
|
|
if (NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control))
|
2024-10-24 23:32:43 +08:00
|
|
|
|
{
|
|
|
|
|
|
JudgmentFlipFlopNode(control); // 连接关系变更时判断
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-10-28 15:21:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2024-10-24 23:32:43 +08:00
|
|
|
|
#endregion
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
2024-10-24 23:32:43 +08:00
|
|
|
|
else
|
2024-09-26 21:00:17 +08:00
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
ConnectionArgSourceType connectionArgSourceType = eventArgs.ConnectionArgSourceType;
|
2024-10-28 15:21:08 +08:00
|
|
|
|
#region 创建/删除节点之间的参数传递关系
|
|
|
|
|
|
#region 创建连接
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接
|
|
|
|
|
|
{
|
|
|
|
|
|
if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("非预期的情况");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
JunctionControlBase startJunction = eventArgs.ConnectionArgSourceType switch
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
ConnectionArgSourceType.GetPreviousNodeData => IFormJunction.ReturnDataJunction, // 自身节点
|
2024-10-24 23:32:43 +08:00
|
|
|
|
ConnectionArgSourceType.GetOtherNodeData => IFormJunction.ReturnDataJunction, // 其它节点的返回值控制点
|
|
|
|
|
|
ConnectionArgSourceType.GetOtherNodeDataOfInvoke => IFormJunction.ReturnDataJunction, // 其它节点的返回值控制点
|
|
|
|
|
|
_ => throw new Exception("窗体事件 FlowEnvironment_NodeConnectChangeEvemt 创建/删除节点之间的参数传递关系 JunctionControlBase 枚举值错误 。非预期的枚举值。") // 应该不会触发
|
|
|
|
|
|
};
|
|
|
|
|
|
|
2024-11-04 23:30:52 +08:00
|
|
|
|
if(IToJunction.ArgDataJunction.Length == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-10-24 23:32:43 +08:00
|
|
|
|
JunctionControlBase endJunction = IToJunction.ArgDataJunction[eventArgs.ArgIndex];
|
|
|
|
|
|
LineType lineType = LineType.Bezier;
|
|
|
|
|
|
// 添加连接
|
|
|
|
|
|
var connection = new ConnectionControl(
|
|
|
|
|
|
lineType,
|
|
|
|
|
|
FlowChartCanvas,
|
|
|
|
|
|
eventArgs.ArgIndex,
|
|
|
|
|
|
eventArgs.ConnectionArgSourceType,
|
|
|
|
|
|
startJunction,
|
2024-11-04 23:30:52 +08:00
|
|
|
|
endJunction
|
2024-10-24 23:32:43 +08:00
|
|
|
|
);
|
|
|
|
|
|
Connections.Add(connection);
|
|
|
|
|
|
fromNodeControl.AddCnnection(connection);
|
|
|
|
|
|
toNodeControl.AddCnnection(connection);
|
2024-10-27 00:54:10 +08:00
|
|
|
|
EndConnection(); // 环境触发了创建节点连接事件
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
}
|
2024-10-28 15:21:08 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
#region 移除连接
|
2024-10-24 23:32:43 +08:00
|
|
|
|
else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remote) // 移除连接
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
// 需要移除连接
|
|
|
|
|
|
var removeConnections = Connections.Where(c => c.Start.MyNode.Guid.Equals(fromNodeGuid)
|
2024-10-27 00:54:10 +08:00
|
|
|
|
&& c.End.MyNode.Guid.Equals(toNodeGuid))
|
|
|
|
|
|
.ToList(); // 获取这两个节点之间的所有连接关系
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
2024-10-28 15:21:08 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var connection in removeConnections)
|
|
|
|
|
|
{
|
2024-10-28 15:21:08 +08:00
|
|
|
|
if (connection.End is ArgJunctionControl junctionControl && junctionControl.ArgIndex == eventArgs.ArgIndex)
|
2024-10-24 23:32:43 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
// 找到符合删除条件的连接线
|
|
|
|
|
|
Connections.Remove(connection); // 从本地记录中移除
|
2024-11-04 23:30:52 +08:00
|
|
|
|
fromNodeControl.RemoveConnection(connection); // 从节点持有的记录移除
|
|
|
|
|
|
toNodeControl.RemoveConnection(connection); // 从节点持有的记录移除
|
2024-10-24 23:32:43 +08:00
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-28 15:21:08 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
//if (NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control))
|
|
|
|
|
|
//{
|
|
|
|
|
|
// JudgmentFlipFlopNode(control); // 连接关系变更时判断
|
|
|
|
|
|
//}
|
2024-10-24 23:32:43 +08:00
|
|
|
|
}
|
2024-10-28 15:21:08 +08:00
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2024-10-24 23:32:43 +08:00
|
|
|
|
#endregion
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 节点移除事件
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <param name="eventArgs"></param>
|
2024-10-20 21:59:42 +08:00
|
|
|
|
private void FlowEnvironment_NodeRemoteEvent(NodeRemoveEventArgs eventArgs)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-18 16:45:41 +08:00
|
|
|
|
var nodeGuid = eventArgs.NodeGuid;
|
2024-10-15 10:55:41 +08:00
|
|
|
|
if (!TryGetControl(nodeGuid, out var nodeControl))
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
if (nodeControl is null) return;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
if (selectNodeControls.Count > 0)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-18 16:45:41 +08:00
|
|
|
|
if (selectNodeControls.Contains(nodeControl))
|
2024-09-17 14:20:27 +08:00
|
|
|
|
{
|
2024-09-18 16:45:41 +08:00
|
|
|
|
selectNodeControls.Remove(nodeControl);
|
2024-09-17 14:20:27 +08:00
|
|
|
|
}
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (nodeControl is FlipflopNodeControl flipflopControl) // 判断是否为触发器
|
2024-09-18 16:45:41 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
var node = flipflopControl?.ViewModel?.NodeModel;
|
|
|
|
|
|
if (node is not null)
|
2024-10-20 12:10:57 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
NodeTreeViewer.RemoteGlobalFlipFlop(node); // 从全局触发器树树视图中移除
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
FlowChartCanvas.Children.Remove(nodeControl);
|
2024-10-24 23:32:43 +08:00
|
|
|
|
nodeControl.RemoveAllConection();
|
2024-10-20 21:59:42 +08:00
|
|
|
|
NodeControls.Remove(nodeControl.ViewModel.NodeModel.Guid);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 编辑项目时添加了节点
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <param name="nodeDataBase"></param>
|
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
|
private void FlowEnvironment_NodeCreateEvent(NodeCreateEventArgs eventArgs)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (eventArgs.NodeModel is not NodeModelBase nodeModelBase)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-22 00:13:13 +08:00
|
|
|
|
if(nodeModelBase is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("OnNodeCreateEvent事件接收到意外的返回值");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
// MethodDetails methodDetailss = eventArgs.MethodDetailss;
|
|
|
|
|
|
PositionOfUI position = eventArgs.Position;
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
// 创建对应控件
|
|
|
|
|
|
NodeControlBase? nodeControl = nodeModelBase.ControlType switch
|
|
|
|
|
|
{
|
|
|
|
|
|
NodeControlType.Action => CreateNodeControl<ActionNodeControl, ActionNodeControlViewModel>(nodeModelBase), //typeof(ActionNodeControl),
|
|
|
|
|
|
NodeControlType.Flipflop => CreateNodeControl<FlipflopNodeControl, FlipflopNodeControlViewModel>(nodeModelBase),
|
|
|
|
|
|
NodeControlType.ExpCondition => CreateNodeControl<ConditionNodeControl, ConditionNodeControlViewModel>(nodeModelBase),
|
|
|
|
|
|
NodeControlType.ExpOp => CreateNodeControl<ExpOpNodeControl, ExpOpNodeViewModel>(nodeModelBase),
|
|
|
|
|
|
NodeControlType.ConditionRegion => CreateNodeControl<ConditionRegionControl, ConditionRegionNodeControlViewModel>(nodeModelBase),
|
|
|
|
|
|
_ => null,
|
|
|
|
|
|
};
|
|
|
|
|
|
if (nodeControl is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
NodeControls.TryAdd(nodeModelBase.Guid, nodeControl);
|
|
|
|
|
|
if (eventArgs.IsAddInRegion && NodeControls.TryGetValue(eventArgs.RegeionGuid, out NodeControlBase? regionControl))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (regionControl is not null)
|
2024-09-17 14:20:27 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
TryPlaceNodeInRegion(regionControl, nodeControl);
|
2024-09-17 14:20:27 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-10-23 19:22:27 +08:00
|
|
|
|
if (!TryPlaceNodeInRegion(nodeControl, position)) // 判断是否为区域,如果是,将节点放置在区域中
|
2024-09-17 14:20:27 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
PlaceNodeOnCanvas(nodeControl, position.X, position.Y); // 将节点放置在画布上
|
2024-09-17 14:20:27 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
#region 节点树视图
|
|
|
|
|
|
if (nodeModelBase.ControlType == NodeControlType.Flipflop)
|
|
|
|
|
|
{
|
|
|
|
|
|
var node = nodeControl?.ViewModel?.NodeModel;
|
|
|
|
|
|
if (node is not null)
|
2024-09-26 21:00:17 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
NodeTreeViewer.AddGlobalFlipFlop(EnvDecorator, node); // 新增的触发器节点添加到全局触发器
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 设置了流程起始控件
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <param name="oldNodeGuid"></param>
|
|
|
|
|
|
/// <param name="newNodeGuid"></param>
|
|
|
|
|
|
private void FlowEnvironment_StartNodeChangeEvent(StartNodeChangeEventArgs eventArgs)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
string oldNodeGuid = eventArgs.OldNodeGuid;
|
|
|
|
|
|
string newNodeGuid = eventArgs.NewNodeGuid;
|
|
|
|
|
|
if (!TryGetControl(newNodeGuid, out var newStartNodeControl)) return;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(oldNodeGuid))
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (!TryGetControl(oldNodeGuid, out var oldStartNodeControl)) return;
|
|
|
|
|
|
oldStartNodeControl.BorderBrush = Brushes.Black;
|
|
|
|
|
|
oldStartNodeControl.BorderThickness = new Thickness(0);
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
newStartNodeControl.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"));
|
|
|
|
|
|
newStartNodeControl.BorderThickness = new Thickness(2);
|
|
|
|
|
|
var node = newStartNodeControl?.ViewModel?.NodeModel;
|
|
|
|
|
|
if (node is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
NodeTreeViewer.LoadNodeTreeOfStartNode(EnvDecorator, node);
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-22 14:10:13 +08:00
|
|
|
|
/// <summary>
|
2024-09-24 22:39:43 +08:00
|
|
|
|
/// 被监视的对象发生改变
|
2024-09-22 14:10:13 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
|
|
|
|
|
private void FlowEnvironment_OnMonitorObjectChange(MonitorObjectEventArgs eventArgs)
|
|
|
|
|
|
{
|
|
|
|
|
|
string nodeGuid = eventArgs.NodeGuid;
|
2024-09-24 22:39:43 +08:00
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
string monitorKey = MonitorObjectEventArgs.ObjSourceType.NodeFlowData switch
|
2024-09-24 22:39:43 +08:00
|
|
|
|
{
|
|
|
|
|
|
MonitorObjectEventArgs.ObjSourceType.NodeFlowData => nodeGuid,
|
2024-09-26 21:00:17 +08:00
|
|
|
|
_ => eventArgs.NewData.GetType().FullName,
|
2024-09-24 22:39:43 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
//NodeControlBase nodeControl = GuidToControl(nodeGuid);
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (ViewObjectViewer.MonitorObj is null) // 如果没有加载过对象
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewObjectViewer.LoadObjectInformation(monitorKey, eventArgs.NewData); // 加载对象 ViewObjectViewerControl.MonitorType.Obj
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (monitorKey.Equals(ViewObjectViewer.MonitorKey)) // 相同对象
|
2024-09-22 14:10:13 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
ViewObjectViewer.RefreshObjectTree(eventArgs.NewData); // 刷新
|
|
|
|
|
|
}
|
2024-09-22 17:37:32 +08:00
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
ViewObjectViewer.LoadObjectInformation(monitorKey, eventArgs.NewData); // 加载对象
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
}
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 节点中断状态改变。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private void FlowEnvironment_OnNodeInterruptStateChange(NodeInterruptStateChangeEventArgs eventArgs)
|
2024-09-22 14:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
string nodeGuid = eventArgs.NodeGuid;
|
2024-10-15 10:55:41 +08:00
|
|
|
|
if (!TryGetControl(nodeGuid, out var nodeControl)) return;
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-10-22 00:13:13 +08:00
|
|
|
|
//if (eventArgs.Class == InterruptClass.None)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// nodeControl.ViewModel.IsInterrupt = false;
|
|
|
|
|
|
//}
|
|
|
|
|
|
//else
|
|
|
|
|
|
//{
|
|
|
|
|
|
// nodeControl.ViewModel.IsInterrupt = true;
|
|
|
|
|
|
//}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
foreach (var menuItem in nodeControl.ContextMenu.Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (menuItem is MenuItem menu)
|
2024-10-20 12:10:57 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if ("取消中断".Equals(menu.Header))
|
2024-09-22 17:37:32 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
menu.Header = "在此中断";
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
else if ("在此中断".Equals(menu.Header))
|
|
|
|
|
|
{
|
|
|
|
|
|
menu.Header = "取消中断";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-22 17:37:32 +08:00
|
|
|
|
}
|
2024-10-20 21:59:42 +08:00
|
|
|
|
}
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 节点触发了中断
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
2024-09-22 17:37:32 +08:00
|
|
|
|
private void FlowEnvironment_OnInterruptTrigger(InterruptTriggerEventArgs eventArgs)
|
2024-09-22 14:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
string nodeGuid = eventArgs.NodeGuid;
|
2024-10-15 10:55:41 +08:00
|
|
|
|
if (!TryGetControl(nodeGuid, out var nodeControl)) return;
|
2024-09-22 17:37:32 +08:00
|
|
|
|
if(eventArgs.Type == InterruptTriggerEventArgs.InterruptTriggerType.Exp)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine($"表达式触发了中断:{eventArgs.Expression}");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine($"节点触发了中断:{nodeGuid}");
|
|
|
|
|
|
}
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// IOC变更
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
|
private void FlowEnvironment_OnIOCMembersChanged(IOCMembersChangedEventArgs eventArgs)
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
IOCObjectViewer.AddDependenciesInstance(eventArgs.Key, eventArgs.Instance);
|
|
|
|
|
|
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 节点需要定位
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
|
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
|
|
|
|
|
private void FlowEnvironment_OnNodeLocate(NodeLocatedEventArgs eventArgs)
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (!TryGetControl(eventArgs.NodeGuid, out var nodeControl)) return;
|
|
|
|
|
|
//scaleTransform.ScaleX = 1;
|
|
|
|
|
|
//scaleTransform.ScaleY = 1;
|
|
|
|
|
|
// 获取控件在 FlowChartCanvas 上的相对位置
|
|
|
|
|
|
Rect controlBounds = VisualTreeHelper.GetDescendantBounds(nodeControl);
|
|
|
|
|
|
Point controlPosition = nodeControl.TransformToAncestor(FlowChartCanvas).Transform(new Point(0, 0));
|
|
|
|
|
|
|
|
|
|
|
|
// 获取控件在画布上的中心点
|
|
|
|
|
|
double controlCenterX = controlPosition.X + controlBounds.Width / 2;
|
|
|
|
|
|
double controlCenterY = controlPosition.Y + controlBounds.Height / 2;
|
|
|
|
|
|
|
|
|
|
|
|
// 考虑缩放因素计算目标位置的中心点
|
|
|
|
|
|
double scaledCenterX = controlCenterX * scaleTransform.ScaleX;
|
|
|
|
|
|
double scaledCenterY = controlCenterY * scaleTransform.ScaleY;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// 计算画布的可视区域大小
|
|
|
|
|
|
//double visibleAreaLeft = scaledCenterX;
|
|
|
|
|
|
//double visibleAreaTop = scaledCenterY;
|
|
|
|
|
|
//double visibleAreaRight = scaledCenterX + FlowChartStackGrid.ActualWidth;
|
|
|
|
|
|
//double visibleAreaBottom = scaledCenterY + FlowChartStackGrid.ActualHeight;
|
|
|
|
|
|
//// 检查控件中心点是否在可视区域内
|
|
|
|
|
|
//bool isInView = scaledCenterX >= visibleAreaLeft && scaledCenterX <= visibleAreaRight &&
|
|
|
|
|
|
// scaledCenterY >= visibleAreaTop && scaledCenterY <= visibleAreaBottom;
|
|
|
|
|
|
|
|
|
|
|
|
//Console.WriteLine($"isInView :{isInView}");
|
|
|
|
|
|
|
|
|
|
|
|
//if (!isInView)
|
|
|
|
|
|
//{
|
|
|
|
|
|
//}
|
|
|
|
|
|
// 计算平移偏移量,使得控件在可视区域的中心
|
|
|
|
|
|
double translateX = scaledCenterX - FlowChartStackGrid.ActualWidth / 2;
|
|
|
|
|
|
double translateY = scaledCenterY - FlowChartStackGrid.ActualHeight / 2;
|
|
|
|
|
|
|
|
|
|
|
|
var translate = this.translateTransform;
|
|
|
|
|
|
// 应用平移变换
|
|
|
|
|
|
translate.X = 0;
|
|
|
|
|
|
translate.Y = 0;
|
|
|
|
|
|
translate.X -= translateX;
|
|
|
|
|
|
translate.Y -= translateY;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置RenderTransform以实现移动效果
|
|
|
|
|
|
TranslateTransform translateTransform = new TranslateTransform();
|
|
|
|
|
|
nodeControl.RenderTransform = translateTransform;
|
|
|
|
|
|
ElasticAnimation(nodeControl, translateTransform, 4, 1, 0.5);
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 控件抖动
|
|
|
|
|
|
/// 来源:https://www.cnblogs.com/RedSky/p/17705411.html
|
|
|
|
|
|
/// 作者:HotSky
|
|
|
|
|
|
/// (……太好用了)
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="translate"></param>
|
2024-10-15 10:55:41 +08:00
|
|
|
|
/// <param name="nodeControl">需要抖动的控件</param>
|
2024-09-27 23:47:25 +08:00
|
|
|
|
/// <param name="power">抖动第一下偏移量</param>
|
|
|
|
|
|
/// <param name="range">减弱幅度(小于等于power,大于0)</param>
|
|
|
|
|
|
/// <param name="speed">持续系数(大于0),越大时间越长,</param>
|
2024-09-30 22:20:02 +08:00
|
|
|
|
private static void ElasticAnimation(NodeControlBase nodeControl, TranslateTransform translate, int power, int range = 1, double speed = 1)
|
2024-09-27 23:47:25 +08:00
|
|
|
|
{
|
|
|
|
|
|
DoubleAnimationUsingKeyFrames animation1 = new DoubleAnimationUsingKeyFrames();
|
|
|
|
|
|
for (int i = power, j = 1; i >= 0; i -= range)
|
|
|
|
|
|
{
|
|
|
|
|
|
animation1.KeyFrames.Add(new LinearDoubleKeyFrame(-i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
|
|
|
|
|
|
animation1.KeyFrames.Add(new LinearDoubleKeyFrame(i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
|
|
|
|
|
|
}
|
|
|
|
|
|
translate.BeginAnimation(TranslateTransform.YProperty, animation1);
|
|
|
|
|
|
DoubleAnimationUsingKeyFrames animation2 = new DoubleAnimationUsingKeyFrames();
|
|
|
|
|
|
for (int i = power, j = 1; i >= 0; i -= range)
|
|
|
|
|
|
{
|
|
|
|
|
|
animation2.KeyFrames.Add(new LinearDoubleKeyFrame(-i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
|
|
|
|
|
|
animation2.KeyFrames.Add(new LinearDoubleKeyFrame(i, TimeSpan.FromMilliseconds(j++ * 100 * speed)));
|
|
|
|
|
|
}
|
|
|
|
|
|
translate.BeginAnimation(TranslateTransform.XProperty, animation2);
|
|
|
|
|
|
|
|
|
|
|
|
animation2.Completed += (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
nodeControl.RenderTransform = null; // 或者重新设置为默认值
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 节点移动
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="eventArgs"></param>
|
2024-10-15 21:56:09 +08:00
|
|
|
|
private void FlowEnvironment_OnNodeMoved(NodeMovedEventArgs eventArgs)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!TryGetControl(eventArgs.NodeGuid, out var nodeControl)) return;
|
2024-10-24 23:32:43 +08:00
|
|
|
|
nodeControl.UpdateLocationConnections();
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
//var newLeft = eventArgs.X;
|
|
|
|
|
|
//var newTop = eventArgs.Y;
|
|
|
|
|
|
//// 限制控件不超出FlowChartCanvas的边界
|
|
|
|
|
|
//if (newLeft >= 0 && newLeft + nodeControl.ActualWidth <= FlowChartCanvas.ActualWidth)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// Canvas.SetLeft(nodeControl, newLeft);
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
//}
|
|
|
|
|
|
//if (newTop >= 0 && newTop + nodeControl.ActualHeight <= FlowChartCanvas.ActualHeight)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// Canvas.SetTop(nodeControl, newTop);
|
|
|
|
|
|
//}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-15 21:56:09 +08:00
|
|
|
|
}
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
2024-09-22 14:10:13 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Guid 转 NodeControl
|
|
|
|
|
|
/// </summary>
|
2024-10-15 10:55:41 +08:00
|
|
|
|
/// <param name="nodeGuid"></param>
|
|
|
|
|
|
/// <param name="nodeControl"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
private bool TryGetControl(string nodeGuid,out NodeControlBase nodeControl)
|
2024-09-22 14:10:13 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (string.IsNullOrEmpty(nodeGuid))
|
|
|
|
|
|
{
|
2024-10-15 10:55:41 +08:00
|
|
|
|
nodeControl = null;
|
|
|
|
|
|
return false;
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}
|
2024-10-15 10:55:41 +08:00
|
|
|
|
if (!NodeControls.TryGetValue(nodeGuid, out nodeControl))
|
2024-09-22 14:10:13 +08:00
|
|
|
|
{
|
2024-10-15 10:55:41 +08:00
|
|
|
|
nodeControl = null;
|
|
|
|
|
|
return false;
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}
|
2024-10-15 10:55:41 +08:00
|
|
|
|
if(nodeControl is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
#region 加载项目文件后触发事件相关方法
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 运行环节加载了项目文件,需要创建节点控件
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="nodeInfo"></param>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <param name="methodDetailss"></param>
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <returns></returns>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <exception cref="NotImplementedException"></exception>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
//private NodeControlBase? CreateNodeControlOfNodeInfo(NodeInfo nodeInfo, MethodDetails methodDetailss)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 创建控件实例
|
|
|
|
|
|
// NodeControlBase nodeControl = nodeInfo.Type switch
|
|
|
|
|
|
// {
|
|
|
|
|
|
// $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleActionNode)}" =>
|
|
|
|
|
|
// CreateNodeControl<SingleActionNode, ActionNodeControl, ActionNodeControlViewModel>(methodDetailss),// 动作节点控件
|
|
|
|
|
|
// $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleFlipflopNode)}" =>
|
|
|
|
|
|
// CreateNodeControl<SingleFlipflopNode, FlipflopNodeControl, FlipflopNodeControlViewModel>(methodDetailss), // 触发器节点控件
|
|
|
|
|
|
|
|
|
|
|
|
// $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleConditionNode)}" =>
|
|
|
|
|
|
// CreateNodeControl<SingleConditionNode, ConditionNodeControl, ConditionNodeControlViewModel>(), // 条件表达式控件
|
|
|
|
|
|
// $"{NodeStaticConfig.NodeSpaceName}.{nameof(SingleExpOpNode)}" =>
|
|
|
|
|
|
// CreateNodeControl<SingleExpOpNode, ExpOpNodeControl, ExpOpNodeViewModel>(), // 操作表达式控件
|
|
|
|
|
|
|
|
|
|
|
|
// $"{NodeStaticConfig.NodeSpaceName}.{nameof(CompositeConditionNode)}" =>
|
|
|
|
|
|
// CreateNodeControl<CompositeConditionNode, ConditionRegionControl, ConditionRegionNodeControlViewModel>(), // 条件区域控件
|
|
|
|
|
|
// _ => throw new NotImplementedException($"非预期的节点类型{nodeInfo.Type}"),
|
|
|
|
|
|
// };
|
|
|
|
|
|
// return nodeControl;
|
|
|
|
|
|
//}
|
2024-08-05 20:32:16 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 加载文件时,添加节点到区域中
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="regionControl"></param>
|
|
|
|
|
|
/// <param name="childNodes"></param>
|
2024-09-30 02:45:49 +08:00
|
|
|
|
//private void AddNodeControlInRegeionControl(NodeControlBase regionControl, NodeInfo[] childNodes)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// foreach (var childNode in childNodes)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// if (FlowEnvironment.TryGetMethodDetails(childNode.MethodName, out MethodDetails md))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var childNodeControl = CreateNodeControlOfNodeInfo(childNode, md);
|
|
|
|
|
|
// if (childNodeControl is null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Console.WriteLine($"无法为节点类型创建节点控件: {childNode.MethodName}\r\n");
|
|
|
|
|
|
// continue;
|
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// if (regionControl is ConditionRegionControl conditionRegion)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// conditionRegion.AddCondition(childNodeControl);
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 节点控件的创建
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建了节点,添加到画布。配置默认事件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="nodeControl"></param>
|
|
|
|
|
|
/// <param name="position"></param>
|
|
|
|
|
|
private void PlaceNodeOnCanvas(NodeControlBase nodeControl, double x, double y)
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
// 添加控件到画布
|
|
|
|
|
|
FlowChartCanvas.Children.Add(nodeControl);
|
|
|
|
|
|
Canvas.SetLeft(nodeControl, x);
|
|
|
|
|
|
Canvas.SetTop(nodeControl, y);
|
|
|
|
|
|
|
|
|
|
|
|
ConfigureContextMenu(nodeControl); // 配置节点右键菜单
|
|
|
|
|
|
ConfigureNodeEvents(nodeControl); // 配置节点事件
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-10-15 21:56:09 +08:00
|
|
|
|
/// 配置节点事件(移动,点击相关)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="nodeControl"></param>
|
|
|
|
|
|
private void ConfigureNodeEvents(NodeControlBase nodeControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
nodeControl.MouseLeftButtonDown += Block_MouseLeftButtonDown;
|
|
|
|
|
|
nodeControl.MouseMove += Block_MouseMove;
|
|
|
|
|
|
nodeControl.MouseLeftButtonUp += Block_MouseLeftButtonUp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 开始创建连接 True线 操作,设置起始块和绘制连接线。
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
//private void StartConnection(NodeControlBase startNodeControl, ConnectionInvokeType connectionType)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var tf = Connections.FirstOrDefault(it => it.Start.MyNode.Guid == startNodeControl.ViewModel.NodeModel.Guid)?.Type;
|
|
|
|
|
|
// IsConnecting = true;
|
|
|
|
|
|
// currentConnectionType = connectionType;
|
|
|
|
|
|
// startConnectNodeControl = startNodeControl;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
// // 确保起点和终点位置的正确顺序
|
|
|
|
|
|
// currentLine = new Line
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Stroke = connectionType == ConnectionInvokeType.IsSucceed ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"))
|
|
|
|
|
|
// : connectionType == ConnectionInvokeType.IsFail ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F18905"))
|
|
|
|
|
|
// : connectionType == ConnectionInvokeType.IsError ? new SolidColorBrush((Color)ColorConverter.ConvertFromString("#AB616B"))
|
|
|
|
|
|
// : new SolidColorBrush((Color)ColorConverter.ConvertFromString("#4A82E4")),
|
|
|
|
|
|
// StrokeDashArray = new DoubleCollection([2]),
|
|
|
|
|
|
// StrokeThickness = 2,
|
|
|
|
|
|
// X1 = Canvas.GetLeft(startConnectNodeControl) + startConnectNodeControl.ActualWidth / 2,
|
|
|
|
|
|
// Y1 = Canvas.GetTop(startConnectNodeControl) + startConnectNodeControl.ActualHeight / 2,
|
|
|
|
|
|
// X2 = Canvas.GetLeft(startConnectNodeControl) + startConnectNodeControl.ActualWidth / 2, // 初始时终点与起点重合
|
|
|
|
|
|
// Y2 = Canvas.GetTop(startConnectNodeControl) + startConnectNodeControl.ActualHeight / 2,
|
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
|
|
// FlowChartCanvas.Children.Add(currentLine);
|
|
|
|
|
|
// this.KeyDown += MainWindow_KeyDown;
|
|
|
|
|
|
//}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
#region 配置右键菜单
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
2024-09-20 10:50:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 配置节点右键菜单
|
|
|
|
|
|
/// </summary>
|
2024-09-22 14:10:13 +08:00
|
|
|
|
/// <param name="nodeControl"><para> 任何情景下都尽量避免直接操作 ViewModel 中的 NodeModel 节点,而是应该调用 FlowEnvironment 提供接口进行操作。</para> 因为 Workbench 应该更加关注UI视觉效果,而非直接干扰流程环境运行的逻辑。<para> 之所以暴露 NodeModel 属性,因为有些场景下不可避免的需要直接获取节点的属性。</para> </param>
|
2024-09-20 10:50:32 +08:00
|
|
|
|
private void ConfigureContextMenu(NodeControlBase nodeControl)
|
|
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
|
2024-09-20 10:50:32 +08:00
|
|
|
|
var contextMenu = new ContextMenu();
|
2024-10-20 21:59:42 +08:00
|
|
|
|
var nodeGuid = nodeControl.ViewModel?.NodeModel?.Guid;
|
2024-10-10 16:49:37 +08:00
|
|
|
|
#region 触发器节点
|
|
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if(nodeControl.ViewModel?.NodeModel.ControlType == NodeControlType.Flipflop)
|
2024-10-10 16:49:37 +08:00
|
|
|
|
{
|
|
|
|
|
|
contextMenu.Items.Add(CreateMenuItem("启动触发器", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
if (s is MenuItem menuItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (menuItem.Header.ToString() == "启动触发器")
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.ActivateFlipflopNode(nodeGuid);
|
2024-10-10 16:49:37 +08:00
|
|
|
|
|
|
|
|
|
|
menuItem.Header = "终结触发器";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.TerminateFlipflopNode(nodeGuid);
|
2024-10-10 16:49:37 +08:00
|
|
|
|
menuItem.Header = "启动触发器";
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (nodeControl.ViewModel?.NodeModel?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
contextMenu.Items.Add(CreateMenuItem("查看返回类型", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
DisplayReturnTypeTreeViewer(returnType);
|
|
|
|
|
|
}));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-22 14:10:13 +08:00
|
|
|
|
#region 右键菜单功能 - 中断
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
contextMenu.Items.Add(CreateMenuItem("在此中断", async (s, e) =>
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
2024-09-22 14:10:13 +08:00
|
|
|
|
if ((s is MenuItem menuItem) && menuItem is not null)
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
if (nodeControl?.ViewModel?.NodeModel?.DebugSetting?.IsInterrupt == true)
|
2024-09-22 14:10:13 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
await EnvDecorator.SetNodeInterruptAsync(nodeGuid,false);
|
|
|
|
|
|
nodeControl.ViewModel.IsInterrupt = false;
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
|
|
|
|
|
menuItem.Header = "取消中断";
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
nodeControl!.ViewModel!.IsInterrupt = true;
|
|
|
|
|
|
await EnvDecorator.SetNodeInterruptAsync(nodeGuid, true);
|
2024-09-22 14:10:13 +08:00
|
|
|
|
menuItem.Header = "在此中断";
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-09-20 10:50:32 +08:00
|
|
|
|
}
|
2024-09-22 14:10:13 +08:00
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
contextMenu.Items.Add(CreateMenuItem("设为起点", (s, e) => EnvDecorator.SetStartNode(nodeGuid)));
|
2024-10-20 21:59:42 +08:00
|
|
|
|
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) => EnvDecorator.RemoveNodeAsync(nodeGuid)));
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
//contextMenu.Items.Add(CreateMenuItem("添加 真分支", (s, e) => StartConnection(nodeControl, ConnectionInvokeType.IsSucceed)));
|
|
|
|
|
|
//contextMenu.Items.Add(CreateMenuItem("添加 假分支", (s, e) => StartConnection(nodeControl, ConnectionInvokeType.IsFail)));
|
|
|
|
|
|
//contextMenu.Items.Add(CreateMenuItem("添加 异常分支", (s, e) => StartConnection(nodeControl, ConnectionInvokeType.IsError)));
|
|
|
|
|
|
//contextMenu.Items.Add(CreateMenuItem("添加 上游分支", (s, e) => StartConnection(nodeControl, ConnectionInvokeType.Upstream)));
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-10 16:49:37 +08:00
|
|
|
|
|
2024-09-22 14:10:13 +08:00
|
|
|
|
#region 右键菜单功能 - 控件对齐
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
var AvoidMenu = new MenuItem();
|
2024-09-22 14:10:13 +08:00
|
|
|
|
AvoidMenu.Items.Add(CreateMenuItem("群组对齐", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, AlignMode.Grouping);
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}));
|
|
|
|
|
|
AvoidMenu.Items.Add(CreateMenuItem("规划对齐", (s, e) =>
|
|
|
|
|
|
{
|
2024-09-22 14:10:13 +08:00
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, AlignMode.Planning);
|
|
|
|
|
|
}));
|
|
|
|
|
|
AvoidMenu.Items.Add(CreateMenuItem("水平中心对齐", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, AlignMode.HorizontalCenter);
|
|
|
|
|
|
}));
|
|
|
|
|
|
AvoidMenu.Items.Add(CreateMenuItem("垂直中心对齐 ", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, AlignMode.VerticalCenter);
|
|
|
|
|
|
}));
|
|
|
|
|
|
|
|
|
|
|
|
AvoidMenu.Items.Add(CreateMenuItem("垂直对齐时水平斜分布", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, AlignMode.Vertical);
|
|
|
|
|
|
}));
|
|
|
|
|
|
AvoidMenu.Items.Add(CreateMenuItem("水平对齐时垂直斜分布", (s, e) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, AlignMode.Horizontal);
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}));
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
AvoidMenu.Header = "对齐";
|
2024-09-22 14:10:13 +08:00
|
|
|
|
contextMenu.Items.Add(AvoidMenu);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-09-20 10:50:32 +08:00
|
|
|
|
nodeControl.ContextMenu = contextMenu;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 查看返回类型(树形结构展开类型的成员)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <param name="type"></param>
|
|
|
|
|
|
private void DisplayReturnTypeTreeViewer(Type type)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
try
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
var typeViewerWindow = new TypeViewerWindow
|
|
|
|
|
|
{
|
|
|
|
|
|
Type = type,
|
|
|
|
|
|
};
|
|
|
|
|
|
typeViewerWindow.LoadTypeInformation();
|
|
|
|
|
|
typeViewerWindow.Show();
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
catch (Exception ex)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
Console.WriteLine(ex);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
#region 拖拽DLL文件到左侧功能区,加载相关节点清单
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// 当拖动文件到窗口时触发,加载DLL文件
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-09-15 12:15:32 +08:00
|
|
|
|
private void Window_Drop(object sender, DragEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
if (e.Data.GetDataPresent(DataFormats.FileDrop))
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
|
|
|
|
|
|
foreach (string file in files)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (file.EndsWith(".dll"))
|
|
|
|
|
|
{
|
2024-11-03 23:51:18 +08:00
|
|
|
|
EnvDecorator.LoadLibrary(file);
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 当拖动文件经过窗口时触发,设置拖放效果为复制
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void Window_DragOver(object sender, DragEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
e.Effects = DragDropEffects.Copy;
|
|
|
|
|
|
e.Handled = true;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
#endregion
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
#region 与流程图/节点相关
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 鼠标在画布移动。
|
|
|
|
|
|
/// 选择控件状态下,调整选择框大小
|
|
|
|
|
|
/// 连接状态下,实时更新连接线的终点位置。
|
|
|
|
|
|
/// 移动画布状态下,移动画布。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void FlowChartCanvas_MouseMove(object sender, MouseEventArgs e)
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
var myData = GlobalJunctionData.MyGlobalConnectingData;
|
|
|
|
|
|
if (myData.IsCreateing && e.LeftButton == MouseButtonState.Pressed)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
if (myData.Type == JunctionOfConnectionType.Invoke)
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewModel.IsConnectionInvokeNode = true; // 正在连接节点的调用关系
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewModel.IsConnectionArgSourceNode = true; // 正在连接节点的调用关系
|
|
|
|
|
|
}
|
2024-10-23 19:22:27 +08:00
|
|
|
|
var currentPoint = e.GetPosition(FlowChartCanvas);
|
2024-10-27 00:54:10 +08:00
|
|
|
|
currentPoint.X -= 2;
|
|
|
|
|
|
currentPoint.Y -= 2;
|
|
|
|
|
|
myData.UpdatePoint(currentPoint);
|
2024-10-23 19:22:27 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
if (IsCanvasDragging && e.MiddleButton == MouseButtonState.Pressed) // 正在移动画布(按住中键)
|
2024-09-18 16:45:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
Point currentMousePosition = e.GetPosition(this);
|
2024-09-20 10:50:32 +08:00
|
|
|
|
double deltaX = currentMousePosition.X - startCanvasDragPoint.X;
|
|
|
|
|
|
double deltaY = currentMousePosition.Y - startCanvasDragPoint.Y;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
|
|
|
|
|
translateTransform.X += deltaX;
|
|
|
|
|
|
translateTransform.Y += deltaY;
|
|
|
|
|
|
|
2024-09-20 10:50:32 +08:00
|
|
|
|
startCanvasDragPoint = currentMousePosition;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
|
|
|
|
|
foreach (var line in Connections)
|
|
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
line.RefreshLine(); // 画布移动时刷新所有连接线
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-21 10:06:44 +08:00
|
|
|
|
if (IsSelectControl) // 正在选取节点
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
2024-09-21 10:06:44 +08:00
|
|
|
|
IsSelectDragging = e.LeftButton == MouseButtonState.Pressed;
|
2024-09-20 10:50:32 +08:00
|
|
|
|
// 获取当前鼠标位置
|
|
|
|
|
|
Point currentPoint = e.GetPosition(FlowChartCanvas);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新选取矩形的位置和大小
|
|
|
|
|
|
double x = Math.Min(currentPoint.X, startSelectControolPoint.X);
|
|
|
|
|
|
double y = Math.Min(currentPoint.Y, startSelectControolPoint.Y);
|
|
|
|
|
|
double width = Math.Abs(currentPoint.X - startSelectControolPoint.X);
|
|
|
|
|
|
double height = Math.Abs(currentPoint.Y - startSelectControolPoint.Y);
|
|
|
|
|
|
|
|
|
|
|
|
Canvas.SetLeft(SelectionRectangle, x);
|
|
|
|
|
|
Canvas.SetTop(SelectionRectangle, y);
|
|
|
|
|
|
SelectionRectangle.Width = width;
|
|
|
|
|
|
SelectionRectangle.Height = height;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 基础节点的拖拽放置创建
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void BaseNodeControl_PreviewMouseMove(object sender, MouseEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (sender is UserControl control)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 创建一个 DataObject 用于拖拽操作,并设置拖拽效果
|
2024-09-15 12:15:32 +08:00
|
|
|
|
var dragData = new DataObject(MouseNodeType.CreateBaseNodeInCanvas, control.GetType());
|
2024-08-05 10:11:58 +08:00
|
|
|
|
DragDrop.DoDragDrop(control, dragData, DragDropEffects.Move);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 放置操作,根据拖放数据创建相应的控件,并处理相关操作
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-10-22 00:13:13 +08:00
|
|
|
|
private void FlowChartCanvas_Drop(object sender, DragEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
try
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
var canvasDropPosition = e.GetPosition(FlowChartCanvas); // 更新画布落点
|
|
|
|
|
|
PositionOfUI position = new PositionOfUI(canvasDropPosition.X, canvasDropPosition.Y);
|
|
|
|
|
|
if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas))
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeData nodeData)
|
|
|
|
|
|
{
|
|
|
|
|
|
Task.Run(async () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
await EnvDecorator.CreateNodeAsync(nodeData.NodeControlType, position, nodeData.MethodDetailsInfo); // 创建DLL文件的节点对象
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-10-22 00:13:13 +08:00
|
|
|
|
else if (e.Data.GetDataPresent(MouseNodeType.CreateBaseNodeInCanvas))
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
if (e.Data.GetData(MouseNodeType.CreateBaseNodeInCanvas) is Type droppedType)
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
NodeControlType nodeControlType = droppedType switch
|
|
|
|
|
|
{
|
|
|
|
|
|
Type when typeof(ConditionRegionControl).IsAssignableFrom(droppedType) => NodeControlType.ConditionRegion, // 条件区域
|
|
|
|
|
|
Type when typeof(ConditionNodeControl).IsAssignableFrom(droppedType) => NodeControlType.ExpCondition,
|
|
|
|
|
|
Type when typeof(ExpOpNodeControl).IsAssignableFrom(droppedType) => NodeControlType.ExpOp,
|
|
|
|
|
|
_ => NodeControlType.None,
|
|
|
|
|
|
};
|
|
|
|
|
|
if (nodeControlType != NodeControlType.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
Task.Run(async () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
await EnvDecorator.CreateNodeAsync(nodeControlType, position); // 创建基础节点对象
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
2024-09-12 20:32:54 +08:00
|
|
|
|
}
|
2024-10-22 00:13:13 +08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine(ex);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-10-23 19:22:27 +08:00
|
|
|
|
/// 判断是否为区域,如果是,将节点放置在区域中
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="nodeControl"></param>
|
2024-10-15 10:55:41 +08:00
|
|
|
|
/// <param name="position"></param>
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <returns></returns>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private bool TryPlaceNodeInRegion(NodeControlBase nodeControl, PositionOfUI position)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-17 14:20:27 +08:00
|
|
|
|
var point = new Point(position.X, position.Y);
|
|
|
|
|
|
HitTestResult hitTestResult = VisualTreeHelper.HitTest(FlowChartCanvas, point);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
if (hitTestResult != null && hitTestResult.VisualHit is UIElement hitElement)
|
|
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
// 准备放置条件表达式控件
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.ExpCondition)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
ConditionRegionControl? conditionRegion = GetParentOfType<ConditionRegionControl>(hitElement);
|
|
|
|
|
|
if (conditionRegion is not null)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-17 14:20:27 +08:00
|
|
|
|
TryPlaceNodeInRegion(conditionRegion, nodeControl);
|
|
|
|
|
|
//// 如果存在条件区域容器
|
|
|
|
|
|
//conditionRegion.AddCondition(nodeControl);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-17 14:20:27 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将节点放在目标区域中
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="regionControl">区域容器</param>
|
|
|
|
|
|
/// <param name="nodeControl">节点控件</param>
|
|
|
|
|
|
private void TryPlaceNodeInRegion(NodeControlBase regionControl, NodeControlBase nodeControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 准备放置条件表达式控件
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.ExpCondition)
|
2024-09-17 14:20:27 +08:00
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
ConditionRegionControl? conditionRegion = regionControl as ConditionRegionControl;
|
|
|
|
|
|
if (conditionRegion is not null)
|
2024-09-17 14:20:27 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 如果存在条件区域容器
|
|
|
|
|
|
conditionRegion.AddCondition(nodeControl);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 拖动效果,根据拖放数据是否为指定类型设置拖放效果
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void FlowChartCanvas_DragOver(object sender, DragEventArgs e)
|
|
|
|
|
|
{
|
2024-09-15 12:15:32 +08:00
|
|
|
|
if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas)
|
|
|
|
|
|
|| e.Data.GetDataPresent(MouseNodeType.CreateBaseNodeInCanvas))
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
e.Effects = DragDropEffects.Move;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
e.Effects = DragDropEffects.None;
|
|
|
|
|
|
}
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-09-24 22:39:43 +08:00
|
|
|
|
/// 控件的鼠标左键按下事件,启动拖动操作。同时显示当前正在传递的数据。
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Block_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
//if (GlobalJunctionData.IsCreatingConnection)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// return;
|
|
|
|
|
|
//}
|
2024-09-24 22:39:43 +08:00
|
|
|
|
if(sender is NodeControlBase nodeControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
ChangeViewerObjOfNode(nodeControl);
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (nodeControl?.ViewModel?.NodeModel?.MethodDetails?.IsProtectionParameter == true) return;
|
2024-09-24 22:39:43 +08:00
|
|
|
|
IsControlDragging = true;
|
|
|
|
|
|
startControlDragPoint = e.GetPosition(FlowChartCanvas); // 记录鼠标按下时的位置
|
|
|
|
|
|
((UIElement)sender).CaptureMouse(); // 捕获鼠标
|
|
|
|
|
|
e.Handled = true; // 防止事件传播影响其他控件
|
|
|
|
|
|
}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-10-24 23:32:43 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-20 17:11:31 +08:00
|
|
|
|
/// 控件的鼠标移动事件,根据鼠标拖动更新控件的位置。批量移动计算移动逻辑。
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Block_MouseMove(object sender, MouseEventArgs e)
|
|
|
|
|
|
{
|
2024-09-20 10:50:32 +08:00
|
|
|
|
if (IsCanvasDragging)
|
|
|
|
|
|
return;
|
|
|
|
|
|
if (IsSelectControl)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
if (IsControlDragging) // 如果正在拖动控件
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-20 17:11:31 +08:00
|
|
|
|
Point currentPosition = e.GetPosition(FlowChartCanvas); // 获取当前鼠标位置
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
|
|
|
|
|
if (selectNodeControls.Count > 0 && sender is NodeControlBase nodeControlMain && selectNodeControls.Contains(nodeControlMain))
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-15 21:56:09 +08:00
|
|
|
|
// 进行批量移动
|
|
|
|
|
|
// 获取旧位置
|
|
|
|
|
|
var oldLeft = Canvas.GetLeft(nodeControlMain);
|
|
|
|
|
|
var oldTop = Canvas.GetTop(nodeControlMain);
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
// 计算被选择控件的偏移量
|
2024-10-15 21:56:09 +08:00
|
|
|
|
var deltaX = /*(int)*/(currentPosition.X - startControlDragPoint.X);
|
|
|
|
|
|
var deltaY = /*(int)*/(currentPosition.Y - startControlDragPoint.Y);
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
// 移动被选择的控件
|
2024-10-15 21:56:09 +08:00
|
|
|
|
var newLeft = oldLeft + deltaX;
|
|
|
|
|
|
var newTop = oldTop + deltaY;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-10-20 21:59:42 +08:00
|
|
|
|
this.EnvDecorator.MoveNode(nodeControlMain.ViewModel.NodeModel.Guid, newLeft, newTop); // 移动节点
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 计算控件实际移动的距离
|
|
|
|
|
|
var actualDeltaX = newLeft - oldLeft;
|
|
|
|
|
|
var actualDeltaY = newTop - oldTop;
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
|
|
|
|
|
// 移动其它选中的控件
|
|
|
|
|
|
foreach (var nodeControl in selectNodeControls)
|
|
|
|
|
|
{
|
2024-10-15 21:56:09 +08:00
|
|
|
|
if (nodeControl != nodeControlMain) // 跳过已经移动的控件
|
2024-09-20 17:11:31 +08:00
|
|
|
|
{
|
2024-10-15 21:56:09 +08:00
|
|
|
|
var otherNewLeft = Canvas.GetLeft(nodeControl) + actualDeltaX;
|
|
|
|
|
|
var otherNewTop = Canvas.GetTop(nodeControl) + actualDeltaY;
|
2024-10-20 21:59:42 +08:00
|
|
|
|
this.EnvDecorator.MoveNode(nodeControl.ViewModel.NodeModel.Guid, otherNewLeft, otherNewTop); // 移动节点
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
|
|
|
|
|
// 更新节点之间线的连接位置
|
2024-09-20 17:11:31 +08:00
|
|
|
|
foreach (var nodeControl in selectNodeControls)
|
|
|
|
|
|
{
|
2024-10-24 23:32:43 +08:00
|
|
|
|
nodeControl.UpdateLocationConnections();
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}
|
2024-09-09 21:06:47 +08:00
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
else
|
2024-10-15 21:56:09 +08:00
|
|
|
|
{ // 单个节点移动
|
|
|
|
|
|
if (sender is not NodeControlBase nodeControl)
|
2024-09-20 17:11:31 +08:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
double deltaX = currentPosition.X - startControlDragPoint.X; // 计算X轴方向的偏移量
|
|
|
|
|
|
double deltaY = currentPosition.Y - startControlDragPoint.Y; // 计算Y轴方向的偏移量
|
2024-10-15 21:56:09 +08:00
|
|
|
|
double newLeft = Canvas.GetLeft(nodeControl) + deltaX; // 新的左边距
|
|
|
|
|
|
double newTop = Canvas.GetTop(nodeControl) + deltaY; // 新的上边距
|
2024-10-20 21:59:42 +08:00
|
|
|
|
this.EnvDecorator.MoveNode(nodeControl.ViewModel.NodeModel.Guid, newLeft, newTop); // 移动节点
|
2024-10-24 23:32:43 +08:00
|
|
|
|
nodeControl.UpdateLocationConnections();
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
startControlDragPoint = currentPosition; // 更新起始点位置
|
2024-09-15 12:15:32 +08:00
|
|
|
|
}
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
// 改变对象树?
|
2024-09-26 21:00:17 +08:00
|
|
|
|
private void ChangeViewerObjOfNode(NodeControlBase nodeControl)
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
var node = nodeControl.ViewModel.NodeModel;
|
2024-09-27 23:47:25 +08:00
|
|
|
|
//if (node is not null && (node.MethodDetails is null || node.MethodDetails.ReturnType != typeof(void))
|
2024-09-30 22:20:02 +08:00
|
|
|
|
if (node is not null && node.MethodDetails?.ReturnType != typeof(void))
|
2024-09-26 21:00:17 +08:00
|
|
|
|
{
|
|
|
|
|
|
var key = node.Guid;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
object instance = null;
|
|
|
|
|
|
//Console.WriteLine("WindowXaml 后台代码中 ChangeViewerObjOfNode 需要重新设计");
|
|
|
|
|
|
//var instance = node.GetFlowData(); // 对象预览树视图获取(后期更改)
|
2024-09-30 22:20:02 +08:00
|
|
|
|
if(instance is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewObjectViewer.LoadObjectInformation(key, instance);
|
|
|
|
|
|
ChangeViewerObj(key, instance);
|
|
|
|
|
|
}
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public void ChangeViewerObj(string key, object instance)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (ViewObjectViewer.MonitorObj is null)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.SetMonitorObjState(key, true); // 通知环境,该节点的数据更新后需要传到UI
|
2024-09-26 21:00:17 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (instance is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (key.Equals(ViewObjectViewer.MonitorKey) == true)
|
|
|
|
|
|
{
|
|
|
|
|
|
ViewObjectViewer.RefreshObjectTree(instance);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.SetMonitorObjState(ViewObjectViewer.MonitorKey,false); // 取消对旧节点的监视
|
|
|
|
|
|
EnvDecorator.SetMonitorObjState(key, true); // 通知环境,该节点的数据更新后需要传到UI
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
#endregion
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
#region UI连接控件操作
|
|
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-10-27 00:54:10 +08:00
|
|
|
|
/// 控件的鼠标左键松开事件,结束拖动操作
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void Block_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
2024-09-09 16:42:01 +08:00
|
|
|
|
if (IsControlDragging)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-09-09 16:42:01 +08:00
|
|
|
|
IsControlDragging = false;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
((UIElement)sender).ReleaseMouseCapture(); // 释放鼠标捕获
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
//if (IsConnecting)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// var formNodeGuid = startConnectNodeControl?.ViewModel.NodeModel.Guid;
|
|
|
|
|
|
// var toNodeGuid = (sender as NodeControlBase)?.ViewModel.NodeModel.Guid;
|
|
|
|
|
|
// if (string.IsNullOrEmpty(formNodeGuid) || string.IsNullOrEmpty(toNodeGuid))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// return;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// EnvDecorator.ConnectNodeAsync(formNodeGuid, toNodeGuid,0,0, currentConnectionType);
|
|
|
|
|
|
//}
|
|
|
|
|
|
//GlobalJunctionData.OK();
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 结束连接操作,清理状态并移除虚线。
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void EndConnection()
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
Mouse.OverrideCursor = null; // 恢复视觉效果
|
|
|
|
|
|
ViewModel.IsConnectionArgSourceNode = false;
|
|
|
|
|
|
ViewModel.IsConnectionInvokeNode = false;
|
|
|
|
|
|
GlobalJunctionData.OK();
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-10 11:05:48 +08:00
|
|
|
|
#region 拖动画布实现缩放平移效果
|
|
|
|
|
|
private void FlowChartCanvas_MouseDown(object sender, MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
2024-09-20 10:50:32 +08:00
|
|
|
|
IsCanvasDragging = true;
|
|
|
|
|
|
startCanvasDragPoint = e.GetPosition(this);
|
|
|
|
|
|
FlowChartCanvas.CaptureMouse();
|
|
|
|
|
|
e.Handled = true; // 防止事件传播影响其他控件
|
2024-09-10 11:05:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void FlowChartCanvas_MouseUp(object sender, MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-10 11:05:48 +08:00
|
|
|
|
if (IsCanvasDragging)
|
|
|
|
|
|
{
|
|
|
|
|
|
IsCanvasDragging = false;
|
|
|
|
|
|
FlowChartCanvas.ReleaseMouseCapture();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 单纯缩放画布,不改变画布大小
|
|
|
|
|
|
private void FlowChartCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
|
|
|
|
|
{
|
2024-09-20 10:50:32 +08:00
|
|
|
|
// if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
2024-09-10 11:05:48 +08:00
|
|
|
|
{
|
2024-09-27 23:47:25 +08:00
|
|
|
|
if (e.Delta < 0 && scaleTransform.ScaleX < 0.05) return;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
if (e.Delta > 0 && scaleTransform.ScaleY > 2.0) return;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
// 获取鼠标在 Canvas 内的相对位置
|
|
|
|
|
|
var mousePosition = e.GetPosition(FlowChartCanvas);
|
|
|
|
|
|
|
|
|
|
|
|
// 缩放因子,根据滚轮方向调整
|
2024-09-27 23:47:25 +08:00
|
|
|
|
//double zoomFactor = e.Delta > 0 ? 0.1 : -0.1;
|
|
|
|
|
|
double zoomFactor = e.Delta > 0 ? 1.1 : 0.9;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
|
|
|
|
|
// 当前缩放比例
|
|
|
|
|
|
double oldScale = scaleTransform.ScaleX;
|
2024-09-27 23:47:25 +08:00
|
|
|
|
double newScale = oldScale * zoomFactor;
|
|
|
|
|
|
//double newScale = oldScale + zoomFactor;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
// 更新缩放比例
|
|
|
|
|
|
scaleTransform.ScaleX = newScale;
|
|
|
|
|
|
scaleTransform.ScaleY = newScale;
|
|
|
|
|
|
|
|
|
|
|
|
// 计算缩放前后鼠标相对于 Canvas 的位置差异
|
|
|
|
|
|
// double offsetX = mousePosition.X - (mousePosition.X * zoomFactor);
|
|
|
|
|
|
// double offsetY = mousePosition.Y - (mousePosition.Y * zoomFactor);
|
|
|
|
|
|
|
|
|
|
|
|
// 更新 TranslateTransform,确保以鼠标位置为中心进行缩放
|
|
|
|
|
|
translateTransform.X -= (mousePosition.X * (newScale - oldScale));
|
|
|
|
|
|
translateTransform.Y -= (mousePosition.Y * (newScale - oldScale));
|
2024-09-10 11:05:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 设置画布宽度高度
|
|
|
|
|
|
private void InitializeCanvas(double width, double height)
|
|
|
|
|
|
{
|
|
|
|
|
|
FlowChartCanvas.Width = width;
|
|
|
|
|
|
FlowChartCanvas.Height = height;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region 动态调整区域大小
|
2024-09-10 11:49:56 +08:00
|
|
|
|
//private void Thumb_DragDelta_TopLeft(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 从左上角调整大小
|
|
|
|
|
|
// double newWidth = Math.Max(FlowChartCanvas.ActualWidth - e.HorizontalChange, 0);
|
|
|
|
|
|
// double newHeight = Math.Max(FlowChartCanvas.ActualHeight - e.VerticalChange, 0);
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// FlowChartCanvas.Width = newWidth;
|
|
|
|
|
|
// FlowChartCanvas.Height = newHeight;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// Canvas.SetLeft(FlowChartCanvas, Canvas.GetLeft(FlowChartCanvas) + e.HorizontalChange);
|
|
|
|
|
|
// Canvas.SetTop(FlowChartCanvas, Canvas.GetTop(FlowChartCanvas) + e.VerticalChange);
|
|
|
|
|
|
//}
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
//private void Thumb_DragDelta_TopRight(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 从右上角调整大小
|
|
|
|
|
|
// double newWidth = Math.Max(FlowChartCanvas.ActualWidth + e.HorizontalChange, 0);
|
|
|
|
|
|
// double newHeight = Math.Max(FlowChartCanvas.ActualHeight - e.VerticalChange, 0);
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// FlowChartCanvas.Width = newWidth;
|
|
|
|
|
|
// FlowChartCanvas.Height = newHeight;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// Canvas.SetTop(FlowChartCanvas, Canvas.GetTop(FlowChartCanvas) + e.VerticalChange);
|
|
|
|
|
|
//}
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
//private void Thumb_DragDelta_BottomLeft(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 从左下角调整大小
|
|
|
|
|
|
// double newWidth = Math.Max(FlowChartCanvas.ActualWidth - e.HorizontalChange, 0);
|
|
|
|
|
|
// double newHeight = Math.Max(FlowChartCanvas.ActualHeight + e.VerticalChange, 0);
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// FlowChartCanvas.Width = newWidth;
|
|
|
|
|
|
// FlowChartCanvas.Height = newHeight;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// Canvas.SetLeft(FlowChartCanvas, Canvas.GetLeft(FlowChartCanvas) + e.HorizontalChange);
|
|
|
|
|
|
//}
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
|
|
|
|
|
private void Thumb_DragDelta_BottomRight(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
{
|
2024-09-17 14:20:27 +08:00
|
|
|
|
// 获取缩放后的水平和垂直变化
|
|
|
|
|
|
double horizontalChange = e.HorizontalChange * scaleTransform.ScaleX;
|
|
|
|
|
|
double verticalChange = e.VerticalChange * scaleTransform.ScaleY;
|
2024-09-10 11:49:56 +08:00
|
|
|
|
|
2024-09-17 14:20:27 +08:00
|
|
|
|
// 计算新的宽度和高度,确保不会小于400
|
|
|
|
|
|
double newWidth = Math.Max(FlowChartCanvas.ActualWidth + horizontalChange, 400);
|
|
|
|
|
|
double newHeight = Math.Max(FlowChartCanvas.ActualHeight + verticalChange, 400);
|
2024-09-10 11:49:56 +08:00
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
newHeight = newHeight < 400 ? 400 : newHeight;
|
|
|
|
|
|
newWidth = newWidth < 400 ? 400 : newWidth;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
InitializeCanvas(newWidth, newHeight);
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
|
|
|
|
|
//// 从右下角调整大小
|
|
|
|
|
|
//double newWidth = Math.Max(FlowChartCanvas.ActualWidth + e.HorizontalChange * scaleTransform.ScaleX, 0);
|
|
|
|
|
|
//double newHeight = Math.Max(FlowChartCanvas.ActualHeight + e.VerticalChange * scaleTransform.ScaleY, 0);
|
|
|
|
|
|
|
|
|
|
|
|
//newWidth = newWidth < 400 ? 400 : newWidth;
|
|
|
|
|
|
//newHeight = newHeight < 400 ? 400 : newHeight;
|
|
|
|
|
|
|
|
|
|
|
|
//if (newWidth > 400 && newHeight > 400)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// FlowChartCanvas.Width = newWidth;
|
|
|
|
|
|
// FlowChartCanvas.Height = newHeight;
|
|
|
|
|
|
|
|
|
|
|
|
// double x = e.HorizontalChange > 0 ? -0.5 : 0.5;
|
|
|
|
|
|
// double y = e.VerticalChange > 0 ? -0.5 : 0.5;
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
2024-09-17 14:20:27 +08:00
|
|
|
|
// double deltaX = x * scaleTransform.ScaleX;
|
|
|
|
|
|
// double deltaY = y * scaleTransform.ScaleY;
|
|
|
|
|
|
// Test(deltaX, deltaY);
|
|
|
|
|
|
//}
|
2024-09-10 11:05:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
//private void Thumb_DragDelta_Left(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 从左侧调整大小
|
|
|
|
|
|
// double newWidth = Math.Max(FlowChartCanvas.ActualWidth - e.HorizontalChange, 0);
|
|
|
|
|
|
|
|
|
|
|
|
// FlowChartCanvas.Width = newWidth;
|
|
|
|
|
|
// Canvas.SetLeft(FlowChartCanvas, Canvas.GetLeft(FlowChartCanvas) + e.HorizontalChange);
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
2024-09-10 11:05:48 +08:00
|
|
|
|
private void Thumb_DragDelta_Right(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
//从右侧调整大小
|
2024-09-18 16:45:41 +08:00
|
|
|
|
// 获取缩放后的水平变化
|
2024-09-17 14:20:27 +08:00
|
|
|
|
double horizontalChange = e.HorizontalChange * scaleTransform.ScaleX;
|
|
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
// 计算新的宽度,确保不会小于400
|
2024-09-17 14:20:27 +08:00
|
|
|
|
double newWidth = Math.Max(FlowChartCanvas.ActualWidth + horizontalChange, 400);
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
|
|
|
|
|
newWidth = newWidth < 400 ? 400 : newWidth;
|
|
|
|
|
|
InitializeCanvas(newWidth, FlowChartCanvas.Height);
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-09-10 11:05:48 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
//private void Thumb_DragDelta_Top(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// // 从顶部调整大小
|
|
|
|
|
|
// double newHeight = Math.Max(FlowChartCanvas.ActualHeight - e.VerticalChange, 0);
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-09-10 11:49:56 +08:00
|
|
|
|
// FlowChartCanvas.Height = newHeight;
|
|
|
|
|
|
// Canvas.SetTop(FlowChartCanvas, Canvas.GetTop(FlowChartCanvas) + e.VerticalChange);
|
|
|
|
|
|
//}
|
2024-09-10 11:05:48 +08:00
|
|
|
|
|
|
|
|
|
|
private void Thumb_DragDelta_Bottom(object sender, DragDeltaEventArgs e)
|
|
|
|
|
|
{
|
2024-09-18 16:45:41 +08:00
|
|
|
|
// 获取缩放后的垂直变化
|
|
|
|
|
|
double verticalChange = e.VerticalChange * scaleTransform.ScaleY;
|
|
|
|
|
|
// 计算新的高度,确保不会小于400
|
|
|
|
|
|
double newHeight = Math.Max(FlowChartCanvas.ActualHeight + verticalChange, 400);
|
|
|
|
|
|
newHeight = newHeight < 400 ? 400 : newHeight;
|
|
|
|
|
|
InitializeCanvas(FlowChartCanvas.Width, newHeight);
|
|
|
|
|
|
}
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
private void Test(double deltaX, double deltaY)
|
|
|
|
|
|
{
|
|
|
|
|
|
//Console.WriteLine((translateTransform.X, translateTransform.Y));
|
|
|
|
|
|
//translateTransform.X += deltaX;
|
|
|
|
|
|
//translateTransform.Y += deltaY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#endregion
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
#endregion
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
#region 画布中框选节点控件动作
|
2024-09-17 14:20:27 +08:00
|
|
|
|
|
2024-09-18 16:45:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 在画布中尝试选取控件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
if (GlobalJunctionData.MyGlobalConnectingData.IsCreateing)
|
2024-10-23 19:22:27 +08:00
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-21 10:06:44 +08:00
|
|
|
|
if (!IsSelectControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 进入选取状态
|
|
|
|
|
|
IsSelectControl = true;
|
|
|
|
|
|
IsSelectDragging = false; // 初始化为非拖动状态
|
|
|
|
|
|
|
|
|
|
|
|
// 记录鼠标起始点
|
|
|
|
|
|
startSelectControolPoint = e.GetPosition(FlowChartCanvas);
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化选取矩形的位置和大小
|
|
|
|
|
|
Canvas.SetLeft(SelectionRectangle, startSelectControolPoint.X);
|
|
|
|
|
|
Canvas.SetTop(SelectionRectangle, startSelectControolPoint.Y);
|
|
|
|
|
|
SelectionRectangle.Width = 0;
|
|
|
|
|
|
SelectionRectangle.Height = 0;
|
|
|
|
|
|
|
|
|
|
|
|
// 显示选取矩形
|
|
|
|
|
|
SelectionRectangle.Visibility = Visibility.Visible;
|
|
|
|
|
|
SelectionRectangle.ContextMenu ??= ConfiguerSelectionRectangle();
|
|
|
|
|
|
|
|
|
|
|
|
// 捕获鼠标,以便在鼠标移动到Canvas外部时仍能处理事件
|
|
|
|
|
|
FlowChartCanvas.CaptureMouse();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
// 如果已经是选取状态,单击则认为结束框选
|
|
|
|
|
|
CompleteSelection();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
e.Handled = true; // 防止事件传播影响其他控件
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-21 10:06:44 +08:00
|
|
|
|
/// <summary>
|
2024-10-24 23:32:43 +08:00
|
|
|
|
/// 在画布中释放鼠标按下,结束选取状态 / 停止创建连线,尝试连接节点
|
2024-09-21 10:06:44 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsSelectControl)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 松开鼠标时判断是否为拖动操作
|
|
|
|
|
|
if (IsSelectDragging)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 完成拖动框选
|
|
|
|
|
|
CompleteSelection();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 释放鼠标捕获
|
|
|
|
|
|
FlowChartCanvas.ReleaseMouseCapture();
|
|
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
// 创建连线
|
2024-10-27 00:54:10 +08:00
|
|
|
|
if (GlobalJunctionData.MyGlobalConnectingData is ConnectingData myData && myData.IsCreateing)
|
2024-10-23 19:22:27 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (myData.IsCanConnected)
|
2024-10-23 19:22:27 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
var canvas = this.FlowChartCanvas;
|
2024-10-23 19:22:27 +08:00
|
|
|
|
var currentendPoint = e.GetPosition(canvas); // 当前鼠标落点
|
2024-10-24 23:32:43 +08:00
|
|
|
|
var changingJunctionPosition = myData.CurrentJunction.TranslatePoint(new Point(0, 0), canvas);
|
|
|
|
|
|
var changingJunctionRect = new Rect(changingJunctionPosition, new Size(myData.CurrentJunction.Width, myData.CurrentJunction.Height));
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
if (changingJunctionRect.Contains(currentendPoint)) // 可以创建连接
|
2024-10-23 19:22:27 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
#region 方法调用关系创建
|
|
|
|
|
|
if (myData.Type == JunctionOfConnectionType.Invoke)
|
2024-10-24 23:32:43 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
this.EnvDecorator.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)
|
2024-10-24 23:32:43 +08:00
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
var argIndex = 0;
|
|
|
|
|
|
if (myData.StartJunction is ArgJunctionControl argJunction1)
|
|
|
|
|
|
{
|
|
|
|
|
|
argIndex = argJunction1.ArgIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (myData.CurrentJunction is ArgJunctionControl argJunction2)
|
|
|
|
|
|
{
|
|
|
|
|
|
argIndex = argJunction2.ArgIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.EnvDecorator.ConnectArgSourceNodeAsync(myData.StartJunction.MyNode.Guid, myData.CurrentJunction.MyNode.Guid,
|
|
|
|
|
|
myData.StartJunction.JunctionType,
|
|
|
|
|
|
myData.CurrentJunction.JunctionType,
|
|
|
|
|
|
myData.ConnectionArgSourceType,
|
|
|
|
|
|
argIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-10-24 23:32:43 +08:00
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
EndConnection();
|
2024-10-23 19:22:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-09-21 10:06:44 +08:00
|
|
|
|
e.Handled = true;
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
2024-09-21 10:06:44 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// 完成选取操作
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void CompleteSelection()
|
|
|
|
|
|
{
|
|
|
|
|
|
IsSelectControl = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 隐藏选取矩形
|
|
|
|
|
|
SelectionRectangle.Visibility = Visibility.Collapsed;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取选取范围
|
|
|
|
|
|
Rect selectionArea = new Rect(Canvas.GetLeft(SelectionRectangle),
|
|
|
|
|
|
Canvas.GetTop(SelectionRectangle),
|
|
|
|
|
|
SelectionRectangle.Width,
|
|
|
|
|
|
SelectionRectangle.Height);
|
|
|
|
|
|
|
|
|
|
|
|
// 处理选取范围内的控件
|
|
|
|
|
|
// selectNodeControls.Clear();
|
|
|
|
|
|
foreach (UIElement element in FlowChartCanvas.Children)
|
|
|
|
|
|
{
|
|
|
|
|
|
Rect elementBounds = new Rect(Canvas.GetLeft(element), Canvas.GetTop(element),
|
|
|
|
|
|
element.RenderSize.Width, element.RenderSize.Height);
|
|
|
|
|
|
|
|
|
|
|
|
if (selectionArea.Contains(elementBounds))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (element is NodeControlBase control)
|
|
|
|
|
|
{
|
|
|
|
|
|
selectNodeControls.Add(control);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 选中后的操作
|
|
|
|
|
|
SelectedNode();
|
|
|
|
|
|
}
|
2024-09-18 16:45:41 +08:00
|
|
|
|
private ContextMenu ConfiguerSelectionRectangle()
|
|
|
|
|
|
{
|
|
|
|
|
|
var contextMenu = new ContextMenu();
|
|
|
|
|
|
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) =>
|
2024-09-17 14:20:27 +08:00
|
|
|
|
{
|
2024-09-21 10:06:44 +08:00
|
|
|
|
if (selectNodeControls.Count > 0)
|
2024-09-18 16:45:41 +08:00
|
|
|
|
{
|
2024-09-21 10:06:44 +08:00
|
|
|
|
foreach (var node in selectNodeControls.ToArray())
|
2024-09-18 16:45:41 +08:00
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
var guid = node?.ViewModel?.NodeModel?.Guid;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
if (!string.IsNullOrEmpty(guid))
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
EnvDecorator.RemoveNodeAsync(guid);
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
SelectionRectangle.Visibility = Visibility.Collapsed;
|
|
|
|
|
|
}));
|
|
|
|
|
|
return contextMenu;
|
|
|
|
|
|
// nodeControl.ContextMenu = contextMenu;
|
|
|
|
|
|
}
|
|
|
|
|
|
private void SelectedNode()
|
|
|
|
|
|
{
|
2024-09-24 22:39:43 +08:00
|
|
|
|
|
|
|
|
|
|
if (selectNodeControls.Count == 0)
|
2024-09-18 16:45:41 +08:00
|
|
|
|
{
|
2024-09-21 10:06:44 +08:00
|
|
|
|
//Console.WriteLine($"没有选择控件");
|
2024-09-20 10:50:32 +08:00
|
|
|
|
SelectionRectangle.Visibility = Visibility.Collapsed;
|
2024-09-18 16:45:41 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-24 22:39:43 +08:00
|
|
|
|
if(selectNodeControls.Count == 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
// ChangeViewerObjOfNode(selectNodeControls[0]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
//Console.WriteLine($"一共选取了{selectNodeControls.Count}个控件");
|
2024-09-18 16:45:41 +08:00
|
|
|
|
foreach (var node in selectNodeControls)
|
|
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
//node.ViewModel.IsSelect =true;
|
2024-09-21 10:06:44 +08:00
|
|
|
|
// node.ViewModel.CancelSelect();
|
2024-09-20 10:50:32 +08:00
|
|
|
|
node.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFC700"));
|
|
|
|
|
|
node.BorderThickness = new Thickness(4);
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
private void CancelSelectNode()
|
|
|
|
|
|
{
|
2024-09-20 17:11:31 +08:00
|
|
|
|
IsSelectControl = false;
|
|
|
|
|
|
foreach (var nodeControl in selectNodeControls)
|
2024-09-18 16:45:41 +08:00
|
|
|
|
{
|
2024-10-22 00:13:13 +08:00
|
|
|
|
//nodeControl.ViewModel.IsSelect = false;
|
2024-09-20 17:11:31 +08:00
|
|
|
|
nodeControl.BorderBrush = Brushes.Black;
|
|
|
|
|
|
nodeControl.BorderThickness = new Thickness(0);
|
2024-10-20 21:59:42 +08:00
|
|
|
|
if (nodeControl.ViewModel.NodeModel.IsStart)
|
2024-09-20 17:11:31 +08:00
|
|
|
|
{
|
|
|
|
|
|
nodeControl.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"));
|
|
|
|
|
|
nodeControl.BorderThickness = new Thickness(2);
|
|
|
|
|
|
}
|
2024-09-18 16:45:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
selectNodeControls.Clear();
|
|
|
|
|
|
}
|
2024-09-10 11:05:48 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
#region 节点对齐 (有些小瑕疵)
|
|
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
//public void UpdateConnectedLines()
|
|
|
|
|
|
//{
|
|
|
|
|
|
// //foreach (var nodeControl in selectNodeControls)
|
|
|
|
|
|
// //{
|
|
|
|
|
|
// // UpdateConnections(nodeControl);
|
|
|
|
|
|
// //}
|
|
|
|
|
|
// this.Dispatcher.Invoke(() =>
|
|
|
|
|
|
// {
|
|
|
|
|
|
// foreach (var line in Connections)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// line.AddOrRefreshLine(); // 节点完成对齐
|
|
|
|
|
|
// }
|
|
|
|
|
|
// });
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
//}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region Plan A 群组对齐
|
|
|
|
|
|
|
|
|
|
|
|
public void AlignControlsWithGrouping(List<NodeControlBase> selectNodeControls, double proximityThreshold = 50, double spacing = 10)
|
|
|
|
|
|
{
|
2024-09-25 22:20:23 +08:00
|
|
|
|
if (selectNodeControls is null || selectNodeControls.Count < 2)
|
2024-09-20 17:11:31 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
// 按照控件的相对位置进行分组
|
|
|
|
|
|
var horizontalGroups = GroupByProximity(selectNodeControls, proximityThreshold, isHorizontal: true);
|
|
|
|
|
|
var verticalGroups = GroupByProximity(selectNodeControls, proximityThreshold, isHorizontal: false);
|
|
|
|
|
|
|
|
|
|
|
|
// 对每个水平群组进行垂直对齐
|
|
|
|
|
|
foreach (var group in horizontalGroups)
|
|
|
|
|
|
{
|
|
|
|
|
|
double avgY = group.Average(c => Canvas.GetTop(c)); // 计算Y坐标平均值
|
|
|
|
|
|
foreach (var control in group)
|
|
|
|
|
|
{
|
|
|
|
|
|
Canvas.SetTop(control, avgY); // 对齐Y坐标
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 对每个垂直群组进行水平对齐
|
|
|
|
|
|
foreach (var group in verticalGroups)
|
|
|
|
|
|
{
|
|
|
|
|
|
double avgX = group.Average(c => Canvas.GetLeft(c)); // 计算X坐标平均值
|
|
|
|
|
|
foreach (var control in group)
|
|
|
|
|
|
{
|
|
|
|
|
|
Canvas.SetLeft(control, avgX); // 对齐X坐标
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 基于控件间的距离来分组,按水平或垂直方向
|
|
|
|
|
|
private List<List<NodeControlBase>> GroupByProximity(List<NodeControlBase> controls, double proximityThreshold, bool isHorizontal)
|
|
|
|
|
|
{
|
|
|
|
|
|
var groups = new List<List<NodeControlBase>>();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var control in controls)
|
|
|
|
|
|
{
|
|
|
|
|
|
bool addedToGroup = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 尝试将控件加入现有的群组
|
|
|
|
|
|
foreach (var group in groups)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsInProximity(group, control, proximityThreshold, isHorizontal))
|
|
|
|
|
|
{
|
|
|
|
|
|
group.Add(control);
|
|
|
|
|
|
addedToGroup = true;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果没有加入任何群组,创建新群组
|
|
|
|
|
|
if (!addedToGroup)
|
|
|
|
|
|
{
|
|
|
|
|
|
groups.Add(new List<NodeControlBase> { control });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return groups;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 判断控件是否接近某个群组
|
|
|
|
|
|
private bool IsInProximity(List<NodeControlBase> group, NodeControlBase control, double proximityThreshold, bool isHorizontal)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var existingControl in group)
|
|
|
|
|
|
{
|
|
|
|
|
|
double distance = isHorizontal
|
|
|
|
|
|
? Math.Abs(Canvas.GetTop(existingControl) - Canvas.GetTop(control)) // 垂直方向的距离
|
|
|
|
|
|
: Math.Abs(Canvas.GetLeft(existingControl) - Canvas.GetLeft(control)); // 水平方向的距离
|
|
|
|
|
|
|
|
|
|
|
|
if (distance <= proximityThreshold)
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region Plan B 规划对齐
|
|
|
|
|
|
public void AlignControlsWithDynamicProgramming(List<NodeControlBase> selectNodeControls, double spacing = 10)
|
|
|
|
|
|
{
|
2024-09-25 22:20:23 +08:00
|
|
|
|
if (selectNodeControls is null || selectNodeControls.Count < 2)
|
2024-09-20 17:11:31 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
int n = selectNodeControls.Count;
|
|
|
|
|
|
double[] dp = new double[n];
|
|
|
|
|
|
int[] split = new int[n];
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化动态规划数组
|
|
|
|
|
|
for (int i = 1; i < n; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
dp[i] = double.MaxValue;
|
|
|
|
|
|
for (int j = 0; j < i; j++)
|
|
|
|
|
|
{
|
|
|
|
|
|
double cost = CalculateAlignmentCost(selectNodeControls, j, i, spacing);
|
|
|
|
|
|
if (dp[j] + cost < dp[i])
|
|
|
|
|
|
{
|
|
|
|
|
|
dp[i] = dp[j] + cost;
|
|
|
|
|
|
split[i] = j;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 回溯找到最优的对齐方式
|
|
|
|
|
|
AlignWithSplit(selectNodeControls, split, n - 1, spacing);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算从控件[j]到控件[i]的对齐代价,并考虑控件的大小和间距
|
|
|
|
|
|
private double CalculateAlignmentCost(List<NodeControlBase> controls, int start, int end, double spacing)
|
|
|
|
|
|
{
|
|
|
|
|
|
double totalWidth = 0;
|
|
|
|
|
|
double totalHeight = 0;
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = start; i <= end; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
totalWidth += controls[i].ActualWidth;
|
|
|
|
|
|
totalHeight += controls[i].ActualHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 水平和垂直方向代价计算,包括控件大小和间距
|
|
|
|
|
|
double widthCost = totalWidth + (end - start) * spacing;
|
|
|
|
|
|
double heightCost = totalHeight + (end - start) * spacing;
|
|
|
|
|
|
|
|
|
|
|
|
// 返回较小的代价,表示更优的对齐方式
|
|
|
|
|
|
return Math.Min(widthCost, heightCost);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 根据split数组调整控件位置,确保控件不重叠
|
|
|
|
|
|
private void AlignWithSplit(List<NodeControlBase> controls, int[] split, int end, double spacing)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (end <= 0)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
AlignWithSplit(controls, split, split[end], spacing);
|
|
|
|
|
|
|
|
|
|
|
|
// 从split[end]到end的控件进行对齐操作
|
|
|
|
|
|
double currentX = Canvas.GetLeft(controls[split[end]]);
|
|
|
|
|
|
double currentY = Canvas.GetTop(controls[split[end]]);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = split[end] + 1; i <= end; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 水平或垂直对齐,确保控件之间有间距
|
|
|
|
|
|
if (currentX + controls[i].ActualWidth + spacing <= Canvas.GetLeft(controls[end]))
|
|
|
|
|
|
{
|
|
|
|
|
|
Canvas.SetLeft(controls[i], currentX + controls[i].ActualWidth + spacing);
|
|
|
|
|
|
currentX += controls[i].ActualWidth + spacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Canvas.SetTop(controls[i], currentY + controls[i].ActualHeight + spacing);
|
|
|
|
|
|
currentY += controls[i].ActualHeight + spacing;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-22 14:10:13 +08:00
|
|
|
|
public enum AlignMode
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 水平对齐
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
Horizontal,
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 垂直对齐
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
Vertical,
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 水平中心对齐
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
HorizontalCenter,
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 垂直中心对齐
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
VerticalCenter,
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 规划对齐
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
Planning,
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 群组对齐
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
Grouping,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public void AlignControlsWithGrouping(List<NodeControlBase> selectNodeControls, AlignMode alignMode, double proximityThreshold = 50, double spacing = 10)
|
|
|
|
|
|
{
|
2024-09-25 22:20:23 +08:00
|
|
|
|
if (selectNodeControls is null || selectNodeControls.Count < 2)
|
2024-09-22 14:10:13 +08:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
switch (alignMode)
|
|
|
|
|
|
{
|
|
|
|
|
|
case AlignMode.Horizontal:
|
|
|
|
|
|
AlignHorizontally(selectNodeControls, spacing);// AlignToCenter
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case AlignMode.Vertical:
|
|
|
|
|
|
|
|
|
|
|
|
AlignVertically(selectNodeControls, spacing);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case AlignMode.HorizontalCenter:
|
|
|
|
|
|
AlignToCenter(selectNodeControls, isHorizontal: false, spacing);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case AlignMode.VerticalCenter:
|
|
|
|
|
|
AlignToCenter(selectNodeControls, isHorizontal: true, spacing);
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case AlignMode.Planning:
|
|
|
|
|
|
AlignControlsWithDynamicProgramming(selectNodeControls, spacing);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case AlignMode.Grouping:
|
|
|
|
|
|
AlignControlsWithGrouping(selectNodeControls, proximityThreshold, spacing);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 垂直对齐并避免重叠
|
|
|
|
|
|
private void AlignHorizontally(List<NodeControlBase> controls, double spacing)
|
|
|
|
|
|
{
|
|
|
|
|
|
double avgY = controls.Average(c => Canvas.GetTop(c)); // 计算Y坐标平均值
|
|
|
|
|
|
double currentY = avgY;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var control in controls.OrderBy(c => Canvas.GetTop(c))) // 按Y坐标排序对齐
|
|
|
|
|
|
{
|
|
|
|
|
|
Canvas.SetTop(control, currentY);
|
|
|
|
|
|
currentY += control.ActualHeight + spacing; // 保证控件之间有足够的垂直间距
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 水平对齐并避免重叠
|
|
|
|
|
|
private void AlignVertically(List<NodeControlBase> controls, double spacing)
|
|
|
|
|
|
{
|
|
|
|
|
|
double avgX = controls.Average(c => Canvas.GetLeft(c)); // 计算X坐标平均值
|
|
|
|
|
|
double currentX = avgX;
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var control in controls.OrderBy(c => Canvas.GetLeft(c))) // 按X坐标排序对齐
|
|
|
|
|
|
{
|
|
|
|
|
|
Canvas.SetLeft(control, currentX);
|
|
|
|
|
|
currentX += control.ActualWidth + spacing; // 保证控件之间有足够的水平间距
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 按中心点对齐
|
|
|
|
|
|
private void AlignToCenter(List<NodeControlBase> controls, bool isHorizontal, double spacing)
|
|
|
|
|
|
{
|
|
|
|
|
|
double avgCenter = isHorizontal
|
|
|
|
|
|
? controls.Average(c => Canvas.GetLeft(c) + c.ActualWidth / 2) // 水平中心点
|
|
|
|
|
|
: controls.Average(c => Canvas.GetTop(c) + c.ActualHeight / 2); // 垂直中心点
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var control in controls)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (isHorizontal)
|
|
|
|
|
|
{
|
|
|
|
|
|
double left = avgCenter - control.ActualWidth / 2;
|
|
|
|
|
|
Canvas.SetLeft(control, left);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
double top = avgCenter - control.ActualHeight / 2;
|
|
|
|
|
|
Canvas.SetTop(control, top);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-09-24 22:39:43 +08:00
|
|
|
|
#region 静态方法:创建节点,创建菜单子项,获取区域
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
private static TNodeControl CreateNodeControl<TNodeControl, TNodeViewModel>(NodeModelBase model)
|
|
|
|
|
|
where TNodeControl : NodeControlBase
|
|
|
|
|
|
where TNodeViewModel : NodeControlViewModelBase
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
|
2024-09-25 22:20:23 +08:00
|
|
|
|
if (model is null)
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("无法创建节点控件");
|
|
|
|
|
|
}
|
2024-10-01 17:34:08 +08:00
|
|
|
|
if (string.IsNullOrEmpty(model.Guid))
|
|
|
|
|
|
{
|
|
|
|
|
|
model.Guid = Guid.NewGuid().ToString();
|
|
|
|
|
|
}
|
2024-10-23 19:22:27 +08:00
|
|
|
|
var viewModel = Activator.CreateInstance(typeof(TNodeViewModel), [model]);
|
|
|
|
|
|
var controlObj = Activator.CreateInstance(typeof(TNodeControl), [viewModel]);
|
|
|
|
|
|
if (controlObj is TNodeControl nodeControl)
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
2024-10-23 19:22:27 +08:00
|
|
|
|
|
|
|
|
|
|
//nodeControl.ExecuteJunctionControl = new NodeExecuteJunctionControl(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nodeControl;
|
2024-09-20 10:50:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new Exception("无法创建节点控件");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
//private static TControl CreateNodeControl<TNode, TControl, TViewModel>(MethodDetails? methodDetails = null)
|
|
|
|
|
|
// where TNode : NodeModelBase
|
|
|
|
|
|
// where TControl : NodeControlBase
|
|
|
|
|
|
// where TViewModel : NodeControlViewModelBase
|
|
|
|
|
|
//{
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
// var nodeObj = Activator.CreateInstance(typeof(TNode));
|
|
|
|
|
|
// var nodeBase = nodeObj as NodeModelBase ?? throw new Exception("无法创建节点控件");
|
2024-10-01 17:34:08 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
// if (string.IsNullOrEmpty(nodeBase.Guid))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// nodeBase.Guid = Guid.NewGuid().ToString();
|
|
|
|
|
|
// }
|
|
|
|
|
|
// if (methodDetails != null)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var md = methodDetails.Clone(nodeBase); // 首先创建属于节点的方法信息,然后创建属于节点的参数信息
|
|
|
|
|
|
// nodeBase.DisplayName = md.MethodTips;
|
|
|
|
|
|
// nodeBase.MethodDetails = md;
|
|
|
|
|
|
// }
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
// var viewModel = Activator.CreateInstance(typeof(TViewModel), [nodeObj]);
|
|
|
|
|
|
// var controlObj = Activator.CreateInstance(typeof(TControl), [viewModel]);
|
|
|
|
|
|
// if (controlObj is TControl control)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// return control;
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else
|
|
|
|
|
|
// {
|
|
|
|
|
|
// throw new Exception("无法创建节点控件");
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建菜单子项
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="header"></param>
|
|
|
|
|
|
/// <param name="handler"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public static MenuItem CreateMenuItem(string header, RoutedEventHandler handler)
|
|
|
|
|
|
{
|
|
|
|
|
|
var menuItem = new MenuItem { Header = header };
|
|
|
|
|
|
menuItem.Click += handler;
|
|
|
|
|
|
return menuItem;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 穿透元素获取区域容器
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <typeparam name="T"></typeparam>
|
|
|
|
|
|
/// <param name="element"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2024-10-23 19:22:27 +08:00
|
|
|
|
public static T? GetParentOfType<T>(DependencyObject element) where T : DependencyObject
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
|
|
|
|
|
while (element != null)
|
|
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
if (element is T e)
|
2024-09-20 10:50:32 +08:00
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
return e;
|
2024-09-20 10:50:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
element = VisualTreeHelper.GetParent(element);
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
2024-09-18 16:45:41 +08:00
|
|
|
|
|
2024-10-23 19:22:27 +08:00
|
|
|
|
#region 节点树、IOC视图管理
|
2024-09-26 21:00:17 +08:00
|
|
|
|
|
|
|
|
|
|
private void JudgmentFlipFlopNode(NodeControlBase nodeControl)
|
|
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
if (nodeControl is FlipflopNodeControl flipflopControl
|
2024-10-20 21:59:42 +08:00
|
|
|
|
&& flipflopControl?.ViewModel?.NodeModel is NodeModelBase nodeModel) // 判断是否为触发器
|
2024-09-26 21:00:17 +08:00
|
|
|
|
{
|
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
foreach (var ct in NodeStaticConfig.ConnectionTypes)
|
|
|
|
|
|
{
|
|
|
|
|
|
count += nodeModel.PreviousNodes[ct].Count;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (count == 0)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
NodeTreeViewer.AddGlobalFlipFlop(EnvDecorator, nodeModel); // 添加到全局触发器树树视图
|
2024-09-26 21:00:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
NodeTreeViewer.RemoteGlobalFlipFlop(nodeModel); // 从全局触发器树树视图中移除
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-09-24 22:39:43 +08:00
|
|
|
|
void LoadIOCObjectViewer()
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
|
|
|
|
|
#region 顶部菜单栏 - 调试功能区
|
2024-08-05 10:11:58 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 运行测试
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private void ButtonDebugRun_Click(object sender, RoutedEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
LogOutWindow?.Show();
|
|
|
|
|
|
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
#if WINDOWS
|
|
|
|
|
|
//Dispatcher uiDispatcher = Application.Current.MainWindow.Dispatcher;
|
|
|
|
|
|
//SynchronizationContext? uiContext = SynchronizationContext.Current;
|
|
|
|
|
|
//EnvDecorator.IOC.CustomRegisterInstance(typeof(SynchronizationContextk).FullName, uiContext, false);
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
// 获取主线程的 SynchronizationContext
|
|
|
|
|
|
Action<SynchronizationContext, Action> uiInvoke = (uiContext, action) => uiContext?.Post(state => action?.Invoke(), null);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Task.Run(async () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
await EnvDecorator.StartAsync();
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// await EnvDecorator.StartAsync();
|
|
|
|
|
|
//await Task.Factory.StartNew(FlowEnvironment.StartAsync);
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-09 16:42:01 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 退出
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-08-05 10:11:58 +08:00
|
|
|
|
private void ButtonDebugFlipflopNode_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator?.ExitFlow(); // 在运行平台上点击了退出
|
2024-09-24 22:39:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 从选定的节点开始运行
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private async void ButtonStartFlowInSelectNode_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
2024-10-15 10:55:41 +08:00
|
|
|
|
if (selectNodeControls.Count == 0)
|
2024-09-24 22:39:43 +08:00
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("请至少选择一个节点");
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (selectNodeControls.Count > 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("请只选择一个节点");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2024-10-20 21:59:42 +08:00
|
|
|
|
await this.EnvDecorator.StartAsyncInSelectNode(selectNodeControls[0].ViewModel.NodeModel.Guid);
|
2024-09-24 22:39:43 +08:00
|
|
|
|
}
|
2024-09-22 14:10:13 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
#region 顶部菜单栏 - 项目文件菜单
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// <summary>
|
2024-09-20 17:11:31 +08:00
|
|
|
|
/// 保存为项目文件
|
2024-08-05 10:11:58 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-10-20 12:10:57 +08:00
|
|
|
|
private async void ButtonSaveFile_Click(object sender, RoutedEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
var projectData = await EnvDecorator.GetProjectInfoAsync();
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-09-15 12:15:32 +08:00
|
|
|
|
projectData.Basic = new Basic
|
|
|
|
|
|
{
|
2024-09-17 14:20:27 +08:00
|
|
|
|
Canvas = new FlowCanvas
|
2024-09-15 12:15:32 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
Height = FlowChartCanvas.Height,
|
|
|
|
|
|
Width = FlowChartCanvas.Width,
|
2024-09-20 17:11:31 +08:00
|
|
|
|
ViewX = translateTransform.X,
|
|
|
|
|
|
ViewY = translateTransform.Y,
|
|
|
|
|
|
ScaleX = scaleTransform.ScaleX,
|
|
|
|
|
|
ScaleY = scaleTransform.ScaleY,
|
2024-09-15 12:15:32 +08:00
|
|
|
|
},
|
2024-09-17 14:20:27 +08:00
|
|
|
|
Versions = "1",
|
2024-09-15 12:15:32 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
//foreach (var node in projectData.Nodes)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// if (NodeControls.TryGetValue(node.Guid, out var nodeControl))
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Point positionRelativeToParent = nodeControl.TranslatePoint(new Point(0, 0), FlowChartCanvas);
|
|
|
|
|
|
// node.Position = new PositionOfUI(positionRelativeToParent.X, positionRelativeToParent.Y);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
2024-09-30 22:20:02 +08:00
|
|
|
|
if (!SaveContentToFile(out string savePath, out Action<string, string>? savaProjectFile))
|
2024-09-20 17:11:31 +08:00
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
Console.WriteLine("保存项目DLL时返回了意外的文件保存路径");
|
2024-09-20 17:11:31 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-15 12:15:32 +08:00
|
|
|
|
|
2024-09-30 22:20:02 +08:00
|
|
|
|
string? librarySavePath = System.IO.Path.GetDirectoryName(savePath);
|
|
|
|
|
|
if (string.IsNullOrEmpty(librarySavePath))
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("保存项目DLL时返回了意外的文件保存路径");
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
Console.WriteLine(savePath);
|
|
|
|
|
|
for (int index = 0; index < projectData.Librarys.Length; index++)
|
|
|
|
|
|
{
|
2024-11-03 21:17:45 +08:00
|
|
|
|
NodeLibraryInfo? library = projectData.Librarys[index];
|
2024-09-20 17:11:31 +08:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
string targetPath = System.IO.Path.Combine(librarySavePath, library.FileName); // 目标文件夹
|
2024-09-20 17:11:31 +08:00
|
|
|
|
//Console.WriteLine("targetPath:" + targetPath);
|
2024-10-20 12:10:57 +08:00
|
|
|
|
#if WINDOWS
|
|
|
|
|
|
//library.Path
|
|
|
|
|
|
string sourceFile = library.FilePath; // 源文件夹
|
2024-09-20 17:11:31 +08:00
|
|
|
|
//Console.WriteLine("sourceFile:" + sourceFile);
|
2024-10-20 12:10:57 +08:00
|
|
|
|
#else
|
|
|
|
|
|
string sourceFile = new Uri(library.Path).LocalPath;
|
|
|
|
|
|
#endif
|
2024-09-20 17:11:31 +08:00
|
|
|
|
// 复制文件到目标目录
|
|
|
|
|
|
File.Copy(sourceFile, targetPath, true);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取相对路径
|
|
|
|
|
|
string relativePath = System.IO.Path.GetRelativePath(savePath, targetPath);
|
|
|
|
|
|
//Console.WriteLine("Relative Path: " + relativePath);
|
2024-10-20 12:10:57 +08:00
|
|
|
|
projectData.Librarys[index].FilePath = relativePath;
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}
|
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine(ex.Message);
|
|
|
|
|
|
//WriteLog($"DLL复制失败:{dll.CodeBase} \r\n错误:{ex}\r\n");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
JObject projectJsonData = JObject.FromObject(projectData);
|
2024-10-15 10:55:41 +08:00
|
|
|
|
savaProjectFile?.Invoke(savePath, projectJsonData.ToString());
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
public static bool SaveContentToFile(out string savePath, out Action<string, string>? savaProjectFile)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
|
|
|
|
|
// 创建一个新的保存文件对话框
|
|
|
|
|
|
SaveFileDialog saveFileDialog = new()
|
|
|
|
|
|
{
|
2024-09-20 17:11:31 +08:00
|
|
|
|
Filter = "DynamicNodeFlow Files (*.dnf)|*.dnf",
|
|
|
|
|
|
DefaultExt = "dnf",
|
2024-08-05 10:11:58 +08:00
|
|
|
|
FileName = "project.dnf"
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 显示保存文件对话框
|
|
|
|
|
|
bool? result = saveFileDialog.ShowDialog();
|
|
|
|
|
|
|
|
|
|
|
|
// 如果用户选择了文件并点击了保存按钮
|
|
|
|
|
|
if (result == true)
|
|
|
|
|
|
{
|
2024-10-15 10:55:41 +08:00
|
|
|
|
savePath = saveFileDialog.FileName;
|
2024-09-20 17:11:31 +08:00
|
|
|
|
savaProjectFile = File.WriteAllText;
|
|
|
|
|
|
return true;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
savePath = string.Empty;
|
|
|
|
|
|
savaProjectFile = null;
|
|
|
|
|
|
return false;
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 打开本地项目文件
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-10-15 21:56:09 +08:00
|
|
|
|
private void ButtonOpenLocalProject_Click(object sender, RoutedEventArgs e)
|
2024-08-05 10:11:58 +08:00
|
|
|
|
{
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
#endregion
|
2024-09-20 10:50:32 +08:00
|
|
|
|
|
2024-10-15 10:55:41 +08:00
|
|
|
|
#region 顶部菜单栏 - 视图管理
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 重置画布
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void ButtonResetCanvas_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
translateTransform.X = 0;
|
|
|
|
|
|
translateTransform.Y = 0;
|
|
|
|
|
|
scaleTransform.ScaleX = 1;
|
|
|
|
|
|
scaleTransform.ScaleY = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
private void ButtonOpenConsoleOutWindow_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
LogOutWindow?.Show();
|
2024-09-20 10:50:32 +08:00
|
|
|
|
}
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
2024-10-15 21:56:09 +08:00
|
|
|
|
#region 顶部菜单栏 - 远程管理
|
|
|
|
|
|
private async void ButtonStartRemoteServer_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
await this.EnvDecorator.StartRemoteServerAsync();
|
2024-10-15 21:56:09 +08:00
|
|
|
|
}
|
2024-10-20 12:10:57 +08:00
|
|
|
|
|
2024-10-15 21:56:09 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 连接远程运行环境
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void ButtonConnectionRemoteEnv_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
var windowEnvRemoteLoginView = new WindowEnvRemoteLoginView(async (addres, port, token) =>
|
2024-10-15 21:56:09 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
ResetFlowEnvironmentEvent();// 移除事件
|
2024-10-27 00:54:10 +08:00
|
|
|
|
(var isConnect, var _) = await this.EnvDecorator.ConnectRemoteEnv(addres, port, token);
|
|
|
|
|
|
InitFlowEnvironmentEvent(); // 重新添加事件(如果没有连接成功,那么依然是原本的环境)
|
2024-10-20 12:10:57 +08:00
|
|
|
|
if (isConnect)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 连接成功,加载远程项目
|
2024-10-28 00:31:41 +08:00
|
|
|
|
_ = Task.Run(async () =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var flowEnvInfo = await EnvDecorator.GetEnvInfoAsync();
|
|
|
|
|
|
EnvDecorator.LoadProject(flowEnvInfo, string.Empty);// 加载远程环境的项目
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2024-10-20 12:10:57 +08:00
|
|
|
|
}
|
2024-10-15 21:56:09 +08:00
|
|
|
|
});
|
|
|
|
|
|
windowEnvRemoteLoginView.Show();
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
#endregion
|
2024-10-15 10:55:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
/// <summary>
|
2024-10-27 00:54:10 +08:00
|
|
|
|
/// 窗体按键监听。
|
2024-09-20 17:11:31 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-09-20 10:50:32 +08:00
|
|
|
|
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
|
|
|
|
|
|
{
|
2024-09-21 10:06:44 +08:00
|
|
|
|
if (e.Key == Key.Tab)
|
|
|
|
|
|
{
|
|
|
|
|
|
e.Handled = true; // 禁止默认的Tab键行为
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
if (e.KeyStates == Keyboard.GetKeyStates(Key.Escape))
|
|
|
|
|
|
{
|
|
|
|
|
|
IsControlDragging = false;
|
|
|
|
|
|
IsCanvasDragging = false;
|
|
|
|
|
|
SelectionRectangle.Visibility = Visibility.Collapsed;
|
|
|
|
|
|
CancelSelectNode();
|
2024-10-27 00:54:10 +08:00
|
|
|
|
EndConnection();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(GlobalJunctionData.MyGlobalConnectingData is ConnectingData myData && myData.IsCreateing)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(myData.Type == JunctionOfConnectionType.Invoke)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConnectionInvokeType connectionInvokeType = e.KeyStates switch
|
|
|
|
|
|
{
|
|
|
|
|
|
KeyStates k when k == Keyboard.GetKeyStates(Key.D1) => ConnectionInvokeType.Upstream,
|
|
|
|
|
|
KeyStates k when k == Keyboard.GetKeyStates(Key.D2) => ConnectionInvokeType.IsSucceed,
|
|
|
|
|
|
KeyStates k when k == Keyboard.GetKeyStates(Key.D3) => ConnectionInvokeType.IsFail,
|
|
|
|
|
|
KeyStates k when k == Keyboard.GetKeyStates(Key.D4) => ConnectionInvokeType.IsError,
|
|
|
|
|
|
_ => ConnectionInvokeType.None,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (connectionInvokeType != ConnectionInvokeType.None)
|
|
|
|
|
|
{
|
|
|
|
|
|
myData.ConnectionInvokeType = connectionInvokeType;
|
|
|
|
|
|
myData.MyLine.Line.UpdateLineColor(connectionInvokeType.ToLineColor());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (myData.Type == JunctionOfConnectionType.Arg)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConnectionArgSourceType connectionArgSourceType = e.KeyStates switch
|
|
|
|
|
|
{
|
|
|
|
|
|
KeyStates k when k == Keyboard.GetKeyStates(Key.D1) => ConnectionArgSourceType.GetOtherNodeData,
|
|
|
|
|
|
KeyStates k when k == Keyboard.GetKeyStates(Key.D2) => ConnectionArgSourceType.GetOtherNodeDataOfInvoke,
|
|
|
|
|
|
_ => ConnectionArgSourceType.GetPreviousNodeData,
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (connectionArgSourceType != ConnectionArgSourceType.GetPreviousNodeData)
|
|
|
|
|
|
{
|
|
|
|
|
|
myData.ConnectionArgSourceType = connectionArgSourceType;
|
|
|
|
|
|
myData.MyLine.Line.UpdateLineColor(connectionArgSourceType.ToLineColor());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
myData.CurrentJunction.InvalidateVisual(); // 刷新目标节点控制点样式
|
|
|
|
|
|
|
2024-09-20 17:11:31 +08:00
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
|
|
|
|
|
|
2024-09-20 10:50:32 +08:00
|
|
|
|
}
|
2024-09-20 17:11:31 +08:00
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 对象装箱测试
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
|
|
|
|
|
private void ButtonTestExpObj_Click(object sender, RoutedEventArgs e)
|
|
|
|
|
|
{
|
2024-09-30 22:20:02 +08:00
|
|
|
|
//string jsonString =
|
|
|
|
|
|
//"""
|
|
|
|
|
|
//{
|
|
|
|
|
|
// "Name": "张三",
|
|
|
|
|
|
// "Age": 24,
|
|
|
|
|
|
// "Address": {
|
|
|
|
|
|
// "City": "北京",
|
|
|
|
|
|
// "PostalCode": "10000"
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
//""";
|
2024-09-27 23:47:25 +08:00
|
|
|
|
|
|
|
|
|
|
var externalData = new Dictionary<string, object>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "Name", "John" },
|
|
|
|
|
|
{ "Age", 30 },
|
|
|
|
|
|
{ "Addresses", new List<Dictionary<string, object>>
|
|
|
|
|
|
{
|
|
|
|
|
|
new Dictionary<string, object>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "Street", "123 Main St" },
|
|
|
|
|
|
{ "City", "New York" }
|
|
|
|
|
|
},
|
|
|
|
|
|
new Dictionary<string, object>
|
|
|
|
|
|
{
|
|
|
|
|
|
{ "Street", "456 Another St" },
|
|
|
|
|
|
{ "City", "Los Angeles" }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (!ObjDynamicCreateHelper.TryResolve(externalData, "RootType",out var result))
|
|
|
|
|
|
{
|
|
|
|
|
|
Console.WriteLine("赋值过程中有错误,请检查属性名和类型!");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2024-09-30 22:20:02 +08:00
|
|
|
|
ObjDynamicCreateHelper.PrintObjectProperties(result!);
|
2024-09-27 23:47:25 +08:00
|
|
|
|
Console.WriteLine( );
|
2024-10-27 00:54:10 +08:00
|
|
|
|
var exp = "@set .Addresses[1].Street = 233";
|
2024-09-30 22:20:02 +08:00
|
|
|
|
var data = SerinExpressionEvaluator.Evaluate(exp, result!, out bool isChange);
|
2024-09-27 23:47:25 +08:00
|
|
|
|
exp = "@get .Addresses[1].Street";
|
2024-09-30 22:20:02 +08:00
|
|
|
|
data = SerinExpressionEvaluator.Evaluate(exp,result!, out isChange);
|
2024-09-27 23:47:25 +08:00
|
|
|
|
Console.WriteLine($"{exp} => {data}");
|
|
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-09-27 23:47:25 +08:00
|
|
|
|
/// <summary>
|
2024-10-15 10:55:41 +08:00
|
|
|
|
/// 卸载DLL文件,清空当前项目
|
2024-09-27 23:47:25 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="sender"></param>
|
|
|
|
|
|
/// <param name="e"></param>
|
2024-10-15 10:55:41 +08:00
|
|
|
|
private void UnloadAllButton_Click(object sender, RoutedEventArgs e)
|
2024-09-27 23:47:25 +08:00
|
|
|
|
{
|
2024-10-20 12:10:57 +08:00
|
|
|
|
EnvDecorator.ClearAll();
|
2024-10-15 10:55:41 +08:00
|
|
|
|
}
|
2024-10-27 00:54:10 +08:00
|
|
|
|
|
2024-10-15 10:55:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 卸载DLL文件,清空当前项目
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private void UnloadAllAssemblies()
|
|
|
|
|
|
{
|
|
|
|
|
|
DllStackPanel.Children.Clear();
|
|
|
|
|
|
FlowChartCanvas.Children.Clear();
|
|
|
|
|
|
Connections.Clear();
|
|
|
|
|
|
NodeControls.Clear();
|
2024-10-24 23:32:43 +08:00
|
|
|
|
//currentLine = null;
|
2024-10-27 00:54:10 +08:00
|
|
|
|
//startConnectNodeControl = null;
|
2024-10-15 10:55:41 +08:00
|
|
|
|
MessageBox.Show("所有DLL已卸载。", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
|
2024-09-27 23:47:25 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-10-15 21:56:09 +08:00
|
|
|
|
|
2024-09-09 16:42:01 +08:00
|
|
|
|
}
|
2024-08-05 10:11:58 +08:00
|
|
|
|
}
|