mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-08 08:56:35 +08:00
实现了多画布下,节点的复制粘贴功能
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Serein.Library;
|
||||
using Serein.Workbench.Customs;
|
||||
using Serein.Workbench.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
<Canvas ClipToBounds="True"
|
||||
x:Name="FlowChartCanvas"
|
||||
Background="#E1FBEA"
|
||||
Background="#FFFFFF"
|
||||
AllowDrop="True"
|
||||
Width="{Binding Model.Width, Mode=TwoWay}"
|
||||
Height="{Binding Model.Height, Mode=TwoWay}"
|
||||
|
||||
@@ -1,14 +1,21 @@
|
||||
using Serein.Library;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Env;
|
||||
using Serein.Workbench.Api;
|
||||
using Serein.Workbench.Customs;
|
||||
using Serein.Workbench.Extension;
|
||||
using Serein.Workbench.Models;
|
||||
using Serein.Workbench.Node;
|
||||
using Serein.Workbench.Node.View;
|
||||
using Serein.Workbench.Services;
|
||||
using Serein.Workbench.Themes;
|
||||
using Serein.Workbench.Tool;
|
||||
using Serein.Workbench.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Tracing;
|
||||
using System.Drawing.Printing;
|
||||
using System.Linq;
|
||||
@@ -19,13 +26,20 @@ using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Media.Media3D;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using static Serein.Workbench.MainWindow;
|
||||
using Binding = System.Windows.Data.Binding;
|
||||
using DragDropEffects = System.Windows.DragDropEffects;
|
||||
using DragEventArgs = System.Windows.DragEventArgs;
|
||||
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
|
||||
using UserControl = System.Windows.Controls.UserControl;
|
||||
using Clipboard = System.Windows.Clipboard;
|
||||
using TextDataFormat = System.Windows.TextDataFormat;
|
||||
|
||||
namespace Serein.Workbench.Views
|
||||
{
|
||||
@@ -34,9 +48,11 @@ namespace Serein.Workbench.Views
|
||||
/// </summary>
|
||||
public partial class FlowCanvasView : UserControl, IFlowCanvas
|
||||
{
|
||||
|
||||
|
||||
private readonly IFlowEnvironment flowEnvironment;
|
||||
private readonly IKeyEventService keyEventService;
|
||||
private readonly FlowNodeService flowNodeService;
|
||||
|
||||
/// <summary>
|
||||
/// 存储所有的连接。考虑集成在运行环境中。
|
||||
/// </summary>
|
||||
@@ -44,7 +60,6 @@ namespace Serein.Workbench.Views
|
||||
|
||||
private FlowCanvasViewModel ViewModel => this.DataContext as FlowCanvasViewModel ?? throw new ArgumentNullException();
|
||||
|
||||
|
||||
#region 画布接口实现
|
||||
private IFlowCanvas Api => this;
|
||||
|
||||
@@ -57,9 +72,10 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
|
||||
public string Name => ViewModel.Model.Name;
|
||||
|
||||
FlowCanvasDetails IFlowCanvas.Model => ViewModel.Model;
|
||||
void IFlowCanvas.Remove(NodeControlBase nodeControl)
|
||||
{
|
||||
ViewModel.NodeControls.Remove(nodeControl.ViewModel.NodeModel.Guid);
|
||||
FlowChartCanvas.Dispatcher.Invoke(() =>
|
||||
{
|
||||
FlowChartCanvas.Children.Remove(nodeControl);
|
||||
@@ -67,11 +83,15 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
void IFlowCanvas.Add(NodeControlBase nodeControl)
|
||||
{
|
||||
ViewModel.NodeControls.TryAdd(nodeControl.ViewModel.NodeModel.Guid, nodeControl);
|
||||
FlowChartCanvas.Dispatcher.Invoke(() =>
|
||||
{
|
||||
FlowChartCanvas.Children.Add(nodeControl);
|
||||
});
|
||||
|
||||
ConfigureNodeEvents(nodeControl); // 配置相关事件
|
||||
ConfigureContextMenu(nodeControl); // 添加右键菜单
|
||||
|
||||
}
|
||||
|
||||
void IFlowCanvas.CreateInvokeConnection(NodeControlBase fromNodeControl, NodeControlBase toNodeControl, ConnectionInvokeType type)
|
||||
@@ -224,6 +244,9 @@ namespace Serein.Workbench.Views
|
||||
/// 标记是否正在拖动画布
|
||||
/// </summary>
|
||||
private bool IsCanvasDragging;
|
||||
/// <summary>
|
||||
/// 是否正在选取控件
|
||||
/// </summary>
|
||||
private bool IsSelectDragging;
|
||||
|
||||
/// <summary>
|
||||
@@ -258,8 +281,7 @@ namespace Serein.Workbench.Views
|
||||
private readonly TranslateTransform translateTransform;
|
||||
#endregion
|
||||
|
||||
|
||||
#region 初始化
|
||||
#region 初始化以及相关事件
|
||||
|
||||
public FlowCanvasView(FlowCanvasDetails model)
|
||||
{
|
||||
@@ -270,9 +292,9 @@ namespace Serein.Workbench.Views
|
||||
|
||||
flowEnvironment = App.GetService<IFlowEnvironment>();
|
||||
flowNodeService = App.GetService<FlowNodeService>();
|
||||
|
||||
keyEventService = App.GetService<IKeyEventService>();
|
||||
flowNodeService.OnCreateNode += OnCreateNode;
|
||||
|
||||
keyEventService.OnKeyDown += KeyEventService_OnKeyDown; ;
|
||||
|
||||
// 缩放平移容器
|
||||
canvasTransformGroup = new TransformGroup();
|
||||
@@ -286,6 +308,10 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置绑定
|
||||
/// </summary>
|
||||
/// <param name="canvasModel"></param>
|
||||
private void SetBinding(FlowCanvasDetails canvasModel)
|
||||
{
|
||||
Binding bindingScaleX = new(nameof(canvasModel.ScaleX)) { Source = canvasModel, Mode = BindingMode.TwoWay };
|
||||
@@ -325,8 +351,7 @@ namespace Serein.Workbench.Views
|
||||
{
|
||||
// 并非添加在容器中,直接放置节点
|
||||
Api.Add(nodeControl); // 添加到对应的画布上
|
||||
ConfigureNodeEvents(nodeControl); // 添加了节点
|
||||
ConfigureContextMenu(nodeControl); // 添加右键菜单
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -349,7 +374,7 @@ namespace Serein.Workbench.Views
|
||||
// 准备放置条件表达式控件
|
||||
if (nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.ExpCondition)
|
||||
{
|
||||
ConditionRegionControl? conditionRegion = GetParentOfType<ConditionRegionControl>(hitElement);
|
||||
ConditionRegionControl? conditionRegion = WpfFuncTool.GetParentOfType<ConditionRegionControl>(hitElement);
|
||||
if (conditionRegion is not null)
|
||||
{
|
||||
targetNodeControl = conditionRegion;
|
||||
@@ -362,7 +387,7 @@ namespace Serein.Workbench.Views
|
||||
else
|
||||
{
|
||||
// 准备放置全局数据控件
|
||||
GlobalDataControl? globalDataControl = GetParentOfType<GlobalDataControl>(hitElement);
|
||||
GlobalDataControl? globalDataControl = WpfFuncTool.GetParentOfType<GlobalDataControl>(hitElement);
|
||||
if (globalDataControl is not null)
|
||||
{
|
||||
targetNodeControl = globalDataControl;
|
||||
@@ -376,6 +401,107 @@ namespace Serein.Workbench.Views
|
||||
|
||||
#endregion
|
||||
|
||||
#region 画布键盘操作
|
||||
/// <summary>
|
||||
/// 监听按键事件
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
private void KeyEventService_OnKeyDown(Key key)
|
||||
{
|
||||
if (!flowNodeService.CurrentSelectCanvas.Guid.Equals(Guid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == Key.Escape)
|
||||
{
|
||||
IsControlDragging = false;
|
||||
IsCanvasDragging = false;
|
||||
SelectionRectangle.Visibility = Visibility.Collapsed;
|
||||
CancelSelectNode();
|
||||
EndConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
// 复制节点
|
||||
if (selectNodeControls.Count > 0 && key == Key.C && (keyEventService.GetKeyState(Key.LeftCtrl) || keyEventService.GetKeyState(Key.RightCtrl)))
|
||||
{
|
||||
var text = flowNodeService.CpoyNodeInfo([.. selectNodeControls.Select(c => c.ViewModel.NodeModel)]);
|
||||
Clipboard.SetDataObject(text, true); // 复制,持久性设置
|
||||
return;
|
||||
}
|
||||
|
||||
// 粘贴节点
|
||||
if (key == Key.V && (keyEventService.GetKeyState(Key.LeftCtrl) || keyEventService.GetKeyState(Key.RightCtrl)))
|
||||
{
|
||||
string clipboardText = Clipboard.GetText(TextDataFormat.Text); // 获取复制的文本
|
||||
var jobject = JObject.Parse(clipboardText);
|
||||
var nodesText = jobject["nodes"]?.ToString();
|
||||
if (!string.IsNullOrWhiteSpace(nodesText))
|
||||
{
|
||||
|
||||
if (Clipboard.ContainsText())
|
||||
{
|
||||
Point mousePosition = Mouse.GetPosition(FlowChartCanvas);
|
||||
PositionOfUI positionOfUI = new PositionOfUI(mousePosition.X, mousePosition.Y); // 坐标数据
|
||||
flowNodeService.PasteNodeInfo(Guid, nodesText, positionOfUI); // 粘贴节点信息
|
||||
}
|
||||
else if (Clipboard.ContainsImage())
|
||||
{
|
||||
// var image = Clipboard.GetImage();
|
||||
}
|
||||
else
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.INFO, "剪贴板中没有可识别的数据。");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var cd = flowNodeService.ConnectingData;
|
||||
if (cd.IsCreateing)
|
||||
{
|
||||
if (cd.Type == JunctionOfConnectionType.Invoke)
|
||||
{
|
||||
ConnectionInvokeType connectionInvokeType = key switch
|
||||
{
|
||||
Key.D1 => ConnectionInvokeType.Upstream,
|
||||
Key.D2 => ConnectionInvokeType.IsSucceed,
|
||||
Key.D3 => ConnectionInvokeType.IsFail,
|
||||
Key.D4 => ConnectionInvokeType.IsError,
|
||||
_ => ConnectionInvokeType.None,
|
||||
};
|
||||
|
||||
if (connectionInvokeType != ConnectionInvokeType.None)
|
||||
{
|
||||
cd.ConnectionInvokeType = connectionInvokeType;
|
||||
cd.MyLine.Line.UpdateLineColor(connectionInvokeType.ToLineColor());
|
||||
}
|
||||
}
|
||||
else if (cd.Type == JunctionOfConnectionType.Arg)
|
||||
{
|
||||
ConnectionArgSourceType connectionArgSourceType = key switch
|
||||
{
|
||||
Key.D1 => ConnectionArgSourceType.GetOtherNodeData,
|
||||
Key.D2 => ConnectionArgSourceType.GetOtherNodeDataOfInvoke,
|
||||
_ => ConnectionArgSourceType.GetPreviousNodeData,
|
||||
};
|
||||
|
||||
if (connectionArgSourceType != ConnectionArgSourceType.GetPreviousNodeData)
|
||||
{
|
||||
cd.ConnectionArgSourceType = connectionArgSourceType;
|
||||
cd.MyLine.Line.UpdateLineColor(connectionArgSourceType.ToLineColor());
|
||||
}
|
||||
}
|
||||
cd.CurrentJunction.InvalidateVisual(); // 刷新目标节点控制点样式
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 画布鼠标操作
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标在画布移动。
|
||||
@@ -385,11 +511,11 @@ namespace Serein.Workbench.Views
|
||||
/// </summary>
|
||||
private void FlowChartCanvas_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
var myData = GlobalJunctionData.MyGlobalConnectingData;
|
||||
if (myData.IsCreateing && e.LeftButton == MouseButtonState.Pressed)
|
||||
var cd = flowNodeService.ConnectingData;
|
||||
if (cd.IsCreateing && e.LeftButton == MouseButtonState.Pressed)
|
||||
{
|
||||
|
||||
if (myData.Type == JunctionOfConnectionType.Invoke)
|
||||
if (cd.Type == JunctionOfConnectionType.Invoke)
|
||||
{
|
||||
ViewModel.IsConnectionInvokeNode = true; // 正在连接节点的调用关系
|
||||
|
||||
@@ -401,7 +527,7 @@ namespace Serein.Workbench.Views
|
||||
var currentPoint = e.GetPosition(FlowChartCanvas);
|
||||
currentPoint.X -= 2;
|
||||
currentPoint.Y -= 2;
|
||||
myData.UpdatePoint(currentPoint);
|
||||
cd.UpdatePoint(currentPoint);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -456,10 +582,10 @@ namespace Serein.Workbench.Views
|
||||
PositionOfUI position = new PositionOfUI(canvasDropPosition.X, canvasDropPosition.Y);
|
||||
if (e.Data.GetDataPresent(MouseNodeType.CreateDllNodeInCanvas))
|
||||
{
|
||||
if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeData nodeData)
|
||||
if (e.Data.GetData(MouseNodeType.CreateDllNodeInCanvas) is MoveNodeModel nodeModel)
|
||||
{
|
||||
flowNodeService.CurrentNodeControlType = nodeData.NodeControlType; // 设置基础节点类型
|
||||
flowNodeService.CurrentDragMdInfo = nodeData.MethodDetailsInfo; // 基础节点不需要参数信息
|
||||
flowNodeService.CurrentNodeControlType = nodeModel.NodeControlType; // 设置基础节点类型
|
||||
flowNodeService.CurrentDragMdInfo = nodeModel.MethodDetailsInfo; // 基础节点不需要参数信息
|
||||
flowNodeService.CurrentMouseLocation = position; // 设置当前鼠标为止
|
||||
flowNodeService.CreateNode(); // 创建来自DLL加载的方法节点
|
||||
}
|
||||
@@ -524,7 +650,8 @@ namespace Serein.Workbench.Views
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
if (GlobalJunctionData.MyGlobalConnectingData.IsCreateing)
|
||||
|
||||
if (flowNodeService.ConnectingData.IsCreateing)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -580,42 +707,42 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
|
||||
// 创建连线
|
||||
if (GlobalJunctionData.MyGlobalConnectingData is ConnectingData myData && myData.IsCreateing)
|
||||
var cd = flowNodeService.ConnectingData;
|
||||
if (cd.IsCreateing)
|
||||
{
|
||||
|
||||
if (myData.IsCanConnected)
|
||||
if (cd.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));
|
||||
var changingJunctionPosition = cd.CurrentJunction.TranslatePoint(new Point(0, 0), canvas);
|
||||
var changingJunctionRect = new Rect(changingJunctionPosition, new Size(cd.CurrentJunction.Width, cd.CurrentJunction.Height));
|
||||
|
||||
if (changingJunctionRect.Contains(currentendPoint)) // 可以创建连接
|
||||
{
|
||||
#region 方法调用关系创建
|
||||
if (myData.Type == JunctionOfConnectionType.Invoke)
|
||||
if (cd.Type == JunctionOfConnectionType.Invoke)
|
||||
{
|
||||
var canvasGuid = this.Guid;
|
||||
|
||||
await flowEnvironment.ConnectInvokeNodeAsync(
|
||||
canvasGuid,
|
||||
myData.StartJunction.MyNode.Guid,
|
||||
myData.CurrentJunction.MyNode.Guid,
|
||||
myData.StartJunction.JunctionType,
|
||||
myData.CurrentJunction.JunctionType,
|
||||
myData.ConnectionInvokeType);
|
||||
cd.StartJunction.MyNode.Guid,
|
||||
cd.CurrentJunction.MyNode.Guid,
|
||||
cd.StartJunction.JunctionType,
|
||||
cd.CurrentJunction.JunctionType,
|
||||
cd.ConnectionInvokeType);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 参数来源关系创建
|
||||
else if (myData.Type == JunctionOfConnectionType.Arg)
|
||||
else if (cd.Type == JunctionOfConnectionType.Arg)
|
||||
{
|
||||
var argIndex = 0;
|
||||
if (myData.StartJunction is ArgJunctionControl argJunction1)
|
||||
if (cd.StartJunction is ArgJunctionControl argJunction1)
|
||||
{
|
||||
argIndex = argJunction1.ArgIndex;
|
||||
}
|
||||
else if (myData.CurrentJunction is ArgJunctionControl argJunction2)
|
||||
else if (cd.CurrentJunction is ArgJunctionControl argJunction2)
|
||||
{
|
||||
argIndex = argJunction2.ArgIndex;
|
||||
}
|
||||
@@ -623,11 +750,11 @@ namespace Serein.Workbench.Views
|
||||
|
||||
await flowEnvironment.ConnectArgSourceNodeAsync(
|
||||
canvasGuid,
|
||||
myData.StartJunction.MyNode.Guid,
|
||||
myData.CurrentJunction.MyNode.Guid,
|
||||
myData.StartJunction.JunctionType,
|
||||
myData.CurrentJunction.JunctionType,
|
||||
myData.ConnectionArgSourceType,
|
||||
cd.StartJunction.MyNode.Guid,
|
||||
cd.CurrentJunction.MyNode.Guid,
|
||||
cd.StartJunction.JunctionType,
|
||||
cd.CurrentJunction.JunctionType,
|
||||
cd.ConnectionArgSourceType,
|
||||
argIndex);
|
||||
}
|
||||
#endregion
|
||||
@@ -640,7 +767,14 @@ namespace Serein.Workbench.Views
|
||||
|
||||
}
|
||||
|
||||
|
||||
#region 拖动画布实现缩放平移效果
|
||||
|
||||
/// <summary>
|
||||
/// 开始拖动画布
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
IsCanvasDragging = true;
|
||||
@@ -649,11 +783,13 @@ namespace Serein.Workbench.Views
|
||||
e.Handled = true; // 防止事件传播影响其他控件
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 停止拖动
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
|
||||
|
||||
|
||||
if (IsCanvasDragging)
|
||||
{
|
||||
IsCanvasDragging = false;
|
||||
@@ -661,7 +797,11 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
}
|
||||
|
||||
// 单纯缩放画布,不改变画布大小
|
||||
/// <summary>
|
||||
/// 单纯缩放画布,不改变画布大小
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void FlowChartCanvas_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
// if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
|
||||
@@ -820,6 +960,9 @@ namespace Serein.Workbench.Views
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region 私有方法
|
||||
|
||||
/// <summary>
|
||||
/// 完成选取操作
|
||||
@@ -887,6 +1030,27 @@ namespace Serein.Workbench.Views
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CancelSelectNode()
|
||||
{
|
||||
IsSelectControl = false;
|
||||
foreach (var nodeControl in selectNodeControls)
|
||||
{
|
||||
//nodeControl.ViewModel.IsSelect = false;
|
||||
nodeControl.BorderBrush = Brushes.Black;
|
||||
nodeControl.BorderThickness = new Thickness(0);
|
||||
|
||||
var startNodeGuid = ViewModel.Model.StartNode;
|
||||
var nodeGuid = nodeControl.ViewModel.NodeModel.Guid;
|
||||
if (startNodeGuid.Equals(nodeGuid))
|
||||
{
|
||||
nodeControl.BorderBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#04FC10"));
|
||||
nodeControl.BorderThickness = new Thickness(2);
|
||||
}
|
||||
}
|
||||
selectNodeControls.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 结束连接操作,清理状态并移除虚线。
|
||||
/// </summary>
|
||||
@@ -895,21 +1059,9 @@ namespace Serein.Workbench.Views
|
||||
Mouse.OverrideCursor = null; // 恢复视觉效果
|
||||
ViewModel.IsConnectionArgSourceNode = false;
|
||||
ViewModel.IsConnectionInvokeNode = false;
|
||||
GlobalJunctionData.OK();
|
||||
flowNodeService.ConnectingData.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建菜单子项
|
||||
/// </summary>
|
||||
/// <param name="header"></param>
|
||||
/// <param name="handler"></param>
|
||||
/// <returns></returns>
|
||||
public static MenuItem CreateMenuItem(string header, RoutedEventHandler handler)
|
||||
{
|
||||
var menuItem = new MenuItem { Header = header };
|
||||
menuItem.Click += handler;
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 选择范围配置
|
||||
@@ -918,7 +1070,7 @@ namespace Serein.Workbench.Views
|
||||
private ContextMenu ConfiguerSelectionRectangle()
|
||||
{
|
||||
var contextMenu = new ContextMenu();
|
||||
contextMenu.Items.Add(CreateMenuItem("删除", (s, e) =>
|
||||
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("删除", (s, e) =>
|
||||
{
|
||||
if (selectNodeControls.Count > 0)
|
||||
{
|
||||
@@ -938,6 +1090,10 @@ namespace Serein.Workbench.Views
|
||||
// nodeControl.ContextMenu = contextMenu;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 节点控件相关事件
|
||||
/// <summary>
|
||||
/// 配置节点事件(移动,点击相关)
|
||||
@@ -950,13 +1106,7 @@ namespace Serein.Workbench.Views
|
||||
nodeControl.MouseMove += Block_MouseMove;
|
||||
nodeControl.MouseLeftButtonUp += Block_MouseLeftButtonUp;
|
||||
|
||||
}
|
||||
private void EmptyNodeEvents(NodeControlBase nodeControl)
|
||||
{
|
||||
|
||||
nodeControl.MouseLeftButtonDown -= Block_MouseLeftButtonDown;
|
||||
nodeControl.MouseMove -= Block_MouseMove;
|
||||
nodeControl.MouseLeftButtonUp -= Block_MouseLeftButtonUp;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -972,8 +1122,8 @@ namespace Serein.Workbench.Views
|
||||
IsControlDragging = true;
|
||||
startControlDragPoint = e.GetPosition(FlowChartCanvas); // 记录鼠标按下时的位置
|
||||
((UIElement)sender).CaptureMouse(); // 捕获鼠标
|
||||
e.Handled = true; // 防止事件传播影响其他控件
|
||||
}
|
||||
e.Handled = true; // 防止事件传播影响其他控件
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -981,12 +1131,13 @@ namespace Serein.Workbench.Views
|
||||
/// </summary>
|
||||
private void Block_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
|
||||
if (IsCanvasDragging)
|
||||
return;
|
||||
if (IsSelectControl)
|
||||
return;
|
||||
|
||||
if (IsControlDragging) // 如果正在拖动控件
|
||||
if (IsControlDragging && !flowNodeService.ConnectingData.IsCreateing) // 如果正在拖动控件
|
||||
{
|
||||
Point currentPosition = e.GetPosition(FlowChartCanvas); // 获取当前鼠标位置
|
||||
|
||||
@@ -1005,21 +1156,26 @@ namespace Serein.Workbench.Views
|
||||
var newLeft = oldLeft + deltaX;
|
||||
var newTop = oldTop + deltaY;
|
||||
|
||||
this.flowEnvironment.MoveNode(Guid, nodeControlMain.ViewModel.NodeModel.Guid, newLeft, newTop); // 移动节点
|
||||
|
||||
// 计算控件实际移动的距离
|
||||
var actualDeltaX = newLeft - oldLeft;
|
||||
var actualDeltaY = newTop - oldTop;
|
||||
|
||||
// 移动其它选中的控件
|
||||
foreach (var nodeControl in selectNodeControls)
|
||||
List<(string Guid, double NewLeft, double NewTop, double MaxWidth, double MaxHeight)> moveSizes =
|
||||
selectNodeControls.Select(control =>
|
||||
(control.ViewModel.NodeModel.Guid,
|
||||
Canvas.GetLeft(control) + actualDeltaX,
|
||||
Canvas.GetTop(control) + actualDeltaY,
|
||||
control.FlowCanvas.Model.Width - control.ActualWidth - 10,
|
||||
control.FlowCanvas.Model.Height - control.ActualHeight - 10)).ToList();
|
||||
|
||||
var isNeedCancel = moveSizes.Exists(item => item.NewLeft < 5 || item.NewTop < 5|| item.NewLeft > item.MaxWidth || item.NewTop > item.MaxHeight);
|
||||
if (isNeedCancel)
|
||||
{
|
||||
if (nodeControl != nodeControlMain) // 跳过已经移动的控件
|
||||
{
|
||||
var otherNewLeft = Canvas.GetLeft(nodeControl) + actualDeltaX;
|
||||
var otherNewTop = Canvas.GetTop(nodeControl) + actualDeltaY;
|
||||
this.flowEnvironment.MoveNode(Guid, nodeControl.ViewModel.NodeModel.Guid, otherNewLeft, otherNewTop); // 移动节点
|
||||
}
|
||||
return;
|
||||
}
|
||||
foreach (var item in moveSizes)
|
||||
{
|
||||
this.flowEnvironment.MoveNode(this.Guid, item.Guid, item.NewLeft, item.NewTop); // 移动节点
|
||||
}
|
||||
|
||||
// 更新节点之间线的连接位置
|
||||
@@ -1038,6 +1194,14 @@ namespace Serein.Workbench.Views
|
||||
double deltaY = currentPosition.Y - startControlDragPoint.Y; // 计算Y轴方向的偏移量
|
||||
double newLeft = Canvas.GetLeft(nodeControl) + deltaX; // 新的左边距
|
||||
double newTop = Canvas.GetTop(nodeControl) + deltaY; // 新的上边距
|
||||
|
||||
// 如果被移动的控件接触到画布边缘,则限制移动范围
|
||||
var canvasModel = nodeControl.FlowCanvas.Model;
|
||||
var canvasWidth = canvasModel.Width - nodeControl.ActualWidth - 10;
|
||||
var canvasHeight= canvasModel.Height - nodeControl.ActualHeight - 10;
|
||||
newLeft = newLeft < 5 ? 5 : newLeft > canvasWidth ? canvasWidth : newLeft;
|
||||
newTop = newTop < 5 ? 5 : newTop > canvasHeight ? canvasHeight : newTop;
|
||||
|
||||
this.flowEnvironment.MoveNode(Guid, nodeControl.ViewModel.NodeModel.Guid, newLeft, newTop); // 移动节点
|
||||
nodeControl.UpdateLocationConnections();
|
||||
}
|
||||
@@ -1095,7 +1259,7 @@ namespace Serein.Workbench.Views
|
||||
|
||||
if (nodeControl.ViewModel?.NodeModel.ControlType == NodeControlType.Flipflop)
|
||||
{
|
||||
contextMenu.Items.Add(CreateMenuItem("启动触发器", (s, e) =>
|
||||
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("启动触发器", (s, e) =>
|
||||
{
|
||||
if (s is MenuItem menuItem)
|
||||
{
|
||||
@@ -1119,7 +1283,7 @@ namespace Serein.Workbench.Views
|
||||
|
||||
if (nodeControl.ViewModel?.NodeModel?.MethodDetails?.ReturnType is Type returnType && returnType != typeof(void))
|
||||
{
|
||||
contextMenu.Items.Add(CreateMenuItem("查看返回类型", (s, e) =>
|
||||
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("查看返回类型", (s, e) =>
|
||||
{
|
||||
DisplayReturnTypeTreeViewer(returnType);
|
||||
}));
|
||||
@@ -1127,8 +1291,8 @@ namespace Serein.Workbench.Views
|
||||
|
||||
|
||||
|
||||
contextMenu.Items.Add(CreateMenuItem("设为起点", (s, e) => flowEnvironment.SetStartNodeAsync(canvasGuid, nodeGuid)));
|
||||
contextMenu.Items.Add(CreateMenuItem("删除", async (s, e) =>
|
||||
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("设为起点", (s, e) => flowEnvironment.SetStartNodeAsync(canvasGuid, nodeGuid)));
|
||||
contextMenu.Items.Add(WpfFuncTool.CreateMenuItem("删除", async (s, e) =>
|
||||
{
|
||||
var result = await flowEnvironment.RemoveNodeAsync(canvasGuid, nodeGuid);
|
||||
}));
|
||||
@@ -1136,28 +1300,28 @@ namespace Serein.Workbench.Views
|
||||
#region 右键菜单功能 - 控件对齐
|
||||
|
||||
var AvoidMenu = new MenuItem();
|
||||
AvoidMenu.Items.Add(CreateMenuItem("群组对齐", (s, e) =>
|
||||
AvoidMenu.Items.Add(WpfFuncTool.CreateMenuItem("群组对齐", (s, e) =>
|
||||
{
|
||||
AlignControlsWithGrouping(selectNodeControls, AlignMode.Grouping);
|
||||
}));
|
||||
AvoidMenu.Items.Add(CreateMenuItem("规划对齐", (s, e) =>
|
||||
AvoidMenu.Items.Add(WpfFuncTool.CreateMenuItem("规划对齐", (s, e) =>
|
||||
{
|
||||
AlignControlsWithGrouping(selectNodeControls, AlignMode.Planning);
|
||||
}));
|
||||
AvoidMenu.Items.Add(CreateMenuItem("水平中心对齐", (s, e) =>
|
||||
AvoidMenu.Items.Add(WpfFuncTool.CreateMenuItem("水平中心对齐", (s, e) =>
|
||||
{
|
||||
AlignControlsWithGrouping(selectNodeControls, AlignMode.HorizontalCenter);
|
||||
}));
|
||||
AvoidMenu.Items.Add(CreateMenuItem("垂直中心对齐 ", (s, e) =>
|
||||
AvoidMenu.Items.Add(WpfFuncTool.CreateMenuItem("垂直中心对齐 ", (s, e) =>
|
||||
{
|
||||
AlignControlsWithGrouping(selectNodeControls, AlignMode.VerticalCenter);
|
||||
}));
|
||||
|
||||
AvoidMenu.Items.Add(CreateMenuItem("垂直对齐时水平斜分布", (s, e) =>
|
||||
AvoidMenu.Items.Add(WpfFuncTool.CreateMenuItem("垂直对齐时水平斜分布", (s, e) =>
|
||||
{
|
||||
AlignControlsWithGrouping(selectNodeControls, AlignMode.Vertical);
|
||||
}));
|
||||
AvoidMenu.Items.Add(CreateMenuItem("水平对齐时垂直斜分布", (s, e) =>
|
||||
AvoidMenu.Items.Add(WpfFuncTool.CreateMenuItem("水平对齐时垂直斜分布", (s, e) =>
|
||||
{
|
||||
AlignControlsWithGrouping(selectNodeControls, AlignMode.Horizontal);
|
||||
}));
|
||||
|
||||
@@ -56,11 +56,11 @@ AllowDrop="True"-->
|
||||
</TabControl>
|
||||
|
||||
<!-- Tab control buttons -->
|
||||
<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right">
|
||||
<!--<StackPanel Orientation="Horizontal" VerticalAlignment="Top" HorizontalAlignment="Right">
|
||||
<Button Content="添加" Command="{Binding AddTabCommand}" Margin="5" Width="80"/>
|
||||
<Button Content="移除" Command="{Binding RemoveTabCommand}" Margin="5" Width="80"/>
|
||||
<!--<Button Content="Rename Tab" Command="{Binding RenameTabCommand}" />-->
|
||||
</StackPanel>
|
||||
--><!--<Button Content="Rename Tab" Command="{Binding RenameTabCommand}" />--><!--
|
||||
</StackPanel>-->
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
|
||||
@@ -126,12 +126,11 @@ namespace Serein.Workbench.Views
|
||||
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is TabControl tabControl
|
||||
&& tabControl.SelectedIndex > 0
|
||||
&& tabControl.SelectedIndex > -1
|
||||
&& DataContext is FlowEditViewModel viewModel
|
||||
&& viewModel.CanvasTabs[tabControl.SelectedIndex] is FlowEditorTabModel tab)
|
||||
{
|
||||
|
||||
viewModel.EndEditingTab(lastTab); // 确认新名称
|
||||
viewModel.EndEditingTab(lastTab); // 取消编辑
|
||||
lastTab = tab;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,11 +9,24 @@
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance vm:FlowLibrarysViewModel}"
|
||||
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
AllowDrop="True"
|
||||
Drop="FlowLibrarysView_Drop"
|
||||
DragOver="FlowLibrarysView_DragOver" >
|
||||
|
||||
<UserControl.Resources>
|
||||
<converter:CountToVisibilityConverter x:Key="CountToVisibilityConverter"/>
|
||||
|
||||
|
||||
<!--<DataTemplate x:Key="NodeListTemplate">
|
||||
<Grid Margin="2">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding NodeType}"/>
|
||||
<TextBlock Text="{Binding AnotherName}" Margin="4,0,0,0"/>
|
||||
<TextBlock Text="{Binding MethodName}" Margin="6,0,0,0"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>-->
|
||||
</UserControl.Resources>
|
||||
|
||||
<ScrollViewer>
|
||||
@@ -31,58 +44,27 @@
|
||||
<TextBlock Text="{Binding LibraryName}" ></TextBlock>
|
||||
<TextBlock Text="{Binding FilePath}" Margin="6,0,0,0"></TextBlock>
|
||||
</StackPanel>
|
||||
|
||||
<!--<custom:FlowMethodInfoListBox Grid.Row="1" Nodes="{Binding ActionNodes}" BackgroundColor="#D0F1F9"/>
|
||||
<custom:FlowMethodInfoListBox Grid.Row="2" Nodes="{Binding FlipflopNodes}" BackgroundColor="#FACFC1"/>
|
||||
<custom:FlowMethodInfoListBox Grid.Row="3" Nodes="{Binding UINodes}" BackgroundColor="#FFFBD7"/>-->
|
||||
|
||||
<ListBox Grid.Row="1" Margin="6,2,2,2" ItemsSource="{Binding ActionNodes}"
|
||||
<custom:FlowMethodInfoListBox Grid.Row="1" ItemsSource="{Binding ActionNodes}" Background="#D0F1F9"/>
|
||||
<custom:FlowMethodInfoListBox Grid.Row="2" ItemsSource="{Binding FlipflopNodes}" Background="#FACFC1"/>
|
||||
<custom:FlowMethodInfoListBox Grid.Row="3" ItemsSource="{Binding UINodes}" Background="#FFFBD7"/>
|
||||
|
||||
<!--<ListBox Grid.Row="1" Margin="6,2,2,2" ItemsSource="{Binding ActionNodes}"
|
||||
Visibility="{Binding ActionNodes, Converter={StaticResource CountToVisibilityConverter}}"
|
||||
Background="#D0F1F9">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="2" >
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding NodeType}"></TextBlock>
|
||||
<TextBlock Text="{Binding AnotherName}" Margin="4,0,0,0"></TextBlock>
|
||||
<TextBlock Text="{Binding MethodName}" Margin="6,0,0,0"></TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
Background="#D0F1F9"
|
||||
ItemTemplate="{StaticResource NodeListTemplate}">
|
||||
</ListBox>
|
||||
|
||||
<ListBox Grid.Row="2" Margin="6,2,2,2" ItemsSource="{Binding FlipflopNodes}"
|
||||
Visibility="{Binding FlipflopNodes, Converter={StaticResource CountToVisibilityConverter}}"
|
||||
Background="#FACFC1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="2" >
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding NodeType}"></TextBlock>
|
||||
<TextBlock Text="{Binding AnotherName}" Margin="4,0,0,0"></TextBlock>
|
||||
<TextBlock Text="{Binding MethodName}" Margin="6,0,0,0"></TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
Background="#FACFC1"
|
||||
ItemTemplate="{StaticResource NodeListTemplate}">
|
||||
</ListBox>
|
||||
|
||||
<ListBox Grid.Row="3" Margin="6,2,2,2" ItemsSource="{Binding UINodes}"
|
||||
Visibility="{Binding UINodes, Converter={StaticResource CountToVisibilityConverter}}"
|
||||
Background="#FFFBD7">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="2" >
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{Binding NodeType}"></TextBlock>
|
||||
<TextBlock Text="{Binding AnotherName}" Margin="4,0,0,0"></TextBlock>
|
||||
<TextBlock Text="{Binding MethodName}" Margin="6,0,0,0"></TextBlock>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
Background="#FFFBD7"
|
||||
ItemTemplate="{StaticResource NodeListTemplate}">
|
||||
</ListBox>-->
|
||||
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
@@ -90,3 +72,9 @@
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
</UserControl>
|
||||
|
||||
|
||||
<!--<custom:FlowMethodInfoListBox Grid.Row="1" Nodes="{Binding ActionNodes}" BackgroundColor="#D0F1F9"/>
|
||||
<custom:FlowMethodInfoListBox Grid.Row="2" Nodes="{Binding FlipflopNodes}" BackgroundColor="#FACFC1"/>
|
||||
<custom:FlowMethodInfoListBox Grid.Row="3" Nodes="{Binding UINodes}" BackgroundColor="#FFFBD7"/> -->
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.Workbench.ViewModels;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
using Serein.Workbench.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -21,10 +22,32 @@ namespace Serein.Workbench.Views
|
||||
/// </summary>
|
||||
public partial class FlowLibrarysView : UserControl
|
||||
{
|
||||
private FlowLibrarysViewModel ViewModel => DataContext as FlowLibrarysViewModel ?? throw new ArgumentNullException();
|
||||
public FlowLibrarysView()
|
||||
{
|
||||
this.DataContext = App.GetService<Locator>().FlowLibrarysViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void FlowLibrarysView_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"))
|
||||
{
|
||||
ViewModel.LoadFileLibrary(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FlowLibrarysView_DragOver(object sender, DragEventArgs e)
|
||||
{
|
||||
e.Effects = DragDropEffects.Copy;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Views"
|
||||
mc:Ignorable="d"
|
||||
Loaded="Window_Loaded"
|
||||
Title="FlowWorkbenchView" Height="450" Width="800">
|
||||
Title="FlowWorkbenchView" Height="450" Width="800"
|
||||
Closing="Window_Closing">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
@@ -23,7 +24,7 @@
|
||||
<local:MainMenuBarView Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="5"/>
|
||||
|
||||
<!--左侧功能区-->
|
||||
<Grid Grid.Row="1" Grid.Column="0" >
|
||||
<Grid Grid.Row="1" Grid.Column="0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
<RowDefinition Height="*"></RowDefinition>
|
||||
@@ -31,10 +32,13 @@
|
||||
<!--<RowDefinition Height="3*"></RowDefinition>-->
|
||||
</Grid.RowDefinitions>
|
||||
<local:BaseNodesView Grid.Row="0" Grid.ColumnSpan="1" Margin="0,0,0,15"/>
|
||||
<local:FlowLibrarysView Grid.Row="1" Grid.ColumnSpan="1" Margin="0,0,0,15"/>
|
||||
<local:FlowLibrarysView Grid.Row="1" Grid.ColumnSpan="1" Margin="0,0,0,15" />
|
||||
</Grid>
|
||||
|
||||
<!--功能区和编辑区的分割线-->
|
||||
<GridSplitter Grid.Row="1" Grid.Column="1" Width="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" Background="#CCD5F0" />
|
||||
<!--流程编辑区-->
|
||||
<local:FlowEditView Grid.Row="1" Grid.Column="2"/>
|
||||
<!--编辑区和视图区的分割线-->
|
||||
<GridSplitter Grid.Row="1" Grid.Column="3" Width="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ResizeBehavior="PreviousAndNext" Background="#CCD5F0" />
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace Serein.Workbench.Views
|
||||
/// </summary>
|
||||
public partial class FlowWorkbenchView : Window
|
||||
{
|
||||
private FlowWorkbenchViewModel ViewModel => ViewModel as FlowWorkbenchViewModel;
|
||||
public FlowWorkbenchView()
|
||||
{
|
||||
this.DataContext = App.GetService<Locator>().FlowWorkbenchViewModel;
|
||||
@@ -40,5 +41,12 @@ namespace Serein.Workbench.Views
|
||||
this.Width = System.Windows.SystemParameters.PrimaryScreenWidth;
|
||||
this.Height = System.Windows.SystemParameters.PrimaryScreenHeight;*/
|
||||
}
|
||||
|
||||
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
|
||||
{
|
||||
// 确保所有窗口关闭
|
||||
LogWindow.Instance.Close();
|
||||
System.Windows.Application.Current.Shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,19 +16,22 @@
|
||||
<MenuItem Header="加载本地项目" ></MenuItem>
|
||||
<MenuItem Header="加载远程项目"></MenuItem>
|
||||
</MenuItem>
|
||||
<MenuItem Header="编辑">
|
||||
<MenuItem Header="增加画布"></MenuItem>
|
||||
<MenuItem Header="删除当前画布"></MenuItem>
|
||||
|
||||
<MenuItem Header="画布">
|
||||
<MenuItem Header="增加画布" Command="{Binding CreateFlowCanvasCommand}"></MenuItem>
|
||||
<MenuItem Header="删除当前画布" Command="{Binding RemoteFlowCanvasCommand}"></MenuItem>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem Header="调试">
|
||||
|
||||
<MenuItem Header="运行">
|
||||
<MenuItem Header="运行(仅当前画布)" Command="{Binding StartCurrentCanvasFlowCommand}"></MenuItem>
|
||||
<MenuItem Header="运行(从起始节点)"></MenuItem>
|
||||
<MenuItem Header="运行(从选定节点)" ></MenuItem>
|
||||
<MenuItem Header="运行" Command="{Binding StartFlowCommand}"></MenuItem>
|
||||
<MenuItem Header="结束流程" ></MenuItem>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem Header="视图">
|
||||
<MenuItem Header="输出窗口" ></MenuItem>
|
||||
<MenuItem Header="输出窗口" Command="{Binding OpenEnvOutWindowCommand}"></MenuItem>
|
||||
<MenuItem Header="重置画布"></MenuItem>
|
||||
<MenuItem Header="定位节点" ></MenuItem>
|
||||
</MenuItem>
|
||||
|
||||
Reference in New Issue
Block a user