mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
重写了节点的view、viewmodel关系,实现了对画布元素的选取功能,重构了底层依赖,添加了对net .Framework4.6.1以上的Framework类库支持
This commit is contained in:
@@ -146,7 +146,7 @@ namespace Serein.WorkBench
|
||||
Shutdown(); // 关闭应用程序
|
||||
}
|
||||
}
|
||||
else if (1 == 1)
|
||||
else if (1 == 11)
|
||||
{
|
||||
string filePath = @"F:\临时\project\U9 project.dnf";
|
||||
//string filePath = @"D:\Project\C#\DynamicControl\SereinFlow\.Output\Debug\net8.0-windows7.0\U9 project.dnf";
|
||||
|
||||
@@ -93,6 +93,10 @@
|
||||
x:Name="FlowChartCanvas"
|
||||
Background="#D9FFEA"
|
||||
AllowDrop="True"
|
||||
Width="1000"
|
||||
Height="700"
|
||||
MouseLeftButtonDown ="FlowChartCanvas_MouseLeftButtonDown"
|
||||
MouseLeftButtonUp="FlowChartCanvas_MouseLeftButtonUp"
|
||||
MouseDown="FlowChartCanvas_MouseDown"
|
||||
MouseMove="FlowChartCanvas_MouseMove"
|
||||
MouseUp="FlowChartCanvas_MouseUp"
|
||||
@@ -100,6 +104,14 @@
|
||||
Drop="FlowChartCanvas_Drop"
|
||||
DragOver="FlowChartCanvas_DragOver">
|
||||
|
||||
<Rectangle x:Name="SelectionRectangle"
|
||||
Stroke="Blue"
|
||||
StrokeThickness="2"
|
||||
Fill="LightBlue"
|
||||
Opacity="0.5"
|
||||
Panel.ZIndex="999999"
|
||||
Visibility="Collapsed"/>
|
||||
|
||||
<!-- Top-Left Thumb -->
|
||||
<!--<Thumb x:Name="TopLeftThumb"
|
||||
Width="10" Height="10"
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
using Microsoft.Win32;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serein.Library.IOC;
|
||||
using Serein.Library.Attributes;
|
||||
using Serein.Library.Utils;
|
||||
using Serein.NodeFlow;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using Serein.WorkBench.Node.View;
|
||||
using Serein.WorkBench.Node.ViewModel;
|
||||
using Serein.WorkBench.Themes;
|
||||
using Serein.WorkBench.tool;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography.Xml;
|
||||
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 System.Windows.Media.Media3D;
|
||||
using System.Windows.Shapes;
|
||||
using System.Xml.Linq;
|
||||
using DataObject = System.Windows.DataObject;
|
||||
|
||||
namespace Serein.WorkBench
|
||||
@@ -126,7 +125,7 @@ namespace Serein.WorkBench
|
||||
/// <summary>
|
||||
/// 一种轻量的IOC容器
|
||||
/// </summary>
|
||||
private ServiceContainer ServiceContainer { get; } = new ServiceContainer();
|
||||
private SereinIoc ServiceContainer { get; } = new SereinIoc();
|
||||
|
||||
/// <summary>
|
||||
/// 全局捕获Console输出事件,打印在这个窗体里面
|
||||
@@ -160,6 +159,20 @@ namespace Serein.WorkBench
|
||||
/// </summary>
|
||||
private readonly List<SingleFlipflopNode> flipflopNodes = [];
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程启动器
|
||||
/// </summary>
|
||||
private NodeFlowStarter nodeFlowStarter;
|
||||
|
||||
#region 与画布相关的字段
|
||||
|
||||
/// <summary>
|
||||
/// 当前选取的控件
|
||||
/// </summary>
|
||||
private readonly List<NodeControlBase> selectControls = [];
|
||||
|
||||
/// <summary>
|
||||
/// 记录拖动开始时的鼠标位置
|
||||
/// </summary>
|
||||
@@ -185,6 +198,10 @@ namespace Serein.WorkBench
|
||||
/// </summary>
|
||||
private bool IsConnecting;
|
||||
/// <summary>
|
||||
/// 标记是否正在尝试选取控件
|
||||
/// </summary>
|
||||
private bool IsSelectControl;
|
||||
/// <summary>
|
||||
/// 标记是否正在拖动控件
|
||||
/// </summary>
|
||||
private bool IsControlDragging;
|
||||
@@ -203,12 +220,10 @@ namespace Serein.WorkBench
|
||||
/// <summary>
|
||||
/// 平移画布
|
||||
/// </summary>
|
||||
private TranslateTransform translateTransform;
|
||||
private TranslateTransform translateTransform;
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程起点
|
||||
/// </summary>
|
||||
private NodeFlowStarter nodeFlowStarter;
|
||||
|
||||
public MainWindow()
|
||||
|
||||
@@ -259,10 +274,10 @@ namespace Serein.WorkBench
|
||||
LoadDll(nf); // 加载DLL
|
||||
LoadNodeControls(nf); // 加载节点
|
||||
|
||||
var startNode = nodeControls.FirstOrDefault(item => item.Node.Guid.Equals(nf.startNode));
|
||||
var startNode = nodeControls.FirstOrDefault(control => control.ViewModel.Node.Guid.Equals(nf.startNode));
|
||||
if (startNode != null)
|
||||
{
|
||||
startNode.Node.IsStart = true;
|
||||
startNode.ViewModel.Node.IsStart = true;
|
||||
SetIsStartBlock(startNode);
|
||||
}
|
||||
}
|
||||
@@ -332,7 +347,7 @@ namespace Serein.WorkBench
|
||||
}
|
||||
else if (regionControl is ActionRegionControl actionRegionControl)
|
||||
{
|
||||
actionRegionControl.AddAction(nodeControl);
|
||||
//actionRegionControl.AddAction(nodeControl);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -396,22 +411,22 @@ namespace Serein.WorkBench
|
||||
{
|
||||
if (connectionType == ConnectionType.IsSucceed)
|
||||
{
|
||||
fromNode.Node.SucceedBranch.Add(toNode.Node);
|
||||
fromNode.ViewModel.Node.SucceedBranch.Add(toNode.ViewModel.Node);
|
||||
}
|
||||
else if (connectionType == ConnectionType.IsFail)
|
||||
{
|
||||
fromNode.Node.FailBranch.Add(toNode.Node);
|
||||
fromNode.ViewModel.Node.FailBranch.Add(toNode.ViewModel.Node);
|
||||
}
|
||||
else if (connectionType == ConnectionType.IsError)
|
||||
{
|
||||
fromNode.Node.ErrorBranch.Add(toNode.Node);
|
||||
fromNode.ViewModel.Node.ErrorBranch.Add(toNode.ViewModel.Node);
|
||||
}
|
||||
else if (connectionType == ConnectionType.Upstream)
|
||||
{
|
||||
fromNode.Node.UpstreamBranch.Add(toNode.Node);
|
||||
fromNode.ViewModel.Node.UpstreamBranch.Add(toNode.ViewModel.Node);
|
||||
}
|
||||
var connection = new Connection { Start = fromNode, End = toNode, Type = connectionType };
|
||||
toNode.Node.PreviousNodes.Add(fromNode.Node);
|
||||
toNode.ViewModel.Node.PreviousNodes.Add(fromNode.ViewModel.Node);
|
||||
BsControl.Draw(FlowChartCanvas, connection);
|
||||
ConfigureLineContextMenu(connection);
|
||||
connections.Add(connection);
|
||||
@@ -465,19 +480,19 @@ namespace Serein.WorkBench
|
||||
|
||||
NodeControlBase control = nodeInfo.type switch
|
||||
{
|
||||
$"{NodeSpaceName}.{nameof(SingleActionNode)}" => CreateNodeControl<SingleActionNode, ActionNodeControl>(md),
|
||||
$"{NodeSpaceName}.{nameof(SingleFlipflopNode)}" => CreateNodeControl<SingleFlipflopNode, FlipflopNodeControl>(md),
|
||||
$"{NodeSpaceName}.{nameof(SingleActionNode)}" => CreateNodeControl<SingleActionNode, ActionNodeControl,ActionNodeControlViewModel>(md),
|
||||
$"{NodeSpaceName}.{nameof(SingleFlipflopNode)}" => CreateNodeControl<SingleFlipflopNode, FlipflopNodeControl,FlipflopNodeControlViewModel>(md),
|
||||
|
||||
$"{NodeSpaceName}.{nameof(SingleConditionNode)}" => CreateNodeControl<SingleConditionNode, ConditionNodeControl>(), // 条件表达式控件
|
||||
$"{NodeSpaceName}.{nameof(SingleExpOpNode)}" => CreateNodeControl<SingleExpOpNode, ExpOpNodeControl>(), // 操作表达式控件
|
||||
$"{NodeSpaceName}.{nameof(SingleConditionNode)}" => CreateNodeControl<SingleConditionNode, ConditionNodeControl,ConditionNodeControlViewModel>(), // 条件表达式控件
|
||||
$"{NodeSpaceName}.{nameof(SingleExpOpNode)}" => CreateNodeControl<SingleExpOpNode, ExpOpNodeControl,ExpOpNodeViewModel>(), // 操作表达式控件
|
||||
|
||||
$"{NodeSpaceName}.{nameof(CompositeActionNode)}" => CreateNodeControl<CompositeActionNode, ActionRegionControl>(),
|
||||
$"{NodeSpaceName}.{nameof(CompositeConditionNode)}" => CreateNodeControl<CompositeConditionNode, ConditionRegionControl>(),
|
||||
//$"{NodeSpaceName}.{nameof(CompositeActionNode)}" => CreateNodeControl<CompositeActionNode, ActionRegionControl>(),
|
||||
$"{NodeSpaceName}.{nameof(CompositeConditionNode)}" => CreateNodeControl<CompositeConditionNode, ConditionRegionControl, ConditionRegionNodeControlViewModel>(),
|
||||
_ => throw new NotImplementedException($"非预期的节点类型{nodeInfo.type}"),
|
||||
};
|
||||
|
||||
// 如果是触发器,则需要添加到集合中
|
||||
if (control is FlipflopNodeControl flipflopNodeControl && flipflopNodeControl.Node is SingleFlipflopNode flipflopNode)
|
||||
if (control is FlipflopNodeControl flipflopNodeControl && flipflopNodeControl.ViewModel.Node is SingleFlipflopNode flipflopNode)
|
||||
{
|
||||
var guid = flipflopNode.Guid;
|
||||
if (!flipflopNodes.Exists(it => it.Guid.Equals(guid)))
|
||||
@@ -485,22 +500,22 @@ namespace Serein.WorkBench
|
||||
flipflopNodes.Add(flipflopNode);
|
||||
}
|
||||
}
|
||||
var node = control.Node;
|
||||
var node = control.ViewModel.Node;
|
||||
if (node != null)
|
||||
{
|
||||
node.Guid = nodeInfo.guid;
|
||||
for (int i = 0; i < nodeInfo.parameterData.Length; i++)
|
||||
{
|
||||
Parameterdata? pd = nodeInfo.parameterData[i];
|
||||
if (control is ConditionNodeControl conditionNodeControl)
|
||||
if (control is ConditionNodeControl conditionNodeControl && conditionNodeControl.ViewModel is ConditionNodeControlViewModel conditionNodeControlViewModel)
|
||||
{
|
||||
conditionNodeControl.ViewModel.IsCustomData = pd.state;
|
||||
conditionNodeControl.ViewModel.CustomData = pd.value;
|
||||
conditionNodeControl.ViewModel.Expression = pd.expression;
|
||||
conditionNodeControlViewModel.IsCustomData = pd.state;
|
||||
conditionNodeControlViewModel.CustomData = pd.value;
|
||||
conditionNodeControlViewModel.Expression = pd.expression;
|
||||
}
|
||||
else if (control is ExpOpNodeControl expOpNodeControl)
|
||||
else if (control is ExpOpNodeControl expOpNodeControl && expOpNodeControl.ViewModel is ExpOpNodeViewModel expOpNodeViewModel)
|
||||
{
|
||||
expOpNodeControl.ViewModel.Expression = pd.expression;
|
||||
expOpNodeViewModel.Expression = pd.expression;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -529,9 +544,10 @@ namespace Serein.WorkBench
|
||||
|
||||
#region 节点控件的创建
|
||||
|
||||
private static TControl CreateNodeControl<TNode, TControl>(MethodDetails? methodDetails = null)
|
||||
private static TControl CreateNodeControl<TNode, TControl,TViewModel>(MethodDetails? methodDetails = null)
|
||||
where TNode : NodeBase
|
||||
where TControl : NodeControlBase
|
||||
where TViewModel : NodeControlViewModelBase
|
||||
{
|
||||
var nodeObj = Activator.CreateInstance(typeof(TNode));
|
||||
var nodeBase = nodeObj as NodeBase;
|
||||
@@ -551,7 +567,8 @@ namespace Serein.WorkBench
|
||||
nodeBase.MethodDetails = md;
|
||||
}
|
||||
|
||||
var controlObj = Activator.CreateInstance(typeof(TControl), [nodeObj] );
|
||||
var viewModel = Activator.CreateInstance(typeof(TViewModel), [nodeObj]);
|
||||
var controlObj = Activator.CreateInstance(typeof(TControl), [viewModel] );
|
||||
if(controlObj is TControl control)
|
||||
{
|
||||
return control;
|
||||
@@ -570,7 +587,7 @@ namespace Serein.WorkBench
|
||||
{
|
||||
var contextMenu = new ContextMenu();
|
||||
|
||||
if (nodeControl.Node?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
|
||||
if (nodeControl.ViewModel.Node?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
|
||||
{
|
||||
contextMenu.Items.Add(CreateMenuItem("查看返回类型", (s, e) =>
|
||||
{
|
||||
@@ -673,39 +690,37 @@ namespace Serein.WorkBench
|
||||
try
|
||||
{
|
||||
Assembly assembly = Assembly.LoadFrom(dllPath); // 加载DLL文件
|
||||
Type[] types = assembly.GetTypes(); // 获取程序集中的所有类型
|
||||
|
||||
List<Type> scanTypes = assembly.GetTypes().Where(t => t.GetCustomAttribute<DynamicFlowAttribute>()?.Scan == true ).ToList();
|
||||
//List<(bool, Type)> scanTypes = scanTypesTemp.Select(t => (t.GetCustomAttribute<Serein.Library.Framework.NodeFlow.Tool.DynamicFlowAttribute>()?.Scan == true, t)).ToList();
|
||||
|
||||
//bool isNetFramework = false;
|
||||
//if(scanTypes.Count == 0)
|
||||
//{
|
||||
// scanTypes = assembly.GetTypes().Where(t => t.GetCustomAttribute<Library.Framework.NodeFlow.Tool.DynamicFlowAttribute>()?.Scan == true).ToList();
|
||||
// if(scanTypes.Count == 0)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// isNetFramework = true;
|
||||
// }
|
||||
//}
|
||||
|
||||
loadedAssemblies.Add(assembly); // 将加载的程序集添加到列表中
|
||||
loadedAssemblyPaths.Add(dllPath); // 记录加载的DLL路径
|
||||
|
||||
Type[] types = assembly.GetTypes(); // 获取程序集中的所有类型
|
||||
|
||||
List<MethodDetails> conditionMethods = [];
|
||||
List<MethodDetails> actionMethods = [];
|
||||
List<MethodDetails> flipflopMethods = [];
|
||||
|
||||
/* // 遍历类型,根据接口分类
|
||||
foreach (Type type in types)
|
||||
{
|
||||
if (typeof(ICondition).IsAssignableFrom(type) && type.IsClass)
|
||||
{
|
||||
conditionTypes.Add(type); // 条件类型
|
||||
}
|
||||
if (typeof(IAction).IsAssignableFrom(type) && type.IsClass)
|
||||
{
|
||||
actionTypes.Add(type); // 动作类型
|
||||
}
|
||||
if (typeof(IState).IsAssignableFrom(type) && type.IsClass)
|
||||
{
|
||||
stateTypes.Add(type); // 状态类型
|
||||
}
|
||||
}*/
|
||||
|
||||
var scanTypes = assembly.GetTypes()
|
||||
.Where(t => t.GetCustomAttribute<DynamicFlowAttribute>()?.Scan == true).ToList();
|
||||
|
||||
foreach (var type in scanTypes)
|
||||
// foreach ((bool isNetFramework,Type type) item in scanTypes)
|
||||
foreach (var item in scanTypes)
|
||||
{
|
||||
//加载DLL
|
||||
var dict = DelegateGenerator.GenerateMethodDetails(ServiceContainer, type);
|
||||
var dict = DelegateGenerator.GenerateMethodDetails(ServiceContainer, item, false);
|
||||
|
||||
foreach (var detail in dict)
|
||||
{
|
||||
@@ -713,33 +728,22 @@ namespace Serein.WorkBench
|
||||
DllMethodDetails.TryAdd(detail.Key, detail.Value);
|
||||
|
||||
// 根据 DynamicType 分类
|
||||
switch (detail.Value.MethodDynamicType)
|
||||
switch (detail.Value.MethodDynamicType.ToString())
|
||||
{
|
||||
case DynamicNodeType.Condition:
|
||||
case nameof(Serein.Library.Enums.NodeType.Condition):
|
||||
conditionMethods.Add(detail.Value);
|
||||
break;
|
||||
case DynamicNodeType.Action:
|
||||
case nameof(Serein.Library.Enums.NodeType.Action):
|
||||
actionMethods.Add(detail.Value);
|
||||
break;
|
||||
case DynamicNodeType.Flipflop:
|
||||
case nameof(Serein.Library.Enums.NodeType.Flipflop):
|
||||
flipflopMethods.Add(detail.Value);
|
||||
break;
|
||||
//case DynamicNodeType.Init:
|
||||
// initMethods.Add(detail.Value);
|
||||
// break;
|
||||
//case DynamicNodeType.Loading:
|
||||
// loadingMethods.Add(detail.Value);
|
||||
// break;
|
||||
//case DynamicNodeType.Exit:
|
||||
// exitMethods.Add(detail.Value);
|
||||
// break;
|
||||
}
|
||||
|
||||
DictMethodDetail.TryAdd(detail.Key, detail.Value);
|
||||
// 将委托缓存到全局字典
|
||||
DelegateCache.GlobalDicDelegates.TryAdd(detail.Key, detail.Value.MethodDelegate);
|
||||
//globalDicDelegates.TryAdd(kvp.Key, kvp.Value.MethodDelegate);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,13 +945,16 @@ namespace Serein.WorkBench
|
||||
|
||||
if (nodeControl != null)
|
||||
{
|
||||
// 尝试放置节点
|
||||
// 首先判断是否为区域,如果是,则尝试将节点放置在区域中
|
||||
if (TryPlaceNodeInRegion(nodeControl, dropPosition, e))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
PlaceNodeOnCanvas(nodeControl, dropPosition);
|
||||
else
|
||||
{
|
||||
// 放置在画布上
|
||||
PlaceNodeOnCanvas(nodeControl, dropPosition);
|
||||
}
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
@@ -963,7 +970,7 @@ namespace Serein.WorkBench
|
||||
return droppedType switch
|
||||
{
|
||||
Type when typeof(ConditionRegionControl).IsAssignableFrom(droppedType)
|
||||
=> CreateNodeControl<CompositeConditionNode, ConditionRegionControl>(), // 条件区域
|
||||
=> CreateNodeControl<CompositeConditionNode, ConditionRegionControl, ConditionRegionNodeControlViewModel>(), // 条件区域
|
||||
|
||||
//Type when typeof(CompositeActionNode).IsAssignableFrom(droppedType)
|
||||
// => CreateNodeControl<CompositeActionNode,ActionRegionControl>(), // 动作区域
|
||||
@@ -982,9 +989,9 @@ namespace Serein.WorkBench
|
||||
return droppedType switch
|
||||
{
|
||||
Type when typeof(ConditionNodeControl).IsAssignableFrom(droppedType)
|
||||
=> CreateNodeControl<SingleConditionNode, ConditionNodeControl>(), // 条件控件
|
||||
=> CreateNodeControl<SingleConditionNode, ConditionNodeControl,ConditionNodeControlViewModel>(), // 条件控件
|
||||
Type when typeof(ExpOpNodeControl).IsAssignableFrom(droppedType)
|
||||
=> CreateNodeControl<SingleExpOpNode, ExpOpNodeControl>(), // 操作表达式控件
|
||||
=> CreateNodeControl<SingleExpOpNode, ExpOpNodeControl,ExpOpNodeViewModel>(), // 操作表达式控件
|
||||
_ => throw new NotImplementedException("非预期的基础节点类型"),
|
||||
};
|
||||
}
|
||||
@@ -1000,13 +1007,13 @@ namespace Serein.WorkBench
|
||||
NodeControlBase control = methodDetails.MethodDynamicType switch
|
||||
{
|
||||
//DynamicNodeType.Condition => CreateNodeControl(typeof(SingleConditionNode), methodDetails), // 单个条件控件
|
||||
DynamicNodeType.Action => CreateNodeControl<SingleActionNode, ActionNodeControl>(methodDetails),// 单个动作控件
|
||||
DynamicNodeType.Flipflop => CreateNodeControl<SingleFlipflopNode, FlipflopNodeControl>(methodDetails), // 单个动作控件
|
||||
Serein.Library.Enums.NodeType.Action => CreateNodeControl<SingleActionNode, ActionNodeControl, ActionNodeControlViewModel>(methodDetails),// 单个动作控件
|
||||
Serein.Library.Enums.NodeType.Flipflop => CreateNodeControl<SingleFlipflopNode, FlipflopNodeControl, FlipflopNodeControlViewModel>(methodDetails), // 单个动作控件
|
||||
_ => throw new NotImplementedException("非预期的Dll节点类型"),
|
||||
};
|
||||
|
||||
// 如果是触发器,则需要添加到集合中
|
||||
if (control is FlipflopNodeControl flipflopNodeControl && flipflopNodeControl.Node is SingleFlipflopNode flipflopNode)
|
||||
if (control is FlipflopNodeControl flipflopNodeControl && flipflopNodeControl.ViewModel.Node is SingleFlipflopNode flipflopNode)
|
||||
{
|
||||
var guid = flipflopNode.Guid;
|
||||
if (!flipflopNodes.Exists(it => it.Guid.Equals(guid)))
|
||||
@@ -1032,45 +1039,19 @@ namespace Serein.WorkBench
|
||||
if (hitTestResult != null && hitTestResult.VisualHit is UIElement hitElement)
|
||||
{
|
||||
var data = e.Data.GetData(MouseNodeType.BaseNodeType);
|
||||
|
||||
|
||||
if(data is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (data == typeof(ConditionNodeControl))
|
||||
{
|
||||
|
||||
ConditionRegionControl conditionRegion = GetParentOfType<ConditionRegionControl>(hitElement);
|
||||
if (conditionRegion != null)
|
||||
{
|
||||
conditionRegion.AddCondition(nodeControl);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
//if (e.Data.GetData(MouseNodeType.DllNodeType) is MethodDetails methodDetails)
|
||||
//{
|
||||
// if (methodDetails.MethodDynamicType == DynamicNodeType.Condition)
|
||||
// {
|
||||
// ConditionRegionControl conditionRegion = GetParentOfType<ConditionRegionControl>(hitElement);
|
||||
// if (conditionRegion != null)
|
||||
// {
|
||||
// conditionRegion.AddCondition(nodeControl);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// else if (methodDetails.MethodDynamicType == DynamicNodeType.Action)
|
||||
// {
|
||||
// ActionRegionControl actionRegion = GetParentOfType<ActionRegionControl>(hitElement);
|
||||
// if (actionRegion != null)
|
||||
// {
|
||||
// actionRegion.AddAction(nodeControl);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1098,7 +1079,7 @@ namespace Serein.WorkBench
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获得目标类型的父类
|
||||
/// 判断当前元素是否是泛型类型
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="element"></param>
|
||||
@@ -1120,19 +1101,7 @@ namespace Serein.WorkBench
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标左键按下事件,关闭所有连接的动画效果
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
//// 关闭所有连线的动画效果
|
||||
//foreach (var connection in connections)
|
||||
//{
|
||||
// connection.StopAnimation();
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 拖动效果,根据拖放数据是否为指定类型设置拖放效果
|
||||
@@ -1284,13 +1253,102 @@ namespace Serein.WorkBench
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 在画布中按下鼠标左键
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
|
||||
{
|
||||
IsSelectControl = true;
|
||||
|
||||
// 开始选取时,记录鼠标起始点
|
||||
startPoint = e.GetPosition(FlowChartCanvas);
|
||||
|
||||
// 初始化选取矩形的位置和大小
|
||||
Canvas.SetLeft(SelectionRectangle, startPoint.X);
|
||||
Canvas.SetTop(SelectionRectangle, startPoint.Y);
|
||||
SelectionRectangle.Width = 0;
|
||||
SelectionRectangle.Height = 0;
|
||||
|
||||
// 显示选取矩形
|
||||
SelectionRectangle.Visibility = Visibility.Visible;
|
||||
|
||||
// 捕获鼠标,以便在鼠标移动到Canvas外部时仍能处理事件
|
||||
FlowChartCanvas.CaptureMouse();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 在画布中释放鼠标按下,结束选取状态
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (IsSelectControl)
|
||||
{
|
||||
|
||||
IsSelectControl = false;
|
||||
// 释放鼠标捕获
|
||||
FlowChartCanvas.ReleaseMouseCapture();
|
||||
|
||||
// 隐藏选取矩形(如果需要保持选取状态,可以删除此行)
|
||||
SelectionRectangle.Visibility = Visibility.Collapsed;
|
||||
|
||||
// 处理选取区域内的元素(例如,获取选取范围内的控件)
|
||||
Rect selectionArea = new Rect(Canvas.GetLeft(SelectionRectangle),
|
||||
Canvas.GetTop(SelectionRectangle),
|
||||
SelectionRectangle.Width,
|
||||
SelectionRectangle.Height);
|
||||
|
||||
|
||||
selectControls.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)
|
||||
{
|
||||
selectControls.Add(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine($"一共选取了{selectControls.Count}个控件");
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 鼠标在画布移动。
|
||||
/// 选择控件状态下,调整选择框大小
|
||||
/// 连接状态下,实时更新连接线的终点位置。
|
||||
/// 移动画布状态下,移动画布。
|
||||
/// </summary>
|
||||
private void FlowChartCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (IsSelectControl && e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
// 获取当前鼠标位置
|
||||
Point currentPoint = e.GetPosition(FlowChartCanvas);
|
||||
|
||||
// 更新选取矩形的位置和大小
|
||||
double x = Math.Min(currentPoint.X, startPoint.X);
|
||||
double y = Math.Min(currentPoint.Y, startPoint.Y);
|
||||
double width = Math.Abs(currentPoint.X - startPoint.X);
|
||||
double height = Math.Abs(currentPoint.Y - startPoint.Y);
|
||||
|
||||
Canvas.SetLeft(SelectionRectangle, x);
|
||||
Canvas.SetTop(SelectionRectangle, y);
|
||||
SelectionRectangle.Width = width;
|
||||
SelectionRectangle.Height = height;
|
||||
}
|
||||
|
||||
if (IsConnecting)
|
||||
{
|
||||
Point position = e.GetPosition(FlowChartCanvas);
|
||||
@@ -1384,26 +1442,26 @@ namespace Serein.WorkBench
|
||||
|
||||
if (currentConnectionType == ConnectionType.IsSucceed)
|
||||
{
|
||||
startConnectBlock.Node.SucceedBranch.Add(targetBlock.Node);
|
||||
startConnectBlock.ViewModel.Node.SucceedBranch.Add(targetBlock.ViewModel.Node);
|
||||
}
|
||||
else if (currentConnectionType == ConnectionType.IsFail)
|
||||
{
|
||||
startConnectBlock.Node.FailBranch.Add(targetBlock.Node);
|
||||
startConnectBlock.ViewModel.Node.FailBranch.Add(targetBlock.ViewModel.Node);
|
||||
}
|
||||
else if (currentConnectionType == ConnectionType.IsError)
|
||||
{
|
||||
startConnectBlock.Node.ErrorBranch.Add(targetBlock.Node);
|
||||
startConnectBlock.ViewModel.Node.ErrorBranch.Add(targetBlock.ViewModel.Node);
|
||||
}
|
||||
else if (currentConnectionType == ConnectionType.Upstream)
|
||||
{
|
||||
startConnectBlock.Node.UpstreamBranch.Add(targetBlock.Node);
|
||||
startConnectBlock.ViewModel.Node.UpstreamBranch.Add(targetBlock.ViewModel.Node);
|
||||
}
|
||||
|
||||
// 保存连接关系
|
||||
BsControl.Draw(FlowChartCanvas, connection);
|
||||
ConfigureLineContextMenu(connection);
|
||||
|
||||
targetBlock.Node.PreviousNodes.Add(startConnectBlock.Node); // 将当前发起连接的节点,添加到被连接的节点的上一节点队列。(用于回溯)
|
||||
targetBlock.ViewModel.Node.PreviousNodes.Add(startConnectBlock.ViewModel.Node); // 将当前发起连接的节点,添加到被连接的节点的上一节点队列。(用于回溯)
|
||||
connections.Add(connection);
|
||||
}
|
||||
EndConnection();
|
||||
@@ -1461,7 +1519,7 @@ namespace Serein.WorkBench
|
||||
/// <param name="nodeControl"></param>
|
||||
private void DeleteBlock(NodeControlBase nodeControl)
|
||||
{
|
||||
if (nodeControl.Node.IsStart)
|
||||
if (nodeControl.ViewModel.Node.IsStart)
|
||||
{
|
||||
if (nodeControls.Count > 1)
|
||||
{
|
||||
@@ -1470,10 +1528,10 @@ namespace Serein.WorkBench
|
||||
}
|
||||
flowStartBlock = null;
|
||||
}
|
||||
var RemoveEonnections = connections.Where(c => c.Start.Node.Guid.Equals(nodeControl.Node.Guid)
|
||||
|| c.End.Node.Guid.Equals(nodeControl.Node.Guid)).ToList();
|
||||
var RemoveEonnections = connections.Where(c => c.Start.ViewModel.Node.Guid.Equals(nodeControl.ViewModel.Node.Guid)
|
||||
|| c.End.ViewModel.Node.Guid.Equals(nodeControl.ViewModel.Node.Guid)).ToList();
|
||||
|
||||
Remove(RemoveEonnections, nodeControl.Node);
|
||||
Remove(RemoveEonnections, nodeControl.ViewModel.Node);
|
||||
// 删除控件
|
||||
FlowChartCanvas.Children.Remove(nodeControl);
|
||||
nodeControls.Remove(nodeControl);
|
||||
@@ -1494,8 +1552,8 @@ namespace Serein.WorkBench
|
||||
var tempArr = connections.ToArray();
|
||||
foreach (var connection in tempArr)
|
||||
{
|
||||
var startNode = connection.Start.Node;
|
||||
var endNode = connection.End.Node;
|
||||
var startNode = connection.Start.ViewModel.Node;
|
||||
var endNode = connection.End.ViewModel.Node;
|
||||
bool IsStartInThisConnection = false;
|
||||
// 要删除的节点(targetNode),在连接关系中是否为起点
|
||||
// 如果是,则需要从 targetNode 中删除子节点。
|
||||
@@ -1570,19 +1628,21 @@ namespace Serein.WorkBench
|
||||
if (nodeControl == null) { return; }
|
||||
if (flowStartBlock != null)
|
||||
{
|
||||
flowStartBlock.Node.IsStart = false;
|
||||
flowStartBlock.ViewModel.Node.IsStart = false;
|
||||
flowStartBlock.BorderBrush = Brushes.Black;
|
||||
flowStartBlock.BorderThickness = new Thickness(0);
|
||||
}
|
||||
|
||||
nodeControl.Node.IsStart = true;
|
||||
nodeControl.ViewModel.Node.IsStart = true;
|
||||
nodeControl.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"));
|
||||
nodeControl.BorderThickness = new Thickness(2);
|
||||
|
||||
flowStartBlock = nodeControl;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 树形结构展开类型的成员
|
||||
/// 查看返回类型(树形结构展开类型的成员)
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
private void DisplayReturnTypeTreeViewer(Type type)
|
||||
@@ -1614,8 +1674,8 @@ namespace Serein.WorkBench
|
||||
return;
|
||||
}
|
||||
// 获取起始节点与终止节点,消除映射关系
|
||||
var StartNode = connectionToRemove.Start.Node;
|
||||
var EndNode = connectionToRemove.End.Node;
|
||||
var StartNode = connectionToRemove.Start.ViewModel.Node;
|
||||
var EndNode = connectionToRemove.End.ViewModel.Node;
|
||||
|
||||
if (connectionToRemove.Type == ConnectionType.IsSucceed)
|
||||
{
|
||||
@@ -1687,95 +1747,6 @@ namespace Serein.WorkBench
|
||||
FlowChartCanvas.Height = height;
|
||||
}
|
||||
|
||||
#region 准备弃用
|
||||
// 画布缩放时调整画布大小(已弃用)
|
||||
private void AdjustCanvasSizeToContainer()
|
||||
{
|
||||
// 获取当前缩放后的画布大小
|
||||
double newWidth = FlowChartCanvas.Width * scaleTransform.ScaleX;
|
||||
double newHeight = FlowChartCanvas.Height * scaleTransform.ScaleY;
|
||||
|
||||
// 设置画布大小,使其至少与ScrollViewer的可视区域大小相同
|
||||
FlowChartCanvas.Width = Math.Max(FlowChartStackPanel.Width, newWidth);
|
||||
FlowChartCanvas.Height = Math.Max(FlowChartStackPanel.Height, newHeight);
|
||||
}
|
||||
// 窗体尺寸发生变化时调整画布大小(已弃用)
|
||||
private void AdjustCanvasSize()
|
||||
{
|
||||
// 获取 ScrollViewer 可视区域的宽度和高度
|
||||
double scrollViewerWidth = FlowChartStackPanel.Width * scaleTransform.ScaleX;
|
||||
double scrollViewerHeight = FlowChartStackPanel.Height * scaleTransform.ScaleY;
|
||||
|
||||
// 调整 Canvas 大小
|
||||
if (scrollViewerWidth > 0 && scrollViewerHeight > 0)
|
||||
{
|
||||
FlowChartCanvas.Width = scrollViewerWidth;
|
||||
FlowChartCanvas.Height = scrollViewerHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// 随着平移拖动动态调整画布大小(弃用)
|
||||
private void AdjustCanvasSizeAndContent(double deltaX, double deltaY)
|
||||
{
|
||||
|
||||
// 获取画布的边界框
|
||||
Rect transformedBounds = FlowChartCanvas.RenderTransform.TransformBounds(new Rect(FlowChartCanvas.RenderSize));
|
||||
|
||||
|
||||
Debug.WriteLine($"deltaX : {deltaX},{deltaY}");
|
||||
Debug.WriteLine($" LTRP : {transformedBounds.Left},{transformedBounds.Top},{transformedBounds.Right},{transformedBounds.Bottom}");
|
||||
|
||||
|
||||
// 检查画布的左边缘是否超出视图
|
||||
if (deltaX > 0 && transformedBounds.Left > 0)
|
||||
{
|
||||
double offsetX = transformedBounds.Left;
|
||||
FlowChartCanvas.Width += offsetX;
|
||||
translateTransform.X -= offsetX;
|
||||
|
||||
Debug.Print($" offsetX : {offsetX}");
|
||||
// 移动所有控件的位置
|
||||
foreach (UIElement child in FlowChartCanvas.Children)
|
||||
{
|
||||
Canvas.SetLeft(child, Canvas.GetLeft(child) + offsetX);
|
||||
}
|
||||
}
|
||||
|
||||
// 检查画布的上边缘是否超出视图
|
||||
//if (transformedBounds.Top > 0)
|
||||
if (deltaY > 0 & transformedBounds.Top > 0)
|
||||
{
|
||||
double offsetY = transformedBounds.Top;
|
||||
FlowChartCanvas.Height += offsetY;
|
||||
translateTransform.Y -= offsetY;
|
||||
Debug.Print($" offsetY : {offsetY}");
|
||||
|
||||
// 移动所有控件的位置
|
||||
foreach (UIElement child in FlowChartCanvas.Children)
|
||||
{
|
||||
Canvas.SetTop(child, Canvas.GetTop(child) + offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
var size = 50;
|
||||
// 检查画布的右边缘是否超出当前宽度
|
||||
if (transformedBounds.Right + size < FlowChartStackPanel.ActualWidth)
|
||||
{
|
||||
|
||||
double extraWidth = FlowChartStackPanel.ActualWidth - transformedBounds.Right;
|
||||
this.FlowChartCanvas.Width += extraWidth;
|
||||
}
|
||||
|
||||
// 检查画布的下边缘是否超出当前高度
|
||||
if (transformedBounds.Bottom + size < FlowChartStackPanel.ActualHeight)
|
||||
{
|
||||
double extraHeight = FlowChartStackPanel.ActualHeight - transformedBounds.Bottom;
|
||||
this.FlowChartCanvas.Height += extraHeight;
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region 动态调整区域大小
|
||||
//private void Thumb_DragDelta_TopLeft(object sender, DragDeltaEventArgs e)
|
||||
@@ -1913,7 +1884,7 @@ namespace Serein.WorkBench
|
||||
private async void ButtonDebugRun_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
logWindow?.Show();
|
||||
var nodes = nodeControls.Select(it => it.Node).ToList();
|
||||
var nodes = nodeControls.Select(control => control.ViewModel.Node).ToList();
|
||||
var methodDetails = DictMethodDetail.Values.ToList();
|
||||
nodeFlowStarter ??= new NodeFlowStarter(ServiceContainer, methodDetails);
|
||||
await nodeFlowStarter.RunAsync(nodes);
|
||||
@@ -1942,19 +1913,19 @@ namespace Serein.WorkBench
|
||||
try
|
||||
{
|
||||
// 生成节点信息
|
||||
var nodeInfos = nodeControls.Select(item =>
|
||||
var nodeInfos = nodeControls.Select(control =>
|
||||
{
|
||||
var node = item.Node;
|
||||
Point positionRelativeToParent = item.TranslatePoint(new Point(0, 0), FlowChartCanvas);
|
||||
var trueNodes = item.Node.SucceedBranch.Select(item => item.Guid); // 真分支
|
||||
var falseNodes = item.Node.FailBranch.Select(item => item.Guid);// 假分支
|
||||
var upstreamNodes = item.Node.UpstreamBranch.Select(item => item.Guid);// 上游分支
|
||||
var node = control.ViewModel.Node;
|
||||
Point positionRelativeToParent = control.TranslatePoint(new Point(0, 0), FlowChartCanvas);
|
||||
var trueNodes = control.ViewModel.Node.SucceedBranch.Select(item => item.Guid); // 真分支
|
||||
var falseNodes = control.ViewModel.Node.FailBranch.Select(item => item.Guid);// 假分支
|
||||
var upstreamNodes = control.ViewModel.Node.UpstreamBranch.Select(item => item.Guid);// 上游分支
|
||||
|
||||
// 常规节点的参数信息
|
||||
List<Parameterdata> parameterData = [];
|
||||
if (node?.MethodDetails?.ExplicitDatas is not null
|
||||
&& (node.MethodDetails.MethodDynamicType == DynamicNodeType.Action
|
||||
|| node.MethodDetails.MethodDynamicType == DynamicNodeType.Flipflop))
|
||||
&& (node.MethodDetails.MethodDynamicType == Serein.Library.Enums.NodeType.Action
|
||||
|| node.MethodDetails.MethodDynamicType == Serein.Library.Enums.NodeType.Flipflop))
|
||||
{
|
||||
parameterData = node.MethodDetails
|
||||
.ExplicitDatas
|
||||
@@ -2022,7 +1993,7 @@ namespace Serein.WorkBench
|
||||
.Select(region =>
|
||||
{
|
||||
WriteLog(region.GetType().ToString() + "\r\n");
|
||||
if (region is ConditionRegionControl && region.Node is CompositeConditionNode conditionRegion) // 条件区域控件
|
||||
if (region is ConditionRegionControl && region.ViewModel.Node is CompositeConditionNode conditionRegion) // 条件区域控件
|
||||
{
|
||||
List<object> childNodes = [];
|
||||
var tmpChildNodes = conditionRegion.ConditionNodes;
|
||||
@@ -2046,11 +2017,11 @@ namespace Serein.WorkBench
|
||||
}
|
||||
return new
|
||||
{
|
||||
guid = region.Node.Guid,
|
||||
guid = region.ViewModel.Node.Guid,
|
||||
childNodes = childNodes
|
||||
};
|
||||
}
|
||||
else if (region is ActionRegionControl && region.Node is CompositeActionNode actionRegion) // 动作区域控件
|
||||
else if (region is ActionRegionControl && region.ViewModel.Node is CompositeActionNode actionRegion) // 动作区域控件
|
||||
{
|
||||
//WriteLog(region.Node.GetType().ToString() + "\r\n");
|
||||
|
||||
@@ -2076,7 +2047,7 @@ namespace Serein.WorkBench
|
||||
}
|
||||
return new
|
||||
{
|
||||
guid = region.Node.Guid,
|
||||
guid = region.ViewModel.Node.Guid,
|
||||
childNodes = childNodes
|
||||
};
|
||||
}
|
||||
@@ -2129,7 +2100,7 @@ namespace Serein.WorkBench
|
||||
["versions"] = "1",
|
||||
},
|
||||
["library"] = JArray.FromObject(dlls),
|
||||
["startNode"] = flowStartBlock == null ? "" : flowStartBlock.Node.Guid,
|
||||
["startNode"] = flowStartBlock == null ? "" : flowStartBlock.ViewModel.Node.Guid,
|
||||
["nodes"] = JArray.FromObject(nodeInfos),
|
||||
["regions"] = JArray.FromObject(regionObjs),
|
||||
};
|
||||
@@ -2245,6 +2216,8 @@ namespace Serein.WorkBench
|
||||
{
|
||||
// AdjustCanvasSize();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#region 创建两个控件之间的连接关系,在UI层面上显示为 带箭头指向的贝塞尔曲线
|
||||
|
||||
|
||||
@@ -10,16 +10,10 @@ namespace Serein.WorkBench.Node.View
|
||||
/// </summary>
|
||||
public partial class ActionNodeControl : NodeControlBase
|
||||
{
|
||||
private readonly ActionNodeControlViewModel actionNodeControlViewModel;
|
||||
public ActionNodeControl(SingleActionNode node) : base(node)
|
||||
public ActionNodeControl(ActionNodeControlViewModel viewModel):base(viewModel)
|
||||
{
|
||||
Node = node;
|
||||
actionNodeControlViewModel = new ActionNodeControlViewModel(node);
|
||||
DataContext = actionNodeControlViewModel;
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,18 +13,21 @@ namespace Serein.WorkBench.Node.View
|
||||
{
|
||||
private Point _dragStartPoint;
|
||||
|
||||
private new readonly CompositeActionNode Node;
|
||||
//private new readonly CompositeActionNode Node;
|
||||
|
||||
public ActionRegionControl() : base()
|
||||
//public override NodeControlViewModel ViewModel { get ; set ; }
|
||||
|
||||
public ActionRegionControl() : base(null)
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
public ActionRegionControl(CompositeActionNode node) : base(node)
|
||||
{
|
||||
InitializeComponent();
|
||||
Node = node;
|
||||
base.Name = "动作组合节点";
|
||||
}
|
||||
//public ActionRegionControl(CompositeActionNode node)
|
||||
//{
|
||||
// InitializeComponent();
|
||||
// //ViewModel = new NodeControlViewModel(node);
|
||||
// DataContext = ViewModel;
|
||||
// base.Name = "动作组合节点";
|
||||
//}
|
||||
|
||||
public void AddAction(NodeControlBase node, bool isTask = false)
|
||||
{
|
||||
@@ -34,8 +37,8 @@ namespace Serein.WorkBench.Node.View
|
||||
Margin = new Thickness(10, 2, 0, 0),
|
||||
Tag = node.MethodDetails,
|
||||
};*/
|
||||
Node?.AddNode((SingleActionNode)node.Node);
|
||||
ActionsListBox.Items.Add(node);
|
||||
/// Node?.AddNode((SingleActionNode)node.ViewModel.Node);
|
||||
// ActionsListBox.Items.Add(node);
|
||||
}
|
||||
|
||||
/* public async Task ExecuteActions(DynamicContext context)
|
||||
|
||||
@@ -8,24 +8,19 @@ namespace Serein.WorkBench.Node.View
|
||||
/// </summary>
|
||||
public partial class ConditionNodeControl : NodeControlBase
|
||||
{
|
||||
public ConditionNodeControlViewModel ViewModel { get; }
|
||||
|
||||
public ConditionNodeControl() : base()
|
||||
{
|
||||
|
||||
ViewModel = new (new ());
|
||||
// 窗体初始化需要
|
||||
ViewModel = new ConditionNodeControlViewModel (new SingleConditionNode());
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ConditionNodeControl(SingleConditionNode node) : base(node)
|
||||
public ConditionNodeControl(ConditionNodeControlViewModel viewModel):base(viewModel)
|
||||
{
|
||||
Node = node;
|
||||
ViewModel = new ConditionNodeControlViewModel(node);
|
||||
DataContext = ViewModel;
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,9 @@
|
||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
||||
MaxWidth="300">
|
||||
<Grid>
|
||||
|
||||
<Border BorderBrush="Black" BorderThickness="1" Padding="10">
|
||||
<StackPanel>
|
||||
<DockPanel Margin="2,2,2,5">
|
||||
<!--<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="40"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>-->
|
||||
<TextBlock Text="条件区域" FontWeight="Bold" HorizontalAlignment="Left" FontSize="14" Margin="0,1,0,0"/>
|
||||
<Button Content="编辑" FontWeight="Bold" HorizontalAlignment="Right"/>
|
||||
</DockPanel>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.WorkBench.Node.ViewModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
@@ -12,26 +13,29 @@ namespace Serein.WorkBench.Node.View
|
||||
public partial class ConditionRegionControl : NodeControlBase
|
||||
{
|
||||
private Point _dragStartPoint;
|
||||
|
||||
public ConditionRegionControl() : base()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public ConditionRegionControl(CompositeConditionNode node) : base(node)
|
||||
public ConditionRegionControl(ConditionRegionNodeControlViewModel viewModel) : base(viewModel)
|
||||
{
|
||||
Node = node;
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 添加条件控件
|
||||
/// </summary>
|
||||
/// <param name="condition"></param>
|
||||
public void AddCondition(NodeControlBase node)
|
||||
{
|
||||
((CompositeConditionNode)Node).AddNode((SingleConditionNode)node.Node);
|
||||
((CompositeConditionNode)ViewModel.Node).AddNode((SingleConditionNode)node.ViewModel.Node);
|
||||
|
||||
this.Width += node.Width;
|
||||
this.Height += node.Height;
|
||||
@@ -46,27 +50,27 @@ namespace Serein.WorkBench.Node.View
|
||||
}
|
||||
|
||||
// Mouse event handlers for dragging
|
||||
private void TypeText_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
_dragStartPoint = e.GetPosition(null);
|
||||
}
|
||||
//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;
|
||||
//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);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
|
||||
@@ -86,8 +90,7 @@ namespace Serein.WorkBench.Node.View
|
||||
DragDrop.DoDragDrop(typeText, dragData, DragDropEffects.Move);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,21 +8,17 @@ namespace Serein.WorkBench.Node.View
|
||||
/// </summary>
|
||||
public partial class ExpOpNodeControl : NodeControlBase
|
||||
{
|
||||
public ExpOpNodeViewModel ViewModel { get; }
|
||||
|
||||
public ExpOpNodeControl()
|
||||
public ExpOpNodeControl() : base()
|
||||
{
|
||||
ViewModel = new (new());
|
||||
// 窗体初始化需要
|
||||
ViewModel = new ExpOpNodeViewModel(new SingleExpOpNode());
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
public ExpOpNodeControl(SingleExpOpNode node):base(node)
|
||||
public ExpOpNodeControl(ExpOpNodeViewModel viewModel) :base(viewModel)
|
||||
{
|
||||
Node = node;
|
||||
ViewModel = new(node);
|
||||
DataContext = ViewModel;
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,31 +8,10 @@ namespace Serein.WorkBench.Node.View
|
||||
/// </summary>
|
||||
public partial class FlipflopNodeControl : NodeControlBase
|
||||
{
|
||||
private readonly FlipflopNodeControlViewModel viewModel;
|
||||
|
||||
public FlipflopNodeControl(SingleFlipflopNode node) : base(node)
|
||||
public FlipflopNodeControl(FlipflopNodeControlViewModel viewModel) : base(viewModel)
|
||||
{
|
||||
Node = node;
|
||||
viewModel = new FlipflopNodeControlViewModel(node);
|
||||
DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
|
||||
}
|
||||
|
||||
//private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
//{
|
||||
// var comboBox = sender as ComboBox;
|
||||
// if (comboBox == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// var selectedExplicitData = comboBox.DataContext as ExplicitData;
|
||||
// if (selectedExplicitData == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Console.WriteLine (selectedExplicitData.DataValue, "Selected Value");
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,27 +15,42 @@ namespace Serein.WorkBench.Node.View
|
||||
/// </summary>
|
||||
public abstract class NodeControlBase : UserControl, IDynamicFlowNode
|
||||
{
|
||||
public NodeBase Node { get; set; }
|
||||
public NodeControlViewModelBase ViewModel { get; set; }
|
||||
|
||||
|
||||
protected NodeControlBase()
|
||||
|
||||
{
|
||||
this.Background = Brushes.Transparent;
|
||||
}
|
||||
protected NodeControlBase(NodeBase node)
|
||||
protected NodeControlBase(NodeControlViewModelBase viewModelBase)
|
||||
{
|
||||
ViewModel = viewModelBase;
|
||||
this.Background = Brushes.Transparent;
|
||||
Node = node;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public abstract class NodeControlViewModel : INotifyPropertyChanged
|
||||
public abstract class NodeControlViewModelBase : INotifyPropertyChanged
|
||||
{
|
||||
public NodeControlViewModelBase(NodeBase node)
|
||||
{
|
||||
this.Node = node;
|
||||
MethodDetails = this.Node.MethodDetails;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 对应的节点实体类
|
||||
/// </summary>
|
||||
public NodeBase Node { get; set; }
|
||||
|
||||
public MethodDetails methodDetails;
|
||||
/// <summary>
|
||||
/// 表示节点控件是否被选中
|
||||
/// </summary>
|
||||
public bool IsSelect { get; set; } = false;
|
||||
|
||||
private MethodDetails methodDetails;
|
||||
|
||||
|
||||
public MethodDetails MethodDetails
|
||||
|
||||
@@ -3,26 +3,13 @@ using Serein.WorkBench.Node.View;
|
||||
|
||||
namespace Serein.WorkBench.Node.ViewModel
|
||||
{
|
||||
public class ActionNodeControlViewModel : NodeControlViewModel
|
||||
public class ActionNodeControlViewModel : NodeControlViewModelBase
|
||||
{
|
||||
private readonly SingleActionNode node;
|
||||
|
||||
public ActionNodeControlViewModel(SingleActionNode node)
|
||||
public ActionNodeControlViewModel(SingleActionNode node):base(node)
|
||||
{
|
||||
this.node = node;
|
||||
MethodDetails = node.MethodDetails;
|
||||
//if (node.MethodDetails.ExplicitDatas.Length == 0)
|
||||
//{
|
||||
// // 没有显式项
|
||||
// IsExistExplicitData = false;
|
||||
// ExplicitDatas = [];
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// explicitDatas = node.MethodDetails.ExplicitDatas;
|
||||
// //ExplicitDatas = node.MethodDetails.ExplicitDatas;
|
||||
// IsExistExplicitData = true;
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using Serein.WorkBench.Node.View;
|
||||
|
||||
namespace Serein.WorkBench.Node.ViewModel
|
||||
{
|
||||
public class ConditionNodeControlViewModel : NodeControlViewModel
|
||||
public class ConditionNodeControlViewModel : NodeControlViewModelBase
|
||||
{
|
||||
private readonly SingleConditionNode singleConditionNode;
|
||||
|
||||
@@ -32,10 +32,9 @@ namespace Serein.WorkBench.Node.ViewModel
|
||||
set { singleConditionNode.Expression = value; OnPropertyChanged(); }
|
||||
}
|
||||
|
||||
public ConditionNodeControlViewModel(SingleConditionNode node)
|
||||
public ConditionNodeControlViewModel(SingleConditionNode node) : base(node)
|
||||
{
|
||||
this.singleConditionNode = node;
|
||||
MethodDetails = node.MethodDetails;
|
||||
IsCustomData = false;
|
||||
CustomData = "";
|
||||
Expression = "PASS";
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using Serein.WorkBench.Node.View;
|
||||
|
||||
namespace Serein.WorkBench.Node.ViewModel
|
||||
{
|
||||
public class ExpOpNodeViewModel: NodeControlViewModel
|
||||
public class ExpOpNodeViewModel: NodeControlViewModelBase
|
||||
{
|
||||
public readonly SingleExpOpNode node;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Serein.WorkBench.Node.ViewModel
|
||||
}
|
||||
|
||||
|
||||
public ExpOpNodeViewModel(SingleExpOpNode node)
|
||||
public ExpOpNodeViewModel(SingleExpOpNode node) : base(node)
|
||||
{
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@@ -3,13 +3,12 @@ using Serein.WorkBench.Node.View;
|
||||
|
||||
namespace Serein.WorkBench.Node.ViewModel
|
||||
{
|
||||
public class FlipflopNodeControlViewModel : NodeControlViewModel
|
||||
public class FlipflopNodeControlViewModel : NodeControlViewModelBase
|
||||
{
|
||||
private readonly SingleFlipflopNode node;
|
||||
public FlipflopNodeControlViewModel(SingleFlipflopNode node)
|
||||
public FlipflopNodeControlViewModel(SingleFlipflopNode node) : base(node)
|
||||
{
|
||||
this.node = node;
|
||||
MethodDetails = node.MethodDetails;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--<ProjectReference Include="..\DynamicControl\DynamicControl.csproj" />-->
|
||||
|
||||
<ProjectReference Include="..\Library.Core\Serein.Library.Core.csproj" />
|
||||
<ProjectReference Include="..\Library.Framework\Serein.Library.Framework.csproj" />
|
||||
<ProjectReference Include="..\Library\Serein.Library.csproj" />
|
||||
<ProjectReference Include="..\NodeFlow\Serein.NodeFlow.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user