@@ -21,6 +21,7 @@ using System.Windows.Interop;
using System.Windows.Media ;
using System.Windows.Media.Animation ;
using System.Windows.Shapes ;
using System.Windows.Threading ;
using DataObject = System . Windows . DataObject ;
namespace Serein.WorkBench
@@ -50,12 +51,6 @@ namespace Serein.WorkBench
/// </summary>
private readonly LogWindow logWindow ;
/// <summary>
/// 节点的命名空间
/// </summary>
public const string NodeSpaceName = $"{nameof(Serein)}.{nameof(Serein.NodeFlow)}.{nameof(Serein.NodeFlow.Model)}" ;
/// <summary>
/// 流程运行环境
/// </summary>
@@ -82,7 +77,7 @@ namespace Serein.WorkBench
/// <summary>
/// 拖动创建节点控件时的鼠标位置
/// </summary>
private Point canvasDropPosition ;
// private Point canvasDropPosition;
/// <summary>
/// 记录拖动开始时的鼠标位置
@@ -138,6 +133,7 @@ namespace Serein.WorkBench
{
ViewModel = new MainWindowViewModel ( this ) ;
FlowEnvironment = ViewModel . FlowEnvironment ;
InitFlowEvent ( ) ;
InitializeComponent ( ) ;
logWindow = new LogWindow ( ) ;
@@ -145,14 +141,23 @@ namespace Serein.WorkBench
// 重定向 Console 输出
var logTextWriter = new LogTextWriter ( WriteLog ) ;
Console . SetOut ( logTextWriter ) ;
InitFlowEvent ( ) ;
InitUI ( ) ;
var project = App . FData ;
if ( project = = null )
{
return ;
}
InitializeCanvas ( project . Basic . Canvas . Width , project . Basic . Canvas . Lenght ) ; // 设置画布大小
FlowEnvironment . LoadProject ( project , App . FileDataPath ) ; // 加载项目
}
private void InitFlowEvent ( )
{
FlowEnvironment . OnDllLoad + = FlowEnvironment_DllLoadEvent ;
FlowEnvironment. OnLoadNode + = FlowEnvironment_NodeLoadEvent ;
// FlowEnvironment. OnLoadNode += FlowEnvironment_NodeLoadEvent;
FlowEnvironment . OnProjectLoaded + = FlowEnvironment_OnProjectLoaded ;
FlowEnvironment . OnStartNodeChange + = FlowEnvironment_StartNodeChangeEvent ;
FlowEnvironment . OnNodeConnectChange + = FlowEnvironment_NodeConnectChangeEvemt ;
FlowEnvironment . OnNodeCreate + = FlowEnvironment_NodeCreateEvent ;
@@ -161,6 +166,7 @@ namespace Serein.WorkBench
}
private void InitUI ( )
{
canvasTransformGroup = new TransformGroup ( ) ;
@@ -171,22 +177,41 @@ namespace Serein.WorkBench
canvasTransformGroup . Children . Add ( translateTransform ) ;
FlowChartCanvas . RenderTransform = canvasTransformGroup ;
FlowChartCanvas . RenderTransformOrigin = new Point ( 0.5 , 0.5 ) ;
}
#region Main窗体加载方法
private void Window_Loaded ( object sender , RoutedEventArgs e )
{
}
private void Window_Closing ( object sender , System . ComponentModel . CancelEventArgs e )
{
logWindow . Close ( ) ;
System . Windows . Application . Current . Shutdown ( ) ;
}
private void Window_ContentRendered ( object sender , EventArgs e )
{
foreach ( var connection in Connections )
{
connection . Refresh ( ) ;
}
}
#endregion
public void WriteLog ( string message )
{
logWindow . AppendText ( message ) ;
}
#region 运 行 环 境 事 件
private void FlowEnvironment_OnProjectLoaded ( ProjectLoadedEventArgs eventArgs )
{
//foreach(var connection in Connections)
//{
// connection.Refresh();
//}
Console . WriteLine ( ( FlowChartStackPanel . ActualWidth , FlowChartStackPanel . ActualHeight ) ) ;
}
/// <summary>
/// 运行完成
/// </summary>
@@ -202,27 +227,30 @@ namespace Serein.WorkBench
/// </summary>
private void FlowEnvironment_DllLoadEvent ( LoadDLLEventArgs eventArgs )
{
Assembly assembly = eventArgs . Assembly ;
List < MethodDetails > methodDetailss = eventArgs . MethodDetailss ;
this . Dispatcher . Invoke ( ( ) = > {
Assembly assembly = eventArgs . Assembly ;
List < MethodDetails > methodDetailss = eventArgs . MethodDetailss ;
var dllControl = new DllControl
{
Header = "DLL name : " + assembly . GetName ( ) . Name // 设置控件标题为程序集名称
} ;
foreach ( var methodDetails in methodDetailss )
{
switch ( methodDetails . MethodDynamicType )
var dllControl = new DllControl
{
case Library . Enums . NodeType . Action :
dllControl . AddAction ( methodDetails . Clone ( ) ) ; // 添加动作类型到控件
break ;
case Library . Enums . NodeType . Flipflop :
dllControl . AddFlipflop ( methodDetails . Clone ( ) ) ; // 添加触发器方法到控件
break ;
Header = "DLL name : " + assembly . GetName ( ) . Name // 设置控件标题为程序集名称
} ;
foreach ( var methodDetails in methodDetailss )
{
switch ( methodDetails . MethodDynamicType )
{
case Library . Enums . NodeType . Action :
dllControl . AddAction ( methodDetails . Clone ( ) ) ; // 添加动作类型到控件
break ;
case Library . Enums . NodeType . Flipflop :
dllControl . AddFlipflop ( methodDetails . Clone ( ) ) ; // 添加触发器方法到控件
break ;
}
}
}
DllStackPanel . Children . Add ( dllControl ) ; // 将控件添加到界面上显示
DllStackPanel . Children . Add ( dllControl ) ; // 将控件添加到界面上显示
} ) ;
}
/// <summary>
@@ -230,34 +258,35 @@ namespace Serein.WorkBench
/// </summary>
/// <param name="nodeInfo"></param>
/// <param name="methodDetailss"></param>
private void FlowEnvironment_NodeLoadEvent( LoadNodeEventArgs eventArgs )
{
if ( ! eventArgs. IsSucceed )
{
MessageBox. Show ( eventArgs. ErrorTips) ;
return ;
}
NodeInfo nodeInfo = eventArgs . NodeInfo ;
MethodDetails methodDetailss = eventArgs . MethodDetailss ;
// private void FlowEnvironment_NodeLoadEvent( LoadNodeEventArgs eventArgs)
// {
// if (! eventArgs. IsSucceed)
// {
// MessageBox.Show( eventArgs. ErrorTips) ;
// return;
// }
// 创建对应的实例( 包含NodeModel, NodeControl, NodeControlViewModel)
NodeControlBase ? nodeControl = CreateNodeControlOfNodeInfo ( nodeInfo , m ethodDetailss) ;
if ( nodeControl = = null )
{
WriteLog ( $"无法为节点类型创建节点控件: {nodeInfo.MethodName}\r\n" ) ;
return ;
// ConfigureNodeControl(nodeInfo, nodeControl, nodeControls, regionControls);
}
// 判断是否属于区域控件,如果是,则加载区域子项
if ( nodeControl is ActionRegionControl | | nodeControl is ConditionRegionControl )
{
AddNodeControlInRegeionControl ( nodeControl , nodeInfo . ChildNodes ) ;
}
// NodeInfo nodeInfo = eventArgs.NodeInfo;
// MethodDetails methodDetailss = eventArgs.M ethodDetailss;
NodeControls . TryAdd ( nodeInfo . Guid , nodeControl ) ; // 存放对应的控件
PlaceNodeOnCanvas ( nodeControl , nodeInfo . Position . X , nodeInfo . Position . Y ) ; // 配置节点,并放置在画布上
}
// // 创建对应的实例( 包含NodeModel, NodeControl, NodeControlViewModel)
// NodeControlBase? nodeControl = CreateNodeControlOfNodeInfo(nodeInfo, methodDetailss);
// if (nodeControl == null)
// {
// WriteLog($"无法为节点类型创建节点控件: {nodeInfo.MethodName}\r\n");
// return;
// // ConfigureNodeControl(nodeInfo, nodeControl, nodeControls, regionControls);
// }
// // 判断是否属于区域控件,如果是,则加载区域子项
// // if (nodeControl is ActionRegionControl || nodeControl is ConditionRegionControl)
// // {
// // AddNodeControlInRegeionControl(nodeControl, nodeInfo.ChildNodes);
// // }
// NodeControls.TryAdd(nodeInfo.Guid, nodeControl); // 存放对应的控件
// PlaceNodeOnCanvas(nodeControl, nodeInfo.Position.X, nodeInfo.Position.Y); // 配置节点,并放置在画布上
//}
/// <summary>
/// 节点连接关系变更
@@ -267,40 +296,48 @@ namespace Serein.WorkBench
/// <param name="connectionType"></param>
private void FlowEnvironment_NodeConnectChangeEvemt ( NodeConnectChangeEventArgs eventArgs )
{
string fromNodeGuid = eventArgs . FromNodeGuid ;
string toNodeGuid = eventArgs . ToNodeGuid ;
if ( ! NodeControls . TryGetValue ( fromNodeGuid , out var fromNode ) | | ! NodeControls . TryGetValue ( toNodeGuid , out var toNode ) )
this . Dispatcher . Invoke ( ( ) = >
{
return ;
}
ConnectionType connectionType = eventArgs . ConnectionType ;
if ( eventArgs . ChangeType = = NodeConnectChangeEventArgs . ConnectChangeType . Create )
{
// 添加连接
var connection = new Connection
string fromNodeGuid = eventArgs . FromNodeGuid ;
string toNodeGuid = eventArgs . ToNodeGuid ;
if ( ! NodeControls . TryGetValue ( fromNodeGuid , out var fromNode ) | | ! NodeControls . TryGetValue ( toNodeGuid , out var toNode ) )
{
Start = fromNode ,
End = toNode ,
Type = connectionType
} ;
BsControl . Draw ( FlowChartCanvas , connection ) ; // 添加贝塞尔曲线显示
ConfigureLineContextMenu ( connection ) ; // 设置连接右键事件
Connections . Add ( connection ) ;
EndConnection ( ) ;
}
else if ( eventArgs . ChangeType = = NodeConnectChangeEventArgs . ConnectChangeType . Remote )
{
// 需要移除连接
var removeConnections = Connections . Where ( c = > c . Start . ViewModel . Node . Guid . Equals ( fromNodeGuid )
& & c . End . ViewModel . Node . Guid . Equals ( toNodeGuid ) )
. ToList ( ) ;
foreach ( var connection in removeConnections )
{
connection . RemoveFromCanvas ( FlowChartCanvas ) ;
Connections . Remove ( connection ) ;
return ;
}
}
ConnectionType connectionType = eventArgs . ConnectionType ;
if ( eventArgs . ChangeType = = NodeConnectChangeEventArgs . ConnectChangeType . Create )
{
lock ( Connections )
{
// 添加连接
var connection = new Connection
{
Start = fromNode ,
End = toNode ,
Type = connectionType
} ;
BsControl . Draw ( FlowChartCanvas , connection ) ; // 添加贝塞尔曲线显示
ConfigureLineContextMenu ( connection ) ; // 设置连接右键事件
Connections . Add ( connection ) ;
EndConnection ( ) ;
}
}
else if ( eventArgs . ChangeType = = NodeConnectChangeEventArgs . ConnectChangeType . Remote )
{
// 需要移除连接
var removeConnections = Connections . Where ( c = > c . Start . ViewModel . Node . Guid . Equals ( fromNodeGuid )
& & c . End . ViewModel . Node . Guid . Equals ( toNodeGuid ) )
. ToList ( ) ;
foreach ( var connection in removeConnections )
{
connection . RemoveFromCanvas ( FlowChartCanvas ) ;
Connections . Remove ( connection ) ;
}
}
} ) ;
}
/// <summary>
@@ -309,14 +346,16 @@ namespace Serein.WorkBench
/// <param name="eventArgs"></param>
private void FlowEnvironment_NodeRemoteEvent ( NodeRemoteEventArgs eventArgs )
{
var nodeGuid = eventArgs . NodeGuid ;
if ( ! NodeControls . TryGetValue ( nodeGuid , out var nodeControl ) )
this . Dispatcher . Invoke ( ( ) = >
{
return ;
}
FlowChartCanvas . Children . Remove ( nodeControl ) ;
NodeControls . Remove ( nodeControl . ViewModel . Node . Guid ) ;
var nodeGuid = eventArgs . NodeGuid ;
if ( ! NodeControls . TryGetValue ( nodeGuid , out var nodeControl ) )
{
return ;
}
FlowChartCanvas . Children . Remove ( nodeControl ) ;
NodeControls . Remove ( nodeControl . ViewModel . Node . Guid ) ;
} ) ;
}
/// <summary>
@@ -326,35 +365,52 @@ namespace Serein.WorkBench
/// <exception cref="NotImplementedException"></exception>
private void FlowEnvironment_NodeCreateEvent ( NodeCreateEventArgs eventArgs )
{
if ( eventArgs . NodeModel is not NodeModelBase nodeModelBase )
this . Dispatcher . Invoke ( ( ) = >
{
return ;
}
if ( eventArgs . NodeModel is not NodeModelBase nodeModelBase )
{
return ;
}
// 创建对应控件
NodeControlBase ? nodeControl = nodeModelBase . ControlType switch
{
NodeControlType . Action = > CreateNodeControl < ActionNodeControl , ActionNodeControlViewModel > ( nodeModelBase ) , //typeof(ActionNodeControl),
NodeControlType . Flipflop = > CreateNodeControl < FlipflopNodeControl , FlipflopNodeControlViewModel > ( nodeModelBase ) ,
NodeControlType . ExpCondition = > CreateNodeControl < ConditionNodeControl , ConditionNodeControlViewModel > ( nodeModelBase ) ,
NodeControlType . ExpOp = > CreateNodeControl < ExpOpNodeControl , ExpOpNodeViewModel > ( nodeModelBase ) ,
NodeControlType . ConditionRegion = > CreateNodeControl < ConditionRegionControl , ConditionRegionNodeControlViewModel > ( nodeModelBase ) ,
_ = > null ,
} ;
if ( nodeControl = = null )
{
return ;
}
// MethodDetails methodDetailss = eventArgs.MethodDetailss;
Position position = eventArgs . Position ;
NodeControls . TryAdd ( nodeModelBase . Guid , nodeControl ) ;
if ( ! TryPlaceNodeInRegion ( nodeControl ) )
{
PlaceNodeOnCanvas ( nodeControl , canvasDropPosition . X , canvasDropPosition . Y ) ;
}
// 创建对应控件
NodeControlBase ? nodeControl = nodeModelBase . ControlType switch
{
NodeControlType . Action = > CreateNodeControl < ActionNodeControl , ActionNodeControlViewModel > ( nodeModelBase ) , //typeof(ActionNodeControl),
NodeControlType . Flipflop = > CreateNodeControl < FlipflopNodeControl , FlipflopNodeControlViewModel > ( nodeModelBase ) ,
NodeControlType . ExpCondition = > CreateNodeControl < ConditionNodeControl , ConditionNodeControlViewModel > ( nodeModelBase ) ,
NodeControlType . ExpOp = > CreateNodeControl < ExpOpNodeControl , ExpOpNodeViewModel > ( nodeModelBase ) ,
NodeControlType . ConditionRegion = > CreateNodeControl < ConditionRegionControl , ConditionRegionNodeControlViewModel > ( nodeModelBase ) ,
_ = > null ,
} ;
if ( nodeControl = = null )
{
return ;
}
NodeControls . TryAdd ( nodeModelBase . Guid , nodeControl ) ;
if ( eventArgs . IsAddInRegion & & NodeControls . TryGetValue ( eventArgs . RegeionGuid , out NodeControlBase ? regionControl ) )
{
if ( regionControl is not null )
{
TryPlaceNodeInRegion ( regionControl , nodeControl ) ;
}
return ;
}
else
{
if ( ! TryPlaceNodeInRegion ( nodeControl , position ) )
{
PlaceNodeOnCanvas ( nodeControl , position . X , position . Y ) ;
}
}
} ) ;
}
@@ -365,29 +421,32 @@ namespace Serein.WorkBench
/// <param name="newNodeGuid"></param>
private void FlowEnvironment_StartNodeChangeEvent ( StartNodeChangeEventArgs eventArgs )
{
string oldNodeGuid = eventArgs . OldNodeGuid ;
string newNodeGuid = eventArgs . NewNodeGuid ;
if ( ! NodeControls . TryGetValue ( newNodeGuid , out var newStartNodeControl ) )
this . Dispatcher . Invoke ( ( ) = >
{
return ;
}
if ( newStartNodeControl = = null )
{
return ;
}
if ( ! string . IsNullOrEmpty ( oldNodeGuid ) )
{
NodeControls . TryGetValue ( oldNodeGuid , out var oldStartNodeControl ) ;
if ( oldStartNodeControl ! = null )
string oldNodeGuid = eventArgs . OldNodeGuid ;
string newNodeGuid = eventArgs . NewNodeGuid ;
if ( ! NodeControls . TryGetValue ( newNodeGuid , out var newStartNodeControl ) )
{
oldStartNodeControl . BorderBrush = Brushes . Black ;
oldStartNodeControl . BorderThickness = new Thickness ( 0 ) ;
return ;
}
if ( newStartNodeControl = = null )
{
return ;
}
if ( ! string . IsNullOrEmpty ( oldNodeGuid ) )
{
NodeControls . TryGetValue ( oldNodeGuid , out var oldStartNodeControl ) ;
if ( oldStartNodeControl ! = null )
{
oldStartNodeControl . BorderBrush = Brushes . Black ;
oldStartNodeControl . BorderThickness = new Thickness ( 0 ) ;
}
}
}
newStartNodeControl . BorderBrush = new SolidColorBrush ( ( Color ) ColorConverter . ConvertFromString ( "#04FC10" ) ) ;
newStartNodeControl . BorderThickness = new Thickness ( 2 ) ;
newStartNodeControl . BorderBrush = new SolidColorBrush ( ( Color ) ColorConverter . ConvertFromString ( "#04FC10" ) ) ;
newStartNodeControl . BorderThickness = new Thickness ( 2 ) ;
} ) ;
}
@@ -396,31 +455,7 @@ namespace Serein.WorkBench
#region 加 载 DynamicNodeFlow 文 件
private void Window_Loaded ( object sender , RoutedEventArgs e )
{
var project = App . FData ;
if ( project = = null )
{
return ;
}
InitializeCanvas ( project . Basic . canvas . width , project . Basic . canvas . lenght ) ; // 设置画布大小
FlowEnvironment . LoadProject ( project , App . FileDataPath ) ; // 加载项目
//LoadDll(project); // 加载DLL
//LoadNodeControls(project); // 加载节点
//var startNode = nodeControls.Values.FirstOrDefault(control => control.ViewModel.Node.Guid.Equals(project.StartNode));
//var startNodeGuid = nodeControls.Keys.FirstOrDefault(guid => guid.Equals(project.StartNode));
//if (!string.IsNullOrEmpty(startNodeGuid))
//{
// FlowEnvironment.SetStartNode(startNodeGuid);
//}
}
/// <summary>
/// 运行环节加载了项目文件,需要创建节点控件
/// </summary>
@@ -433,17 +468,17 @@ namespace Serein.WorkBench
// 创建控件实例
NodeControlBase nodeControl = nodeInfo . Type switch
{
$"{NodeSpaceName}.{nameof(SingleActionNode)}" = >
$"{NodeStaticConfig. NodeSpaceName}.{nameof(SingleActionNode)}" = >
CreateNodeControl < SingleActionNode , ActionNodeControl , ActionNodeControlViewModel > ( methodDetailss ) , // 动作节点控件
$"{NodeSpaceName}.{nameof(SingleFlipflopNode)}" = >
$"{NodeStaticConfig. NodeSpaceName}.{nameof(SingleFlipflopNode)}" = >
CreateNodeControl < SingleFlipflopNode , FlipflopNodeControl , FlipflopNodeControlViewModel > ( methodDetailss ) , // 触发器节点控件
$"{NodeSpaceName}.{nameof(SingleConditionNode)}" = >
$"{NodeStaticConfig. NodeSpaceName}.{nameof(SingleConditionNode)}" = >
CreateNodeControl < SingleConditionNode , ConditionNodeControl , ConditionNodeControlViewModel > ( ) , // 条件表达式控件
$"{NodeSpaceName}.{nameof(SingleExpOpNode)}" = >
$"{NodeStaticConfig. NodeSpaceName}.{nameof(SingleExpOpNode)}" = >
CreateNodeControl < SingleExpOpNode , ExpOpNodeControl , ExpOpNodeViewModel > ( ) , // 操作表达式控件
$"{NodeSpaceName}.{nameof(CompositeConditionNode)}" = >
$"{NodeStaticConfig. NodeSpaceName}.{nameof(CompositeConditionNode)}" = >
CreateNodeControl < CompositeConditionNode , ConditionRegionControl , ConditionRegionNodeControlViewModel > ( ) , // 条件区域控件
_ = > throw new NotImplementedException ( $"非预期的节点类型{nodeInfo.Type}" ) ,
} ;
@@ -755,13 +790,14 @@ namespace Serein.WorkBench
/// <param name="e"></param>
private void FlowChartCanvas_Drop ( object sender , DragEventArgs e )
{
canvasDropPosition = e . GetPosition ( FlowChartCanvas ) ; // 更新画布落点
var canvasDropPosition = e . GetPosition ( FlowChartCanvas ) ; // 更新画布落点
Position position = new Position ( canvasDropPosition . X , canvasDropPosition . Y ) ;
if ( e . Data . GetDataPresent ( MouseNodeType . CreateDllNodeInCanvas ) )
{
if ( e . Data . GetData ( MouseNodeType . CreateDllNodeInCanvas ) is MoveNodeData nodeData )
{
// 创建DLL文件的节点对象
FlowEnvironment . CreateNode ( nodeData . NodeControlType , nodeData . MethodDetails ) ;
FlowEnvironment . CreateNode ( nodeData . NodeControlType , position , nodeData . MethodDetails ) ;
}
}
else if ( e . Data . GetDataPresent ( MouseNodeType . CreateBaseNodeInCanvas ) )
@@ -778,7 +814,7 @@ namespace Serein.WorkBench
if ( nodeControlType ! = NodeControlType . None )
{
// 创建基础节点对象
FlowEnvironment . CreateNode ( nodeControlType ) ;
FlowEnvironment . CreateNode ( nodeControlType , position );
}
}
}
@@ -792,9 +828,10 @@ namespace Serein.WorkBench
/// <param name="dropPosition"></param>
/// <param name="e"></param>
/// <returns></returns>
private bool TryPlaceNodeInRegion ( NodeControlBase nodeControl )
private bool TryPlaceNodeInRegion ( NodeControlBase nodeControl , Position position )
{
HitTestResult hitTestResult = VisualTreeHelper . HitTest ( FlowChartCanvas , canvasDropP osition) ;
var point = new Point ( position . X , p osition. Y );
HitTestResult hitTestResult = VisualTreeHelper . HitTest ( FlowChartCanvas , point ) ;
if ( hitTestResult ! = null & & hitTestResult . VisualHit is UIElement hitElement )
{
// 准备放置条件表达式控件
@@ -803,10 +840,12 @@ namespace Serein.WorkBench
ConditionRegionControl conditionRegion = GetParentOfType < ConditionRegionControl > ( hitElement ) ;
if ( conditionRegion ! = null )
{
// 如果存在条件区域容器
conditionRegion . AddCondition ( nodeControl ) ;
TryPlaceNodeInRegion ( conditionRegion , nodeControl ) ;
//// 如果存在条件区域容器
//conditionRegion.AddCondition(nodeControl);
return true ;
}
}
}
return false ;
@@ -831,8 +870,26 @@ namespace Serein.WorkBench
return null ;
}
/// <summary>
/// 将节点放在目标区域中
/// </summary>
/// <param name="regionControl">区域容器</param>
/// <param name="nodeControl">节点控件</param>
private void TryPlaceNodeInRegion ( NodeControlBase regionControl , NodeControlBase nodeControl )
{
// 准备放置条件表达式控件
if ( nodeControl . ViewModel . Node . ControlType = = NodeControlType . ExpCondition )
{
ConditionRegionControl conditionRegion = regionControl as ConditionRegionControl ;
if ( conditionRegion ! = null )
{
// 如果存在条件区域容器
conditionRegion . AddCondition ( nodeControl ) ;
}
}
}
/// <summary>
/// 拖动效果,根据拖放数据是否为指定类型设置拖放效果
/// </summary>
@@ -1038,6 +1095,7 @@ namespace Serein.WorkBench
}
}
#endregion
#region 画 布 中 框 选 节 点 控 件 动 作
/// <summary>
@@ -1120,7 +1178,7 @@ namespace Serein.WorkBench
/// </summary>
private void FlowChartCanvas_MouseMove ( object sender , MouseEventArgs e )
{
if ( IsSelectControl & & e . LeftButton = = MouseButtonState . Pressed )
if ( IsSelectControl & & e . LeftButton = = MouseButtonState . Pressed ) // 正在选取节点
{
// 获取当前鼠标位置
Point currentPoint = e . GetPosition ( FlowChartCanvas ) ;
@@ -1137,7 +1195,8 @@ namespace Serein.WorkBench
SelectionRectangle . Height = height ;
}
if ( IsConnecting )
if ( IsConnecting ) // 正在连接节点
{
Point position = e . GetPosition ( FlowChartCanvas ) ;
if ( currentLine = = null | | startConnectNodeControl = = null )
@@ -1149,7 +1208,7 @@ namespace Serein.WorkBench
currentLine . X2 = position . X ;
currentLine . Y2 = position . Y ;
}
if ( IsCanvasDragging )
if ( IsCanvasDragging ) // 正在移动画布
{
Point currentMousePosition = e . GetPosition ( this ) ;
double deltaX = currentMousePosition . X - startPoint . X ;
@@ -1160,9 +1219,6 @@ namespace Serein.WorkBench
startPoint = currentMousePosition ;
// AdjustCanvasSizeAndContent(deltaX, deltaY);
foreach ( var line in Connections )
{
line . Refresh ( ) ;
@@ -1173,6 +1229,7 @@ namespace Serein.WorkBench
}
#endregion
#region 拖 动 画 布 实 现 缩 放 平 移 效 果
private void FlowChartCanvas_MouseDown ( object sender , MouseButtonEventArgs e )
{
@@ -1197,16 +1254,25 @@ namespace Serein.WorkBench
// 单纯缩放画布,不改变画布大小
private void FlowChartCanvas_MouseWheel ( object sender , MouseWheelEventArgs e )
{
//var w = (int)(FlowChartCanvas.Width * scaleTransform.ScaleX);
//var h = (int)(FlowChartCanvas.Height * scaleTransform.ScaleY);
//var TMP1 = w / FlowChartStackPanel.ActualWidth < 0.9;
//var TMP2 = h / FlowChartStackPanel.ActualHeight < 0.9;
//Console.WriteLine("w"+(w, FlowChartStackPanel.ActualWidth, TMP1));
//Console.WriteLine("h"+(h, FlowChartStackPanel.ActualHeight, TMP2));
if ( Keyboard . IsKeyDown ( Key . LeftCtrl ) | | Keyboard . IsKeyDown ( Key . RightCtrl ) )
{
if ( e . Delta < 0 & & scaleTransform . ScaleX < 0.2 ) return ;
if ( e . Delta > 0 & & scaleTransform . ScaleX > 2.0 ) return ;
if ( e . Delta > 0 & & scaleTransform . ScaleY > 1.5 ) return ;
double scale = e . Delta > 0 ? 0.1 : - 0.1 ;
scaleTransform . ScaleX + = scale ;
scaleTransform . ScaleY + = scale ;
}
}
@@ -1215,6 +1281,8 @@ namespace Serein.WorkBench
{
FlowChartCanvas . Width = width ;
FlowChartCanvas . Height = height ;
//FlowChartStackPanel.Width = width;
//FlowChartStackPanel.Height = height;
}
@@ -1258,19 +1326,49 @@ namespace Serein.WorkBench
private void Thumb_DragDelta_BottomRight ( object sender , DragDeltaEventArgs e )
{
// 从右下角调整大小
double newWidth = Math . Max ( FlowChartCanvas . ActualWidth + e . HorizontalChange * scaleTransform . ScaleX , 0 ) ;
double newHeight = Math . Max ( FlowChartCanvas . ActualHeight + e . VerticalChange * scaleTransform . ScaleY , 0 ) ;
// 获取缩放后的水平和垂直变化
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 ) ;
newWidth = newWidth < 400 ? 400 : newWidth ;
newHeight = newHeight < 400 ? 400 : newHeight ;
// 更新 Canvas 大小
FlowChartCanvas . Width = newWidth ;
FlowChartCanvas . Height = newHeight ;
// 如果宽度和高度超过400, 调整TranslateTransform以保持左上角不动
if ( newWidth > 400 & & newHeight > 400 )
{
// 计算平移的变化,保持左上角不动
double deltaX = - horizontalChange / 2 ; // 水平方向的平移
double deltaY = - verticalChange / 2 ; // 垂直方向的平移
// 调整TranslateTransform以补偿尺寸变化
translateTransform . X + = deltaX ;
translateTransform . Y + = deltaY ;
}
//// 从右下角调整大小
//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)
@@ -1285,30 +1383,113 @@ namespace Serein.WorkBench
private void Thumb_DragDelta_Right ( object sender , DragDeltaEventArgs e )
{
//从右侧调整大小
double newWidth = Math . Max ( FlowChartCanvas. ActualWidth + e . HorizontalChange * scaleTransform. ScaleX, 0 ) ;
newWidth = newWidth < 400 ? 400 : newWidth ;
// double newWidth = Math.Max( FlowChartCanvas. ActualWidth + e. HorizontalChange * scaleTransform. ScaleX, 0) ;
// newWidth = newWidth < 400 ? 400 : newWidth;
//if (newWidth > 400)
//{
// FlowChartCanvas.Width = newWidth;
// double x = e.HorizontalChange > 0 ? -0.5 : 0.5;
// double y = 0;
// double deltaX = x * scaleTransform.ScaleX;
// double deltaY = y * 0;
// Test(deltaX, deltaY);
//}
// 获取缩放后的水平和垂直变化
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);
// 更新 Canvas 大小
FlowChartCanvas . Width = newWidth ;
//FlowChartCanvas.Height = newHeight;
// 如果宽度和高度超过400, 调整TranslateTransform以保持左上角不动
if ( newWidth > 400 /*&& newHeight > 400*/ )
{
// 计算平移的变化,保持左上角不动
double deltaX = - horizontalChange / 2 ; // 水平方向的平移
//double deltaY = -verticalChange / 2; // 垂直方向的平移
// 调整TranslateTransform以补偿尺寸变化
translateTransform . X + = deltaX ;
//translateTransform.Y += deltaY;
}
}
//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 newHeight = Math . Max ( FlowChartCanvas . ActualHeight + e . VerticalChange * scaleTransform . ScaleY , 0 ) ;
newHeight = newHeight < 400 ? 400 : newHeight ;
// // 从底部调整大小
// double oldHeight = FlowChartCanvas.Height ;
//double newHeight = Math.Max(FlowChartCanvas.ActualHeight + e.VerticalChange * scaleTransform.ScaleY, 0);
////newHeight = newHeight < 400 ? 400 : newHeight;
//if(newHeight > 400)
//{
// FlowChartCanvas.Height = newHeight;
// double x = 0;
// double y = e.VerticalChange > 0 ? -0.5 : 0.5 ;
// double deltaX = x * 0;
// double deltaY = y * (scaleTransform.ScaleY);
// Test(deltaX, deltaY);
//}
// 获取缩放后的水平和垂直变化
//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 ) ;
// 更新 Canvas 大小
//FlowChartCanvas.Width = newWidth;
FlowChartCanvas . Height = newHeight ;
// 如果宽度和高度超过400, 调整TranslateTransform以保持左上角不动
if ( /*newWidth > 400 &&*/ newHeight > 400 )
{
// 计算平移的变化,保持左上角不动
//double deltaX = -horizontalChange / 2; // 水平方向的平移
double deltaY = - verticalChange / 2 ; // 垂直方向的平移
// 调整TranslateTransform以补偿尺寸变化
//translateTransform.X += deltaX;
translateTransform . Y + = deltaY ;
}
}
private void Test ( double deltaX , double deltaY )
{
translateTransform . X + = deltaX ;
translateTransform . Y + = deltaY ;
//Console.WriteLine((translateTransform.X, translateTransform.Y));
}
#endregion
#endregion
@@ -1358,7 +1539,8 @@ namespace Serein.WorkBench
/// <param name="e"></param>
private void ButtonDebugFlipflopNode_Click ( object sender , RoutedEventArgs e )
{
FlowEnvironment . Exi t( ) ; // 在运行平台上点击了退出
Console . WriteLine ( ( FlowChartStackPanel . ActualWidth , FlowChartStackPanel . ActualHeigh t) ) ;
FlowEnvironment ? . Exit ( ) ; // 在运行平台上点击了退出
}
/// <summary>
@@ -1373,26 +1555,24 @@ namespace Serein.WorkBench
var projectData = FlowEnvironment . SaveProject ( ) ;
projectData . Basic = new Basic
{
c anvas = new FlowCanvas
C anvas = new FlowCanvas
{
l enght = ( float ) FlowChartCanvas . Width ,
w idth = ( float ) FlowChartCanvas . Height ,
L enght = ( float ) FlowChartCanvas . Width ,
W idth = ( float ) FlowChartCanvas . Height ,
} ,
v ersions = "1" ,
V ersions = "1" ,
} ;
foreach ( var node in projectData . Nodes )
{
var control = new ActionNodeControl ( null ) ; // GetControl(node.Guid);
Point positionRelativeToParent = c ontrol. TranslatePoint ( new Point ( 0 , 0 ) , FlowChartCanvas ) ;
node . Position = new Position
if ( NodeC ontrols . TryGetValue ( node . Guid , out var nodeControl ) )
{
X = ( float ) positionRelativeToParent . X ,
Y = ( float ) positionRelativeToParent . Y ,
} ;
Point positionRelativeToParent = nodeControl . TranslatePoint ( new Point ( 0 , 0 ) , FlowChartCanvas ) ;
node . Position = new Position ( positionRelativeToParent . X , positionRelativeToParent . Y ) ;
}
}
var projectJsonData = JArray . FromObject ( projectData ) ;
var projectJsonData = JObject . FromObject ( projectData ) ;
var savePath = SaveContentToFile ( projectJsonData . ToString ( ) ) ;
savePath = System . IO . Path . GetDirectoryName ( savePath ) ;
@@ -1696,8 +1876,6 @@ namespace Serein.WorkBench
return Uri . UnescapeDataString ( relativeUri . ToString ( ) . Replace ( '/' , System . IO . Path . DirectorySeparatorChar ) ) ;
}
}
#region 创 建 两 个 控 件 之 间 的 连 接 关 系 , 在 UI层面上显示为 带 箭 头 指 向 的 贝 塞 尔 曲 线
@@ -1725,7 +1903,9 @@ namespace Serein.WorkBench
canvas . Children . Add ( connection . ArrowPath ) ;
}
BezierLineDrawer . UpdateBezierLine ( canvas , connection . Start , connection . End , connection . BezierPath , connection . ArrowPath ) ;
return connection ;
}
@@ -1826,7 +2006,8 @@ namespace Serein.WorkBench
public void Refresh ( )
{
BsControl. Draw ( Canvas , this ) ;
// BsControl.Draw(Canvas, this) ;
BezierLineDrawer . UpdateBezierLine ( Canvas , Start , End , BezierPath , ArrowPath ) ;
}
}
@@ -1925,6 +2106,7 @@ namespace Serein.WorkBench
arrowGeometry . Figures . Add ( arrowFigure ) ;
arrowPath . Data = arrowGeometry ;
}
// 计算终点落点位置
private static Point CalculateEndpointOutsideElement ( FrameworkElement element , Canvas canvas , Point startPoint , out Localhost localhost )