From c47320d4de3dc583dad595797e4e09a8ff2581fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E4=B8=80=E6=B3=93=E7=A7=8B=E6=B0=B4?= <1090698674@qq.com>
Date: Thu, 2 Jan 2025 13:58:40 +0800
Subject: [PATCH] Delete WorkBench directory
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
移除不要的项目文件夹
---
WorkBench/App.xaml | 22 -
WorkBench/App.xaml.cs | 75 -
WorkBench/AssemblyInfo.cs | 10 -
WorkBench/LogWindow.xaml | 24 -
WorkBench/LogWindow.xaml.cs | 162 -
WorkBench/MainWindow.xaml | 259 --
WorkBench/MainWindow.xaml.cs | 3027 -----------------
WorkBench/MainWindowViewModel.cs | 101 -
WorkBench/Node/NodeControlViewModelBase.cs | 48 -
WorkBench/Node/View/ActionNodeControl.xaml | 118 -
WorkBench/Node/View/ActionNodeControl.xaml.cs | 83 -
WorkBench/Node/View/ConditionNodeControl.xaml | 110 -
.../Node/View/ConditionNodeControl.xaml.cs | 58 -
.../Node/View/ConditionRegionControl.xaml | 22 -
.../Node/View/ConditionRegionControl.xaml.cs | 94 -
WorkBench/Node/View/DllControlControl.xaml | 34 -
WorkBench/Node/View/DllControlControl.xaml.cs | 164 -
WorkBench/Node/View/ExpOpNodeControl.xaml | 47 -
WorkBench/Node/View/ExpOpNodeControl.xaml.cs | 56 -
WorkBench/Node/View/FlipflopNodeControl.xaml | 110 -
.../Node/View/FlipflopNodeControl.xaml.cs | 72 -
.../ViewModel/ActionNodeControlViewModel.cs | 13 -
.../ConditionNodeControlViewModel.cs | 54 -
.../ConditionRegionNodeControlViewModel.cs | 18 -
.../ViewModel/FlipflopNodeControlViewModel.cs | 14 -
.../Node/ViewModel/TypeToStringConverter.cs | 27 -
WorkBench/Serein.WorkBench.csproj | 74 -
.../Serein.WorkBench_d2hd4tgu_wpftmp.csproj | 288 --
WorkBench/Themes/IOCObjectViewControl.xaml | 28 -
WorkBench/Themes/IOCObjectViewControl.xaml.cs | 128 -
WorkBench/Themes/InputDialog.xaml | 16 -
WorkBench/Themes/InputDialog.xaml.cs | 42 -
WorkBench/Themes/MethodDetailsControl.xaml | 129 -
WorkBench/Themes/MethodDetailsControl.xaml.cs | 90 -
WorkBench/Themes/NodeTreeItemViewControl.xaml | 59 -
.../Themes/NodeTreeItemViewControl.xaml.cs | 280 --
WorkBench/Themes/NodeTreeViewControl.xaml | 47 -
WorkBench/Themes/NodeTreeViewControl.xaml.cs | 85 -
WorkBench/Themes/ObjectViewerControl.xaml | 31 -
WorkBench/Themes/ObjectViewerControl.xaml.cs | 670 ----
WorkBench/Themes/TypeViewerWindow.xaml | 16 -
WorkBench/Themes/TypeViewerWindow.xaml.cs | 279 --
WorkBench/Themes/WindowDialogInput.xaml | 30 -
WorkBench/Themes/WindowDialogInput.xaml.cs | 70 -
.../InvertableBooleanToVisibilityConverter.cs | 41 -
.../Tool/Converters/ThumbPositionConverter.cs | 79 -
.../Tool/Converters/TypeToColorConverter.cs | 26 -
47 files changed, 7330 deletions(-)
delete mode 100644 WorkBench/App.xaml
delete mode 100644 WorkBench/App.xaml.cs
delete mode 100644 WorkBench/AssemblyInfo.cs
delete mode 100644 WorkBench/LogWindow.xaml
delete mode 100644 WorkBench/LogWindow.xaml.cs
delete mode 100644 WorkBench/MainWindow.xaml
delete mode 100644 WorkBench/MainWindow.xaml.cs
delete mode 100644 WorkBench/MainWindowViewModel.cs
delete mode 100644 WorkBench/Node/NodeControlViewModelBase.cs
delete mode 100644 WorkBench/Node/View/ActionNodeControl.xaml
delete mode 100644 WorkBench/Node/View/ActionNodeControl.xaml.cs
delete mode 100644 WorkBench/Node/View/ConditionNodeControl.xaml
delete mode 100644 WorkBench/Node/View/ConditionNodeControl.xaml.cs
delete mode 100644 WorkBench/Node/View/ConditionRegionControl.xaml
delete mode 100644 WorkBench/Node/View/ConditionRegionControl.xaml.cs
delete mode 100644 WorkBench/Node/View/DllControlControl.xaml
delete mode 100644 WorkBench/Node/View/DllControlControl.xaml.cs
delete mode 100644 WorkBench/Node/View/ExpOpNodeControl.xaml
delete mode 100644 WorkBench/Node/View/ExpOpNodeControl.xaml.cs
delete mode 100644 WorkBench/Node/View/FlipflopNodeControl.xaml
delete mode 100644 WorkBench/Node/View/FlipflopNodeControl.xaml.cs
delete mode 100644 WorkBench/Node/ViewModel/ActionNodeControlViewModel.cs
delete mode 100644 WorkBench/Node/ViewModel/ConditionNodeControlViewModel.cs
delete mode 100644 WorkBench/Node/ViewModel/ConditionRegionNodeControlViewModel.cs
delete mode 100644 WorkBench/Node/ViewModel/FlipflopNodeControlViewModel.cs
delete mode 100644 WorkBench/Node/ViewModel/TypeToStringConverter.cs
delete mode 100644 WorkBench/Serein.WorkBench.csproj
delete mode 100644 WorkBench/Serein.WorkBench_d2hd4tgu_wpftmp.csproj
delete mode 100644 WorkBench/Themes/IOCObjectViewControl.xaml
delete mode 100644 WorkBench/Themes/IOCObjectViewControl.xaml.cs
delete mode 100644 WorkBench/Themes/InputDialog.xaml
delete mode 100644 WorkBench/Themes/InputDialog.xaml.cs
delete mode 100644 WorkBench/Themes/MethodDetailsControl.xaml
delete mode 100644 WorkBench/Themes/MethodDetailsControl.xaml.cs
delete mode 100644 WorkBench/Themes/NodeTreeItemViewControl.xaml
delete mode 100644 WorkBench/Themes/NodeTreeItemViewControl.xaml.cs
delete mode 100644 WorkBench/Themes/NodeTreeViewControl.xaml
delete mode 100644 WorkBench/Themes/NodeTreeViewControl.xaml.cs
delete mode 100644 WorkBench/Themes/ObjectViewerControl.xaml
delete mode 100644 WorkBench/Themes/ObjectViewerControl.xaml.cs
delete mode 100644 WorkBench/Themes/TypeViewerWindow.xaml
delete mode 100644 WorkBench/Themes/TypeViewerWindow.xaml.cs
delete mode 100644 WorkBench/Themes/WindowDialogInput.xaml
delete mode 100644 WorkBench/Themes/WindowDialogInput.xaml.cs
delete mode 100644 WorkBench/Tool/Converters/InvertableBooleanToVisibilityConverter.cs
delete mode 100644 WorkBench/Tool/Converters/ThumbPositionConverter.cs
delete mode 100644 WorkBench/Tool/Converters/TypeToColorConverter.cs
diff --git a/WorkBench/App.xaml b/WorkBench/App.xaml
deleted file mode 100644
index baa41de..0000000
--- a/WorkBench/App.xaml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/App.xaml.cs b/WorkBench/App.xaml.cs
deleted file mode 100644
index a90c015..0000000
--- a/WorkBench/App.xaml.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using Newtonsoft.Json;
-using Serein.Library;
-using Serein.Library.Utils;
-using System.Diagnostics;
-using System.IO;
-using System.Windows;
-
-namespace Serein.Workbench
-{
-
- ///
- /// Interaction logic for App.xaml
- ///
- public partial class App : Application
- {
- private async Task LoadLocalProjectAsync()
- {
-
-#if DEBUG
- if (1 == 1)
- {
- // 这里是测试代码,可以删除
- string filePath;
- filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\Release\net8.0\PLCproject.dnf";
- filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\Release\banyunqi\project.dnf";
- filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\debug\net8.0\project.dnf";
- //filePath = @"C:\Users\Az\source\repos\CLBanyunqiState\CLBanyunqiState\bin\debug\net8.0\test.dnf";
- string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
- App.FlowProjectData = JsonConvert.DeserializeObject(content);
- App.FileDataPath = System.IO.Path.GetDirectoryName(filePath)!; // filePath;//
- var dir = Path.GetDirectoryName(filePath);
- }
-#endif
- }
-
- public static SereinProjectData? FlowProjectData { get; set; }
- public static string FileDataPath { get; set; } = "";
-
- private async void Application_Startup(object sender, StartupEventArgs e)
- {
- // 检查是否传入了参数
- if (e.Args.Length == 1)
- {
- // 获取文件路径
- string filePath = e.Args[0];
- // 检查文件是否存在
- if (!System.IO.File.Exists(filePath))
- {
- MessageBox.Show($"文件未找到:{filePath}");
- Shutdown(); // 关闭应用程序
- return;
- }
-
- try
- {
- // 读取文件内容
- string content = System.IO.File.ReadAllText(filePath); // 读取整个文件内容
- FlowProjectData = JsonConvert.DeserializeObject(content);
- FileDataPath = System.IO.Path.GetDirectoryName(filePath) ?? "";
- }
- catch (Exception ex)
- {
- MessageBox.Show($"读取文件时发生错误:{ex.Message}");
- Shutdown(); // 关闭应用程序
- }
-
- }
- await this.LoadLocalProjectAsync();
-
-
- }
- }
-
-}
-
diff --git a/WorkBench/AssemblyInfo.cs b/WorkBench/AssemblyInfo.cs
deleted file mode 100644
index b0ec827..0000000
--- a/WorkBench/AssemblyInfo.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Windows;
-
-[assembly: ThemeInfo(
- ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
- //(used if a resource is not found in the page,
- // or application resource dictionaries)
- ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
- //(used if a resource is not found in the page,
- // app, or any theme specific resource dictionaries)
-)]
diff --git a/WorkBench/LogWindow.xaml b/WorkBench/LogWindow.xaml
deleted file mode 100644
index 29bc07e..0000000
--- a/WorkBench/LogWindow.xaml
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/LogWindow.xaml.cs b/WorkBench/LogWindow.xaml.cs
deleted file mode 100644
index 495a979..0000000
--- a/WorkBench/LogWindow.xaml.cs
+++ /dev/null
@@ -1,162 +0,0 @@
-using System.Windows;
-
-namespace Serein.Workbench
-{
- ///
- /// DebugWindow.xaml 的交互逻辑
- ///
- using System;
- using System.IO;
- using System.Text;
- using System.Threading.Tasks;
- using System.Timers;
- using System.Windows;
-
- ///
- /// LogWindow.xaml 的交互逻辑
- ///
- public partial class LogWindow : Window
- {
- private StringBuilder logBuffer = new StringBuilder();
- private int logUpdateInterval = 200; // 批量更新的时间间隔(毫秒)
- private Timer logUpdateTimer;
- private const int MaxLines = 1000; // 最大显示的行数
- private bool autoScroll = true; // 自动滚动标识
- private int flushThreshold = 5; // 设置日志刷新阈值
- private const int maxFlushSize = 1000; // 每次最大刷新字符数
-
- public LogWindow()
- {
- InitializeComponent();
-
- // 初始化定时器,用于批量更新日志
- logUpdateTimer = new Timer(logUpdateInterval);
- logUpdateTimer.Elapsed += (s, e) => FlushLog(); // 定时刷新日志
- logUpdateTimer.Start();
-
- // 添加滚动事件处理,判断用户是否手动滚动
- // LogTextBox.ScrollChanged += LogTextBox_ScrollChanged;
- }
-
- ///
- /// 添加日志到缓冲区
- ///
- public void AppendText(string text)
- {
- lock (logBuffer)
- {
- logBuffer.Append(text);
-
- // 异步写入日志到文件
- // Task.Run(() => File.AppendAllText("log.txt", text));
- //FlushLog();
- // 如果日志达到阈值,立即刷新
- if (logBuffer.Length > flushThreshold)
- {
- FlushLog();
- }
- }
- }
-
- ///
- /// 清空日志缓冲区并更新到 TextBox 中
- ///
- private void FlushLog()
- {
- if (logBuffer.Length == 0) return;
-
- Dispatcher.InvokeAsync(() =>
- {
- lock (logBuffer)
- {
- // 仅追加部分日志,避免一次更新过多内容
- string logContent = logBuffer.Length > maxFlushSize
- ? logBuffer.ToString(0, maxFlushSize)
- : logBuffer.ToString();
- logBuffer.Remove(0, logContent.Length); // 清空已更新的部分
-
- LogTextBox.Dispatcher.Invoke(() =>
- {
- LogTextBox.AppendText(logContent);
- });
-
- }
-
- // 不必每次都修剪日志,当行数超过限制20%时再修剪
- if (LogTextBox.LineCount > MaxLines * 1.2)
- {
- TrimLog();
- }
-
- ScrollToEndIfNeeded(); // 根据是否需要自动滚动来决定
- }, System.Windows.Threading.DispatcherPriority.Background);
- }
-
- ///
- /// 限制日志输出的最大行数,超出时删除旧日志
- ///
- private void TrimLog()
- {
- if (LogTextBox.LineCount > MaxLines)
- {
- // 删除最早的多余行
- LogTextBox.Text = LogTextBox.Text.Substring(
- LogTextBox.GetCharacterIndexFromLineIndex(LogTextBox.LineCount - MaxLines));
- }
- }
-
- ///
- /// 检测用户是否手动滚动了文本框
- ///
- private void LogTextBox_ScrollChanged(object sender, System.Windows.Controls.ScrollChangedEventArgs e)
- {
- if (e.ExtentHeightChange == 0) // 用户手动滚动时
- {
- // 判断是否滚动到底部
- //autoScroll = LogTextBox.VerticalOffset == LogTextBox.ScrollableHeight;
- }
- }
-
- ///
- /// 根据 autoScroll 标志决定是否滚动到末尾
- ///
- private void ScrollToEndIfNeeded()
- {
- if (autoScroll)
- {
- LogTextBox.ScrollToEnd(); // 仅在需要时滚动到末尾
- }
- }
-
- ///
- /// 清空日志
- ///
- public void Clear()
- {
- Dispatcher.BeginInvoke(() =>
- {
- LogTextBox.Clear();
- });
- }
-
- ///
- /// 点击清空日志按钮时触发
- ///
- private void ClearLog_Click(object sender, RoutedEventArgs e)
- {
- LogTextBox.Clear();
- }
-
- ///
- /// 窗口关闭事件,隐藏窗体而不是关闭
- ///
- private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
- {
- logBuffer?.Clear();
- Clear();
- e.Cancel = true; // 取消关闭操作
- this.Hide(); // 隐藏窗体而不是关闭
- }
- }
-
-}
diff --git a/WorkBench/MainWindow.xaml b/WorkBench/MainWindow.xaml
deleted file mode 100644
index 87cef37..0000000
--- a/WorkBench/MainWindow.xaml
+++ /dev/null
@@ -1,259 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/MainWindow.xaml.cs b/WorkBench/MainWindow.xaml.cs
deleted file mode 100644
index f8c3a5a..0000000
--- a/WorkBench/MainWindow.xaml.cs
+++ /dev/null
@@ -1,3027 +0,0 @@
-using Microsoft.Win32;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
-using Serein.Library;
-using Serein.Library.Api;
-using Serein.Library.Utils;
-using Serein.NodeFlow;
-using Serein.NodeFlow.Tool;
-using Serein.Workbench.Extension;
-using Serein.Workbench.Node;
-using Serein.Workbench.Node.View;
-using Serein.Workbench.Node.ViewModel;
-using Serein.Workbench.Themes;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Animation;
-using DataObject = System.Windows.DataObject;
-
-namespace Serein.Workbench
-{
- ///
- /// 拖拽创建节点类型
- ///
- public static class MouseNodeType
- {
- ///
- /// 创建来自DLL的节点
- ///
- public static string CreateDllNodeInCanvas { get; } = nameof(CreateDllNodeInCanvas);
- ///
- /// 创建基础节点
- ///
- public static string CreateBaseNodeInCanvas { get; } = nameof(CreateBaseNodeInCanvas);
- }
-
-
-
- ///
- /// Interaction logic for MainWindow.xaml,第一次用git,不太懂
- ///
- public partial class MainWindow : Window
- {
- ///
- /// 全局捕获Console输出事件,打印在这个窗体里面
- ///
- private readonly LogWindow LogOutWindow = new LogWindow();
-
- ///
- /// 流程环境装饰器,方便在本地与远程环境下切换
- ///
- private IFlowEnvironment EnvDecorator => ViewModel.FlowEnvironment;
- private IFlowEnvironmentEvent EnvEventDecorator => ViewModel.FlowEnvironment as IFlowEnvironmentEvent;
- private MainWindowViewModel ViewModel { get; set; }
-
-
- ///
- /// 节点对应的控件类型
- ///
- // private Dictionary NodeUITypes { get; } = [];
-
- ///
- /// 存储所有与节点有关的控件
- /// 任何情景下都应避免直接操作 ViewModel 中的 NodeModel 节点,
- /// 而是应该调用 FlowEnvironment 提供接口进行操作,
- /// 因为 Workbench 应该更加关注UI视觉效果,而非直接干扰流程环境运行的逻辑。
- /// 之所以暴露 NodeModel 属性,因为有些场景下不可避免的需要直接获取节点的属性。
- ///
- private Dictionary NodeControls { get; } = [];
-
- ///
- /// 存储所有的连接。考虑集成在运行环境中。
- ///
- private List Connections { get; } = [];
-
- ///
- /// 起始节点
- ///
- //private NodeControlBase StartNodeControl{ get; set; }
-
- #region 与画布相关的字段
-
- ///
- /// 标记是否正在尝试选取控件
- ///
- private bool IsSelectControl;
- ///
- /// 标记是否正在进行连接操作
- ///
- //private bool IsConnecting;
- ///
- /// 标记是否正在拖动控件
- ///
- private bool IsControlDragging;
- ///
- /// 标记是否正在拖动画布
- ///
- private bool IsCanvasDragging;
- private bool IsSelectDragging;
-
- ///
- /// 当前选取的控件
- ///
- private readonly List selectNodeControls = [];
-
- ///
- /// 记录开始拖动节点控件时的鼠标位置
- ///
- private Point startControlDragPoint;
- ///
- /// 记录移动画布开始时的鼠标位置
- ///
- private Point startCanvasDragPoint;
- ///
- /// 记录开始选取节点控件时的鼠标位置
- ///
- private Point startSelectControolPoint;
-
-
- ///
- /// 记录开始连接的文本块
- ///
- //private NodeControlBase? startConnectNodeControl;
- ///
- /// 当前正在绘制的连接线
- ///
- //private Line? currentLine;
- ///
- /// 当前正在绘制的真假分支属性
- ///
- //private ConnectionInvokeType currentConnectionType;
-
-
- ///
- /// 组合变换容器
- ///
- private readonly TransformGroup canvasTransformGroup;
- ///
- /// 缩放画布
- ///
- private readonly ScaleTransform scaleTransform;
- ///
- /// 平移画布
- ///
- private readonly TranslateTransform translateTransform;
- #endregion
-
-
- public MainWindow()
- {
- ViewModel = new MainWindowViewModel(this);
- this.DataContext = ViewModel;
- InitializeComponent();
-
- ViewObjectViewer.FlowEnvironment = EnvDecorator; // 设置 节点树视图 的环境为装饰器
- IOCObjectViewer.FlowEnvironment = EnvDecorator; // 设置 IOC容器视图 的环境为装饰器
- IOCObjectViewer.SelectObj += ViewObjectViewer.LoadObjectInformation; // 使选择 IOC容器视图 的某项(对象)时,可以在 数据视图 呈现数据
-
- #region 为 NodeControlType 枚举 不同项添加对应的 Control类型 、 ViewModel类型
- NodeMVVMManagement.RegisterUI(NodeControlType.Action, typeof(ActionNodeControl), typeof(ActionNodeControlViewModel));
- NodeMVVMManagement.RegisterUI(NodeControlType.Flipflop, typeof(FlipflopNodeControl), typeof(FlipflopNodeControlViewModel));
- NodeMVVMManagement.RegisterUI(NodeControlType.ExpOp, typeof(ExpOpNodeControl), typeof(ExpOpNodeControlViewModel));
- NodeMVVMManagement.RegisterUI(NodeControlType.ExpCondition, typeof(ConditionNodeControl), typeof(ConditionNodeControlViewModel));
- NodeMVVMManagement.RegisterUI(NodeControlType.ConditionRegion, typeof(ConditionRegionControl), typeof(ConditionRegionNodeControlViewModel));
- NodeMVVMManagement.RegisterUI(NodeControlType.GlobalData, typeof(GlobalDataControl), typeof(GlobalDataNodeControlViewModel));
- NodeMVVMManagement.RegisterUI(NodeControlType.Script, typeof(ScriptNodeControl), typeof(ScriptNodeControlViewModel));
- #endregion
-
-
- #region 缩放平移容器
- canvasTransformGroup = new TransformGroup();
- scaleTransform = new ScaleTransform();
- translateTransform = new TranslateTransform();
- canvasTransformGroup.Children.Add(scaleTransform);
- canvasTransformGroup.Children.Add(translateTransform);
- FlowChartCanvas.RenderTransform = canvasTransformGroup;
- #endregion
-
- InitFlowEnvironmentEvent(); // 配置环境事件
-
-
- }
-
-
-
- ///
- /// 初始化环境事件
- ///
- private void InitFlowEnvironmentEvent()
- {
- EnvEventDecorator.OnDllLoad += FlowEnvironment_DllLoadEvent;
- EnvEventDecorator.OnProjectSaving += EnvDecorator_OnProjectSaving;
- EnvEventDecorator.OnProjectLoaded += FlowEnvironment_OnProjectLoaded;
- EnvEventDecorator.OnStartNodeChange += FlowEnvironment_StartNodeChangeEvent;
- EnvEventDecorator.OnNodeConnectChange += FlowEnvironment_NodeConnectChangeEvemt;
- EnvEventDecorator.OnNodeCreate += FlowEnvironment_NodeCreateEvent;
- EnvEventDecorator.OnNodeRemove += FlowEnvironment_NodeRemoveEvent;
- EnvEventDecorator.OnNodePlace += EnvDecorator_OnNodePlaceEvent;
- EnvEventDecorator.OnNodeTakeOut += EnvDecorator_OnNodeTakeOutEvent;
- EnvEventDecorator.OnFlowRunComplete += FlowEnvironment_OnFlowRunCompleteEvent;
-
-
- EnvEventDecorator.OnMonitorObjectChange += FlowEnvironment_OnMonitorObjectChangeEvent;
- EnvEventDecorator.OnNodeInterruptStateChange += FlowEnvironment_OnNodeInterruptStateChangeEvent;
- EnvEventDecorator.OnInterruptTrigger += FlowEnvironment_OnInterruptTriggerEvent;
-
- EnvEventDecorator.OnIOCMembersChanged += FlowEnvironment_OnIOCMembersChangedEvent;
-
- EnvEventDecorator.OnNodeLocated += FlowEnvironment_OnNodeLocateEvent;
- EnvEventDecorator.OnNodeMoved += FlowEnvironment_OnNodeMovedEvent;
- EnvEventDecorator.OnEnvOut += FlowEnvironment_OnEnvOutEvent;
- }
-
-
-
- ///
- /// 移除环境事件
- ///
- private void ResetFlowEnvironmentEvent()
- {
- EnvEventDecorator.OnDllLoad -= FlowEnvironment_DllLoadEvent;
- EnvEventDecorator.OnProjectSaving -= EnvDecorator_OnProjectSaving;
- EnvEventDecorator.OnProjectLoaded -= FlowEnvironment_OnProjectLoaded;
- EnvEventDecorator.OnStartNodeChange -= FlowEnvironment_StartNodeChangeEvent;
- EnvEventDecorator.OnNodeConnectChange -= FlowEnvironment_NodeConnectChangeEvemt;
- EnvEventDecorator.OnNodeCreate -= FlowEnvironment_NodeCreateEvent;
- EnvEventDecorator.OnNodeRemove -= FlowEnvironment_NodeRemoveEvent;
- EnvEventDecorator.OnNodePlace -= EnvDecorator_OnNodePlaceEvent;
- EnvEventDecorator.OnNodeTakeOut -= EnvDecorator_OnNodeTakeOutEvent;
- EnvEventDecorator.OnFlowRunComplete -= FlowEnvironment_OnFlowRunCompleteEvent;
-
-
- EnvEventDecorator.OnMonitorObjectChange -= FlowEnvironment_OnMonitorObjectChangeEvent;
- EnvEventDecorator.OnNodeInterruptStateChange -= FlowEnvironment_OnNodeInterruptStateChangeEvent;
- EnvEventDecorator.OnInterruptTrigger -= FlowEnvironment_OnInterruptTriggerEvent;
-
- EnvEventDecorator.OnIOCMembersChanged -= FlowEnvironment_OnIOCMembersChangedEvent;
- EnvEventDecorator.OnNodeLocated -= FlowEnvironment_OnNodeLocateEvent;
- EnvEventDecorator.OnNodeMoved -= FlowEnvironment_OnNodeMovedEvent;
-
- EnvEventDecorator.OnEnvOut -= FlowEnvironment_OnEnvOutEvent;
-
- }
-
- #region 窗体加载方法
- private async void Window_Loaded(object sender, RoutedEventArgs e)
- {
- var currentPath = System.IO.Directory.GetCurrentDirectory(); // 当前目录
- var baseLibraryFilePath = Path.Combine(currentPath, FlowLibraryManagement.SereinBaseLibrary);
- if (File.Exists(baseLibraryFilePath))
- {
- EnvDecorator.LoadLibrary(baseLibraryFilePath); // 默认加载
- }
-
- if (App.FlowProjectData is not null)
- {
- try
- {
- await Task.Run(() =>
- {
- EnvDecorator.LoadProject(new FlowEnvInfo { Project = App.FlowProjectData }, App.FileDataPath); // 加载项目
- });
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }
-
- //
- }
- private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
- {
- LogOutWindow.Close();
- System.Windows.Application.Current.Shutdown();
- }
- private void Window_ContentRendered(object sender, EventArgs e)
- {
- SereinEnv.WriteLine(InfoType.INFO, "load project...");
- var project = App.FlowProjectData;
- if (project is null)
- {
- return;
- }
- InitializeCanvas(project.Basic.Canvas.Width, project.Basic.Canvas.Height);// 设置画布大小
- //foreach (var connection in Connections)
- //{
- // connection.RefreshLine(); // 窗体完成加载后试图刷新所有连接线
- //}
- SereinEnv.WriteLine(InfoType.INFO, $"运行环境当前工作目录:{System.IO.Directory.GetCurrentDirectory()}");
-
- var canvasData = project.Basic.Canvas;
- if (canvasData is not null)
- {
- 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;
- }
-
-
- }
-
-
-
-
- #endregion
-
- #region 运行环境事件
-
- ///
- /// 环境内容输出
- ///
- ///
- ///
- private void FlowEnvironment_OnEnvOutEvent(InfoType type, string value)
- {
- LogOutWindow.AppendText($"{DateTime.Now} [{type}] : {value}{Environment.NewLine}");
- }
-
- ///
- /// 需要保存项目
- ///
- ///
- ///
- private void EnvDecorator_OnProjectSaving(ProjectSavingEventArgs eventArgs)
- {
- SereinProjectData projectData;
- try
- {
- projectData = EnvDecorator.GetProjectInfoAsync()
- .GetAwaiter().GetResult(); // 保存项目
-
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
-
- projectData.Basic = new Basic
- {
- Canvas = new FlowCanvas
- {
- Height = FlowChartCanvas.Height,
- Width = FlowChartCanvas.Width,
- ViewX = translateTransform.X,
- ViewY = translateTransform.Y,
- ScaleX = scaleTransform.ScaleX,
- ScaleY = scaleTransform.ScaleY,
- },
- Versions = "1",
- };
-
- // 创建一个新的保存文件对话框
- SaveFileDialog saveFileDialog = new()
- {
- Filter = "DynamicNodeFlow Files (*.dnf)|*.dnf",
- DefaultExt = "dnf",
- FileName = "project.dnf"
- // FileName = System.IO.Path.GetFileName(App.FileDataPath)
- };
-
- // 显示保存文件对话框
- bool? result = saveFileDialog.ShowDialog();
- // 如果用户选择了文件并点击了保存按钮
- if (result == false)
- {
- SereinEnv.WriteLine(InfoType.ERROR, "取消保存文件");
- return;
- }
-
- var savePath = saveFileDialog.FileName;
- string? librarySavePath = System.IO.Path.GetDirectoryName(savePath);
- if (string.IsNullOrEmpty(librarySavePath))
- {
- SereinEnv.WriteLine(InfoType.ERROR, "保存项目DLL时返回了意外的文件保存路径");
- return;
- }
-
-
- Uri saveProjectFileUri = new Uri(savePath);
- SereinEnv.WriteLine(InfoType.INFO, "项目文件保存路径:" + savePath);
- for (int index = 0; index < projectData.Librarys.Length; index++)
- {
- NodeLibraryInfo? library = projectData.Librarys[index];
- string sourceFilePath = new Uri(library.FilePath).LocalPath; // 源文件夹
- string targetFilePath = System.IO.Path.Combine(librarySavePath, library.FileName); // 目标文件夹
-
- try
- {
- if (File.Exists(sourceFilePath))
- {
- if (!File.Exists(targetFilePath))
- {
- SereinEnv.WriteLine(InfoType.INFO, $"源文件路径 : {sourceFilePath}");
- SereinEnv.WriteLine(InfoType.INFO, $"目标路径 : {targetFilePath}");
- File.Copy(sourceFilePath, targetFilePath, true);
-
- }
- else
- {
- SereinEnv.WriteLine(InfoType.WARN, $"目标路径已有类库文件: {targetFilePath}");
- }
- }
- else
- {
- SereinEnv.WriteLine(InfoType.WARN, $"源文件不存在 : {targetFilePath}");
- }
- }
- catch (IOException ex)
- {
-
- SereinEnv.WriteLine(InfoType.ERROR, ex.Message);
- }
- var dirName = System.IO.Path.GetDirectoryName(targetFilePath);
- if (!string.IsNullOrEmpty(dirName))
- {
- var tmpUri2 = new Uri(targetFilePath);
- var relativePath = saveProjectFileUri.MakeRelativeUri(tmpUri2).ToString(); // 转为类库的相对文件路径
-
-
-
-
- //string relativePath = System.IO.Path.GetRelativePath(savePath, targetPath);
- projectData.Librarys[index].FilePath = relativePath;
- }
-
- }
-
- JObject projectJsonData = JObject.FromObject(projectData);
- File.WriteAllText(savePath, projectJsonData.ToString());
-
-
- }
-
- ///
- /// 加载完成
- ///
- ///
- private void FlowEnvironment_OnProjectLoaded(ProjectLoadedEventArgs eventArgs)
- {
- }
-
- ///
- /// 运行完成
- ///
- ///
- ///
- private void FlowEnvironment_OnFlowRunCompleteEvent(FlowEventArgs eventArgs)
- {
- SereinEnv.WriteLine(InfoType.INFO, "-------运行完成---------\r\n");
- this.Dispatcher.Invoke(() =>
- {
- IOCObjectViewer.ClearObjItem();
- });
- }
-
- ///
- /// 加载了DLL文件,dll内容
- ///
- private void FlowEnvironment_DllLoadEvent(LoadDllEventArgs eventArgs)
- {
- NodeLibraryInfo nodeLibraryInfo = eventArgs.NodeLibraryInfo;
- List methodDetailss = eventArgs.MethodDetailss;
-
- var dllControl = new DllControl(nodeLibraryInfo);
-
- foreach (var methodDetailsInfo in methodDetailss)
- {
- if (!EnumHelper.TryConvertEnum(methodDetailsInfo.NodeType, out var nodeType))
- {
- continue;
- }
- switch (nodeType)
- {
- case Library.NodeType.Action:
- dllControl.AddAction(methodDetailsInfo); // 添加动作类型到控件
- break;
- case Library.NodeType.Flipflop:
- dllControl.AddFlipflop(methodDetailsInfo); // 添加触发器方法到控件
- break;
- }
-
- }
- var menu = new ContextMenu();
- menu.Items.Add(CreateMenuItem("卸载", (s, e) =>
- {
- if (this.EnvDecorator.TryUnloadLibrary(nodeLibraryInfo.AssemblyName))
- {
- DllStackPanel.Children.Remove(dllControl);
- }
- else
- {
- SereinEnv.WriteLine(InfoType.INFO, "卸载失败");
- }
- }));
-
- dllControl.ContextMenu = menu;
-
- DllStackPanel.Children.Add(dllControl); // 将控件添加到界面上显示
-
- }
-
- ///
- /// 节点连接关系变更
- ///
- ///
- private void FlowEnvironment_NodeConnectChangeEvemt(NodeConnectChangeEventArgs eventArgs)
- {
- string fromNodeGuid = eventArgs.FromNodeGuid;
- string toNodeGuid = eventArgs.ToNodeGuid;
- if (!TryGetControl(fromNodeGuid, out var fromNodeControl)
- || !TryGetControl(toNodeGuid, out var toNodeControl))
- {
- return;
- }
-
- if (eventArgs.JunctionOfConnectionType == JunctionOfConnectionType.Invoke)
- {
- ConnectionInvokeType connectionType = eventArgs.ConnectionInvokeType;
- #region 创建/删除节点之间的调用关系
- #region 创建连接
- if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接
- {
- if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction)
- {
- SereinEnv.WriteLine(InfoType.INFO, "非预期的连接");
- return;
- }
- JunctionControlBase startJunction = IFormJunction.NextStepJunction;
- JunctionControlBase endJunction = IToJunction.ExecuteJunction;
-
- // 添加连接
- var connection = new ConnectionControl(
- FlowChartCanvas,
- connectionType,
- startJunction,
- endJunction
- );
-
- if (toNodeControl is FlipflopNodeControl flipflopControl
- && flipflopControl?.ViewModel?.NodeModel is NodeModelBase nodeModel) // 某个节点连接到了触发器,尝试从全局触发器视图中移除该触发器
- {
- NodeTreeViewer.RemoveGlobalFlipFlop(nodeModel); // 从全局触发器树树视图中移除
- }
- Connections.Add(connection);
- fromNodeControl.AddCnnection(connection);
- toNodeControl.AddCnnection(connection);
- EndConnection(); // 环境触发了创建节点连接事件
-
- }
- #endregion
- #region 移除连接
- else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remove) // 移除连接
- {
- // 需要移除连接
- 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))
- .ToList();
-
-
- foreach (var connection in removeConnections)
- {
- Connections.Remove(connection);
- fromNodeControl.RemoveConnection(connection); // 移除连接
- toNodeControl.RemoveConnection(connection); // 移除连接
- if (NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control))
- {
- JudgmentFlipFlopNode(control); // 连接关系变更时判断
- }
- }
- }
- #endregion
- #endregion
- }
- else
- {
- ConnectionArgSourceType connectionArgSourceType = eventArgs.ConnectionArgSourceType;
- #region 创建/删除节点之间的参数传递关系
- #region 创建连接
- if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Create) // 添加连接
- {
- if (fromNodeControl is not INodeJunction IFormJunction || toNodeControl is not INodeJunction IToJunction)
- {
- SereinEnv.WriteLine(InfoType.INFO, "非预期的情况");
- return;
- }
-
- JunctionControlBase startJunction = eventArgs.ConnectionArgSourceType switch
- {
- ConnectionArgSourceType.GetPreviousNodeData => IFormJunction.ReturnDataJunction, // 自身节点
- ConnectionArgSourceType.GetOtherNodeData => IFormJunction.ReturnDataJunction, // 其它节点的返回值控制点
- ConnectionArgSourceType.GetOtherNodeDataOfInvoke => IFormJunction.ReturnDataJunction, // 其它节点的返回值控制点
- _ => throw new Exception("窗体事件 FlowEnvironment_NodeConnectChangeEvemt 创建/删除节点之间的参数传递关系 JunctionControlBase 枚举值错误 。非预期的枚举值。") // 应该不会触发
- };
-
- if(IToJunction.ArgDataJunction.Length <= eventArgs.ArgIndex)
- {
- _ = Task.Run(async () =>
- {
- await Task.Delay(500);
- FlowEnvironment_NodeConnectChangeEvemt(eventArgs);
- });
- return;
- }
- JunctionControlBase endJunction = IToJunction.ArgDataJunction[eventArgs.ArgIndex];
- LineType lineType = LineType.Bezier;
- // 添加连接
- var connection = new ConnectionControl(
- lineType,
- FlowChartCanvas,
- eventArgs.ArgIndex,
- eventArgs.ConnectionArgSourceType,
- startJunction,
- endJunction,
- IToJunction
- );
- Connections.Add(connection);
- fromNodeControl.AddCnnection(connection);
- toNodeControl.AddCnnection(connection);
- EndConnection(); // 环境触发了创建节点连接事件
-
-
- }
- #endregion
- #region 移除连接
- else if (eventArgs.ChangeType == NodeConnectChangeEventArgs.ConnectChangeType.Remove) // 移除连接
- {
- // 需要移除连接
- var removeConnections = Connections.Where(c => c.Start.MyNode.Guid.Equals(fromNodeGuid)
- && c.End.MyNode.Guid.Equals(toNodeGuid))
- .ToList(); // 获取这两个节点之间的所有连接关系
-
-
-
- foreach (var connection in removeConnections)
- {
- if (connection.End is ArgJunctionControl junctionControl && junctionControl.ArgIndex == eventArgs.ArgIndex)
- {
- // 找到符合删除条件的连接线
- Connections.Remove(connection); // 从本地记录中移除
- fromNodeControl.RemoveConnection(connection); // 从节点持有的记录移除
- toNodeControl.RemoveConnection(connection); // 从节点持有的记录移除
- }
-
-
- //if (NodeControls.TryGetValue(connection.End.MyNode.Guid, out var control))
- //{
- // JudgmentFlipFlopNode(control); // 连接关系变更时判断
- //}
- }
- }
- #endregion
- #endregion
- }
- }
-
- ///
- /// 节点移除事件
- ///
- ///
- private void FlowEnvironment_NodeRemoveEvent(NodeRemoveEventArgs eventArgs)
- {
- var nodeGuid = eventArgs.NodeGuid;
- if (!TryGetControl(nodeGuid, out var nodeControl))
- {
- return;
- }
-
- if (nodeControl is null) return;
- if (selectNodeControls.Count > 0)
- {
- if (selectNodeControls.Contains(nodeControl))
- {
- selectNodeControls.Remove(nodeControl);
- }
- }
-
- if (nodeControl is FlipflopNodeControl flipflopControl) // 判断是否为触发器
- {
- var node = flipflopControl?.ViewModel?.NodeModel;
- if (node is not null)
- {
- NodeTreeViewer.RemoveGlobalFlipFlop(node); // 从全局触发器树树视图中移除
- }
- }
-
-
-
- FlowChartCanvas.Children.Remove(nodeControl);
- nodeControl.RemoveAllConection();
- NodeControls.Remove(nodeControl.ViewModel.NodeModel.Guid);
- }
-
- ///
- /// 添加节点事件
- ///
- /// 添加节点事件参数
- ///
- private void FlowEnvironment_NodeCreateEvent(NodeCreateEventArgs eventArgs)
- {
- var nodeModel = eventArgs.NodeModel;
- if (NodeControls.ContainsKey(nodeModel.Guid))
- {
- SereinEnv.WriteLine(InfoType.WARN, $"OnNodeCreateEvent 事件接收到意外的返回值:节点Guid重复 - {nodeModel.Guid}");
- return;
- }
-
- PositionOfUI position = eventArgs.Position;
-
- if(!NodeMVVMManagement.TryGetType(nodeModel.ControlType, out var nodeMVVM))
- {
- SereinEnv.WriteLine(InfoType.INFO, $"无法创建{nodeModel.ControlType}节点,节点类型尚未注册。");
- return;
- }
- if(nodeMVVM.ControlType == null
- || nodeMVVM.ViewModelType == null)
- {
- SereinEnv.WriteLine(InfoType.INFO, $"无法创建{nodeModel.ControlType}节点,UI类型尚未注册(请通过 NodeMVVMManagement.RegisterUI() 方法进行注册)。");
- return;
- }
-
- var nodeCanvas = FlowChartCanvas;
- NodeControlBase nodeControl;
- try
- {
- nodeControl = CreateNodeControl(nodeMVVM.ControlType, // 控件UI类型
- nodeMVVM.ViewModelType, // 控件VIewModel类型
- nodeModel, // 控件数据实体
- nodeCanvas); // 所在画布
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
-
- NodeControls.TryAdd(nodeModel.Guid, nodeControl); // 添加到
- if (TryPlaceNodeInRegion(nodeControl, position, out var regionControl)) // 判断添加到区域容器
- {
- // 通知运行环境调用加载节点子项的方法
- _ = EnvDecorator.PlaceNodeToContainerAsync(nodeControl.ViewModel.NodeModel.Guid, // 待移动的节点
- regionControl.ViewModel.NodeModel.Guid); // 目标的容器节点
- }
- else
- {
- // 并非添加在容器中,直接放置节点
- PlaceNodeOnCanvas(nodeControl, position.X, position.Y);
- }
-
-
- #region 节点树视图
- if (nodeModel.ControlType == NodeControlType.Flipflop)
- {
- var node = nodeControl?.ViewModel?.NodeModel;
- if (node is not null)
- {
- NodeTreeViewer.AddGlobalFlipFlop(EnvDecorator, node); // 新增的触发器节点添加到全局触发器
- }
- }
-
- GC.Collect();
- #endregion
-
- }
-
- ///
- /// 放置一个节点
- ///
- ///
- ///
- private void EnvDecorator_OnNodePlaceEvent(NodePlaceEventArgs eventArgs)
- {
- string nodeGuid = eventArgs.NodeGuid;
- string containerNodeGuid = eventArgs.ContainerNodeGuid;
- if (!TryGetControl(nodeGuid, out var nodeControl)
- || !TryGetControl(containerNodeGuid, out var containerNodeControl))
- {
- return;
- }
- if(containerNodeControl is not INodeContainerControl containerControl)
- {
- SereinEnv.WriteLine(InfoType.WARN,
- $"节点[{nodeGuid}]无法放置于节点[{containerNodeGuid}]," +
- $"因为后者并不实现 INodeContainerControl 接口");
- return;
- }
- nodeControl.PlaceToContainer(containerControl); // 放置在容器节点中
- }
-
- ///
- /// 取出一个节点
- ///
- ///
- private void EnvDecorator_OnNodeTakeOutEvent(NodeTakeOutEventArgs eventArgs)
- {
- string nodeGuid = eventArgs.NodeGuid;
- if (!TryGetControl(nodeGuid, out var nodeControl))
- {
- return;
- }
- nodeControl.TakeOutContainer(); // 从容器节点中取出
-
- }
-
-
-
- ///
- /// 设置了流程起始控件
- ///
- ///
- ///
- private void FlowEnvironment_StartNodeChangeEvent(StartNodeChangeEventArgs eventArgs)
- {
- string oldNodeGuid = eventArgs.OldNodeGuid;
- string newNodeGuid = eventArgs.NewNodeGuid;
- if (!TryGetControl(newNodeGuid, out var newStartNodeControl)) return;
- if (!string.IsNullOrEmpty(oldNodeGuid))
- {
- if (!TryGetControl(oldNodeGuid, out var oldStartNodeControl)) return;
- oldStartNodeControl.BorderBrush = Brushes.Black;
- oldStartNodeControl.BorderThickness = new Thickness(0);
- }
-
- 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);
- }
-
- }
-
- ///
- /// 被监视的对象发生改变
- ///
- ///
- private void FlowEnvironment_OnMonitorObjectChangeEvent(MonitorObjectEventArgs eventArgs)
- {
- string nodeGuid = eventArgs.NodeGuid;
-
- string monitorKey = MonitorObjectEventArgs.ObjSourceType.NodeFlowData switch
- {
- MonitorObjectEventArgs.ObjSourceType.NodeFlowData => nodeGuid,
- _ => eventArgs.NewData.GetType().FullName,
- };
-
- //NodeControlBase nodeControl = GuidToControl(nodeGuid);
- if (ViewObjectViewer.MonitorObj is null) // 如果没有加载过对象
- {
- ViewObjectViewer.LoadObjectInformation(monitorKey, eventArgs.NewData); // 加载对象 ViewObjectViewerControl.MonitorType.Obj
- }
- else
- {
- if (monitorKey.Equals(ViewObjectViewer.MonitorKey)) // 相同对象
- {
- ViewObjectViewer.RefreshObjectTree(eventArgs.NewData); // 刷新
- }
- else
- {
- ViewObjectViewer.LoadObjectInformation(monitorKey, eventArgs.NewData); // 加载对象
- }
- }
-
- }
-
- ///
- /// 节点中断状态改变。
- ///
- ///
- private void FlowEnvironment_OnNodeInterruptStateChangeEvent(NodeInterruptStateChangeEventArgs eventArgs)
- {
- string nodeGuid = eventArgs.NodeGuid;
- if (!TryGetControl(nodeGuid, out var nodeControl)) return;
-
- //if (eventArgs.Class == InterruptClass.None)
- //{
- // nodeControl.ViewModel.IsInterrupt = false;
- //}
- //else
- //{
- // nodeControl.ViewModel.IsInterrupt = true;
- //}
- if(nodeControl.ContextMenu == null)
- {
- return;
- }
- foreach (var menuItem in nodeControl.ContextMenu.Items)
- {
- if (menuItem is MenuItem menu)
- {
- if ("取消中断".Equals(menu.Header))
- {
- menu.Header = "在此中断";
- }
- else if ("在此中断".Equals(menu.Header))
- {
- menu.Header = "取消中断";
- }
-
- }
- }
-
- }
-
- ///
- /// 节点触发了中断
- ///
- ///
- ///
- private void FlowEnvironment_OnInterruptTriggerEvent(InterruptTriggerEventArgs eventArgs)
- {
- string nodeGuid = eventArgs.NodeGuid;
- if (!TryGetControl(nodeGuid, out var nodeControl)) return;
- if(eventArgs.Type == InterruptTriggerEventArgs.InterruptTriggerType.Exp)
- {
- SereinEnv.WriteLine(InfoType.INFO, $"表达式触发了中断:{eventArgs.Expression}");
- }
- else
- {
- SereinEnv.WriteLine(InfoType.INFO, $"节点触发了中断:{nodeGuid}");
- }
- }
-
- ///
- /// IOC变更
- ///
- ///
- ///
- private void FlowEnvironment_OnIOCMembersChangedEvent(IOCMembersChangedEventArgs eventArgs)
- {
- IOCObjectViewer.AddDependenciesInstance(eventArgs.Key, eventArgs.Instance);
-
- }
-
- ///
- /// 节点需要定位
- ///
- ///
- ///
- private void FlowEnvironment_OnNodeLocateEvent(NodeLocatedEventArgs eventArgs)
- {
- 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);
-
- }
-
- ///
- /// 控件抖动
- /// 来源:https://www.cnblogs.com/RedSky/p/17705411.html
- /// 作者:HotSky
- /// (……太好用了)
- ///
- ///
- /// 需要抖动的控件
- /// 抖动第一下偏移量
- /// 减弱幅度(小于等于power,大于0)
- /// 持续系数(大于0),越大时间越长,
- private static void ElasticAnimation(NodeControlBase nodeControl, TranslateTransform translate, int power, int range = 1, double speed = 1)
- {
- 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; // 或者重新设置为默认值
- };
- }
-
- ///
- /// 节点移动
- ///
- ///
- private void FlowEnvironment_OnNodeMovedEvent(NodeMovedEventArgs eventArgs)
- {
- if (!TryGetControl(eventArgs.NodeGuid, out var nodeControl)) return;
- nodeControl.UpdateLocationConnections();
-
- //var newLeft = eventArgs.X;
- //var newTop = eventArgs.Y;
- //// 限制控件不超出FlowChartCanvas的边界
- //if (newLeft >= 0 && newLeft + nodeControl.ActualWidth <= FlowChartCanvas.ActualWidth)
- //{
- // Canvas.SetLeft(nodeControl, newLeft);
-
- //}
- //if (newTop >= 0 && newTop + nodeControl.ActualHeight <= FlowChartCanvas.ActualHeight)
- //{
- // Canvas.SetTop(nodeControl, newTop);
- //}
-
-
- }
-
- ///
- /// Guid 转 NodeControl
- ///
- ///
- ///
- ///
- private bool TryGetControl(string nodeGuid,out NodeControlBase nodeControl)
- {
- if (string.IsNullOrEmpty(nodeGuid))
- {
- nodeControl = null;
- return false;
- }
- if (!NodeControls.TryGetValue(nodeGuid, out nodeControl))
- {
- nodeControl = null;
- return false;
- }
- if(nodeControl is null)
- {
- return false;
- }
- return true;
- }
-
- #endregion
-
-
- #region 节点控件的创建
-
-
- ///
- /// 创建了节点,添加到画布。配置默认事件
- ///
- ///
- ///
- ///
- private void PlaceNodeOnCanvas(NodeControlBase nodeControl, double x, double y)
- {
- // 添加控件到画布
- FlowChartCanvas.Children.Add(nodeControl);
- Canvas.SetLeft(nodeControl, x);
- Canvas.SetTop(nodeControl, y);
-
- ConfigureContextMenu(nodeControl); // 配置节点右键菜单
- ConfigureNodeEvents(nodeControl); // 配置节点事件
- }
-
- ///
- /// 配置节点事件(移动,点击相关)
- ///
- ///
- private void ConfigureNodeEvents(NodeControlBase nodeControl)
- {
- nodeControl.MouseLeftButtonDown += Block_MouseLeftButtonDown;
- nodeControl.MouseMove += Block_MouseMove;
- nodeControl.MouseLeftButtonUp += Block_MouseLeftButtonUp;
- }
-
-
- #endregion
-
- #region 配置右键菜单
-
- ///
- /// 配置节点右键菜单
- ///
- ///
- /// 任何情景下都尽量避免直接修改 ViewModel 中的 NodeModel 节点实体相关数据。
- /// 而是应该调用 FlowEnvironment 提供接口进行操作。
- /// 因为 Workbench 应该更加关注UI视觉效果,而非直接干扰流程环境运行的逻辑。
- /// 之所以暴露 NodeModel 属性,因为有些场景下不可避免的需要直接获取节点的属性。
- ///
- private void ConfigureContextMenu(NodeControlBase nodeControl)
- {
-
- var contextMenu = new ContextMenu();
- var nodeGuid = nodeControl.ViewModel?.NodeModel?.Guid;
- #region 触发器节点
-
- if(nodeControl.ViewModel?.NodeModel.ControlType == NodeControlType.Flipflop)
- {
- contextMenu.Items.Add(CreateMenuItem("启动触发器", (s, e) =>
- {
- if (s is MenuItem menuItem)
- {
- if (menuItem.Header.ToString() == "启动触发器")
- {
- EnvDecorator.ActivateFlipflopNode(nodeGuid);
-
- menuItem.Header = "终结触发器";
- }
- else
- {
- EnvDecorator.TerminateFlipflopNode(nodeGuid);
- menuItem.Header = "启动触发器";
-
- }
- }
- }));
- }
-
- #endregion
-
- if (nodeControl.ViewModel?.NodeModel?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
- {
- contextMenu.Items.Add(CreateMenuItem("查看返回类型", (s, e) =>
- {
- DisplayReturnTypeTreeViewer(returnType);
- }));
- }
-
-
-
- contextMenu.Items.Add(CreateMenuItem("设为起点", (s, e) => EnvDecorator.SetStartNodeAsync(nodeGuid)));
- contextMenu.Items.Add(CreateMenuItem("删除", async (s, e) =>
- {
- var result = await EnvDecorator.RemoveNodeAsync(nodeGuid);
- }));
-
- #region 右键菜单功能 - 控件对齐
-
- var AvoidMenu = new MenuItem();
- AvoidMenu.Items.Add(CreateMenuItem("群组对齐", (s, e) =>
- {
- AlignControlsWithGrouping(selectNodeControls, AlignMode.Grouping);
- }));
- AvoidMenu.Items.Add(CreateMenuItem("规划对齐", (s, e) =>
- {
- 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);
- }));
-
- AvoidMenu.Header = "对齐";
- contextMenu.Items.Add(AvoidMenu);
-
-
- #endregion
-
- nodeControl.ContextMenu = contextMenu;
- }
-
- ///
- /// 查看返回类型(树形结构展开类型的成员)
- ///
- ///
- private void DisplayReturnTypeTreeViewer(Type type)
- {
- try
- {
- var typeViewerWindow = new TypeViewerWindow
- {
- Type = type,
- };
- typeViewerWindow.LoadTypeInformation();
- typeViewerWindow.Show();
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(InfoType.ERROR, ex.ToString());
- }
- }
- #endregion
-
- #region 拖拽DLL文件到左侧功能区,加载相关节点清单
- ///
- /// 当拖动文件到窗口时触发,加载DLL文件
- ///
- ///
- ///
- private void Window_Drop(object sender, DragEventArgs e)
- {
- if (e.Data.GetDataPresent(DataFormats.FileDrop))
- {
- string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
- foreach (string file in files)
- {
- if (file.EndsWith(".dll"))
- {
- try
- {
- EnvDecorator.LoadLibrary(file);
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }
- }
- }
- }
-
- ///
- /// 当拖动文件经过窗口时触发,设置拖放效果为复制
- ///
- ///
- ///
- private void Window_DragOver(object sender, DragEventArgs e)
- {
- e.Effects = DragDropEffects.Copy;
- e.Handled = true;
- }
-
- #endregion
-
- #region 与流程图/节点相关
-
- ///
- /// 鼠标在画布移动。
- /// 选择控件状态下,调整选择框大小
- /// 连接状态下,实时更新连接线的终点位置。
- /// 移动画布状态下,移动画布。
- ///
- private void FlowChartCanvas_MouseMove(object sender, MouseEventArgs e)
- {
- var myData = GlobalJunctionData.MyGlobalConnectingData;
- if (myData.IsCreateing && e.LeftButton == MouseButtonState.Pressed)
- {
-
- if (myData.Type == JunctionOfConnectionType.Invoke)
- {
- ViewModel.IsConnectionInvokeNode = true; // 正在连接节点的调用关系
-
- }
- else
- {
- ViewModel.IsConnectionArgSourceNode = true; // 正在连接节点的调用关系
- }
- var currentPoint = e.GetPosition(FlowChartCanvas);
- currentPoint.X -= 2;
- currentPoint.Y -= 2;
- myData.UpdatePoint(currentPoint);
- return;
- }
-
-
-
- if (IsCanvasDragging && e.MiddleButton == MouseButtonState.Pressed) // 正在移动画布(按住中键)
- {
- Point currentMousePosition = e.GetPosition(this);
- double deltaX = currentMousePosition.X - startCanvasDragPoint.X;
- double deltaY = currentMousePosition.Y - startCanvasDragPoint.Y;
-
- translateTransform.X += deltaX;
- translateTransform.Y += deltaY;
-
- startCanvasDragPoint = currentMousePosition;
-
- foreach (var line in Connections)
- {
- line.RefreshLine(); // 画布移动时刷新所有连接线
- }
- }
-
- if (IsSelectControl) // 正在选取节点
- {
- IsSelectDragging = e.LeftButton == MouseButtonState.Pressed;
- // 获取当前鼠标位置
- 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;
-
- }
- }
-
- ///
- /// 基础节点的拖拽放置创建
- ///
- ///
- ///
- private void BaseNodeControl_PreviewMouseMove(object sender, MouseEventArgs e)
- {
- if (sender is UserControl control)
- {
- if(e.LeftButton == MouseButtonState.Pressed)
- {
- // 创建一个 DataObject 用于拖拽操作,并设置拖拽效果
- var dragData = new DataObject(MouseNodeType.CreateBaseNodeInCanvas, control.GetType());
- DragDrop.DoDragDrop(control, dragData, DragDropEffects.Move);
- }
-
- }
- }
-
- ///
- /// 放置操作,根据拖放数据创建相应的控件,并处理相关操作
- ///
- ///
- ///
- private void FlowChartCanvas_Drop(object sender, DragEventArgs e)
- {
- try
- {
- var canvasDropPosition = e.GetPosition(FlowChartCanvas); // 更新画布落点
- PositionOfUI position = new PositionOfUI(canvasDropPosition.X, canvasDropPosition.Y);
- if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas))
- {
- if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeData nodeData)
- {
- Task.Run(async () =>
- {
- await EnvDecorator.CreateNodeAsync(nodeData.NodeControlType, position, nodeData.MethodDetailsInfo); // 创建DLL文件的节点对象
- });
- }
- }
- else if (e.Data.GetDataPresent(MouseNodeType.CreateBaseNodeInCanvas))
- {
- if (e.Data.GetData(MouseNodeType.CreateBaseNodeInCanvas) is Type droppedType)
- {
- 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,
- Type when typeof(GlobalDataControl).IsAssignableFrom(droppedType) => NodeControlType.GlobalData,
- Type when typeof(ScriptNodeControl).IsAssignableFrom(droppedType) => NodeControlType.Script,
- _ => NodeControlType.None,
- };
- if (nodeControlType != NodeControlType.None)
- {
- Task.Run(async () =>
- {
- await EnvDecorator.CreateNodeAsync(nodeControlType, position); // 创建基础节点对象
- });
- }
- }
- }
- e.Handled = true;
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(InfoType.ERROR, ex.ToString());
- }
- }
-
- ///
- /// 尝试判断是否为区域,如果是,将节点放置在区域中
- ///
- ///
- ///
- /// 目标节点控件
- ///
- private bool TryPlaceNodeInRegion(NodeControlBase nodeControl,
- PositionOfUI position,
- out NodeControlBase targetNodeControl)
- {
- var point = new Point(position.X, position.Y);
- HitTestResult hitTestResult = VisualTreeHelper.HitTest(FlowChartCanvas, point);
- if (hitTestResult != null && hitTestResult.VisualHit is UIElement hitElement)
- {
- // 准备放置条件表达式控件
- if (nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.ExpCondition)
- {
- ConditionRegionControl? conditionRegion = GetParentOfType(hitElement);
- if (conditionRegion is not null)
- {
- targetNodeControl = conditionRegion;
- //// 如果存在条件区域容器
- //conditionRegion.AddCondition(nodeControl);
- return true;
- }
- }
-
- else
- {
- // 准备放置全局数据控件
- GlobalDataControl? globalDataControl = GetParentOfType(hitElement);
- if (globalDataControl is not null)
- {
- targetNodeControl = globalDataControl;
- return true;
- }
- }
- }
- targetNodeControl = null;
- return false;
- }
-
- /////
- ///// 将节点放在目标区域中
- /////
- ///// 区域容器
- ///// 节点控件
- //private void TryPlaceNodeInRegion(NodeControlBase regionControl, NodeControlBase nodeControl)
- //{
- // // 准备放置条件表达式控件
- // if (nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.ExpCondition)
- // {
- // if (regionControl is ConditionRegionControl conditionRegion)
- // {
- // conditionRegion.AddCondition(nodeControl); // 条件区域容器
- // }
- // }
- // else if(regionControl.ViewModel.NodeModel.ControlType == NodeControlType.GlobalData)
- // {
- // if (regionControl is GlobalDataControl globalDataControl)
- // {
- // // 全局数据节点容器
- // globalDataControl.SetDataNodeControl(nodeControl);
- // }
- // }
- //}
-
-
-
- ///
- /// 拖动效果,根据拖放数据是否为指定类型设置拖放效果
- ///
- ///
- ///
- private void FlowChartCanvas_DragOver(object sender, DragEventArgs e)
- {
- if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas)
- || e.Data.GetDataPresent(MouseNodeType.CreateBaseNodeInCanvas))
- {
- e.Effects = DragDropEffects.Move;
- }
- else
- {
- e.Effects = DragDropEffects.None;
- }
- e.Handled = true;
- }
-
- ///
- /// 控件的鼠标左键按下事件,启动拖动操作。同时显示当前正在传递的数据。
- ///
- private void Block_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- //if (GlobalJunctionData.IsCreatingConnection)
- //{
- // return;
- //}
- if(sender is NodeControlBase nodeControl)
- {
- ChangeViewerObjOfNode(nodeControl);
- if (nodeControl?.ViewModel?.NodeModel?.MethodDetails?.IsProtectionParameter == true) return;
- IsControlDragging = true;
- startControlDragPoint = e.GetPosition(FlowChartCanvas); // 记录鼠标按下时的位置
- ((UIElement)sender).CaptureMouse(); // 捕获鼠标
- e.Handled = true; // 防止事件传播影响其他控件
- }
- }
-
- ///
- /// 控件的鼠标移动事件,根据鼠标拖动更新控件的位置。批量移动计算移动逻辑。
- ///
- private void Block_MouseMove(object sender, MouseEventArgs e)
- {
- if (IsCanvasDragging)
- return;
- if (IsSelectControl)
- return;
-
- if (IsControlDragging) // 如果正在拖动控件
- {
- Point currentPosition = e.GetPosition(FlowChartCanvas); // 获取当前鼠标位置
-
- if (selectNodeControls.Count > 0 && sender is NodeControlBase nodeControlMain && selectNodeControls.Contains(nodeControlMain))
- {
- // 进行批量移动
- // 获取旧位置
- var oldLeft = Canvas.GetLeft(nodeControlMain);
- var oldTop = Canvas.GetTop(nodeControlMain);
-
- // 计算被选择控件的偏移量
- var deltaX = /*(int)*/(currentPosition.X - startControlDragPoint.X);
- var deltaY = /*(int)*/(currentPosition.Y - startControlDragPoint.Y);
-
- // 移动被选择的控件
- var newLeft = oldLeft + deltaX;
- var newTop = oldTop + deltaY;
-
- this.EnvDecorator.MoveNode(nodeControlMain.ViewModel.NodeModel.Guid, newLeft, newTop); // 移动节点
-
- // 计算控件实际移动的距离
- var actualDeltaX = newLeft - oldLeft;
- var actualDeltaY = newTop - oldTop;
-
- // 移动其它选中的控件
- foreach (var nodeControl in selectNodeControls)
- {
- if (nodeControl != nodeControlMain) // 跳过已经移动的控件
- {
- var otherNewLeft = Canvas.GetLeft(nodeControl) + actualDeltaX;
- var otherNewTop = Canvas.GetTop(nodeControl) + actualDeltaY;
- this.EnvDecorator.MoveNode(nodeControl.ViewModel.NodeModel.Guid, otherNewLeft, otherNewTop); // 移动节点
- }
- }
-
- // 更新节点之间线的连接位置
- foreach (var nodeControl in selectNodeControls)
- {
- nodeControl.UpdateLocationConnections();
- }
- }
- else
- { // 单个节点移动
- if (sender is not NodeControlBase nodeControl)
- {
- return;
- }
- double deltaX = currentPosition.X - startControlDragPoint.X; // 计算X轴方向的偏移量
- double deltaY = currentPosition.Y - startControlDragPoint.Y; // 计算Y轴方向的偏移量
- double newLeft = Canvas.GetLeft(nodeControl) + deltaX; // 新的左边距
- double newTop = Canvas.GetTop(nodeControl) + deltaY; // 新的上边距
- this.EnvDecorator.MoveNode(nodeControl.ViewModel.NodeModel.Guid, newLeft, newTop); // 移动节点
- nodeControl.UpdateLocationConnections();
- }
- startControlDragPoint = currentPosition; // 更新起始点位置
- }
-
- }
-
-
- // 改变对象树?
- private void ChangeViewerObjOfNode(NodeControlBase nodeControl)
- {
- var node = nodeControl.ViewModel.NodeModel;
- //if (node is not null && (node.MethodDetails is null || node.MethodDetails.ReturnType != typeof(void))
- if (node is not null && node.MethodDetails?.ReturnType != typeof(void))
- {
- var key = node.Guid;
- object instance = null;
- //Console.WriteLine("WindowXaml 后台代码中 ChangeViewerObjOfNode 需要重新设计");
- //var instance = node.GetFlowData(); // 对象预览树视图获取(后期更改)
- if(instance is not null)
- {
- ViewObjectViewer.LoadObjectInformation(key, instance);
- ChangeViewerObj(key, instance);
- }
- }
- }
- public void ChangeViewerObj(string key, object instance)
- {
- if (ViewObjectViewer.MonitorObj is null)
- {
- // EnvDecorator.SetMonitorObjState(key, true); // 通知环境,该节点的数据更新后需要传到UI
- return;
- }
- if (instance is null)
- {
- return;
- }
- if (key.Equals(ViewObjectViewer.MonitorKey) == true)
- {
- ViewObjectViewer.RefreshObjectTree(instance);
- return;
- }
- else
- {
- //EnvDecorator.SetMonitorObjState(ViewObjectViewer.MonitorKey,false); // 取消对旧节点的监视
- //EnvDecorator.SetMonitorObjState(key, true); // 通知环境,该节点的数据更新后需要传到UI
- }
- }
- #endregion
-
- #region UI连接控件操作
-
- ///
- /// 控件的鼠标左键松开事件,结束拖动操作
- ///
- private void Block_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- if (IsControlDragging)
- {
- IsControlDragging = false;
- ((UIElement)sender).ReleaseMouseCapture(); // 释放鼠标捕获
-
- }
-
- //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();
- }
-
-
- ///
- /// 结束连接操作,清理状态并移除虚线。
- ///
- private void EndConnection()
- {
- Mouse.OverrideCursor = null; // 恢复视觉效果
- ViewModel.IsConnectionArgSourceNode = false;
- ViewModel.IsConnectionInvokeNode = false;
- GlobalJunctionData.OK();
- }
-
- #region 拖动画布实现缩放平移效果
- private void FlowChartCanvas_MouseDown(object sender, MouseButtonEventArgs e)
- {
- IsCanvasDragging = true;
- startCanvasDragPoint = e.GetPosition(this);
- FlowChartCanvas.CaptureMouse();
- e.Handled = true; // 防止事件传播影响其他控件
- }
-
- private void FlowChartCanvas_MouseUp(object sender, MouseButtonEventArgs e)
- {
-
-
-
- if (IsCanvasDragging)
- {
- IsCanvasDragging = false;
- FlowChartCanvas.ReleaseMouseCapture();
- }
- }
-
- // 单纯缩放画布,不改变画布大小
- private void FlowChartCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
- {
- // if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
- {
- if (e.Delta < 0 && scaleTransform.ScaleX < 0.05) return;
- if (e.Delta > 0 && scaleTransform.ScaleY > 2.0) return;
- // 获取鼠标在 Canvas 内的相对位置
- var mousePosition = e.GetPosition(FlowChartCanvas);
-
- // 缩放因子,根据滚轮方向调整
- //double zoomFactor = e.Delta > 0 ? 0.1 : -0.1;
- double zoomFactor = e.Delta > 0 ? 1.1 : 0.9;
-
- // 当前缩放比例
- double oldScale = scaleTransform.ScaleX;
- double newScale = oldScale * zoomFactor;
- //double newScale = oldScale + zoomFactor;
- // 更新缩放比例
- 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));
- }
- }
-
- // 设置画布宽度高度
- private void InitializeCanvas(double width, double height)
- {
- FlowChartCanvas.Width = width;
- FlowChartCanvas.Height = height;
- }
-
-
- #region 动态调整区域大小
- //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);
-
- // FlowChartCanvas.Width = newWidth;
- // FlowChartCanvas.Height = newHeight;
-
- // Canvas.SetLeft(FlowChartCanvas, Canvas.GetLeft(FlowChartCanvas) + e.HorizontalChange);
- // Canvas.SetTop(FlowChartCanvas, Canvas.GetTop(FlowChartCanvas) + e.VerticalChange);
- //}
-
- //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);
-
- // FlowChartCanvas.Width = newWidth;
- // FlowChartCanvas.Height = newHeight;
-
- // Canvas.SetTop(FlowChartCanvas, Canvas.GetTop(FlowChartCanvas) + e.VerticalChange);
- //}
-
- //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);
-
- // FlowChartCanvas.Width = newWidth;
- // FlowChartCanvas.Height = newHeight;
-
- // Canvas.SetLeft(FlowChartCanvas, Canvas.GetLeft(FlowChartCanvas) + e.HorizontalChange);
- //}
-
- private void Thumb_DragDelta_BottomRight(object sender, DragDeltaEventArgs e)
- {
- // 获取缩放后的水平和垂直变化
- double horizontalChange = e.HorizontalChange * scaleTransform.ScaleX;
- double verticalChange = e.VerticalChange * scaleTransform.ScaleY;
-
- // 计算新的宽度和高度,确保不会小于400
- double newWidth = Math.Max(FlowChartCanvas.ActualWidth + horizontalChange, 400);
- double newHeight = Math.Max(FlowChartCanvas.ActualHeight + verticalChange, 400);
-
- newHeight = newHeight < 400 ? 400 : newHeight;
- newWidth = newWidth < 400 ? 400 : newWidth;
-
- InitializeCanvas(newWidth, newHeight);
-
- //// 从右下角调整大小
- //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;
-
- // double deltaX = x * scaleTransform.ScaleX;
- // double deltaY = y * scaleTransform.ScaleY;
- // Test(deltaX, deltaY);
- //}
- }
-
- //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);
- //}
-
- private void Thumb_DragDelta_Right(object sender, DragDeltaEventArgs e)
- {
- //从右侧调整大小
- // 获取缩放后的水平变化
- double horizontalChange = e.HorizontalChange * scaleTransform.ScaleX;
-
- // 计算新的宽度,确保不会小于400
- double newWidth = Math.Max(FlowChartCanvas.ActualWidth + horizontalChange, 400);
-
- newWidth = newWidth < 400 ? 400 : newWidth;
- InitializeCanvas(newWidth, FlowChartCanvas.Height);
-
- }
-
- //private void Thumb_DragDelta_Top(object sender, DragDeltaEventArgs e)
- //{
- // // 从顶部调整大小
- // double newHeight = Math.Max(FlowChartCanvas.ActualHeight - e.VerticalChange, 0);
-
- // FlowChartCanvas.Height = newHeight;
- // Canvas.SetTop(FlowChartCanvas, Canvas.GetTop(FlowChartCanvas) + e.VerticalChange);
- //}
-
- private void Thumb_DragDelta_Bottom(object sender, DragDeltaEventArgs e)
- {
- // 获取缩放后的垂直变化
- double verticalChange = e.VerticalChange * scaleTransform.ScaleY;
- // 计算新的高度,确保不会小于400
- double newHeight = Math.Max(FlowChartCanvas.ActualHeight + verticalChange, 400);
- newHeight = newHeight < 400 ? 400 : newHeight;
- InitializeCanvas(FlowChartCanvas.Width, newHeight);
- }
-
-
- private void Test(double deltaX, double deltaY)
- {
- //Console.WriteLine((translateTransform.X, translateTransform.Y));
- //translateTransform.X += deltaX;
- //translateTransform.Y += deltaY;
- }
-
- #endregion
- #endregion
-
-
-
- #endregion
-
- #region 画布中框选节点控件动作
-
- ///
- /// 在画布中尝试选取控件
- ///
- ///
- ///
- private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- if (GlobalJunctionData.MyGlobalConnectingData.IsCreateing)
- {
- return;
- }
- 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; // 防止事件传播影响其他控件
- }
-
- ///
- /// 在画布中释放鼠标按下,结束选取状态 / 停止创建连线,尝试连接节点
- ///
- ///
- ///
- private void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
- {
- if (IsSelectControl)
- {
- // 松开鼠标时判断是否为拖动操作
- if (IsSelectDragging)
- {
- // 完成拖动框选
- CompleteSelection();
- }
-
- // 释放鼠标捕获
- FlowChartCanvas.ReleaseMouseCapture();
- }
-
- // 创建连线
- if (GlobalJunctionData.MyGlobalConnectingData is ConnectingData myData && myData.IsCreateing)
- {
-
- if (myData.IsCanConnected)
- {
- var canvas = this.FlowChartCanvas;
- var currentendPoint = e.GetPosition(canvas); // 当前鼠标落点
- var changingJunctionPosition = myData.CurrentJunction.TranslatePoint(new Point(0, 0), canvas);
- var changingJunctionRect = new Rect(changingJunctionPosition, new Size(myData.CurrentJunction.Width, myData.CurrentJunction.Height));
-
- if (changingJunctionRect.Contains(currentendPoint)) // 可以创建连接
- {
- #region 方法调用关系创建
- if (myData.Type == JunctionOfConnectionType.Invoke)
- {
- 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)
- {
- 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
- }
- EndConnection();
- }
-
- }
- e.Handled = true;
-
- }
-
- /// 完成选取操作
- ///
- 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)
- {
- if (!selectNodeControls.Contains(control))
- {
- selectNodeControls.Add(control);
- }
- }
- }
- }
-
- // 选中后的操作
- SelectedNode();
- }
- private ContextMenu ConfiguerSelectionRectangle()
- {
- var contextMenu = new ContextMenu();
- contextMenu.Items.Add(CreateMenuItem("删除", (s, e) =>
- {
- if (selectNodeControls.Count > 0)
- {
- foreach (var node in selectNodeControls.ToArray())
- {
- var guid = node?.ViewModel?.NodeModel?.Guid;
- if (!string.IsNullOrEmpty(guid))
- {
- EnvDecorator.RemoveNodeAsync(guid);
- }
- }
- }
- SelectionRectangle.Visibility = Visibility.Collapsed;
- }));
- return contextMenu;
- // nodeControl.ContextMenu = contextMenu;
- }
- private void SelectedNode()
- {
-
- if (selectNodeControls.Count == 0)
- {
- //Console.WriteLine($"没有选择控件");
- SelectionRectangle.Visibility = Visibility.Collapsed;
- return;
- }
- if(selectNodeControls.Count == 1)
- {
- // ChangeViewerObjOfNode(selectNodeControls[0]);
- }
-
- //Console.WriteLine($"一共选取了{selectNodeControls.Count}个控件");
- foreach (var node in selectNodeControls)
- {
- //node.ViewModel.IsSelect =true;
- // node.ViewModel.CancelSelect();
- node.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFC700"));
- node.BorderThickness = new Thickness(4);
- }
- }
- private void CancelSelectNode()
- {
- IsSelectControl = false;
- foreach (var nodeControl in selectNodeControls)
- {
- //nodeControl.ViewModel.IsSelect = false;
- nodeControl.BorderBrush = Brushes.Black;
- nodeControl.BorderThickness = new Thickness(0);
- if (nodeControl.ViewModel.NodeModel.IsStart)
- {
- nodeControl.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"));
- nodeControl.BorderThickness = new Thickness(2);
- }
- }
- selectNodeControls.Clear();
- }
- #endregion
-
- #region 节点对齐 (有些小瑕疵)
-
- //public void UpdateConnectedLines()
- //{
- // //foreach (var nodeControl in selectNodeControls)
- // //{
- // // UpdateConnections(nodeControl);
- // //}
- // this.Dispatcher.Invoke(() =>
- // {
- // foreach (var line in Connections)
- // {
- // line.AddOrRefreshLine(); // 节点完成对齐
- // }
- // });
-
- //}
-
-
- #region Plan A 群组对齐
-
- public void AlignControlsWithGrouping(List selectNodeControls, double proximityThreshold = 50, double spacing = 10)
- {
- if (selectNodeControls is null || selectNodeControls.Count < 2)
- 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> GroupByProximity(List controls, double proximityThreshold, bool isHorizontal)
- {
- var groups = new List>();
-
- 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 { control });
- }
- }
-
- return groups;
- }
-
- // 判断控件是否接近某个群组
- private bool IsInProximity(List 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 selectNodeControls, double spacing = 10)
- {
- if (selectNodeControls is null || selectNodeControls.Count < 2)
- 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 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 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
-
- public enum AlignMode
- {
- ///
- /// 水平对齐
- ///
- Horizontal,
- ///
- /// 垂直对齐
- ///
- Vertical,
- ///
- /// 水平中心对齐
- ///
- HorizontalCenter,
- ///
- /// 垂直中心对齐
- ///
- VerticalCenter,
-
- ///
- /// 规划对齐
- ///
- Planning,
- ///
- /// 群组对齐
- ///
- Grouping,
- }
-
-
- public void AlignControlsWithGrouping(List selectNodeControls, AlignMode alignMode, double proximityThreshold = 50, double spacing = 10)
- {
- if (selectNodeControls is null || selectNodeControls.Count < 2)
- 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 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 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 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);
- }
- }
- }
-
- #endregion
-
- #region 静态方法:创建节点,创建菜单子项,获取区域
-
- ///
- /// 创建节点控件
- ///
- /// 节点控件视图控件类型
- /// 节点控件ViewModel类型
- /// 节点Model实例
- /// 节点所在画布
- ///
- /// 无法创建节点控件
- private static NodeControlBase CreateNodeControl(Type controlType, Type viewModelType, NodeModelBase model, Canvas nodeCanvas)
- {
- if ((controlType is null)
- || viewModelType is null
- || model is null)
- {
- throw new Exception("无法创建节点控件");
- }
- if (typeof(NodeControlBase).IsSubclassOf(controlType) || typeof(NodeControlViewModelBase).IsSubclassOf(viewModelType))
- {
- throw new Exception("无法创建节点控件");
- }
-
- if (string.IsNullOrEmpty(model.Guid))
- {
- model.Guid = Guid.NewGuid().ToString();
- }
-
- var viewModel = Activator.CreateInstance(viewModelType, [model]);
- var controlObj = Activator.CreateInstance(controlType, [viewModel]);
- if (controlObj is NodeControlBase nodeControl)
- {
- nodeControl.NodeCanvas = nodeCanvas;
- return nodeControl;
- }
- else
- {
- throw new Exception("无法创建节点控件");
- }
- }
-
-
- ///
- /// 创建菜单子项
- ///
- ///
- ///
- ///
- public static MenuItem CreateMenuItem(string header, RoutedEventHandler handler)
- {
- var menuItem = new MenuItem { Header = header };
- menuItem.Click += handler;
- return menuItem;
- }
-
-
-
- ///
- /// 穿透元素获取区域容器
- ///
- ///
- ///
- ///
- public static T? GetParentOfType(DependencyObject element) where T : DependencyObject
- {
- while (element != null)
- {
- if (element is T e)
- {
- return e;
- }
- element = VisualTreeHelper.GetParent(element);
- }
- return null;
- }
-
- #endregion
-
- #region 节点树、IOC视图管理
-
- private void JudgmentFlipFlopNode(NodeControlBase nodeControl)
- {
- if (nodeControl is FlipflopNodeControl flipflopControl
- && flipflopControl?.ViewModel?.NodeModel is NodeModelBase nodeModel) // 判断是否为触发器
- {
- int count = 0;
- foreach (var ct in NodeStaticConfig.ConnectionTypes)
- {
- count += nodeModel.PreviousNodes[ct].Count;
- }
- if (count == 0)
- {
- NodeTreeViewer.AddGlobalFlipFlop(EnvDecorator, nodeModel); // 添加到全局触发器树树视图
- }
- else
- {
- NodeTreeViewer.RemoveGlobalFlipFlop(nodeModel); // 从全局触发器树树视图中移除
- }
- }
- }
- void LoadIOCObjectViewer()
- {
-
- }
- #endregion
-
-
-
- #region 顶部菜单栏 - 调试功能区
-
- ///
- /// 运行测试
- ///
- ///
- ///
- private async void ButtonDebugRun_Click(object sender, RoutedEventArgs e)
- {
- LogOutWindow?.Show();
-
-
-
-#if WINDOWS
- //Dispatcher uiDispatcher = Application.Current.MainWindow.Dispatcher;
- //SynchronizationContext? uiContext = SynchronizationContext.Current;
- //EnvDecorator.IOC.CustomRegisterInstance(typeof(SynchronizationContextk).FullName, uiContext, false);
-#endif
-
- // 获取主线程的 SynchronizationContext
- Action uiInvoke = (uiContext, action) => uiContext?.Post(state => action?.Invoke(), null);
-
- SereinEnv.WriteLine(InfoType.INFO, "流程开始运行");
- try
- {
- await EnvDecorator.StartFlowAsync();
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
-
- // await EnvDecorator.StartAsync();
- //await Task.Factory.StartNew(FlowEnvironment.StartAsync);
- }
-
- ///
- /// 退出
- ///
- ///
- ///
- private async void ButtonDebugFlipflopNode_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- await EnvDecorator.ExitFlowAsync(); // 在运行平台上点击了退出
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }
-
- ///
- /// 从选定的节点开始运行
- ///
- ///
- ///
- private async void ButtonStartFlowInSelectNode_Click(object sender, RoutedEventArgs e)
- {
- if (selectNodeControls.Count == 0)
- {
- SereinEnv.WriteLine(InfoType.INFO, "请至少选择一个节点");
- }
- else if (selectNodeControls.Count > 1)
- {
- SereinEnv.WriteLine(InfoType.INFO, "请只选择一个节点");
- }
- try
- {
- await this.EnvDecorator.StartAsyncInSelectNode(selectNodeControls[0].ViewModel.NodeModel.Guid);
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }
-
-
-
-
- #endregion
-
- #region 顶部菜单栏 - 项目文件菜单
-
-
- ///
- /// 保存为项目文件
- ///
- ///
- ///
- private async void ButtonSaveFile_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- EnvDecorator.SaveProject();
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }
-
-
- ///
- /// 打开本地项目文件
- ///
- ///
- ///
- private void ButtonOpenLocalProject_Click(object sender, RoutedEventArgs e)
- {
-
- }
-
-
-
-#endregion
-
- #region 顶部菜单栏 - 视图管理
- ///
- /// 重置画布
- ///
- ///
- ///
- 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)
- {
- LogOutWindow?.Show();
- }
- ///
- /// 定位节点
- ///
- ///
- ///
- private void ButtonLocationNode_Click(object sender, RoutedEventArgs e)
- {
- InputDialog inputDialog = new InputDialog();
- inputDialog.Closed += (s, e) =>
- {
- var nodeGuid = inputDialog.InputValue;
- EnvDecorator.NodeLocated(nodeGuid);
- };
- inputDialog.ShowDialog();
- }
-
- #endregion
-
- #region 顶部菜单栏 - 远程管理
- private async void ButtonStartRemoteServer_Click(object sender, RoutedEventArgs e)
- {
- try
- {
- await this.EnvDecorator.StartRemoteServerAsync();
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }
-
- ///
- /// 连接远程运行环境
- ///
- ///
- ///
- private void ButtonConnectionRemoteEnv_Click(object sender, RoutedEventArgs e)
- {
- var windowEnvRemoteLoginView = new WindowEnvRemoteLoginView(async (addres, port, token) =>
- {
- ResetFlowEnvironmentEvent();// 移除事件
- (var isConnect, var _) = await this.EnvDecorator.ConnectRemoteEnv(addres, port, token);
- InitFlowEnvironmentEvent(); // 重新添加事件(如果没有连接成功,那么依然是原本的环境)
- if (isConnect)
- {
- // 连接成功,加载远程项目
- _ = Task.Run(async () =>
- {
- try
- {
- var flowEnvInfo = await EnvDecorator.GetEnvInfoAsync();
- EnvDecorator.LoadProject(flowEnvInfo, string.Empty);// 加载远程环境的项目
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- });
-
- }
- });
- windowEnvRemoteLoginView.Show();
-
- }
- #endregion
-
-
-
- ///
- /// 窗体按键监听。
- ///
- ///
- ///
- private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
- {
- if (e.Key == Key.Tab)
- {
- e.Handled = true; // 禁止默认的Tab键行为
- }
-
- #region 复制粘贴选择的节点
- if (Keyboard.Modifiers == ModifierKeys.Control)
- {
- if (e.Key == Key.C && selectNodeControls.Count > 0)
- {
- CpoyNodeInfo();
- }
- else if (e.Key == Key.V)
- {
- PasteNodeInfo();
- }
- }
- #endregion
- if (e.KeyStates == Keyboard.GetKeyStates(Key.Escape))
- {
- IsControlDragging = false;
- IsCanvasDragging = false;
- SelectionRectangle.Visibility = Visibility.Collapsed;
- CancelSelectNode();
- 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(); // 刷新目标节点控制点样式
-
- }
-
-
- }
-
- #region 复制节点,粘贴节点
-
- ///
- /// 复制节点
- ///
- private void CpoyNodeInfo()
- {
- if(selectNodeControls.Count == 0)
- {
- return;
- }
- // 处理复制操作
- var dictSelection = selectNodeControls
- .Select(control => control.ViewModel.NodeModel).ToList();
-
-
- // 遍历当前已选节点
- foreach (var node in dictSelection.ToArray())
- {
- if(node.ChildrenNode.Count == 0)
- {
- continue;
- }
- // 遍历这些节点的子节点,添加过来
- foreach (var childNode in node.ChildrenNode)
- {
- dictSelection.Add(childNode);
- }
- }
-
- var nodeInfos = dictSelection.Select(item => item.ToInfo());
-
- JObject json = new JObject()
- {
- ["nodes"] = JArray.FromObject(nodeInfos)
- };
-
- var jsonText = json.ToString();
-
-
- try
- {
- //Clipboard.SetDataObject(result, true); // 持久性设置
- Clipboard.SetDataObject(jsonText, true); // 持久性设置
- SereinEnv.WriteLine(InfoType.INFO, $"复制已选节点({dictSelection.Count}个)");
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(InfoType.ERROR, $"复制失败:{ex.Message}");
- }
- }
-
- ///
- /// 粘贴节点
- ///
- private void PasteNodeInfo()
- {
- if (Clipboard.ContainsText())
- {
- try
- {
-
- string clipboardText = Clipboard.GetText(TextDataFormat.Text);
- string jsonText = JObject.Parse(clipboardText)["nodes"].ToString();
- List nodes = JsonConvert.DeserializeObject>(jsonText);
- if (nodes is null || nodes.Count < 0)
- {
- return;
- }
-
- #region 节点去重
- Dictionary guids = new Dictionary(); // 记录 Guid
- // 遍历当前已选节点
- foreach (var node in nodes.ToArray())
- {
- if (NodeControls.ContainsKey(node.Guid) && !guids.ContainsKey(node.Guid))
- {
- // 如果是没出现过、且在当前记录中重复的Guid,则记录并新增对应的映射。
- guids.TryAdd(node.Guid, Guid.NewGuid().ToString());
- }
- else
- {
- // 出现过的Guid,说明重复添加了。应该不会走到这。
- continue;
- }
-
- if (node.ChildNodeGuids is null)
- {
- continue; // 跳过没有子节点的节点
- }
-
- // 遍历这些节点的子节点,获得完整的已选节点信息
- foreach (var childNodeGuid in node.ChildNodeGuids)
- {
- if (NodeControls.ContainsKey(node.Guid) && !NodeControls.ContainsKey(node.Guid))
- {
- // 当前Guid并不重复,跳过替换
- continue;
- }
- if (!guids.ContainsKey(childNodeGuid))
- {
- // 如果是没出现过的Guid,则记录并新增对应的映射。
- guids.TryAdd(node.Guid, Guid.NewGuid().ToString());
- }
-
- if (!string.IsNullOrEmpty(childNodeGuid)
- && NodeControls.TryGetValue(childNodeGuid, out var nodeControl))
- {
-
- var newNodeInfo = nodeControl.ViewModel.NodeModel.ToInfo();
- nodes.Add(newNodeInfo);
- }
- }
- }
-
- //var flashText = new FlashText.NET.TextReplacer();
-
- //var t = guids.Select(kvp => (kvp.Key, kvp.Value)).ToArray();
- //var result = flashText.ReplaceWords(jsonText, t);
-
- StringBuilder sb = new StringBuilder(jsonText);
- foreach (var kv in guids)
- {
- sb.Replace(kv.Key, kv.Value);
- }
- string result = sb.ToString();
-
-
- /*var replacer = new GuidReplacer();
- foreach (var kv in guids)
- {
- replacer.AddReplacement(kv.Key, kv.Value);
- }
- string result = replacer.Replace(jsonText);*/
-
-
- //SereinEnv.WriteLine(InfoType.ERROR, result);
- nodes = JsonConvert.DeserializeObject>(result);
-
- if (nodes is null || nodes.Count < 0)
- {
- return;
- }
- #endregion
-
- Point mousePosition = Mouse.GetPosition(FlowChartCanvas);
- PositionOfUI positionOfUI = new PositionOfUI(mousePosition.X, mousePosition.Y); // 坐标数据
-
- // 获取第一个节点的原始位置
- var index0NodeX = nodes[0].Position.X;
- var index0NodeY = nodes[0].Position.Y;
-
- // 计算所有节点相对于第一个节点的偏移量
- foreach (var node in nodes)
- {
-
- var offsetX = node.Position.X - index0NodeX;
- var offsetY = node.Position.Y - index0NodeY;
-
- // 根据鼠标位置平移节点
- node.Position = new PositionOfUI(positionOfUI.X + offsetX, positionOfUI.Y + offsetY);
- }
-
- _ = EnvDecorator.LoadNodeInfosAsync(nodes);
- }
- catch (Exception ex)
- {
-
- //SereinEnv.WriteLine(InfoType.ERROR, $"粘贴节点时发生异常:{ex}");
- }
- // SereinEnv.WriteLine(InfoType.INFO, $"剪贴板文本内容: {clipboardText}");
- }
- else if (Clipboard.ContainsImage())
- {
- // var image = Clipboard.GetImage();
- }
- else
- {
- SereinEnv.WriteLine(InfoType.INFO, "剪贴板中没有可识别的数据。");
- }
- }
-
- #endregion
-
-
-
- /* ///
- /// 对象装箱测试
- ///
- ///
- ///
- private void ButtonTestExpObj_Click(object sender, RoutedEventArgs e)
- {
- //string jsonString =
- //"""
- //{
- // "Name": "张三",
- // "Age": 24,
- // "Address": {
- // "City": "北京",
- // "PostalCode": "10000"
- // }
- //}
- //""";
-
- var externalData = new Dictionary
- {
- { "Name", "John" },
- { "Age", 30 },
- { "Addresses", new List>
- {
- new Dictionary
- {
- { "Street", "123 Main St" },
- { "City", "New York" }
- },
- new Dictionary
- {
- { "Street", "456 Another St" },
- { "City", "Los Angeles" }
- }
- }
- }
- };
-
- if (!ObjDynamicCreateHelper.TryResolve(externalData, "RootType",out var result))
- {
- SereinEnv.WriteLine(InfoType.ERROR, "赋值过程中有错误,请检查属性名和类型!");
- return;
- }
- ObjDynamicCreateHelper.PrintObjectProperties(result!);
- var exp = "@set .Addresses[1].Street = 233";
- var data = SerinExpressionEvaluator.Evaluate(exp, result!, out bool isChange);
- exp = "@get .Addresses[1].Street";
- data = SerinExpressionEvaluator.Evaluate(exp,result!, out isChange);
- SereinEnv.WriteLine(InfoType.INFO, $"{exp} => {data}");
- }
-*/
- }
-}
\ No newline at end of file
diff --git a/WorkBench/MainWindowViewModel.cs b/WorkBench/MainWindowViewModel.cs
deleted file mode 100644
index 0aedffd..0000000
--- a/WorkBench/MainWindowViewModel.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using Serein.Library.Api;
-using Serein.Library.Utils;
-using Serein.NodeFlow.Env;
-using System.ComponentModel;
-using System.Windows;
-
-namespace Serein.Workbench
-{
- ///
- /// 工作台数据视图
- ///
- ///
- public class MainWindowViewModel: INotifyPropertyChanged
- {
- private readonly MainWindow window ;
-
- ///
- /// 运行环境
- ///
- public IFlowEnvironment FlowEnvironment { get; set; }
-
- ///
- /// 工作台数据视图
- ///
- ///
- public MainWindowViewModel(MainWindow window)
- {
- UIContextOperation? uIContextOperation = null;
- Application.Current.Dispatcher.Invoke(() =>
- {
- SynchronizationContext? uiContext = SynchronizationContext.Current; // 在UI线程上获取UI线程上下文信息
- if (uiContext != null)
- {
- uIContextOperation = new UIContextOperation(uiContext); // 封装一个调用UI线程的工具类
- }
- });
-
- if (uIContextOperation is null)
- {
- throw new Exception("无法封装 UIContextOperation ");
- }
- else
- {
- FlowEnvironment = new FlowEnvironmentDecorator(uIContextOperation);
- //_ = FlowEnvironment.StartRemoteServerAsync();
- this.window = window;
- }
- }
-
-
- private bool _isConnectionInvokeNode = false;
- ///
- /// 是否正在连接节点的方法调用关系
- ///
- public bool IsConnectionInvokeNode { get => _isConnectionInvokeNode; set
- {
- if (_isConnectionInvokeNode != value)
- {
- SetProperty(ref _isConnectionInvokeNode, value);
- }
- }
- }
-
- private bool _isConnectionArgSouceNode = false;
- ///
- /// 是否正在连接节点的参数传递关系
- ///
- public bool IsConnectionArgSourceNode { get => _isConnectionArgSouceNode; set
- {
- if (_isConnectionArgSouceNode != value)
- {
- SetProperty(ref _isConnectionArgSouceNode, value);
- }
- }
- }
-
-
- ///
- /// 略
- /// 此事件为自动生成
- ///
- public event PropertyChangedEventHandler? PropertyChanged;
- ///
- /// 通知属性变更
- ///
- /// 类型
- /// 绑定的变量
- /// 新的数据
- ///
- protected void SetProperty(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
- {
- if (Equals(storage, value))
- {
- return;
- }
-
- storage = value;
- PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
- }
- }
-}
diff --git a/WorkBench/Node/NodeControlViewModelBase.cs b/WorkBench/Node/NodeControlViewModelBase.cs
deleted file mode 100644
index ed58ff9..0000000
--- a/WorkBench/Node/NodeControlViewModelBase.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System.ComponentModel;
-using Serein.Library;
-using System.Runtime.CompilerServices;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System;
-
-namespace Serein.Workbench.Node.ViewModel
-{
- public abstract class NodeControlViewModelBase
- {
- /////
- ///// 对应的节点实体类
- /////
- public NodeModelBase NodeModel { get; }
-
- public NodeControlViewModelBase(NodeModelBase nodeModel)
- {
- NodeModel = nodeModel;
-
- }
-
-
- private bool isInterrupt;
- /////
- ///// 控制中断状态的视觉效果
- /////
- public bool IsInterrupt
- {
- get => NodeModel.DebugSetting.IsInterrupt;
- set
- {
- NodeModel.DebugSetting.IsInterrupt = value;
- OnPropertyChanged();
- }
- }
-
-
-
- public event PropertyChangedEventHandler? PropertyChanged;
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
-
-
- }
-}
diff --git a/WorkBench/Node/View/ActionNodeControl.xaml b/WorkBench/Node/View/ActionNodeControl.xaml
deleted file mode 100644
index fb71a3f..0000000
--- a/WorkBench/Node/View/ActionNodeControl.xaml
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Node/View/ActionNodeControl.xaml.cs b/WorkBench/Node/View/ActionNodeControl.xaml.cs
deleted file mode 100644
index f26e7ba..0000000
--- a/WorkBench/Node/View/ActionNodeControl.xaml.cs
+++ /dev/null
@@ -1,83 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.ViewModel;
-using System.Runtime.CompilerServices;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Media;
-
-namespace Serein.Workbench.Node.View
-{
- ///
- /// ActionNode.xaml 的交互逻辑
- ///
- public partial class ActionNodeControl : NodeControlBase, INodeJunction
- {
- public ActionNodeControl(ActionNodeControlViewModel viewModel) : base(viewModel)
- {
- DataContext = viewModel;
- InitializeComponent();
- if(ExecuteJunctionControl.MyNode != null)
- {
-
- ExecuteJunctionControl.MyNode.Guid = viewModel.NodeModel.Guid;
- }
- }
-
- ///
- /// 入参控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
-
- ///
- /// 下一个调用方法控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.NextStepJunction => this.NextStepJunctionControl;
-
- ///
- /// 返回值控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
-
- ///
- /// 方法入参控制点(可能有,可能没)
- ///
- JunctionControlBase[] INodeJunction.ArgDataJunction
- {
- get
- {
- // 获取 MethodDetailsControl 实例
- var methodDetailsControl = this.MethodDetailsControl;
- var itemsControl = FindVisualChild(methodDetailsControl); // 查找 ItemsControl
- if (itemsControl != null)
- {
- var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
- var controls = new List();
-
- for (int i = 0; i < itemsControl.Items.Count; i++)
- {
- var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
- if (container != null)
- {
- var argControl = FindVisualChild(container);
- if (argControl != null)
- {
- controls.Add(argControl); // 收集 ArgJunctionControl 实例
- }
- }
- }
- return argDataJunction = controls.ToArray();
- }
- else
- {
- return [];
- }
- }
-
-
- }
-
-
-
-
- }
-}
diff --git a/WorkBench/Node/View/ConditionNodeControl.xaml b/WorkBench/Node/View/ConditionNodeControl.xaml
deleted file mode 100644
index f6f8c07..0000000
--- a/WorkBench/Node/View/ConditionNodeControl.xaml
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Node/View/ConditionNodeControl.xaml.cs b/WorkBench/Node/View/ConditionNodeControl.xaml.cs
deleted file mode 100644
index f1ce898..0000000
--- a/WorkBench/Node/View/ConditionNodeControl.xaml.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.ViewModel;
-
-namespace Serein.Workbench.Node.View
-{
- ///
- /// ConditionNode.xaml 的交互逻辑
- ///
- public partial class ConditionNodeControl : NodeControlBase, INodeJunction
- {
- public ConditionNodeControl() : base()
- {
- // 窗体初始化需要
- base.ViewModel = new ConditionNodeControlViewModel (new SingleConditionNode(null));
- DataContext = ViewModel;
- InitializeComponent();
- }
-
- public ConditionNodeControl(ConditionNodeControlViewModel viewModel):base(viewModel)
- {
- DataContext = viewModel;
- InitializeComponent();
- }
-
- ///
- /// 入参控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
-
- ///
- /// 下一个调用方法控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.NextStepJunction => this.NextStepJunctionControl;
-
- ///
- /// 返回值控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
-
- ///
- /// 方法入参控制点(可能有,可能没)
- ///
- private JunctionControlBase[] argDataJunction;
- ///
- /// 方法入参控制点(可能有,可能没)
- ///
- JunctionControlBase[] INodeJunction.ArgDataJunction
- {
- get
- {
- argDataJunction = new JunctionControlBase[1];
- argDataJunction[0] = this.ArgJunctionControl;
- return argDataJunction;
- }
- }
-
- }
-}
diff --git a/WorkBench/Node/View/ConditionRegionControl.xaml b/WorkBench/Node/View/ConditionRegionControl.xaml
deleted file mode 100644
index c7932cc..0000000
--- a/WorkBench/Node/View/ConditionRegionControl.xaml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Node/View/ConditionRegionControl.xaml.cs b/WorkBench/Node/View/ConditionRegionControl.xaml.cs
deleted file mode 100644
index 9e50faa..0000000
--- a/WorkBench/Node/View/ConditionRegionControl.xaml.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.ViewModel;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Input;
-
-namespace Serein.Workbench.Node.View
-{
- ///
- /// ConditionRegion.xaml 的交互逻辑
- ///
- public partial class ConditionRegionControl : NodeControlBase
- {
- public new CompositeConditionNode ViewModel => ViewModel;
-
- public ConditionRegionControl() : base()
- {
- InitializeComponent();
- }
-
- public ConditionRegionControl(ConditionRegionNodeControlViewModel viewModel) : base(viewModel)
- {
- DataContext = viewModel;
- InitializeComponent();
- }
-
-
-
- ///
- /// 添加条件控件
- ///
- ///
- public void AddCondition(NodeControlBase node)
- {
-
- //((CompositeConditionNode)ViewModel.NodeModel).AddNode((SingleConditionNode)node.ViewModel.NodeModel);
- ViewModel.AddNode((SingleConditionNode)node.ViewModel.NodeModel);
-
- this.Width += node.Width;
- this.Height += node.Height;
- ConditionsListBox.Items.Add(node);
- }
-
- private void ConditionsListBox_Drop(object sender, DragEventArgs e)
- {
- e.Handled = true;
- }
-
- // Mouse event handlers for dragging
- //private void TypeText_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- //{
- // _dragStartPoint = e.GetPosition(null);
- //}
-
- //private void TypeText_MouseMove(object sender, MouseEventArgs e)
- //{
- // Point mousePos = e.GetPosition(null);
- // Vector diff = _dragStartPoint - mousePos;
-
- // if (e.LeftButton == MouseButtonState.Pressed &&
- // (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
- // Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
- // {
- // if (sender is TextBlock typeText)
- // {
- // var dragData = new DataObject(MouseNodeType.RegionType, typeText.Tag);
- // DragDrop.DoDragDrop(typeText, dragData, DragDropEffects.Move);
- // }
- // }
- //}
-
-
-
- /*private void TypeText_MouseMove(object sender, MouseEventArgs e)
- {
- Point mousePos = e.GetPosition(null);
- Vector diff = _dragStartPoint - mousePos;
-
- if (e.LeftButton == MouseButtonState.Pressed &&
- (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
- Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
- {
- TextBlock typeText = sender as TextBlock;
- if (typeText != null)
- {
- DataObject dragData = new DataObject("Type", typeText.Tag);
- DragDrop.DoDragDrop(typeText, dragData, DragDropEffects.Move);
- }
- }
- }*/
-
- }
-}
diff --git a/WorkBench/Node/View/DllControlControl.xaml b/WorkBench/Node/View/DllControlControl.xaml
deleted file mode 100644
index 5090058..0000000
--- a/WorkBench/Node/View/DllControlControl.xaml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Node/View/DllControlControl.xaml.cs b/WorkBench/Node/View/DllControlControl.xaml.cs
deleted file mode 100644
index 912aeae..0000000
--- a/WorkBench/Node/View/DllControlControl.xaml.cs
+++ /dev/null
@@ -1,164 +0,0 @@
-using Serein.Library;
-using Serein.Library.Utils;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-
-namespace Serein.Workbench.Node.View
-{
-
-
-
-
-
- ///
- /// UserControl1.xaml 的交互逻辑
- ///
- public partial class DllControl : UserControl
- {
- private readonly NodeLibraryInfo nodeLibraryInfo;
-
- public DllControl()
- {
- Header = "DLL文件"; // 设置初始值
- InitializeComponent();
- }
- public DllControl(NodeLibraryInfo nodeLibraryInfo)
- {
- this.nodeLibraryInfo = nodeLibraryInfo;
- Header = "DLL name : " + nodeLibraryInfo.AssemblyName;
- InitializeComponent();
- }
-
-
-
- ///
- /// Header 依赖属性,用于绑定标题
- ///
- public string Header
- {
- get { return (string)GetValue(HeaderProperty); }
- set { SetValue(HeaderProperty, value); }
- }
-
- public static readonly DependencyProperty HeaderProperty =
- DependencyProperty.Register("Header", typeof(string), typeof(DllControl), new PropertyMetadata(string.Empty));
-
-
- ///
- /// 向动作面板添加类型的文本块
- ///
- /// 要添加的类型
- public void AddAction(MethodDetailsInfo mdInfo)
- {
- AddTypeToListBox(mdInfo, ActionsListBox);
- ActionNodeGroupBox.Visibility = Visibility.Visible;
- }
-
- ///
- /// 向触发器面板添加类型的文本块
- ///
- /// 要添加的类型
- public void AddFlipflop(MethodDetailsInfo mdInfo)
- {
- AddTypeToListBox(mdInfo, FlipflopsListBox);
- FlipflopNodeGroupBox.Visibility = Visibility.Visible;
- }
-
- ///
- /// 向指定面板添加类型的文本块
- ///
- /// 要添加的方法信息
- /// 要添加到的面板
- private void AddTypeToListBox(MethodDetailsInfo mdInfo, ListBox listBox)
- {
- // 创建一个新的 TextBlock 并设置其属性
- TextBlock typeText = new TextBlock
- {
- Text = $"{mdInfo.MethodAnotherName} - {mdInfo.MethodName}",
- Margin = new Thickness(10, 2, 0, 0),
- Tag = mdInfo
- };
- // 为 TextBlock 添加鼠标左键按下事件处理程序
- typeText.MouseLeftButtonDown += TypeText_MouseLeftButtonDown;
- // 为 TextBlock 添加鼠标移动事件处理程序
- typeText.MouseMove += TypeText_MouseMove;
- // 将 TextBlock 添加到指定的面板
- listBox.Items.Add(typeText);
- }
-
- ///
- /// 存储拖拽开始时的鼠标位置
- ///
- private Point _dragStartPoint;
-
- ///
- /// 处理 TextBlock 的鼠标左键按下事件
- ///
- /// 事件源
- /// 事件参数
- private void TypeText_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
- {
- // 记录鼠标按下时的位置
- _dragStartPoint = e.GetPosition(null);
- }
-
- ///
- /// 处理 TextBlock 的鼠标移动事件
- ///
- /// 事件源
- /// 事件参数
- private void TypeText_MouseMove(object sender, MouseEventArgs e)
- {
- // 获取当前鼠标位置
- Point mousePos = e.GetPosition(null);
- // 计算鼠标移动的距离
- Vector diff = _dragStartPoint - mousePos;
-
- // 判断是否符合拖拽的最小距离要求
- if (e.LeftButton == MouseButtonState.Pressed &&
- (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
- Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
- {
- // 获取触发事件的 TextBlock
-
-
- if (sender is TextBlock typeText && typeText.Tag is MethodDetailsInfo mdInfo)
- {
- if (!EnumHelper.TryConvertEnum(mdInfo.NodeType, out var nodeType))
- {
- return;
- }
-
- MoveNodeData moveNodeData = new MoveNodeData
- {
-
- NodeControlType = nodeType switch
- {
- NodeType.Action => NodeControlType.Action,
- NodeType.Flipflop => NodeControlType.Flipflop,
- _ => NodeControlType.None,
- },
- MethodDetailsInfo = mdInfo,
- };
- if(moveNodeData.NodeControlType == NodeControlType.None)
- {
- return;
- }
-
- // 创建一个 DataObject 用于拖拽操作,并设置拖拽效果
- DataObject dragData = new DataObject(MouseNodeType.CreateDllNodeInCanvas, moveNodeData);
- DragDrop.DoDragDrop(typeText, dragData, DragDropEffects.Move);
- }
- }
- }
-
-
-
-
-
-
-
-
- }
-}
\ No newline at end of file
diff --git a/WorkBench/Node/View/ExpOpNodeControl.xaml b/WorkBench/Node/View/ExpOpNodeControl.xaml
deleted file mode 100644
index 54f3794..0000000
--- a/WorkBench/Node/View/ExpOpNodeControl.xaml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Node/View/ExpOpNodeControl.xaml.cs b/WorkBench/Node/View/ExpOpNodeControl.xaml.cs
deleted file mode 100644
index 6b0f814..0000000
--- a/WorkBench/Node/View/ExpOpNodeControl.xaml.cs
+++ /dev/null
@@ -1,56 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.ViewModel;
-
-namespace Serein.Workbench.Node.View
-{
- ///
- /// ExprOpNodeControl.xaml 的交互逻辑
- ///
- public partial class ExpOpNodeControl : NodeControlBase, INodeJunction
- {
- public ExpOpNodeControl() : base()
- {
- // 窗体初始化需要
- ViewModel = new ExpOpNodeControlViewModel(new SingleExpOpNode(null));
- DataContext = ViewModel;
- InitializeComponent();
- }
- public ExpOpNodeControl(ExpOpNodeControlViewModel viewModel) :base(viewModel)
- {
- DataContext = viewModel;
- InitializeComponent();
- }
-
- ///
- /// 入参控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
-
- ///
- /// 下一个调用方法控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.NextStepJunction => this.NextStepJunctionControl;
-
- ///
- /// 返回值控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
-
- ///
- /// 方法入参控制点(可能有,可能没)
- ///
- private JunctionControlBase[] argDataJunction;
- ///
- /// 方法入参控制点(可能有,可能没)
- ///
- JunctionControlBase[] INodeJunction.ArgDataJunction
- {
- get
- {
- argDataJunction = new JunctionControlBase[1];
- argDataJunction[0] = this.ArgJunctionControl;
- return argDataJunction;
- }
- }
- }
-}
diff --git a/WorkBench/Node/View/FlipflopNodeControl.xaml b/WorkBench/Node/View/FlipflopNodeControl.xaml
deleted file mode 100644
index 1a445b9..0000000
--- a/WorkBench/Node/View/FlipflopNodeControl.xaml
+++ /dev/null
@@ -1,110 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Node/View/FlipflopNodeControl.xaml.cs b/WorkBench/Node/View/FlipflopNodeControl.xaml.cs
deleted file mode 100644
index e325f13..0000000
--- a/WorkBench/Node/View/FlipflopNodeControl.xaml.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.ViewModel;
-using System.Windows.Controls;
-using System.Windows;
-
-namespace Serein.Workbench.Node.View
-{
- ///
- /// StateNode.xaml 的交互逻辑
- ///
- public partial class FlipflopNodeControl : NodeControlBase, INodeJunction
- {
- public FlipflopNodeControl(FlipflopNodeControlViewModel viewModel) : base(viewModel)
- {
- DataContext = viewModel;
- InitializeComponent();
- }
-
-
- ///
- /// 入参控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
-
- ///
- /// 下一个调用方法控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.NextStepJunction => this.NextStepJunctionControl;
-
- ///
- /// 返回值控制点(可能有,可能没)
- ///
- JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
-
- ///
- /// 方法入参控制点(可能有,可能没)
- ///
- JunctionControlBase[] INodeJunction.ArgDataJunction
- {
- get
- {
- // 获取 MethodDetailsControl 实例
- var methodDetailsControl = this.MethodDetailsControl;
- var itemsControl = FindVisualChild(methodDetailsControl); // 查找 ItemsControl
- if (itemsControl != null)
- {
- var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
- var controls = new List();
-
- for (int i = 0; i < itemsControl.Items.Count; i++)
- {
- var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
- if (container != null)
- {
- var argControl = FindVisualChild(container);
- if (argControl != null)
- {
- controls.Add(argControl); // 收集 ArgJunctionControl 实例
- }
- }
- }
- return argDataJunction = controls.ToArray();
- }
- else
- {
- return [];
- }
- }
- }
-
- }
-}
diff --git a/WorkBench/Node/ViewModel/ActionNodeControlViewModel.cs b/WorkBench/Node/ViewModel/ActionNodeControlViewModel.cs
deleted file mode 100644
index 8325690..0000000
--- a/WorkBench/Node/ViewModel/ActionNodeControlViewModel.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.View;
-
-namespace Serein.Workbench.Node.ViewModel
-{
- public class ActionNodeControlViewModel : NodeControlViewModelBase
- {
- public ActionNodeControlViewModel(SingleActionNode node) : base(node)
- {
- // this.NodelModel = node;
- }
- }
-}
diff --git a/WorkBench/Node/ViewModel/ConditionNodeControlViewModel.cs b/WorkBench/Node/ViewModel/ConditionNodeControlViewModel.cs
deleted file mode 100644
index 81ab99d..0000000
--- a/WorkBench/Node/ViewModel/ConditionNodeControlViewModel.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.View;
-
-namespace Serein.Workbench.Node.ViewModel
-{
- ///
- /// 条件节点
- ///
- public class ConditionNodeControlViewModel : NodeControlViewModelBase
- {
- public new SingleConditionNode NodeModel { get; }
-
- ///
- /// 是否为自定义参数
- ///
- public bool IsCustomData
- {
- get => NodeModel.IsExplicitData;
- set { NodeModel.IsExplicitData = value; OnPropertyChanged(); }
- }
- ///
- /// 自定义参数值
- ///
- public string? CustomData
- {
- get => NodeModel.ExplicitData;
- set { NodeModel.ExplicitData = value ; OnPropertyChanged(); }
- }
- ///
- /// 表达式
- ///
- public string Expression
- {
- get => NodeModel.Expression;
- set { NodeModel.Expression = value; OnPropertyChanged(); }
- }
-
- ///
- /// 条件节点
- ///
- ///
- public ConditionNodeControlViewModel(SingleConditionNode node) : base(node)
- {
- this.NodeModel = node;
- if(node is null)
- {
- IsCustomData = false;
- CustomData = "";
- Expression = "PASS";
- }
- }
-
- }
-}
diff --git a/WorkBench/Node/ViewModel/ConditionRegionNodeControlViewModel.cs b/WorkBench/Node/ViewModel/ConditionRegionNodeControlViewModel.cs
deleted file mode 100644
index 5f86836..0000000
--- a/WorkBench/Node/ViewModel/ConditionRegionNodeControlViewModel.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.View;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Serein.Workbench.Node.ViewModel
-{
- public class ConditionRegionNodeControlViewModel : NodeControlViewModelBase
- {
- public ConditionRegionNodeControlViewModel(CompositeConditionNode node):base(node)
- {
-
- }
- }
-}
diff --git a/WorkBench/Node/ViewModel/FlipflopNodeControlViewModel.cs b/WorkBench/Node/ViewModel/FlipflopNodeControlViewModel.cs
deleted file mode 100644
index 3ab4e2e..0000000
--- a/WorkBench/Node/ViewModel/FlipflopNodeControlViewModel.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using Serein.NodeFlow.Model;
-using Serein.Workbench.Node.View;
-
-namespace Serein.Workbench.Node.ViewModel
-{
- public class FlipflopNodeControlViewModel : NodeControlViewModelBase
- {
- public new SingleFlipflopNode NodelModel { get;}
- public FlipflopNodeControlViewModel(SingleFlipflopNode node) : base(node)
- {
- this.NodelModel = node;
- }
- }
-}
diff --git a/WorkBench/Node/ViewModel/TypeToStringConverter.cs b/WorkBench/Node/ViewModel/TypeToStringConverter.cs
deleted file mode 100644
index b80547c..0000000
--- a/WorkBench/Node/ViewModel/TypeToStringConverter.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Data;
-
-namespace Serein.Workbench.Node.ViewModel
-{
- public class TypeToStringConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- if (value is Type type)
- {
- return type.ToString();
- }
- return string.Empty;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/WorkBench/Serein.WorkBench.csproj b/WorkBench/Serein.WorkBench.csproj
deleted file mode 100644
index ad7578f..0000000
--- a/WorkBench/Serein.WorkBench.csproj
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
- WinExe
- net8.0-windows
- enable
- enable
- True
- D:\Project\C#\DynamicControl\SereinFlow\.Output
- MIT
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Code
-
-
-
-
diff --git a/WorkBench/Serein.WorkBench_d2hd4tgu_wpftmp.csproj b/WorkBench/Serein.WorkBench_d2hd4tgu_wpftmp.csproj
deleted file mode 100644
index c5a404c..0000000
--- a/WorkBench/Serein.WorkBench_d2hd4tgu_wpftmp.csproj
+++ /dev/null
@@ -1,288 +0,0 @@
-
-
- Serein.WorkBench
- obj\Release\
- obj\
- D:\Project\C#\DynamicControl\SereinFlow\WorkBench\obj\
- <_TargetAssemblyProjectName>Serein.WorkBench
-
-
-
- WinExe
- net8.0-windows
- enable
- enable
- True
- D:\Project\C#\DynamicControl\SereinFlow\.Output
- MIT
- true
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Code
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/WorkBench/Themes/IOCObjectViewControl.xaml b/WorkBench/Themes/IOCObjectViewControl.xaml
deleted file mode 100644
index eba1b4b..0000000
--- a/WorkBench/Themes/IOCObjectViewControl.xaml
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/IOCObjectViewControl.xaml.cs b/WorkBench/Themes/IOCObjectViewControl.xaml.cs
deleted file mode 100644
index 7d231d5..0000000
--- a/WorkBench/Themes/IOCObjectViewControl.xaml.cs
+++ /dev/null
@@ -1,128 +0,0 @@
-using Serein.Library.Api;
-using Serein.Library.Utils;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-using System.Xml.Linq;
-
-namespace Serein.Workbench.Themes
-{
- ///
- /// IOCObjectViewControl.xaml 的交互逻辑
- ///
- public partial class IOCObjectViewControl : UserControl
- {
- public Action SelectObj { get; set; }
-
- public IOCObjectViewControl()
- {
- InitializeComponent();
- }
-
- private class IOCObj
- {
- public string Key { get; set; }
- public object Instance { get; set; }
- }
-
- ///
- /// 运行环境
- ///
- public IFlowEnvironment FlowEnvironment { get; set; }
-
- ///
- /// 添加一个实例
- ///
- ///
- ///
- public void AddDependenciesInstance(string key,object instance)
- {
- IOCObj iOCObj = new IOCObj
- {
- Key = key,
- Instance = instance,
- };
- Application.Current.Dispatcher.Invoke(() =>
- {
- TextBlock textBlock = new TextBlock();
- textBlock.Text = key;
- textBlock.Tag = iOCObj;
- textBlock.MouseDown += (s, e) =>
- {
- if (s is TextBlock block && block.Tag is IOCObj iocObj)
- {
- SelectObj?.Invoke(iocObj.Key, iocObj.Instance);
- //FlowEnvironment.SetMonitorObjState(iocObj.Instance, true); // 通知环境,该节点的数据更新后需要传到UI
- }
- };
- DependenciesListBox.Items.Add(textBlock);
- SortLisbox(DependenciesListBox);
- });
-
- }
-
- ///
- /// 刷新一个实例
- ///
- ///
- ///
- public void RefreshDependenciesInstance(string key, object instance)
- {
- foreach (var item in DependenciesListBox.Items)
- {
- if (item is TextBlock block && block.Tag is IOCObj iocObj && iocObj.Key.Equals(key))
- {
- iocObj.Instance = instance;
- }
- }
- }
-
- public void ClearObjItem()
- {
- DependenciesListBox.Dispatcher.Invoke(() =>
- {
- DependenciesListBox.Items.Clear();
- });
-
- }
-
- private static void SortLisbox(ListBox listBox)
- {
- var sortedItems = listBox.Items.Cast().OrderBy(x => x.Text).ToList();
- listBox.Items.Clear();
- foreach (var item in sortedItems)
- {
- listBox.Items.Add(item);
- }
- }
-
- public void RemoveDependenciesInstance(string key)
- {
- object? itemControl = null;
- foreach (var item in DependenciesListBox.Items)
- {
- if (item is TextBlock block && block.Tag is IOCObj iocObj && iocObj.Key.Equals(key))
- {
- itemControl = item;
- }
- }
- if (itemControl is not null)
- {
- DependenciesListBox.Items.Remove(itemControl);
- }
- }
-
- }
-}
diff --git a/WorkBench/Themes/InputDialog.xaml b/WorkBench/Themes/InputDialog.xaml
deleted file mode 100644
index d095e23..0000000
--- a/WorkBench/Themes/InputDialog.xaml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/InputDialog.xaml.cs b/WorkBench/Themes/InputDialog.xaml.cs
deleted file mode 100644
index 42efeec..0000000
--- a/WorkBench/Themes/InputDialog.xaml.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Shapes;
-
-namespace Serein.Workbench.Themes
-{
- ///
- /// InputDialog.xaml 的交互逻辑
- ///
- public partial class InputDialog : Window
- {
- public string InputValue { get; private set; }
-
- public InputDialog()
- {
- InitializeComponent();
- }
-
- private void ConfirmButton_Click(object sender, RoutedEventArgs e)
- {
- InputValue = InputTextBox.Text;
- DialogResult = true; // 设置返回结果为 true
- Close(); // 关闭窗口
- }
-
- private void CancelButton_Click(object sender, RoutedEventArgs e)
- {
- DialogResult = false; // 设置返回结果为 false
- Close(); // 关闭窗口
- }
- }
-}
diff --git a/WorkBench/Themes/MethodDetailsControl.xaml b/WorkBench/Themes/MethodDetailsControl.xaml
deleted file mode 100644
index 71259a4..0000000
--- a/WorkBench/Themes/MethodDetailsControl.xaml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/MethodDetailsControl.xaml.cs b/WorkBench/Themes/MethodDetailsControl.xaml.cs
deleted file mode 100644
index 32caab5..0000000
--- a/WorkBench/Themes/MethodDetailsControl.xaml.cs
+++ /dev/null
@@ -1,90 +0,0 @@
-using Serein.Library;
-using Serein.Workbench.Node;
-using System.Collections;
-using System.Globalization;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Input;
-
-namespace Serein.Workbench.Themes
-{
- public class MultiConditionConverter : IMultiValueConverter
- {
- public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
- {
- if (values.Length == 2 && values[0] is Type valueType && values[1] is bool isEnabled)
- {
- if (isEnabled)
- {
- // 返回文本框
- if (valueType == typeof(string) || valueType == typeof(int) || valueType == typeof(double))
- {
- return "TextBoxTemplate";
- }
- // 返回可选列表框
- else if (typeof(IEnumerable).IsAssignableFrom(valueType))
- {
- return "ComboBoxTemplate";
- }
- }
- }
- return DependencyProperty.UnsetValue;
- }
-
- public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-
-
-
- ///
- /// 方法参数控件
- ///
- public partial class MethodDetailsControl : UserControl
- {
- static MethodDetailsControl()
- {
- DefaultStyleKeyProperty.OverrideMetadata(typeof(MethodDetailsControl), new FrameworkPropertyMetadata(typeof(MethodDetailsControl)));
-
- }
-
- #region 绑定的方法信息
- public MethodDetails MethodDetails
- {
- get { return (MethodDetails)GetValue(MethodDetailsProperty); }
- set { SetValue(MethodDetailsProperty, value); }
- }
-
- public static readonly DependencyProperty MethodDetailsProperty = DependencyProperty.Register(nameof(MethodDetails), typeof(MethodDetails),
- typeof(MethodDetailsControl), new PropertyMetadata(null, new PropertyChangedCallback(OnPropertyChange)));
-
- #endregion
-
-
- static void OnPropertyChange(DependencyObject sender, DependencyPropertyChangedEventArgs args)
- {
- //var MethodDetails = (MethodDetails)args.NewValue;
- //MethodDetails.ExplicitDatas[0].
- }
-
-
- public ICommand CommandAddParams { get; }
-
- public MethodDetailsControl()
- {
- CommandAddParams = new RelayCommand(ExecuteAddParams);
- }
-
- private void ExecuteAddParams(object parameter)
- {
- // 方法逻辑
- this.MethodDetails.AddParamsArg();
- }
-
-
-
- }
-}
diff --git a/WorkBench/Themes/NodeTreeItemViewControl.xaml b/WorkBench/Themes/NodeTreeItemViewControl.xaml
deleted file mode 100644
index 8f599a2..0000000
--- a/WorkBench/Themes/NodeTreeItemViewControl.xaml
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs b/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs
deleted file mode 100644
index ffd9711..0000000
--- a/WorkBench/Themes/NodeTreeItemViewControl.xaml.cs
+++ /dev/null
@@ -1,280 +0,0 @@
-using Serein.Library;
-using Serein.Library.Api;
-using Serein.Library.Utils;
-using System.Windows;
-using System.Windows.Controls;
-
-namespace Serein.Workbench.Themes
-{
- ///
- /// NodeTreeVIewControl.xaml 的交互逻辑
- ///
- public partial class NodeTreeItemViewControl : UserControl
- {
- public NodeTreeItemViewControl()
- {
- InitializeComponent();
- foreach (var ct in NodeStaticConfig.ConnectionTypes)
- {
- var guid = ToGridView(this, ct);
- guid.Visibility = Visibility.Collapsed;
- }
- }
-
-
- ///
- /// 保存的节点数据
- ///
- private NodeModelBase nodeModel;
- private IFlowEnvironment flowEnvironment { get; set; }
-
-
- private class NodeTreeModel
- {
- public NodeModelBase RootNode { get; set; }
- public Dictionary> ChildNodes { get; set; }
- }
-
-
- public void InitAndLoadTree(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel)
- {
- this.flowEnvironment = flowEnvironment;
- this.nodeModel = nodeModel;
- RefreshTree();
- }
-
- public TreeViewItem RefreshTree()
- {
- NodeModelBase rootNodeModel = this.nodeModel;
- NodeTreeModel nodeTreeModel = new NodeTreeModel
- {
- RootNode = rootNodeModel,
- ChildNodes = new Dictionary>()
- {
- {ConnectionInvokeType.Upstream, []},
- {ConnectionInvokeType.IsSucceed, [rootNodeModel]},
- {ConnectionInvokeType.IsFail, []},
- {ConnectionInvokeType.IsError, []},
- }
- };
- string? itemName = rootNodeModel.MethodDetails?.MethodAnotherName;
- if (string.IsNullOrEmpty(itemName))
- {
- itemName = rootNodeModel.ControlType.ToString();
- }
- var rootNode = new TreeViewItem
- {
- Header = itemName,
- Tag = nodeTreeModel,
- };
- LoadNodeItem(this, nodeTreeModel);
- rootNode.Expanded += TreeViewItem_Expanded; // 监听展开事件
- rootNode.IsExpanded = true;
- return rootNode;
- }
-
-
-
-
- ///
- /// 展开子项事件
- ///
- ///
- ///
- private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
- {
- if (sender is TreeViewItem item && item.Tag is NodeTreeModel nodeTreeModel)
- {
- item.Items.Clear();
- NodeTreeItemViewControl? nodeTreeItemViewControl = LoadTNoderee(nodeTreeModel);
-
- if (nodeTreeItemViewControl is not null)
- {
- LoadNodeItem(nodeTreeItemViewControl, nodeTreeModel);
- item.Items.Add(nodeTreeItemViewControl);
-
- }
- item.IsSelected = false;
- }
-
- e.Handled = true;
- }
-
- ///
- /// 加载面板
- ///
- ///
- ///
- private void LoadNodeItem(NodeTreeItemViewControl nodeTreeItemViewControl, NodeTreeModel nodeTreeModel)
- {
-
- foreach (var ct in NodeStaticConfig.ConnectionTypes)
- {
- var treeViewer = ToTreeView(nodeTreeItemViewControl, ct);
- var guid = ToGridView(nodeTreeItemViewControl, ct);
- treeViewer.Items.Clear(); // 移除对象树的所有节点
- var list = nodeTreeModel.ChildNodes[ct];
-
- if (list.Count > 0)
- {
- foreach (var child in list)
- {
- NodeTreeModel tmpNodeTreeModel = new NodeTreeModel
- {
- RootNode = child,
- ChildNodes = child.SuccessorNodes,
- };
- string? itemName = child?.MethodDetails?.MethodAnotherName;
- if (string.IsNullOrEmpty(itemName))
- {
- itemName = child?.ControlType.ToString();
- }
- TreeViewItem treeViewItem = new TreeViewItem
- {
- Header = itemName,
- Tag = tmpNodeTreeModel
- };
- treeViewItem.Expanded += TreeViewItem_Expanded;
-
- var contextMenu = new ContextMenu();
- contextMenu.Items.Add(MainWindow.CreateMenuItem("从此节点执行", async (s, e) =>
- {
- try
- {
- await flowEnvironment.StartAsyncInSelectNode(tmpNodeTreeModel.RootNode.Guid);
- }
- catch (Exception ex)
- {
- SereinEnv.WriteLine(ex);
- return;
- }
- }));
- contextMenu.Items.Add(MainWindow.CreateMenuItem("定位", (s, e) => flowEnvironment.NodeLocated(tmpNodeTreeModel.RootNode.Guid)));
-
- treeViewItem.ContextMenu = contextMenu;
- treeViewItem.Margin = new Thickness(-20, 0, 0, 0);
- treeViewer.Items.Add(treeViewItem);
- }
- guid.Visibility = Visibility.Visible;
- }
- else
- {
- guid.Visibility = Visibility.Collapsed;
- }
- }
-
-
- }
-
- ///
- /// 加载节点子项
- ///
- ///
- ///
- private NodeTreeItemViewControl? LoadTNoderee(NodeTreeModel nodeTreeModel)
- {
- NodeTreeItemViewControl nodeTreeItemViewControl = null;
- foreach (var connectionType in NodeStaticConfig.ConnectionTypes)
- {
- var childNodeModels = nodeTreeModel.ChildNodes[connectionType];
- if (childNodeModels.Count > 0)
- {
- nodeTreeItemViewControl ??= new NodeTreeItemViewControl();
- }
- else
- {
- continue;
- }
-
- TreeView treeView = ToTreeView(nodeTreeItemViewControl, connectionType);
- foreach (var childNodeModel in childNodeModels)
- {
- NodeTreeModel tempNodeTreeModel = new NodeTreeModel
- {
- RootNode = childNodeModel,
- ChildNodes = childNodeModel.SuccessorNodes,
- };
-
- string? itemName = childNodeModel?.MethodDetails?.MethodAnotherName;
- if (string.IsNullOrEmpty(itemName))
- {
- itemName = childNodeModel?.ControlType.ToString();
- }
- TreeViewItem treeViewItem = new TreeViewItem
- {
- Header = itemName,
- Tag = tempNodeTreeModel
- };
- treeViewItem.Margin = new Thickness(-20, 0, 0, 0);
- treeViewItem.Visibility = Visibility.Visible;
- treeView.Items.Add(treeViewItem);
- }
- }
- if (nodeTreeItemViewControl is not null)
- {
- foreach (var connectionType in NodeStaticConfig.ConnectionTypes)
- {
- var childNodeModels = nodeTreeModel.ChildNodes[connectionType];
- if (childNodeModels.Count > 0)
- {
- nodeTreeItemViewControl ??= new NodeTreeItemViewControl();
- }
- else
- {
- continue;
- }
- }
- }
- return nodeTreeItemViewControl;
- }
-
- ///
- /// 折叠事件
- ///
- ///
- ///
- private void TreeViewItem_Collapsed(object sender, RoutedEventArgs e)
- {
- if (sender is TreeViewItem item && item.Items.Count > 0)
- {
- item.Items.Clear();
- }
- }
- public static TreeView ToTreeView(NodeTreeItemViewControl item, ConnectionInvokeType connectionType)
- {
- return connectionType switch
- {
- ConnectionInvokeType.Upstream => item.UpstreamTreeNodes,
- ConnectionInvokeType.IsError => item.IsErrorTreeNodes,
- ConnectionInvokeType.IsFail => item.IsFailTreeNodes,
- ConnectionInvokeType.IsSucceed => item.IsSucceedTreeNodes,
- _ => throw new Exception("LoadNodeItem Error :ConnectionType is " + connectionType)
- };
- }
- public static Grid ToGridView(NodeTreeItemViewControl item, ConnectionInvokeType connectionType)
- {
- return connectionType switch
- {
- ConnectionInvokeType.Upstream => item.UpstreamTreeGuid,
- ConnectionInvokeType.IsError => item.IsErrorTreeGuid,
- ConnectionInvokeType.IsFail => item.IsFailTreeGuid,
- ConnectionInvokeType.IsSucceed => item.IsSucceedTreeGuid,
- _ => throw new Exception("LoadNodeItem Error :ConnectionType is " + connectionType)
- };
- }
-
- //public static System.Windows.Shapes.Rectangle ToRectangle(NodeTreeItemViewControl item, ConnectionType connectionType)
- //{
- // return connectionType switch
- // {
- // ConnectionType.Upstream => item.UpstreamTreeRectangle,
- // ConnectionType.IsError => item.IsErrorRectangle,
- // ConnectionType.IsFail => item.IsFailRectangle,
- // ConnectionType.IsSucceed => item.IsSucceedRectangle,
- // _ => throw new Exception("LoadNodeItem Error :ConnectionType is " + connectionType)
- // };
- //}
-
-
- }
-}
diff --git a/WorkBench/Themes/NodeTreeViewControl.xaml b/WorkBench/Themes/NodeTreeViewControl.xaml
deleted file mode 100644
index 372f5dd..0000000
--- a/WorkBench/Themes/NodeTreeViewControl.xaml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/NodeTreeViewControl.xaml.cs b/WorkBench/Themes/NodeTreeViewControl.xaml.cs
deleted file mode 100644
index 08f8c11..0000000
--- a/WorkBench/Themes/NodeTreeViewControl.xaml.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using Serein.Library;
-using Serein.Library.Api;
-using System.Windows.Controls;
-
-namespace Serein.Workbench.Themes
-{
- ///
- /// NodeTreeViewControl.xaml 的交互逻辑
- ///
- public partial class NodeTreeViewControl : UserControl
- {
- public NodeTreeViewControl()
- {
- InitializeComponent();
- }
-
- private string startNodeGuid = string.Empty;
- private Dictionary globalFlipflopNodes = [];
- private Dictionary unemployedNodes = [];
-
- public void LoadNodeTreeOfStartNode(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel)
- {
- startNodeGuid = nodeModel.Guid;
- StartNodeViewer.InitAndLoadTree(flowEnvironment, nodeModel);
- }
-
- #region 触发器
- public void AddGlobalFlipFlop(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel)
- {
- if (!globalFlipflopNodes.ContainsKey(nodeModel.Guid))
- {
- NodeTreeItemViewControl flipflopTreeViewer = new NodeTreeItemViewControl();
- flipflopTreeViewer.InitAndLoadTree(flowEnvironment, nodeModel);
- globalFlipflopNodes.Add(nodeModel.Guid, flipflopTreeViewer);
- GlobalFlipflopNodeListbox.Items.Add(flipflopTreeViewer);
- }
- }
- public void RefreshGlobalFlipFlop(NodeModelBase nodeModel)
- {
- if (globalFlipflopNodes.TryGetValue(nodeModel.Guid, out var viewer))
- {
- viewer.RefreshTree();
- }
- }
- public void RemoveGlobalFlipFlop(NodeModelBase nodeModel)
- {
- if (globalFlipflopNodes.TryGetValue(nodeModel.Guid, out var viewer))
- {
- globalFlipflopNodes.Remove(nodeModel.Guid);
- GlobalFlipflopNodeListbox.Items.Remove(viewer);
- }
- }
- #endregion
-
-
- #region 无业游民(定义:不存在于起始节点与全局触发器的调用链上的节点,只能手动刷新?)
- public void AddUnemployed(IFlowEnvironment flowEnvironment, NodeModelBase nodeModel)
- {
- if (!unemployedNodes.ContainsKey(nodeModel.Guid))
- {
- NodeTreeItemViewControl flipflopTreeViewer = new NodeTreeItemViewControl();
- flipflopTreeViewer.InitAndLoadTree(flowEnvironment, nodeModel);
- unemployedNodes.Add(nodeModel.Guid, flipflopTreeViewer);
- GlobalFlipflopNodeListbox.Items.Add(flipflopTreeViewer);
- }
- }
- public void RefreshUnemployed(NodeModelBase nodeModel)
- {
- if (unemployedNodes.TryGetValue(nodeModel.Guid, out var viewer))
- {
- viewer.RefreshTree();
- }
- }
- public void RemoteUnemployed(NodeModelBase nodeModel)
- {
- if (unemployedNodes.TryGetValue(nodeModel.Guid, out var viewer))
- {
- unemployedNodes.Remove(nodeModel.Guid);
- GlobalFlipflopNodeListbox.Items.Remove(viewer);
- }
- }
- #endregion
-
- }
-}
diff --git a/WorkBench/Themes/ObjectViewerControl.xaml b/WorkBench/Themes/ObjectViewerControl.xaml
deleted file mode 100644
index d6b3497..0000000
--- a/WorkBench/Themes/ObjectViewerControl.xaml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/ObjectViewerControl.xaml.cs b/WorkBench/Themes/ObjectViewerControl.xaml.cs
deleted file mode 100644
index d3d68ab..0000000
--- a/WorkBench/Themes/ObjectViewerControl.xaml.cs
+++ /dev/null
@@ -1,670 +0,0 @@
-using Newtonsoft.Json.Linq;
-using Serein.Library.Api;
-using Serein.Library.Utils.SereinExpression;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Reflection;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Markup.Primitives;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
-using System.Xml.Linq;
-using static Serein.Workbench.Themes.TypeViewerWindow;
-
-namespace Serein.Workbench.Themes
-{
-
- public class FlowDataDetails
- {
- ///
- /// 属性名称
- ///
- public string? Name { get; set; }
- ///
- /// 属性类型
- ///
- public TreeItemType ItemType { get; set; }
- ///
- /// 数据类型
- ///
- public Type? DataType { get; set; }
- ///
- /// 数据
- ///
- public object? DataValue { get; set; }
- ///
- /// 数据路径
- ///
- public string DataPath { get; set; } = string.Empty;
- }
-
-
- ///
- /// ObjectViewerControl.xaml 的交互逻辑
- ///
- public partial class ObjectViewerControl : UserControl
- {
- public ObjectViewerControl()
- {
- InitializeComponent();
- }
-
- ///
- /// 监视类型
- ///
- public enum MonitorType
- {
- ///
- /// 作用于对象(对象的引用)的监视
- ///
- NodeFlowData,
- ///
- /// 作用与节点(FLowData)的监视
- ///
- IOCObj,
- }
-
- ///
- /// 运行环境
- ///
- public IFlowEnvironment? FlowEnvironment { get; set; }
-
- ///
- /// 监视对象的键
- ///
- public string? MonitorKey { get => monitorKey; }
- ///
- /// 正在监视的对象
- ///
- public object? MonitorObj { get => monitorObj; }
-
- ///
- /// 监视表达式
- ///
- public string? MonitorExpression { get => ExpressionTextBox.Text.ToString(); }
-
- private string? monitorKey;
- private object? monitorObj;
-
- // 用于存储当前展开的节点路径
- private HashSet expandedNodePaths = new HashSet();
-
-
- ///
- /// 加载对象信息,展示其成员
- ///
- /// 要展示的对象
- public void LoadObjectInformation(string key, object obj)
- {
- if (obj == null) return;
- monitorKey = key;
- monitorObj = obj;
- expandedNodePaths.Clear();
- LoadTree(obj);
- }
-
- ///
- /// 刷新对象
- ///
- ///
- ///
- private void RefreshButton_Click(object sender, RoutedEventArgs e)
- {
- RefreshObjectTree(monitorObj);
- }
-
- ///
- /// 更新表达式
- ///
- ///
- ///
- private async void UpMonitorExpressionButton_Click(object sender, RoutedEventArgs e)
- {
- //if (FlowEnvironment is not null && await FlowEnvironment.AddInterruptExpressionAsync(monitorKey, MonitorExpression)) // 对象预览器尝试添加中断表达式
- //{
- // if (string.IsNullOrEmpty(MonitorExpression))
- // {
- // ExpressionTextBox.Text = "表达式已清空";
- // }
- // else
- // {
- // UpMonitorExpressionButton.Content = "更新监视表达式";
- // }
- //}
- }
-
- private TreeViewItem? LoadTree(object? obj)
- {
- if (obj is null) return null;
- var objectType = obj.GetType();
- FlowDataDetails flowDataDetails = new FlowDataDetails
- {
- Name = objectType.Name,
- DataType = objectType,
- DataValue = obj,
- DataPath = ""
- };
- var rootNode = new TreeViewItem
- {
- Header = objectType.Name,
- Tag = flowDataDetails,
- };
-
-
- ObjectTreeView.Items.Clear(); // 移除对象树的所有节点
- ObjectTreeView.Items.Add(rootNode); // 添加所有节点
- rootNode.Expanded += TreeViewItem_Expanded; // 监听展开事件
- rootNode.Collapsed += TreeViewItem_Collapsed; // 监听折叠事件
- // 这里创建了一个子项,并给这个子项创建了“正在加载”的子项
- // 然后移除了原来对象树的所有项,再把这个新创建的子项添加上去
- // 绑定了展开/折叠事件后,自动展开第一层,开始反射obj的成员,并判断obj的成员生成什么样的节点
- rootNode.IsExpanded = true;
- return rootNode;
- }
-
- ///
- /// 刷新对象属性树
- ///
- public void RefreshObjectTree(object? obj)
- {
- monitorObj = obj;
- var rootNode = LoadTree(obj);
- if (rootNode is not null)
- {
- ExpandPreviouslyExpandedNodes(rootNode); // 遍历节点,展开之前记录的节点
-
- }
-
- }
-
- ///
- /// 展开父节点,如果路径存在哈希记录,则将其自动展开,并递归展开后的子节点。
- ///
- ///
- private void ExpandPreviouslyExpandedNodes(TreeViewItem node)
- {
- if (node == null) return;
- if(node.Tag is FlowDataDetails flowDataDetails)
- {
- if (expandedNodePaths.Contains(flowDataDetails.DataPath))
- {
- node.IsExpanded = true;
- }
- }
-
- foreach (TreeViewItem child in node.Items)
- {
- ExpandPreviouslyExpandedNodes(child);
- }
- }
-
- ///
- /// 展开子项事件
- ///
- ///
- ///
- private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
- {
- if (sender is TreeViewItem item)
- {
- if (item.Tag is FlowDataDetails flowDataDetails) // FlowDataDetails flowDataDetails object obj
- {
- if (flowDataDetails.ItemType != TreeItemType.Item && item.Items.Count != 0)
- {
- return;
- }
- if(flowDataDetails.DataValue is null || flowDataDetails.DataType is null)
- {
- return;
- }
-
- // 记录当前节点的路径
- var path = flowDataDetails.DataPath;
- expandedNodePaths.Add(path);
- AddMembersToTreeNode(item, flowDataDetails.DataValue, flowDataDetails.DataType);
-
- }
- }
- }
-
- ///
- /// 折叠事件
- ///
- ///
- ///
- private void TreeViewItem_Collapsed(object sender, RoutedEventArgs e)
- {
- if (sender is TreeViewItem item && item.Items.Count > 0)
- {
- if (item.Tag is FlowDataDetails flowDataDetails)
- {
- // 记录当前节点的路径
- var path = flowDataDetails.DataPath;
- if(path != "")
- {
- expandedNodePaths.Remove(path);
- }
- }
- }
- }
-
- ///
- /// 反射对象数据添加子节点
- ///
- ///
- ///
- ///
- private void AddMembersToTreeNode(TreeViewItem treeViewNode, object obj, Type type)
- {
- // 获取公开的属性
- var members = type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
- foreach (var member in members)
- {
- if (member.Name.StartsWith(".") ||
- member.Name.StartsWith("get_") ||
- member.Name.StartsWith("set_")
- )
- {
- // 跳过构造函数、属性的get/set方法
- continue;
- }
-
- TreeViewItem? memberNode = ConfigureTreeViewItem(obj, member); // 根据对象成员生成节点对象
- if (memberNode is not null)
- {
- treeViewNode.Items.Add(memberNode); // 添加到当前节点
-
- // 配置数据路径
- FlowDataDetails subFlowDataDetails = (FlowDataDetails)memberNode.Tag;
- string superPath = ((FlowDataDetails)treeViewNode.Tag).DataPath;
- string subPath = superPath + "." + subFlowDataDetails.Name;
- subFlowDataDetails.DataPath = subPath;
-
- // 配置右键菜单
- var contextMenu = new ContextMenu();
- contextMenu.Items.Add(MainWindow.CreateMenuItem($"表达式", (s, e) =>
- {
- ExpressionTextBox.Text = subPath; // 获取表达式
-
- }));
- memberNode.ContextMenu = contextMenu;
- }
- }
- }
-
- ///
- /// 配置节点子项
- ///
- ///
- ///
- ///
- private TreeViewItem? ConfigureTreeViewItem(object obj, MemberInfo member)
- {
- if (obj == null)
- {
- return null;
- }
- #region 属性
- if (member is PropertyInfo property)
- {
- #region 集合类型(非字符串)
- if (property.PropertyType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(property.PropertyType) && property.GetValue(obj) is IEnumerable collection && collection is not null)
- {
- TreeViewItem memberNode = new TreeViewItem { Header = member.Name };
- // 处理集合类型的属性
- memberNode.Tag = new FlowDataDetails
- {
- ItemType = TreeItemType.IEnumerable,
- DataType = property.PropertyType,
- Name = property.Name,
- DataValue = collection,
- };
-
- int index = 0;
- foreach (var item in collection)
- {
- var itemNode = new TreeViewItem { Header = $"[{index++}] {item}" ?? "null" };
- memberNode.Tag = new FlowDataDetails
- {
- ItemType = TreeItemType.Item,
- DataType = item?.GetType(),
- Name = property.Name,
- DataValue = itemNode,
- };
- memberNode.Items.Add(itemNode);
- }
- memberNode.Header = $"{property.Name} : {property.PropertyType.Name} [{index}]";
- if (!property.PropertyType.IsPrimitive && property.PropertyType != typeof(string))
- {
- memberNode.Expanded += TreeViewItem_Expanded;
- memberNode.Collapsed += TreeViewItem_Collapsed;
- }
- return memberNode;
- }
- #endregion
- #region 值类型与未判断的类型
- else
- {
- TreeViewItem memberNode = new TreeViewItem { Header = member.Name };
- string propertyValue = GetPropertyValue(obj, property, out object? value);
- memberNode.Tag = new FlowDataDetails
- {
- ItemType = TreeItemType.Property,
- DataType = property.PropertyType,
- Name = property.Name,
- DataValue = value,
- }; ;
-
- memberNode.Header = $"{property.Name} : {property.PropertyType.Name} = {propertyValue}";
- if (!property.PropertyType.IsPrimitive && property.PropertyType != typeof(string))
- {
- memberNode.Expanded += TreeViewItem_Expanded;
- memberNode.Collapsed += TreeViewItem_Collapsed;
- }
- return memberNode;
- }
-
- #endregion
- }
- #endregion
- #region 字段
- else if (member is FieldInfo field)
- {
- #region 集合类型(非字符串)
- if (field.FieldType != typeof(string) && typeof(IEnumerable).IsAssignableFrom(field.FieldType) && field.GetValue(obj) is IEnumerable collection && collection is not null)
- {
- TreeViewItem memberNode = new TreeViewItem { Header = member.Name };
- // 处理集合类型的字段
- memberNode.Tag = new FlowDataDetails
- {
- ItemType = TreeItemType.IEnumerable,
- DataType = field.FieldType,
- Name = field.Name,
- DataValue = collection,
- };
-
- int index = 0;
- foreach (var item in collection)
- {
- var itemNode = new TreeViewItem { Header = $"[{index++}] {item}" ?? "null" };
- memberNode.Tag = new FlowDataDetails
- {
- ItemType = TreeItemType.Item,
- DataType = item?.GetType(),
- Name = field.Name,
- DataValue = itemNode,
- };
- //collectionNode.Items.Add(itemNode);
- memberNode.Items.Add(itemNode);
- }
- memberNode.Header = $"{field.Name} : {field.FieldType.Name} [{index}]";
- if (!field.FieldType.IsPrimitive && field.FieldType != typeof(string))
- {
- memberNode.Expanded += TreeViewItem_Expanded;
- memberNode.Collapsed += TreeViewItem_Collapsed;
- }
- return memberNode;
- }
- #endregion
- #region 值类型与未判断的类型
- else
- {
- TreeViewItem memberNode = new TreeViewItem { Header = member.Name };
- string fieldValue = GetFieldValue(obj, field, out object? value);
-
- memberNode.Tag = new FlowDataDetails
- {
- ItemType = TreeItemType.Field,
- DataType = field.FieldType,
- Name = field.Name,
- DataValue = value,
-
- };
- memberNode.Header = $"{field.Name} : {field.FieldType.Name} = {fieldValue}";
-
- if (!field.FieldType.IsPrimitive && field.FieldType != typeof(string))
- {
- memberNode.Expanded += TreeViewItem_Expanded;
- memberNode.Collapsed += TreeViewItem_Collapsed;
- }
- return memberNode;
- }
- #endregion
- }
- #endregion
- #region 返回null
- else
- {
- return null;
- }
- #endregion
-
- }
-
- ///
- /// 获取属性类型的成员
- ///
- ///
- ///
- ///
- private string GetPropertyValue(object obj, PropertyInfo property,out object? value)
- {
- try
- {
- if(obj is null)
- {
- value = null;
- return "Error";
- }
- var properties = obj.GetType().GetProperties();
-
- // 获取实例属性值
- value = property.GetValue(obj);
- return value?.ToString() ?? "null"; // 返回值或“null”
- }
- catch
- {
- value = null;
- return "Error";
- }
- }
-
- ///
- /// 获取字段类型的成员
- ///
- ///
- ///
- ///
- private string GetFieldValue(object obj, FieldInfo field, out object? value)
- {
- try
- {
- value = field.GetValue(obj);
- return value?.ToString() ?? "null";
- }
- catch
- {
- value = null;
- return "Error";
- }
- }
-
- }
-}
-
-
-///
-/// 上次刷新时间
-///
-//private DateTime lastRefreshTime = DateTime.MinValue;
-///
-/// 刷新间隔
-///
-//private readonly TimeSpan refreshInterval = TimeSpan.FromSeconds(0.1);
-// 当前时间
-//var currentTime = DateTime.Now;
-//if (currentTime - lastRefreshTime < refreshInterval)
-//{
-// return; // 跳过过于频繁的刷新调用
-//}
-//else
-//{
-// lastRefreshTime = currentTime;// 记录这次的刷新时间
-//}
-//
-
-///
-/// 从当前节点获取至父节点的路径,例如 "node1.node2.node3.node4"
-///
-/// 目标节点
-/// 节点路径
-//private string GetNodeFullPath(TreeViewItem node)
-//{
-// if (node == null)
-// return string.Empty;
-
-// FlowDataDetails flowDataDetails = (FlowDataDetails)node.Tag;
-// var parent = GetParentTreeViewItem(node);
-// if (parent != null)
-// {
-// // 递归获取父节点的路径,并拼接当前节点的 Header
-// return $"{GetNodeFullPath(parent)}.{flowDataDetails.Name}";
-// }
-// else
-// {
-// // 没有父节点,则说明这是根节点,直接返回 Header
-// return "";
-// }
-//}
-
-///
-/// 获取指定节点的父级节点
-///
-/// 目标节点
-/// 父节点
-//private TreeViewItem GetParentTreeViewItem(TreeViewItem node)
-//{
-// DependencyObject parent = VisualTreeHelper.GetParent(node);
-// while (parent != null && !(parent is TreeViewItem))
-// {
-// parent = VisualTreeHelper.GetParent(parent);
-// }
-// return parent as TreeViewItem;
-//}
-
-
-
-
-
-
-///
-/// 根据成员类别配置右键菜单
-///
-///
-///
-///
-///
-//private bool ConfigureTreeItemMenu(TreeViewItem memberNode, MemberInfo member, out ContextMenu? contextMenu)
-//{
-// if (ConfigureTreeItemMenu(memberNode, member, out ContextMenu? contextMenu))
-// {
-// memberNode.ContextMenu = contextMenu; // 设置子项节点的事件
-// }
-
-// bool isChange = false;
-// if (member is PropertyInfo property)
-// {
-// isChange = true;
-// contextMenu = new ContextMenu();
-// contextMenu.Items.Add(MainWindow.CreateMenuItem($"表达式", (s, e) =>
-// {
-// string fullPath = GetNodeFullPath(memberNode);
-// string copyValue = /*"@Get " + */fullPath;
-// ExpressionTextBox.Text = copyValue;
-// // Clipboard.SetDataObject(copyValue);
-
-// }));
-// }
-// else if (member is MethodInfo method)
-// {
-// //isChange = true;
-// contextMenu = new ContextMenu();
-// }
-// else if (member is FieldInfo field)
-// {
-// isChange = true;
-// contextMenu = new ContextMenu();
-// contextMenu.Items.Add(MainWindow.CreateMenuItem($"表达式", (s, e) =>
-// {
-// string fullPath = GetNodeFullPath(memberNode);
-// string copyValue = /*"@Get " +*/ fullPath;
-// ExpressionTextBox.Text = copyValue;
-// // Clipboard.SetDataObject(copyValue);
-// }));
-// }
-// else
-// {
-// contextMenu = new ContextMenu();
-// }
-// return isChange;
-//}
-
-
-
-
-
-/////
-///// 刷新按钮的点击事件
-/////
-//private void RefreshButton_Click(object sender, RoutedEventArgs e)
-//{
-// RefreshObjectTree();
-//}
-
-//private bool IsTimerRefres = false;
-//private void TimerRefreshButton_Click(object sender, RoutedEventArgs e)
-//{
-// if (IsTimerRefres)
-// {
-// IsTimerRefres = false;
-// TimerRefreshButton.Content = "定时刷新";
-// }
-// else
-// {
-// IsTimerRefres = true;
-// TimerRefreshButton.Content = "取消刷新";
-
-// _ = Task.Run(async () => {
-// while (true)
-// {
-// if (IsTimerRefres)
-// {
-// Application.Current.Dispatcher.Invoke(() =>
-// {
-// RefreshObjectTree(); // 刷新UI
-// });
-// await Task.Delay(100);
-// }
-// else
-// {
-// break;
-// }
-// }
-// IsTimerRefres = false;
-// });
-// }
-
-//}
-
diff --git a/WorkBench/Themes/TypeViewerWindow.xaml b/WorkBench/Themes/TypeViewerWindow.xaml
deleted file mode 100644
index 856de67..0000000
--- a/WorkBench/Themes/TypeViewerWindow.xaml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/TypeViewerWindow.xaml.cs b/WorkBench/Themes/TypeViewerWindow.xaml.cs
deleted file mode 100644
index 7c390bd..0000000
--- a/WorkBench/Themes/TypeViewerWindow.xaml.cs
+++ /dev/null
@@ -1,279 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Shapes;
-
-namespace Serein.Workbench.Themes
-{
- ///
- /// TypeViewerWindow.xaml 的交互逻辑
- ///
- public partial class TypeViewerWindow : Window
- {
- public TypeViewerWindow()
- {
- InitializeComponent();
- }
-
- public Type Type { get; set; }
-
- public void LoadTypeInformation()
- {
- if (Type == null)
- return;
-
- NodeFlowDataObjectDetails typeNodeDetails = new NodeFlowDataObjectDetails
- {
- Name = Type.Name,
- DataType = Type,
- };
- var rootNode = new TreeViewItem { Header = Type.Name, Tag = typeNodeDetails };
- AddPlaceholderNode(rootNode); // 添加占位符节点
- TypeTreeView.Items.Clear();
- TypeTreeView.Items.Add(rootNode);
-
- rootNode.Expanded += TreeViewItem_Expanded; // 监听节点展开事件
- }
-
- ///
- /// 添加占位符节点
- ///
- private void AddPlaceholderNode(TreeViewItem node)
- {
- node.Items.Add(new TreeViewItem { Header = "Loading..." });
- }
-
- ///
- /// 节点展开事件,延迟加载子节点
- ///
- private void TreeViewItem_Expanded(object sender, RoutedEventArgs e)
- {
- var item = (TreeViewItem)sender;
-
- // 如果已经加载过子节点,则不再重复加载
- if (item.Items.Count == 1 && item.Items[0] is TreeViewItem placeholder && placeholder.Header.ToString() == "Loading...")
- {
- item.Items.Clear();
- if (item.Tag is NodeFlowDataObjectDetails typeNodeDetails)
- {
- AddMembersToTreeNode(item, typeNodeDetails.DataType);
- }
-
- }
-
-
- }
-
- ///
- /// 添加属性节点
- ///
- private void AddMembersToTreeNode(TreeViewItem node, Type type)
- {
- var members = type.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly);
- foreach (var member in members)
- {
- TreeViewItem memberNode = ConfigureTreeViewItem(member); // 生成类型节点的子项
- if (ConfigureTreeItemMenu(memberNode,member, out ContextMenu? contextMenu))
- {
- memberNode.ContextMenu = contextMenu; // 设置子项节点的事件
- }
-
- node.Items.Add(memberNode); // 添加到父节点中
- }
- }
-
-
- ///
- /// 生成类型节点的子项
- ///
- ///
- ///
- private TreeViewItem ConfigureTreeViewItem(MemberInfo member)
- {
- TreeViewItem memberNode = new TreeViewItem { Header = member.Name };
- if (member is PropertyInfo property)
- {
- NodeFlowDataObjectDetails typeNodeDetails = new NodeFlowDataObjectDetails
- {
- ItemType = TreeItemType.Property,
- DataType = property.PropertyType,
- Name = property.Name,
- DataValue = property,
- };
- memberNode.Tag = typeNodeDetails;
-
- var propertyType = typeNodeDetails.DataType;
- memberNode.Header = $"{member.Name} : {propertyType.Name}";
-
- if (!propertyType.IsPrimitive && propertyType != typeof(string))
- {
- // 延迟加载类型的子属性,添加占位符节点
- AddPlaceholderNode(memberNode);
- memberNode.Expanded += TreeViewItem_Expanded; // 监听展开事件
- }
- }
- else if (member is MethodInfo method)
- {
- NodeFlowDataObjectDetails typeNodeDetails = new NodeFlowDataObjectDetails
- {
- ItemType = TreeItemType.Method,
- DataType = typeof(MethodInfo),
- Name = method.Name,
- DataValue = null,
- };
- memberNode.Tag = typeNodeDetails;
-
- var parameters = method.GetParameters();
- var paramStr = string.Join(", ", parameters.Select(p => $"{p.ParameterType.Name} {p.Name}"));
- memberNode.Header = $"{member.Name}({paramStr})";
- }
- else if (member is FieldInfo field)
- {
- NodeFlowDataObjectDetails typeNodeDetails = new NodeFlowDataObjectDetails
- {
- ItemType = TreeItemType.Field,
- DataType = field.FieldType,
- Name = field.Name,
- DataValue = field,
- };
- memberNode.Tag = typeNodeDetails;
- memberNode.Header = $"{member.Name} : {field.FieldType.Name}";
- }
- return memberNode;
- }
-
-
- ///
- /// 设置子项节点的事件
- ///
- ///
- ///
- private bool ConfigureTreeItemMenu(TreeViewItem memberNode, MemberInfo member,out ContextMenu? contextMenu)
- {
- bool isChange = false;
- if (member is PropertyInfo property)
- {
- isChange = true;
- contextMenu = new ContextMenu();
- contextMenu.Items.Add(MainWindow.CreateMenuItem($"取值表达式", (s, e) =>
- {
- string fullPath = GetNodeFullPath(memberNode);
- string copyValue = "@Get " + fullPath;
- Clipboard.SetDataObject(copyValue);
- }));
- }
- else if (member is MethodInfo method)
- {
- //isChange = true;
- contextMenu = new ContextMenu();
- }
- else if (member is FieldInfo field)
- {
- isChange = true;
- contextMenu = new ContextMenu();
- contextMenu.Items.Add(MainWindow.CreateMenuItem($"取值表达式", (s, e) =>
- {
- string fullPath = GetNodeFullPath(memberNode);
- string copyValue = "@Get " + fullPath;
- Clipboard.SetDataObject(copyValue);
- }));
- }
- else
- {
- contextMenu = new ContextMenu();
- }
- return isChange;
- }
-
-
-
- ///
- /// 获取当前节点的完整路径,例如 "node1.node2.node3.node4"
- ///
- /// 目标节点
- /// 节点路径
- private string GetNodeFullPath(TreeViewItem node)
- {
- if (node == null)
- return string.Empty;
-
- NodeFlowDataObjectDetails typeNodeDetails = (NodeFlowDataObjectDetails)node.Tag;
- var parent = GetParentTreeViewItem(node);
- if (parent != null)
- {
- // 递归获取父节点的路径,并拼接当前节点的 Header
- return $"{GetNodeFullPath(parent)}.{typeNodeDetails.Name}";
- }
- else
- {
- // 没有父节点,则说明这是根节点,直接返回 Header
- return "";
- // return typeNodeDetails.Name.ToString();
- }
- }
-
- ///
- /// 获取指定节点的父级节点
- ///
- /// 目标节点
- /// 父节点
- private TreeViewItem? GetParentTreeViewItem(TreeViewItem node)
- {
- DependencyObject parent = VisualTreeHelper.GetParent(node);
- while (parent != null && parent is not TreeViewItem)
- {
- parent = VisualTreeHelper.GetParent(parent);
- }
- return parent as TreeViewItem;
- }
-
-
-
- public class NodeFlowDataObjectDetails
- {
- ///
- /// 属性名称
- ///
- public string Name { get; set; }
- ///
- /// 属性类型
- ///
- public TreeItemType ItemType { get; set; }
- ///
- /// 数据类型
- ///
- public Type DataType { get; set; }
- ///
- /// 数据(调试用?)
- ///
- public object DataValue { get; set; }
- ///
- /// 数据路径
- ///
- public string DataPath { get; set; }
- }
-
- public enum TreeItemType
- {
- Property,
- Method,
- Field,
- IEnumerable,
- Item,
- }
-
-
-
- }
-
-}
diff --git a/WorkBench/Themes/WindowDialogInput.xaml b/WorkBench/Themes/WindowDialogInput.xaml
deleted file mode 100644
index 7d8611a..0000000
--- a/WorkBench/Themes/WindowDialogInput.xaml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/WorkBench/Themes/WindowDialogInput.xaml.cs b/WorkBench/Themes/WindowDialogInput.xaml.cs
deleted file mode 100644
index f5f5441..0000000
--- a/WorkBench/Themes/WindowDialogInput.xaml.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using Serein.Library;
-using Serein.Library.Utils;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Shapes;
-
-namespace Serein.Workbench.Themes
-{
- ///
- /// WindowDialogInput.xaml 的交互逻辑
- ///
- public partial class WindowEnvRemoteLoginView : Window
- {
- private Action ConnectRemoteFlowEnv;
-
- ///
- /// 弹窗输入
- ///
- ///
- public WindowEnvRemoteLoginView(Action connectRemoteFlowEnv)
- {
- WindowStartupLocation = WindowStartupLocation.CenterScreen;
- InitializeComponent();
- ConnectRemoteFlowEnv = connectRemoteFlowEnv;
- }
-
- private void ButtonTestConnect_Client(object sender, RoutedEventArgs e)
- {
- var addres = this.TextBlockAddres.Text;
- _ = int.TryParse(this.TextBlockPort.Text, out var port);
- _ = Task.Run(() => {
- bool success = false;
- try
- {
- TcpClient tcpClient = new TcpClient();
- var result = tcpClient.BeginConnect(addres, port, null, null);
- success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(3));
- }
- catch
- {
- success = false;
- }
- if (!success)
- {
- SereinEnv.WriteLine(InfoType.ERROR, $"无法连接远程:{addres}:{port}");
- }
- });
-
- }
-
- private void ButtonTestLoginEnv_Client(object sender, RoutedEventArgs e)
- {
- var addres = this.TextBlockAddres.Text;
- _ = int.TryParse(this.TextBlockPort.Text, out var port);
- var token = this.TextBlockToken.Text;
- ConnectRemoteFlowEnv?.Invoke(addres, port, token);
- }
- }
-}
diff --git a/WorkBench/Tool/Converters/InvertableBooleanToVisibilityConverter.cs b/WorkBench/Tool/Converters/InvertableBooleanToVisibilityConverter.cs
deleted file mode 100644
index e830c6d..0000000
--- a/WorkBench/Tool/Converters/InvertableBooleanToVisibilityConverter.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Data;
-using System.Windows;
-
-namespace Serein.Workbench.Tool.Converters
-{
- ///
- /// 根据bool类型控制可见性
- ///
- [ValueConversion(typeof(bool), typeof(Visibility))]
- public class InvertableBooleanToVisibilityConverter : IValueConverter
- {
- enum Parameters
- {
- Normal, Inverted
- }
-
- public object Convert(object value, Type targetType,
- object parameter, CultureInfo culture)
- {
- var boolValue = (bool)value;
- var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);
-
- if (direction == Parameters.Inverted)
- return !boolValue ? Visibility.Visible : Visibility.Collapsed;
-
- return boolValue ? Visibility.Visible : Visibility.Collapsed;
- }
-
- public object? ConvertBack(object value, Type targetType,
- object parameter, CultureInfo culture)
- {
- return null;
- }
- }
-}
diff --git a/WorkBench/Tool/Converters/ThumbPositionConverter.cs b/WorkBench/Tool/Converters/ThumbPositionConverter.cs
deleted file mode 100644
index df6adbf..0000000
--- a/WorkBench/Tool/Converters/ThumbPositionConverter.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Data;
-
-namespace Serein.Workbench.Tool.Converters
-{
- ///
- /// 画布拉动范围距离计算器
- ///
- public class RightThumbPositionConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- if (value is double width)
- return width - 10; // Adjust for Thumb width
- return 0;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
- ///
- /// 画布拉动范围距离计算器
- ///
- public class BottomThumbPositionConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- if (value is double height)
- return height - 10; // Adjust for Thumb height
- return 0;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
- ///
- /// 画布拉动范围距离计算器
- ///
- public class VerticalCenterThumbPositionConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- if (value is double height)
- return height / 2 - 5; // Centering Thumb vertically
- return 0;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
- ///
- /// 画布拉动范围距离计算器
- ///
- public class HorizontalCenterThumbPositionConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- if (value is double width)
- return width / 2 - 5; // Centering Thumb horizontally
- return 0;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-
-}
diff --git a/WorkBench/Tool/Converters/TypeToColorConverter.cs b/WorkBench/Tool/Converters/TypeToColorConverter.cs
deleted file mode 100644
index 6d27425..0000000
--- a/WorkBench/Tool/Converters/TypeToColorConverter.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using Serein.Library;
-using System.Globalization;
-using System.Windows.Data;
-using System.Windows.Media;
-
-namespace Serein.Workbench.Tool.Converters
-{
- ///
- /// 根据控件类型切换颜色
- ///
- public class TypeToColorConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- // 根据 ControlType 返回颜色
- return value switch
- {
- NodeControlType.Action => Brushes.Blue,
- NodeControlType.Flipflop => Brushes.Green,
- _ => Brushes.Black,
- };
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
- }
-}