mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
设计了流程接口节点,能够切换本节点数据、目标节点数据,目前还有数据来源相关操作没有实现
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Serein.Library.Api
|
||||
@@ -11,6 +12,7 @@ namespace Serein.Library.Api
|
||||
/// </summary>
|
||||
public interface IDynamicFlowNode
|
||||
{
|
||||
Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace Serein.Library
|
||||
ParameterData = parameterData.ToArray(),
|
||||
ErrorNodes = errorNodes.ToArray(),
|
||||
Position = nodeModel.Position,
|
||||
IsProtectionParameter = nodeModel.MethodDetails.IsProtectionParameter,
|
||||
IsProtectionParameter = nodeModel.DebugSetting.IsProtectionParameter,
|
||||
IsInterrupt = nodeModel.DebugSetting.IsInterrupt,
|
||||
IsEnable = nodeModel.DebugSetting.IsEnable,
|
||||
ParentNodeGuid = nodeModel.ContainerNode?.Guid,
|
||||
@@ -139,7 +139,7 @@ namespace Serein.Library
|
||||
nodeModel.Guid = nodeInfo.Guid;
|
||||
nodeModel.Position = nodeInfo.Position ?? new PositionOfUI(0, 0);// 加载位置信息
|
||||
var md = nodeModel.MethodDetails; // 当前节点的方法说明
|
||||
nodeModel.MethodDetails.IsProtectionParameter = nodeInfo.IsProtectionParameter; // 保护参数
|
||||
nodeModel.DebugSetting.IsProtectionParameter = nodeInfo.IsProtectionParameter; // 保护参数
|
||||
nodeModel.DebugSetting.IsInterrupt = nodeInfo.IsInterrupt; // 是否中断
|
||||
nodeModel.DebugSetting.IsEnable = nodeInfo.IsEnable; // 是否使能
|
||||
nodeModel.IsPublic = nodeInfo.IsPublic; // 是否全局公开
|
||||
@@ -169,7 +169,7 @@ namespace Serein.Library
|
||||
|
||||
for (int i = 0; i < nodeInfo.ParameterData.Length; i++)
|
||||
{
|
||||
if (i >= pds.Length)
|
||||
if (i >= pds.Length && nodeModel.ControlType != NodeControlType.FlowCall)
|
||||
{
|
||||
nodeModel.Env.WriteLine(InfoType.ERROR, $"保存的参数数量大于方法此时的入参参数数量:[{nodeInfo.Guid}][{nodeInfo.MethodName}]");
|
||||
break;
|
||||
|
||||
@@ -30,12 +30,6 @@ namespace Serein.Library
|
||||
private string _assemblyName;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否保护参数
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private bool _isProtectionParameter;
|
||||
|
||||
/// <summary>
|
||||
/// 调用节点方法时需要的实例(多个相同的节点将拥有相同的类型)
|
||||
/// </summary>
|
||||
@@ -245,7 +239,6 @@ namespace Serein.Library
|
||||
ReturnType = this.ReturnType, // 拷贝
|
||||
MethodName = this.MethodName, // 拷贝
|
||||
MethodLockName = this.MethodLockName, // 拷贝
|
||||
IsProtectionParameter = this.IsProtectionParameter, // 拷贝
|
||||
ParamsArgIndex = this.ParamsArgIndex, // 拷贝
|
||||
ParameterDetailss = this.ParameterDetailss?.Select(p => p?.CloneOfModel(nodeModel)).ToArray(), // 拷贝属于节点方法的新入参描述
|
||||
};
|
||||
@@ -255,6 +248,10 @@ namespace Serein.Library
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (string.IsNullOrEmpty(this.MethodName))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
var tmp = this.MethodName.Split('.') ;
|
||||
var methodName = tmp[tmp.Length - 1];
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -22,6 +22,13 @@ namespace Serein.Library
|
||||
NodeModel = nodeModel;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 是否保护参数
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private bool _isProtectionParameter;
|
||||
|
||||
/// <summary>
|
||||
/// 对应的节点
|
||||
/// </summary>
|
||||
@@ -37,7 +44,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 是否中断节点。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true, CustomCodeAtEnd = "ChangeInterruptState(value);")] // CustomCode = "NodeModel?.Env?.SetNodeInterruptAsync(NodeModel?.Guid, value);"
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private bool _isInterrupt = false;
|
||||
|
||||
}
|
||||
@@ -66,18 +73,16 @@ namespace Serein.Library
|
||||
public Func<Task> GetInterruptTask => _getInterruptTask;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 改变中断状态
|
||||
/// </summary>
|
||||
public void ChangeInterruptState(bool state)
|
||||
|
||||
partial void OnIsInterruptChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
if (state && _getInterruptTask is null)
|
||||
if (newValue && _getInterruptTask is null)
|
||||
{
|
||||
// 设置获取中断的委托
|
||||
_getInterruptTask = () => NodeModel.Env.IOC.Get<FlowInterruptTool>().WaitTriggerAsync(NodeModel.Guid);
|
||||
|
||||
|
||||
}
|
||||
else if (!state)
|
||||
else if (!newValue)
|
||||
{
|
||||
if (_getInterruptTask is null)
|
||||
{
|
||||
@@ -90,11 +95,13 @@ namespace Serein.Library
|
||||
_cancelInterrupt.Invoke();
|
||||
_getInterruptTask = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,11 +11,13 @@ namespace Serein.Library
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 节点基类(数据)
|
||||
/// </summary>
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
public abstract partial class NodeModelBase : IDynamicFlowNode
|
||||
public abstract partial class NodeModelBase : INotifyPropertyChanged, IDynamicFlowNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点运行环境
|
||||
@@ -56,9 +58,15 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 是否公开
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true, CustomCodeAtEnd = "NodePublicStateChanged();")]
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private bool _isPublic;
|
||||
|
||||
/* /// <summary>
|
||||
/// 是否保护参数
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private bool _isProtectionParameter;*/
|
||||
|
||||
/// <summary>
|
||||
/// 附加的调试功能
|
||||
/// </summary>
|
||||
@@ -68,7 +76,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 方法描述。包含参数信息。不包含Method与委托,如若需要调用对应的方法,需要通过MethodName从环境中获取委托进行调用。
|
||||
/// </summary>
|
||||
[PropertyInfo(IsProtection = true)]
|
||||
[PropertyInfo]
|
||||
private MethodDetails _methodDetails ;
|
||||
}
|
||||
|
||||
@@ -108,7 +116,7 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 不同分支的子节点(流程调用)
|
||||
/// </summary>
|
||||
public Dictionary<ConnectionInvokeType, List<NodeModelBase>> SuccessorNodes { get; }
|
||||
public Dictionary<ConnectionInvokeType, List<NodeModelBase>> SuccessorNodes { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 该节点的容器节点
|
||||
@@ -123,10 +131,9 @@ namespace Serein.Library
|
||||
/// <summary>
|
||||
/// 节点公开状态发生改变
|
||||
/// </summary>
|
||||
private void NodePublicStateChanged()
|
||||
partial void OnIsPublicChanged(bool oldValue, bool newValue)
|
||||
{
|
||||
|
||||
if (IsPublic)
|
||||
if (newValue)
|
||||
{
|
||||
// 公开节点
|
||||
if (!CanvasDetails.PublicNodes.Contains(this))
|
||||
@@ -143,6 +150,8 @@ namespace Serein.Library
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,33 +62,37 @@ namespace Serein.Library
|
||||
{
|
||||
this.DebugSetting.CancelInterrupt?.Invoke();
|
||||
}
|
||||
this.DebugSetting.NodeModel = null;
|
||||
this.DebugSetting = null;
|
||||
if (this.MethodDetails.ParameterDetailss != null)
|
||||
|
||||
if (this.IsPublic)
|
||||
{
|
||||
foreach (var pd in this.MethodDetails.ParameterDetailss)
|
||||
{
|
||||
pd.DataValue = null;
|
||||
pd.Items = null;
|
||||
pd.NodeModel = null;
|
||||
pd.ExplicitType = null;
|
||||
pd.DataType = null;
|
||||
pd.Name = null;
|
||||
pd.ArgDataSourceNodeGuid = null;
|
||||
pd.InputType = ParameterValueInputType.Input;
|
||||
}
|
||||
this.CanvasDetails.PublicNodes.Remove(this);
|
||||
}
|
||||
|
||||
this.MethodDetails.ParameterDetailss = null;
|
||||
//this.MethodDetails.ActingInstance = null;
|
||||
this.MethodDetails.NodeModel = null;
|
||||
this.MethodDetails.ReturnType = null;
|
||||
this.MethodDetails.AssemblyName = null;
|
||||
this.MethodDetails.MethodAnotherName = null;
|
||||
this.MethodDetails.MethodLockName = null;
|
||||
this.MethodDetails.MethodName = null;
|
||||
this.MethodDetails.ActingInstanceType = null;
|
||||
this.MethodDetails = null;
|
||||
this.DebugSetting.NodeModel = null;
|
||||
this.DebugSetting = null;
|
||||
if(this.MethodDetails is not null)
|
||||
{
|
||||
if (this.MethodDetails.ParameterDetailss != null)
|
||||
{
|
||||
foreach (var pd in this.MethodDetails.ParameterDetailss)
|
||||
{
|
||||
pd.DataValue = null;
|
||||
pd.Items = null;
|
||||
pd.NodeModel = null;
|
||||
pd.ExplicitType = null;
|
||||
pd.DataType = null;
|
||||
pd.Name = null;
|
||||
pd.ArgDataSourceNodeGuid = null;
|
||||
pd.InputType = ParameterValueInputType.Input;
|
||||
}
|
||||
}
|
||||
this.MethodDetails.ParameterDetailss = null;
|
||||
this.MethodDetails.NodeModel = null;
|
||||
this.MethodDetails.ReturnType = null;
|
||||
this.MethodDetails.ActingInstanceType = null;
|
||||
this.MethodDetails = null;
|
||||
}
|
||||
|
||||
this.Position = null;
|
||||
this.DisplayName = null;
|
||||
|
||||
@@ -99,6 +103,8 @@ namespace Serein.Library
|
||||
/// 执行节点对应的方法
|
||||
/// </summary>
|
||||
/// <param name="context">流程上下文</param>
|
||||
/// <param name="token"></param>
|
||||
/// <param name="args">自定义参数</param>
|
||||
/// <returns>节点传回数据对象</returns>
|
||||
public virtual async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace Serein.Library
|
||||
//Convertor = this.Convertor,
|
||||
DataType = this.DataType,
|
||||
Name = this.Name,
|
||||
DataValue = string.IsNullOrEmpty(DataValue) ? string.Empty : DataValue,
|
||||
DataValue = this.DataValue,
|
||||
Items = this.Items?.Select(it => it).ToArray(),
|
||||
IsParams = this.IsParams,
|
||||
Description = this.Description,
|
||||
|
||||
@@ -6,7 +6,9 @@ using Serein.Library.Utils.SereinExpression;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.NodeFlow.Tool;
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Mime;
|
||||
using System.Reactive;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
@@ -57,6 +59,7 @@ namespace Serein.NodeFlow.Env
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.GlobalData, typeof(SingleGlobalDataNode)); // 全局数据节点
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.Script, typeof(SingleScriptNode)); // 脚本节点
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.NetScript, typeof(SingleNetScriptNode)); // 脚本节点
|
||||
NodeMVVMManagement.RegisterModel(NodeControlType.FlowCall, typeof(SingleFlowCallNode)); // 流程调用节点
|
||||
#endregion
|
||||
|
||||
#region 注册基本服务类
|
||||
@@ -887,11 +890,12 @@ namespace Serein.NodeFlow.Env
|
||||
#region 从NodeInfo创建NodeModel
|
||||
foreach (NodeInfo? nodeInfo in nodeInfos)
|
||||
{
|
||||
|
||||
if (!EnumHelper.TryConvertEnum<NodeControlType>(nodeInfo.Type, out var controlType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
#region 获取方法描述
|
||||
MethodDetails? methodDetails;
|
||||
if (controlType.IsBaseNode())
|
||||
|
||||
@@ -20,6 +20,10 @@ namespace Serein.NodeFlow
|
||||
/// <returns></returns>
|
||||
public static bool IsBaseNode(this NodeControlType nodeControlType)
|
||||
{
|
||||
if(nodeControlType == NodeControlType.FlowCall)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var nodeDesc = EnumHelper.GetAttribute<NodeControlType, DescriptionAttribute>(nodeControlType);
|
||||
if("base".Equals(nodeDesc?.Description, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
||||
@@ -1,23 +1,161 @@
|
||||
using Serein.Library;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Dynamic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
|
||||
namespace Serein.NodeFlow.Model
|
||||
{
|
||||
|
||||
[NodeProperty(ValuePath = NodeValuePath.Node)]
|
||||
public partial class SingleFlowCallNode
|
||||
{
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 使用目标节点的参数(如果为true,则使用目标节点的入参,如果为false,则使用节点自定义入参)
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private bool _isShareParam = true ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 流程调用节点
|
||||
/// </summary>
|
||||
public class SingleFlowCallNode : NodeModelBase
|
||||
public partial class SingleFlowCallNode : NodeModelBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 接口节点
|
||||
/// </summary>
|
||||
private NodeModelBase targetNode;
|
||||
/// <summary>
|
||||
/// 接口节点Guid
|
||||
/// </summary>
|
||||
public string? TargetNodeGuid => targetNode?.Guid;
|
||||
|
||||
|
||||
public SingleFlowCallNode(IFlowEnvironment environment) : base(environment)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重置接口节点
|
||||
/// </summary>
|
||||
public void ResetTargetNode()
|
||||
{
|
||||
if(targetNode is not null)
|
||||
{
|
||||
// 取消接口
|
||||
targetNode.PropertyChanged -= TargetNode_PropertyChanged;
|
||||
this.MethodDetails = null;
|
||||
foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes)
|
||||
{
|
||||
this.SuccessorNodes[ctType] = new List<NodeModelBase>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置接口节点(如果传入null,则视为取消设置)
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetTargetNode(NodeModelBase? value)
|
||||
{
|
||||
if( value is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.targetNode = value;
|
||||
tmpMethodDetails = targetNode.MethodDetails.CloneOfNode(this); // 从目标节点复制一份
|
||||
targetNode.PropertyChanged += TargetNode_PropertyChanged;
|
||||
this.MethodDetails = tmpMethodDetails;
|
||||
this.SuccessorNodes = targetNode.SuccessorNodes;
|
||||
}
|
||||
|
||||
private MethodDetails tmpMethodDetails;
|
||||
partial void OnIsShareParamChanged(bool value)
|
||||
{
|
||||
if (targetNode is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (value)
|
||||
{
|
||||
tmpMethodDetails = this.MethodDetails;
|
||||
this.MethodDetails = targetNode.MethodDetails;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.MethodDetails = tmpMethodDetails;
|
||||
OnPropertyChanged(nameof(MethodDetails));
|
||||
}
|
||||
}
|
||||
|
||||
/* partial void OnTargetNodeGuidChanged(string value)
|
||||
{
|
||||
var guid = value;
|
||||
if (string.IsNullOrEmpty(guid))
|
||||
{
|
||||
targetNode = null;
|
||||
return;
|
||||
}
|
||||
if (!Env.TryGetNodeModel(guid, out targetNode))
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"流程接口找不到节点{guid}");
|
||||
return;
|
||||
}
|
||||
SetTargetNode(targetNode);
|
||||
//OnIsShareParamChanged(IsShareParam); // 更新参数状态
|
||||
}*/
|
||||
|
||||
|
||||
private void TargetNode_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
// 如果不再公开
|
||||
if (sender is NodeModelBase node && !node.IsPublic)
|
||||
{
|
||||
this.SuccessorNodes = [];
|
||||
targetNode.PropertyChanged -= TargetNode_PropertyChanged;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 从节点Guid刷新实体
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool UploadTargetNode()
|
||||
{
|
||||
if (targetNode is null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(TargetNodeGuid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Env.TryGetNodeModel(TargetNodeGuid, out var targetNode) || targetNode is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.targetNode = targetNode;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 需要调用其它流程图中的某个节点
|
||||
/// </summary>
|
||||
@@ -25,9 +163,48 @@ namespace Serein.NodeFlow.Model
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
public override async Task<FlowResult> ExecutingAsync(IDynamicContext context, CancellationToken token)
|
||||
{
|
||||
await base.ExecutingAsync(context, token);
|
||||
return new FlowResult(this, context, null);
|
||||
{
|
||||
if (!UploadTargetNode())
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
return await base.ExecutingAsync(context, token);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 保存全局变量的数据
|
||||
/// </summary>
|
||||
/// <param name="nodeInfo"></param>
|
||||
/// <returns></returns>
|
||||
public override NodeInfo SaveCustomData(NodeInfo nodeInfo)
|
||||
{
|
||||
dynamic data = new ExpandoObject();
|
||||
data.TargetNodeGuid = targetNode?.Guid; // 变量名称
|
||||
data.IsShareParam = IsShareParam;
|
||||
nodeInfo.CustomData = data;
|
||||
return nodeInfo;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 加载全局变量的数据
|
||||
/// </summary>
|
||||
/// <param name="nodeInfo"></param>
|
||||
public override void LoadCustomData(NodeInfo nodeInfo)
|
||||
{
|
||||
string targetNodeGuid = nodeInfo.CustomData?.TargetNodeGuid ?? "";
|
||||
this.IsShareParam = nodeInfo.CustomData?.IsShareParam;
|
||||
if (Env.TryGetNodeModel(targetNodeGuid, out var targetNode))
|
||||
{
|
||||
this.targetNode = targetNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
SereinEnv.WriteLine(InfoType.ERROR, $"流程接口节点[{this.Guid}]无法找到对应的节点:{targetNodeGuid}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ namespace Serein.NodeFlow.Model
|
||||
/// <summary>
|
||||
/// 表达式
|
||||
/// </summary>
|
||||
[PropertyInfo(IsNotification = true, CustomCodeAtStart = "// ChangeName(value);")]
|
||||
[PropertyInfo(IsNotification = true)]
|
||||
private string _keyName;
|
||||
|
||||
}
|
||||
@@ -101,14 +101,7 @@ namespace Serein.NodeFlow.Model
|
||||
DataNode = null;
|
||||
}
|
||||
|
||||
private void ChangeName(string newName)
|
||||
{
|
||||
if(SereinEnv.GetFlowGlobalData(_keyName) == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SereinEnv.ChangeNameFlowGlobalData(_keyName, newName);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设置全局数据
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<Compile Remove="ConnectionType.cs" />
|
||||
<Compile Remove="DynamicContext.cs" />
|
||||
<Compile Remove="MethodDetails.cs" />
|
||||
<Compile Remove="Model\CompositeConditionNode.cs" />
|
||||
<Compile Remove="NodeStaticConfig.cs" />
|
||||
<Compile Remove="Tool\Attribute.cs" />
|
||||
<Compile Remove="Tool\DynamicTool.cs" />
|
||||
|
||||
@@ -166,6 +166,8 @@ namespace Serein.Library.NodeGenerator
|
||||
|
||||
var isProtection = attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsProtection), value => bool.Parse(value)); // 是否为保护字段
|
||||
|
||||
sb.AppendLine($" partial void On{propertyName}Changed({fieldType} oldValue,{fieldType} newValue);");
|
||||
sb.AppendLine($" partial void On{propertyName}Changed({fieldType} value);");
|
||||
// 生成 getter / setter
|
||||
sb.AppendLine(leadingTrivia);
|
||||
sb.AppendLine($" public {fieldType} {propertyName}");
|
||||
@@ -175,13 +177,10 @@ namespace Serein.Library.NodeGenerator
|
||||
sb.AppendLine(" {");
|
||||
sb.AppendLine($" if ({fieldName} {(isProtection ? "== default" : "!= value")})"); // 非保护的Setter
|
||||
sb.AppendLine(" {");
|
||||
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.CustomCodeAtStart), value => !string.IsNullOrEmpty(value))) // 自定义代码
|
||||
{
|
||||
var customCode = attributeInfo[nameof(PropertyInfo)][nameof(PropertyInfo.CustomCodeAtStart)] as string;
|
||||
customCode = customCode.Trim().Substring(1, customCode.Length - 2);
|
||||
sb.AddCode(5, $"{customCode} // 添加的自定义代码");
|
||||
}
|
||||
sb.AppendLine($" var __oldValue = {fieldName};");
|
||||
sb.AppendLine($" SetProperty<{fieldType}>(ref {fieldName}, value); // 通知UI属性发生改变了");
|
||||
sb.AppendLine($" On{propertyName}Changed(value);");
|
||||
sb.AppendLine($" On{propertyName}Changed(__oldValue, value);");
|
||||
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsPrint), value => bool.Parse(value))) // 是否打印
|
||||
{
|
||||
sb.AddCode(5, $"Console.WriteLine({fieldName});");
|
||||
@@ -217,14 +216,7 @@ namespace Serein.Library.NodeGenerator
|
||||
}
|
||||
|
||||
}
|
||||
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.CustomCodeAtEnd), value => !string.IsNullOrEmpty(value))) // 自定义代码
|
||||
{
|
||||
var customCode = attributeInfo[nameof(PropertyInfo)][nameof(PropertyInfo.CustomCodeAtEnd)] as string;
|
||||
customCode = customCode.Trim().Substring(1, customCode.Length - 2);
|
||||
sb.AddCode(5, $"{customCode} // 添加的自定义代码");
|
||||
}
|
||||
//sb.AppendLine($" {fieldName} = value;");
|
||||
//sb.AppendLine($" OnPropertyChanged(); // 通知UI属性发生改变了");
|
||||
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine(" }"); // 属性的结尾大括号
|
||||
@@ -253,6 +245,11 @@ namespace Serein.Library.NodeGenerator
|
||||
sb.AppendLine(" PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); ");
|
||||
sb.AppendLine(" } ");
|
||||
|
||||
sb.AppendLine(" protected void OnPropertyChanged(string propertyName) => ");
|
||||
sb.AppendLine(" PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName)); ");
|
||||
sb.AppendLine(" ");
|
||||
sb.AppendLine(" ");
|
||||
sb.AppendLine(" ");
|
||||
//sb.AppendLine(" /// <summary> ");
|
||||
//sb.AppendLine(" /// 略 ");
|
||||
//sb.AppendLine(" /// <para>此方法为自动生成</para> ");
|
||||
|
||||
30
Workbench/Converters/BoolToVisibilityConverter.cs
Normal file
30
Workbench/Converters/BoolToVisibilityConverter.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using System.Windows;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Serein.Workbench.Converters
|
||||
{
|
||||
public class BoolToVisibilityConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
Debug.WriteLine($"targetType:{targetType} value:{targetType} parameter:{parameter}");
|
||||
if (value is bool b)
|
||||
{
|
||||
return b ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
return Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value is Visibility v && v == Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Workbench/Converters/EnumToBooleanConverter.cs
Normal file
27
Workbench/Converters/EnumToBooleanConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Serein.Workbench.Converters
|
||||
{
|
||||
public class EnumToBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value == null || parameter == null)
|
||||
return false;
|
||||
|
||||
return value.ToString().Equals(parameter.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
using System.Windows;
|
||||
|
||||
namespace Serein.Workbench.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据bool类型控制可见性
|
||||
/// </summary>
|
||||
[ValueConversion(typeof(bool), typeof(Visibility))]
|
||||
public class InvertableBooleanToVisibilityConverter : IValueConverter
|
||||
{
|
||||
enum Parameters
|
||||
{
|
||||
/// <summary>
|
||||
/// True为可见,False为不可见
|
||||
/// </summary>
|
||||
Normal,
|
||||
/// <summary>
|
||||
/// False为可见,True为不可见
|
||||
/// </summary>
|
||||
Inverted
|
||||
}
|
||||
|
||||
public object Convert(object value, Type targetType,
|
||||
object parameter, CultureInfo culture)
|
||||
{
|
||||
var boolValue = (bool)value;
|
||||
var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);
|
||||
|
||||
if (direction == Parameters.Inverted)
|
||||
return !boolValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
return boolValue ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public object? ConvertBack(object value, Type targetType,
|
||||
object parameter, CultureInfo culture)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
27
Workbench/Converters/MethodDetailsSelectorConverter.cs
Normal file
27
Workbench/Converters/MethodDetailsSelectorConverter.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Serein.Workbench.Converters
|
||||
{
|
||||
public class MethodDetailsSelectorConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
bool isShareParam = (bool)values[0];
|
||||
var nodeDetails = values[1];
|
||||
var selectNodeDetails = values[2];
|
||||
|
||||
return isShareParam ? nodeDetails : selectNodeDetails;
|
||||
}
|
||||
|
||||
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
Workbench/Converters/ThumbPositionConverter.cs
Normal file
79
Workbench/Converters/ThumbPositionConverter.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace Serein.Workbench.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class RightThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is double width)
|
||||
return width - 10; // Adjust for Thumb width
|
||||
return 0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class BottomThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is double height)
|
||||
return height - 10; // Adjust for Thumb height
|
||||
return 0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class VerticalCenterThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is double height)
|
||||
return height / 2 - 5; // Centering Thumb vertically
|
||||
return 0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 画布拉动范围距离计算器
|
||||
/// </summary>
|
||||
public class HorizontalCenterThumbPositionConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
if (value is double width)
|
||||
return width / 2 - 5; // Centering Thumb horizontally
|
||||
return 0;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
26
Workbench/Converters/TypeToColorConverter.cs
Normal file
26
Workbench/Converters/TypeToColorConverter.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Serein.Library;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Serein.Workbench.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据控件类型切换颜色
|
||||
/// </summary>
|
||||
public class TypeToColorConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
// 根据 ControlType 返回颜色
|
||||
return value switch
|
||||
{
|
||||
NodeControlType.Action => Brushes.Blue,
|
||||
NodeControlType.Flipflop => Brushes.Green,
|
||||
_ => Brushes.Black,
|
||||
};
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ using System.Windows.Documents;
|
||||
using System.Threading;
|
||||
using Serein.Workbench.Services;
|
||||
using Serein.Workbench.Tool;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Serein.Workbench.Node.View
|
||||
{
|
||||
@@ -169,15 +170,24 @@ namespace Serein.Workbench.Node.View
|
||||
private readonly FlowNodeService flowNodeService;
|
||||
protected JunctionControlBase()
|
||||
{
|
||||
flowNodeService = App.GetService<FlowNodeService>();
|
||||
|
||||
|
||||
this.Width = 25;
|
||||
this.Height = 20;
|
||||
this.MouseDown += JunctionControlBase_MouseDown;
|
||||
this.MouseMove += JunctionControlBase_MouseMove;
|
||||
this.MouseLeave += JunctionControlBase_MouseLeave; ;
|
||||
this.MouseLeave += JunctionControlBase_MouseLeave;
|
||||
#if DEBUG
|
||||
|
||||
if (DesignerProperties.GetIsInDesignMode(new DependencyObject()))
|
||||
return;
|
||||
|
||||
#endif
|
||||
flowNodeService = App.GetService<FlowNodeService>();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region 控件属性,所在的节点
|
||||
public static readonly DependencyProperty NodeProperty =
|
||||
DependencyProperty.Register(nameof(MyNode), typeof(NodeModelBase), typeof(JunctionControlBase), new PropertyMetadata(default(NodeModelBase)));
|
||||
@@ -238,7 +248,11 @@ namespace Serein.Workbench.Node.View
|
||||
{
|
||||
if(_isMouseOver != value)
|
||||
{
|
||||
flowNodeService.ConnectingData.CurrentJunction = this;
|
||||
if(flowNodeService is not null)
|
||||
{
|
||||
|
||||
flowNodeService.ConnectingData.CurrentJunction = this;
|
||||
}
|
||||
_isMouseOver = value;
|
||||
InvalidateVisual();
|
||||
}
|
||||
@@ -261,6 +275,10 @@ namespace Serein.Workbench.Node.View
|
||||
/// <returns></returns>
|
||||
protected Brush GetBackgrounp()
|
||||
{
|
||||
if(flowNodeService is null)
|
||||
{
|
||||
return Brushes.Transparent;
|
||||
}
|
||||
var cd = flowNodeService.ConnectingData;
|
||||
if(!cd.IsCreateing)
|
||||
{
|
||||
|
||||
@@ -8,9 +8,6 @@ namespace Serein.Workbench.Node.View
|
||||
{
|
||||
public class ExecuteJunctionControl : JunctionControlBase
|
||||
{
|
||||
|
||||
|
||||
|
||||
public ExecuteJunctionControl()
|
||||
{
|
||||
base.JunctionType = JunctionType.Execute;
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Serein.Workbench.Node.View
|
||||
/// <summary>
|
||||
/// 节点控件基类(控件)
|
||||
/// </summary>
|
||||
public abstract class NodeControlBase : UserControl, IDynamicFlowNode
|
||||
public abstract class NodeControlBase : UserControl //, IDynamicFlowNode
|
||||
{
|
||||
/// <summary>
|
||||
/// 节点所在的画布(以后需要将画布封装出来,实现多画布的功能)
|
||||
|
||||
@@ -4,10 +4,11 @@ using System.Runtime.CompilerServices;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace Serein.Workbench.Node.ViewModel
|
||||
{
|
||||
public abstract class NodeControlViewModelBase
|
||||
public abstract partial class NodeControlViewModelBase : ObservableObject
|
||||
{
|
||||
|
||||
///// <summary>
|
||||
@@ -21,30 +22,14 @@ namespace Serein.Workbench.Node.ViewModel
|
||||
|
||||
}
|
||||
|
||||
|
||||
private bool isInterrupt;
|
||||
private bool isReadonlyOnView = true;
|
||||
|
||||
///// <summary>
|
||||
///// 控制中断状态的视觉效果
|
||||
///// </summary>
|
||||
public bool IsInterrupt
|
||||
{
|
||||
get => NodeModel.DebugSetting.IsInterrupt;
|
||||
set
|
||||
{
|
||||
NodeModel.DebugSetting.IsInterrupt = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 工作台预览基本节点时,避免其中的文本框响应拖拽事件导致卡死
|
||||
/// </summary>
|
||||
public bool IsEnabledOnView { get => isReadonlyOnView; set
|
||||
{
|
||||
OnPropertyChanged(); isReadonlyOnView = value;
|
||||
}
|
||||
}
|
||||
[ObservableProperty]
|
||||
private bool isEnabledOnView = true;
|
||||
|
||||
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||
xmlns:converters="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||
xmlns:converter="clr-namespace:Serein.Workbench.Converters"
|
||||
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||
d:DataContext="{d:DesignInstance vm:ActionNodeControlViewModel}"
|
||||
mc:Ignorable="d"
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<UserControl.Resources>
|
||||
<!--<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />-->
|
||||
<converters:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||
<converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
<!--<ResourceDictionary Source="/Serein.Workbench;Node/View/NodeExecuteJunctionControl.xaml" x:Key="NodeExecuteJunctionControl"/>-->
|
||||
|
||||
</UserControl.Resources>
|
||||
@@ -69,10 +69,13 @@
|
||||
<local:NextStepJunctionControl Grid.Column="2" MyNode="{Binding NodeModel}" x:Name="NextStepJunctionControl" HorizontalAlignment="Right" Grid.RowSpan="2"/>
|
||||
|
||||
</Grid>
|
||||
|
||||
<themes:MethodDetailsControl Grid.Row="2" x:Name="MethodDetailsControl" MethodDetails="{Binding NodeModel.MethodDetails}"/>
|
||||
<Border Grid.Row="2" x:Name="ParameterProtectionMask" Background="LightBlue" Opacity="0.5" BorderThickness="0"
|
||||
Visibility="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay,
|
||||
Converter={StaticResource InvertedBoolConverter}, ConverterParameter=Normal}" />
|
||||
|
||||
<Border Grid.Row="2" x:Name="ParameterProtectionMask" Background="#40508D" Opacity="0.5" BorderThickness="0"
|
||||
Visibility="{Binding NodeModel.DebugSetting.IsProtectionParameter, Mode=TwoWay,
|
||||
Converter={StaticResource BoolToVisibilityConverter}, ConverterParameter=Normal}" />
|
||||
|
||||
<Grid Grid.Row="3" Background="#D5F0FC" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="50"/>
|
||||
@@ -105,7 +108,7 @@
|
||||
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay}"/>
|
||||
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsProtectionParameter, Mode=TwoWay}"/>
|
||||
<TextBlock Text="参数保护"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ namespace Serein.Workbench.Node.View
|
||||
InitializeComponent();
|
||||
if(ExecuteJunctionControl.MyNode != null)
|
||||
{
|
||||
|
||||
ExecuteJunctionControl.MyNode.Guid = viewModel.NodeModel.Guid;
|
||||
ExecuteJunctionControl.MyNode.Guid = viewModel.NodeModel.Guid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,46 +37,40 @@ namespace Serein.Workbench.Node.View
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.ReturnDataJunction => this.ResultJunctionControl;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction
|
||||
{
|
||||
get
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction => GetArgJunction();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
private JunctionControlBase[] GetArgJunction()
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
|
||||
namespace Serein.Workbench.Node.View
|
||||
@@ -10,8 +11,10 @@ namespace Serein.Workbench.Node.View
|
||||
{
|
||||
public ConditionNodeControl() : base()
|
||||
{
|
||||
|
||||
// 窗体初始化需要
|
||||
base.ViewModel = new ConditionNodeControlViewModel (new SingleConditionNode(null));
|
||||
var env = App.GetService<IFlowEnvironment>();
|
||||
base.ViewModel = new ConditionNodeControlViewModel (new SingleConditionNode(env));
|
||||
base.ViewModel.IsEnabledOnView = false;
|
||||
DataContext = ViewModel;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||
d:DataContext="{d:DesignInstance vm:ExpOpNodeViewModel}"
|
||||
d:DataContext="{d:DesignInstance vm:ExpOpNodeControlViewModel}"
|
||||
mc:Ignorable="d"
|
||||
MaxWidth="300">
|
||||
<Grid>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
|
||||
namespace Serein.Workbench.Node.View
|
||||
@@ -11,7 +12,8 @@ namespace Serein.Workbench.Node.View
|
||||
public ExpOpNodeControl() : base()
|
||||
{
|
||||
// 窗体初始化需要
|
||||
ViewModel = new ExpOpNodeControlViewModel(new SingleExpOpNode(null));
|
||||
var env = App.GetService<IFlowEnvironment>();
|
||||
ViewModel = new ExpOpNodeControlViewModel(new SingleExpOpNode(env));
|
||||
base.ViewModel.IsEnabledOnView = false;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:Converters="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||
xmlns:converter="clr-namespace:Serein.Workbench.Converters"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||
@@ -14,12 +14,10 @@
|
||||
<UserControl.Resources>
|
||||
<vm:TypeToStringConverter x:Key="TypeToStringConverter"/>
|
||||
<!--<themes:ConditionControl x:Key="ConditionControl"/>-->
|
||||
<Converters:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||
<converter:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Border BorderBrush="#FCB334" BorderThickness="1">
|
||||
|
||||
|
||||
<Grid>
|
||||
<Grid.ToolTip>
|
||||
<ToolTip Background="LightYellow" Foreground="#071042" Content="{Binding NodeModel.MethodDetails, UpdateSourceTrigger=PropertyChanged}" />
|
||||
@@ -53,17 +51,11 @@
|
||||
|
||||
</Grid>
|
||||
|
||||
<!--<StackPanel Grid.Row="0" Orientation="Horizontal" Background="#FCB334">
|
||||
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsEnable, Mode=TwoWay}" VerticalContentAlignment="Center"/>
|
||||
<CheckBox IsChecked="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay}" VerticalContentAlignment="Center"/>
|
||||
|
||||
<TextBlock Text="{Binding NodeModel.MethodDetails.MethodTips, UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</StackPanel>-->
|
||||
|
||||
<!--方法描述-->
|
||||
<themes:MethodDetailsControl x:Name="MethodDetailsControl" Grid.Row="1" MethodDetails="{Binding NodeModel.MethodDetails}" />
|
||||
|
||||
<Border Grid.Row="2" x:Name="ParameterProtectionMask" Background="LightBlue" Opacity="0.5" BorderBrush="#0A4651" BorderThickness="0"
|
||||
Visibility="{Binding NodeModel.MethodDetails.IsProtectionParameter, Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" />
|
||||
<Border Grid.Row="2" x:Name="ParameterProtectionMask" Background="#40508D" Opacity="0.5" BorderBrush="#0A4651" BorderThickness="0"
|
||||
Visibility="{Binding NodeModel.DebugSetting.IsProtectionParameter, Converter={StaticResource InvertedBoolConverter},ConverterParameter=Normal}" />
|
||||
<!--<Border Grid.Row="0" Background="#FCB334" >
|
||||
|
||||
</Border>-->
|
||||
@@ -94,7 +86,7 @@
|
||||
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="2,1,2,1">
|
||||
<CheckBox IsChecked="{Binding NodeModel.MethodDetails.IsProtectionParameter, Mode=TwoWay}"/>
|
||||
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsProtectionParameter, Mode=TwoWay}"/>
|
||||
<TextBlock Text="参数保护" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
@@ -34,37 +34,33 @@ namespace Serein.Workbench.Node.View
|
||||
/// <summary>
|
||||
/// 方法入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction
|
||||
{
|
||||
get
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction => GetArgJunction();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
private JunctionControlBase[] GetArgJunction()
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,152 @@
|
||||
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.FlowCallNodeControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance vm:FlipflopNodeControlViewModel}">
|
||||
<Grid>
|
||||
<!--选择画布-->
|
||||
<!--选择公开的节点-->
|
||||
</Grid>
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||
xmlns:converter="clr-namespace:Serein.Workbench.Converters"
|
||||
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||
mc:Ignorable="d"
|
||||
MaxWidth="300"
|
||||
|
||||
d:DataContext="{d:DesignInstance vm:FlowCallNodeControlViewModel}">
|
||||
|
||||
<UserControl.Resources>
|
||||
<converter:CountToVisibilityConverter x:Key="CountToVisibilityConverter"/>
|
||||
<converter:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
|
||||
<converter:MethodDetailsSelectorConverter x:Key="MethodDetailsSelector"/>
|
||||
<converter:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||
</UserControl.Resources>
|
||||
|
||||
|
||||
<Border BorderBrush="#C7FFE7" BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ToolTip>
|
||||
<ToolTip Background="LightYellow" Foreground="#071042" Content="{Binding NodeModel.MethodDetails}" />
|
||||
</Grid.ToolTip>
|
||||
|
||||
|
||||
|
||||
|
||||
<!--<TextBlock Text="{Binding NodeModel.DebugSetting.IsInterrupt}}"></TextBlock>-->
|
||||
<!--DataContext="{Binding}-->
|
||||
|
||||
<Border x:Name="InterruptBorder" Tag="{Binding NodeModel.DebugSetting.IsInterrupt}">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding Path=Tag,RelativeSource={RelativeSource Mode=Self}}" Value="True">
|
||||
<Setter Property="BorderBrush" Value="Red" />
|
||||
<Setter Property="BorderThickness" Value="2" />
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding Path=Tag,RelativeSource={RelativeSource Mode=Self}}" Value="False">
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
|
||||
|
||||
<Grid Background="#C7FFE7" >
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Grid Grid.Row="0" >
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<local:ExecuteJunctionControl Grid.Column="0" MyNode="{Binding NodeModel}" x:Name="ExecuteJunctionControl" HorizontalAlignment="Left" Grid.RowSpan="2"/>
|
||||
<StackPanel Grid.Column="1" Grid.RowSpan="2" Orientation="Horizontal">
|
||||
<TextBlock Text="[流程接口]" HorizontalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding NodeModel.DisplayName, Mode=TwoWay}" HorizontalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
|
||||
<Grid x:Name="MethodInfoGrid" Grid.Row="2" Margin="10,0,10,0">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="60" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Text="画布" Grid.Row="0" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Width="40"/>
|
||||
<ComboBox Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
DisplayMemberPath="Model.Name"
|
||||
SelectedItem="{Binding SelectCanvas}"
|
||||
ItemsSource="{Binding Canvass}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
IsEnabled="{Binding IsEnabledOnView}"/>
|
||||
|
||||
<TextBlock Text="节点" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center" Width="40" Visibility="{Binding SelectCanvas.Model.PublicNodes, Converter={StaticResource CountToVisibilityConverter}}"/>
|
||||
<ComboBox DisplayMemberPath="DisplayName"
|
||||
Grid.Row="1" Grid.Column="1"
|
||||
SelectedItem="{Binding SelectNode}"
|
||||
ItemsSource="{Binding SelectCanvas.Model.PublicNodes, Mode=TwoWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
IsEnabled="{Binding IsEnabledOnView}"
|
||||
Visibility="{Binding SelectCanvas.Model.PublicNodes, Converter={StaticResource CountToVisibilityConverter}}">
|
||||
</ComboBox>
|
||||
|
||||
<themes:MethodDetailsControl Grid.Row="2" Grid.ColumnSpan="2" x:Name="MethodDetailsControl">
|
||||
<themes:MethodDetailsControl.MethodDetails>
|
||||
<MultiBinding Converter="{StaticResource MethodDetailsSelector}">
|
||||
<Binding Path="FlowCallNode.IsShareParam" UpdateSourceTrigger="PropertyChanged"/>
|
||||
<Binding Path="SelectNode.MethodDetails" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
|
||||
<Binding Path="FlowCallNode.MethodDetails" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"/>
|
||||
</MultiBinding>
|
||||
</themes:MethodDetailsControl.MethodDetails>
|
||||
</themes:MethodDetailsControl>
|
||||
</Grid>
|
||||
|
||||
<Border Grid.Row="2" x:Name="ParameterProtectionMask"
|
||||
|
||||
Background="#40508D" Opacity="0.5" BorderThickness="0"
|
||||
Visibility="{Binding NodeModel.DebugSetting.IsProtectionParameter, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter }}" />
|
||||
|
||||
<StackPanel Grid.Row="3" Background="Azure" Orientation="Horizontal" Margin="3">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding FlowCallNode.IsShareParam, Mode=TwoWay}"/>
|
||||
<TextBlock Text="共享参数"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsEnable, Mode=TwoWay}"/>
|
||||
<TextBlock Text="是否使能"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsProtectionParameter, Mode=TwoWay}"/>
|
||||
<TextBlock Text="参数保护"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<CheckBox IsChecked="{Binding NodeModel.DebugSetting.IsInterrupt, Mode=TwoWay}"/>
|
||||
<TextBlock Text="中断节点"/>
|
||||
</StackPanel>
|
||||
|
||||
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</local:NodeControlBase>
|
||||
|
||||
@@ -1,17 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Serein.Library;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Serein.Workbench.Node.View
|
||||
{
|
||||
@@ -20,17 +12,79 @@ namespace Serein.Workbench.Node.View
|
||||
/// </summary>
|
||||
public partial class FlowCallNodeControl : NodeControlBase, INodeJunction
|
||||
{
|
||||
private new FlowCallNodeControlViewModel ViewModel { get; set; }
|
||||
public FlowCallNodeControl()
|
||||
{
|
||||
var env = App.GetService<IFlowEnvironment>();
|
||||
base.ViewModel = new FlowCallNodeControlViewModel(new SingleFlowCallNode(env));
|
||||
base.ViewModel.IsEnabledOnView = false;
|
||||
DataContext = base.ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
public FlowCallNodeControl(FlowCallNodeControlViewModel viewModel) : base(viewModel)
|
||||
{
|
||||
DataContext = viewModel;
|
||||
ViewModel = viewModel;
|
||||
InitializeComponent();
|
||||
ViewModel.UploadMethodDetailsControl = UploadMethodDetailsControl;
|
||||
|
||||
public JunctionControlBase ExecuteJunction => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public JunctionControlBase NextStepJunction => throw new NotImplementedException();
|
||||
private void UploadMethodDetailsControl(MethodDetails methodDetails)
|
||||
{
|
||||
//MethodDetailsControl.MethodDetails = methodDetails;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.ExecuteJunction => this.ExecuteJunctionControl;
|
||||
|
||||
/// <summary>
|
||||
/// 下一个调用方法控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.NextStepJunction => throw new NotImplementedException("不存在下一个调用控制点");
|
||||
|
||||
/// <summary>
|
||||
/// 返回值控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase INodeJunction.ReturnDataJunction => throw new NotImplementedException("不存在返回值控制点");
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 方法入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction => GetArgJunction();
|
||||
|
||||
private JunctionControlBase[] GetArgJunction()
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
//var methodDetailsControl = ViewModel.NodeModel.IsShareParam ? this.SelectMethodDetailsControl : this.MyMethodDetailsControl;
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
{
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
}
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
public JunctionControlBase[] ArgDataJunction => throw new NotImplementedException();
|
||||
|
||||
public JunctionControlBase ReturnDataJunction => throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Api;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
|
||||
@@ -12,7 +13,8 @@ namespace Serein.Workbench.Node.View
|
||||
public GlobalDataControl() : base()
|
||||
{
|
||||
// 窗体初始化需要
|
||||
base.ViewModel = new GlobalDataNodeControlViewModel(new SingleGlobalDataNode(null));
|
||||
var env = App.GetService<IFlowEnvironment>();
|
||||
base.ViewModel = new GlobalDataNodeControlViewModel(new SingleGlobalDataNode(env));
|
||||
base.ViewModel.IsEnabledOnView = false;
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -24,7 +25,9 @@ namespace Serein.Workbench.Node.View
|
||||
{
|
||||
public NetScriptNodeControl()
|
||||
{
|
||||
base.ViewModel = new NetScriptNodeControlViewModel(new SingleNetScriptNode(null));
|
||||
|
||||
var env = App.GetService<IFlowEnvironment>();
|
||||
base.ViewModel = new NetScriptNodeControlViewModel(new SingleNetScriptNode(env));
|
||||
base.ViewModel.IsEnabledOnView = false;
|
||||
base.DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Library.Api;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Node.ViewModel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -29,7 +30,9 @@ namespace Serein.Workbench.Node.View
|
||||
|
||||
public ScriptNodeControl()
|
||||
{
|
||||
base.ViewModel = new ScriptNodeControlViewModel(null);
|
||||
|
||||
var env = App.GetService<IFlowEnvironment>();
|
||||
base.ViewModel = new ScriptNodeControlViewModel(new SingleScriptNode(env));
|
||||
base.ViewModel.IsEnabledOnView = false;
|
||||
base.DataContext = viewModel;
|
||||
InitializeComponent();
|
||||
@@ -68,39 +71,33 @@ namespace Serein.Workbench.Node.View
|
||||
/// <summary>
|
||||
/// 方法入参控制点(可能有,可能没)
|
||||
/// </summary>
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction
|
||||
{
|
||||
get
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null && base.ViewModel.NodeModel.MethodDetails.ParameterDetailss != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
JunctionControlBase[] INodeJunction.ArgDataJunction => GetArgJunction();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
private JunctionControlBase[] GetArgJunction()
|
||||
{
|
||||
// 获取 MethodDetailsControl 实例
|
||||
var methodDetailsControl = this.MethodDetailsControl;
|
||||
var itemsControl = FindVisualChild<ItemsControl>(methodDetailsControl); // 查找 ItemsControl
|
||||
if (itemsControl != null)
|
||||
{
|
||||
var argDataJunction = new JunctionControlBase[base.ViewModel.NodeModel.MethodDetails.ParameterDetailss.Length];
|
||||
var controls = new List<JunctionControlBase>();
|
||||
|
||||
for (int i = 0; i < itemsControl.Items.Count; i++)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
{
|
||||
var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as FrameworkElement;
|
||||
if (container != null)
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
var argControl = FindVisualChild<ArgJunctionControl>(container);
|
||||
if (argControl != null)
|
||||
{
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
controls.Add(argControl); // 收集 ArgJunctionControl 实例
|
||||
}
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
return argDataJunction = controls.ToArray();
|
||||
}
|
||||
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
using Serein.NodeFlow.Model;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Serein.Library;
|
||||
using Serein.NodeFlow.Model;
|
||||
using Serein.Workbench.Api;
|
||||
using Serein.Workbench.Services;
|
||||
using Serein.Workbench.ViewModels;
|
||||
using Serein.Workbench.Views;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -9,10 +18,101 @@ namespace Serein.Workbench.Node.ViewModel
|
||||
{
|
||||
public partial class FlowCallNodeControlViewModel : NodeControlViewModelBase
|
||||
{
|
||||
public new SingleFlowCallNode NodelModel { get; }
|
||||
/// <summary>
|
||||
/// 刷新方法控件
|
||||
/// </summary>
|
||||
public Action<MethodDetails> UploadMethodDetailsControl;
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
private SingleFlowCallNode flowCallNode;
|
||||
|
||||
/// <summary>
|
||||
/// 当前所选画布
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private FlowCanvasViewModel _selectCanvas;
|
||||
|
||||
/// <summary>
|
||||
/// 当前所选节点
|
||||
/// </summary>
|
||||
[ObservableProperty]
|
||||
private NodeModelBase _selectNode;
|
||||
|
||||
|
||||
[ObservableProperty]
|
||||
private FlowCanvasViewModel[] canvass;
|
||||
|
||||
|
||||
|
||||
private readonly FlowNodeService flowNodeService;
|
||||
private readonly IFlowEEForwardingService flowEEForwardingService;
|
||||
|
||||
public FlowCallNodeControlViewModel(SingleFlowCallNode node) : base(node)
|
||||
{
|
||||
this.NodelModel = node;
|
||||
this.FlowCallNode = node;
|
||||
flowNodeService = App.GetService<FlowNodeService>();
|
||||
flowEEForwardingService = App.GetService<IFlowEEForwardingService>();
|
||||
RershCanvass(); // 首次加载
|
||||
InitNodeData();
|
||||
InitEvent();
|
||||
}
|
||||
private void InitNodeData()
|
||||
{
|
||||
if (string.IsNullOrEmpty(FlowCallNode.TargetNodeGuid))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var targetNodeControl = flowNodeService.FlowNodeControls.FirstOrDefault(n => n.ViewModel.NodeModel.Guid.Equals(FlowCallNode.TargetNodeGuid));
|
||||
if (targetNodeControl is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (targetNodeControl.FlowCanvas is FlowCanvasView view
|
||||
&& view.DataContext is FlowCanvasViewModel viewModel)
|
||||
{
|
||||
SelectCanvas = viewModel;
|
||||
SelectNode = targetNodeControl.ViewModel.NodeModel;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitEvent()
|
||||
{
|
||||
flowEEForwardingService.OnCanvasCreate += (e) => RershCanvass(); // 画布创建了
|
||||
flowEEForwardingService.OnCanvasRemove += (e) => RershCanvass(); // 画布移除了
|
||||
}
|
||||
|
||||
partial void OnSelectCanvasChanged(FlowCanvasViewModel value)
|
||||
{
|
||||
FlowCallNode.ResetTargetNode();
|
||||
}
|
||||
|
||||
partial void OnSelectNodeChanged(NodeModelBase value)
|
||||
{
|
||||
FlowCallNode.SetTargetNode(value);
|
||||
}
|
||||
|
||||
private void RershCanvass()
|
||||
{
|
||||
var canvass = flowNodeService.FlowCanvass.Select(f => (FlowCanvasViewModel)f.DataContext).ToArray(); // .Where(f => f.Model.PublicNodes.Count > 0)
|
||||
Canvass = canvass;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*private void RershMds()
|
||||
{
|
||||
if (NodeModel.IsShareParam && SelectNode is not null)
|
||||
{
|
||||
UploadMethodDetailsControl?.Invoke(SelectNode.MethodDetails);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
UploadMethodDetailsControl?.Invoke(base.NodeModel.MethodDetails);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
<ItemGroup>
|
||||
<Compile Remove="Node\NodeModel\**" />
|
||||
<Compile Remove="Themes\Condition\**" />
|
||||
<Compile Remove="Tool\Converters\**" />
|
||||
<EmbeddedResource Remove="Node\NodeModel\**" />
|
||||
<EmbeddedResource Remove="Themes\Condition\**" />
|
||||
<EmbeddedResource Remove="Tool\Converters\**" />
|
||||
<None Remove="Node\NodeModel\**" />
|
||||
<None Remove="Themes\Condition\**" />
|
||||
<None Remove="Tool\Converters\**" />
|
||||
<Page Remove="Node\NodeModel\**" />
|
||||
<Page Remove="Themes\Condition\**" />
|
||||
<Page Remove="Tool\Converters\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -30,6 +34,7 @@
|
||||
<Compile Remove="Node\INodeContainerControl.cs" />
|
||||
<Compile Remove="Node\Junction\NodeJunctionViewBase.cs" />
|
||||
<Compile Remove="Node\NodeBase.cs" />
|
||||
<Compile Remove="Node\ViewModel\ConditionRegionNodeControlViewModel.cs" />
|
||||
<Compile Remove="Node\View\ActionRegionControl.xaml.cs" />
|
||||
<Compile Remove="Node\View\ConditionRegionControl.xaml.cs" />
|
||||
<Compile Remove="Node\View\DllControlControl.xaml.cs" />
|
||||
|
||||
@@ -102,6 +102,7 @@ namespace Serein.Workbench.Services
|
||||
/// 当前所有画布
|
||||
/// </summary>
|
||||
public FlowCanvasView[] FlowCanvass => Canvass.Select(c => c.Value).ToArray();
|
||||
public NodeControlBase[] FlowNodeControls => NodeControls.Select(c => c.Value).ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// 记录流程画布
|
||||
@@ -145,10 +146,10 @@ namespace Serein.Workbench.Services
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.Flipflop, typeof(FlipflopNodeControl), typeof(FlipflopNodeControlViewModel));
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.ExpOp, typeof(ExpOpNodeControl), typeof(ExpOpNodeControlViewModel));
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.ExpCondition, typeof(ConditionNodeControl), typeof(ConditionNodeControlViewModel));
|
||||
//flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.ConditionRegion, typeof(ConditionRegionControl), typeof(ConditionRegionNodeControlViewModel));
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.GlobalData, typeof(GlobalDataControl), typeof(GlobalDataNodeControlViewModel));
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.Script, typeof(ScriptNodeControl), typeof(ScriptNodeControlViewModel));
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.NetScript, typeof(NetScriptNodeControl), typeof(NetScriptNodeControlViewModel));
|
||||
flowEnvironment.NodeMVVMManagement.RegisterUI(NodeControlType.FlowCall, typeof(FlowCallNodeControl), typeof(FlowCallNodeControlViewModel));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -301,6 +302,11 @@ namespace Serein.Workbench.Services
|
||||
}
|
||||
#endregion
|
||||
|
||||
//if (nodeModel.ControlType == NodeControlType.FlowCall)
|
||||
//{
|
||||
// Console.WriteLine("test");
|
||||
//}
|
||||
|
||||
#region 创建控件
|
||||
|
||||
NodeControlBase nodeControl;
|
||||
@@ -335,6 +341,7 @@ namespace Serein.Workbench.Services
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"无法移除画布,画布不存在。");
|
||||
return;
|
||||
}
|
||||
Canvass.Remove(eventArgs.CanvasGuid);
|
||||
OnRemoveFlowCanvasView.Invoke(nodeCanvas);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Serein.Workbench.Services
|
||||
{
|
||||
@@ -56,16 +57,25 @@ namespace Serein.Workbench.Services
|
||||
|
||||
private readonly IFlowEnvironment flowEnvironment;
|
||||
private readonly IFlowEEForwardingService flowEEForwardingService;
|
||||
private readonly IKeyEventService keyEventService;
|
||||
private readonly FlowNodeService flowNodeService;
|
||||
|
||||
/// <summary>
|
||||
/// 管理工作台的事件
|
||||
/// </summary>
|
||||
/// <param name="flowEnvironment"></param>
|
||||
/// <param name="flowEEForwardingService"></param>
|
||||
public WorkbenchEventService(IFlowEnvironment flowEnvironment, IFlowEEForwardingService flowEEForwardingService)
|
||||
/// <param name="keyEventService"></param>
|
||||
/// <param name="flowNodeService"></param>
|
||||
public WorkbenchEventService(IFlowEnvironment flowEnvironment,
|
||||
IFlowEEForwardingService flowEEForwardingService,
|
||||
IKeyEventService keyEventService,
|
||||
FlowNodeService flowNodeService)
|
||||
{
|
||||
this.flowEnvironment = flowEnvironment;
|
||||
this.flowEEForwardingService = flowEEForwardingService;
|
||||
this.keyEventService = keyEventService;
|
||||
this.flowNodeService = flowNodeService;
|
||||
InitEvents();
|
||||
}
|
||||
|
||||
@@ -73,6 +83,12 @@ namespace Serein.Workbench.Services
|
||||
{
|
||||
flowEEForwardingService.OnProjectSaving += SaveProjectToLocalFile;
|
||||
flowEEForwardingService.OnEnvOut += FlowEEForwardingService_OnEnvOut;
|
||||
keyEventService.OnKeyDown += KeyEventService_OnKeyDown; ;
|
||||
}
|
||||
|
||||
private void KeyEventService_OnKeyDown(System.Windows.Input.Key key)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void FlowEEForwardingService_OnEnvOut(InfoType type, string value)
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:serein="clr-namespace:Serein.Library;assembly=Serein.Library"
|
||||
xmlns:converters="clr-namespace:Serein.Workbench.Tool.Converters">
|
||||
xmlns:converter="clr-namespace:Serein.Workbench.Converters">
|
||||
|
||||
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
|
||||
<converters:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||
<converters:EnumToBooleanConverter x:Key="EnumToBooleanConverter"/>
|
||||
|
||||
<converter:InvertableBooleanToVisibilityConverter x:Key="InvertedBoolConverter"/>
|
||||
<converter:EnumToBooleanConverter x:Key="EnumToBooleanConverter"/>
|
||||
<local:DescriptionOrNameConverter x:Key="DescOrNameConverter"/>
|
||||
|
||||
|
||||
<Style TargetType="{x:Type local:MethodDetailsControl}">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
@@ -112,6 +112,29 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</MultiDataTrigger>
|
||||
|
||||
<!--显示FlowCall节点方法入参名称-->
|
||||
<MultiDataTrigger>
|
||||
<MultiDataTrigger.Conditions>
|
||||
<Condition Binding="{Binding NodeModel.ControlType}" Value="{x:Static serein:NodeControlType.FlowCall}"/>
|
||||
</MultiDataTrigger.Conditions>
|
||||
<Setter Property="ContentTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate>
|
||||
|
||||
<TextBlock Grid.Column="0" MinWidth="50">
|
||||
<TextBlock.Text>
|
||||
<MultiBinding Converter="{StaticResource DescOrNameConverter}">
|
||||
<Binding Path="Description"/>
|
||||
<Binding Path="Name"/>
|
||||
</MultiBinding>
|
||||
</TextBlock.Text>
|
||||
</TextBlock>
|
||||
|
||||
</DataTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</MultiDataTrigger>
|
||||
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Auto">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<!--<nodeView:NetScriptNodeControl x:Name="NetScriptNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>-->
|
||||
<nodeView:ScriptNodeControl x:Name="ScriptNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:GlobalDataControl x:Name="GlobalDataControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ExpOpNodeControl x:Name="ExpOpNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ConditionNodeControl x:Name="ConditionNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:FlowCallNodeControl MaxWidth="250" MaxHeight="100" x:Name="FlowCallNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ScriptNodeControl MaxWidth="250" MaxHeight="100" x:Name="ScriptNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:GlobalDataControl MaxWidth="250" MaxHeight="100" x:Name="GlobalDataControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ExpOpNodeControl MaxWidth="250" MaxHeight="100" x:Name="ExpOpNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<nodeView:ConditionNodeControl MaxWidth="250" MaxHeight="100" x:Name="ConditionNodeControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>
|
||||
<!--<nodeView:ConditionRegionControl x:Name="ConditionRegionControl" Margin="10" AllowDrop="True" PreviewMouseMove="BaseNodeControl_PreviewMouseMove"/>-->
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Views"
|
||||
xmlns:tool="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||
xmlns:converter="clr-namespace:Serein.Workbench.Converters"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450"
|
||||
@@ -12,10 +12,10 @@
|
||||
d:DataContext="{d:DesignInstance vm:FlowCanvasViewModel}">
|
||||
|
||||
<UserControl.Resources>
|
||||
<tool:RightThumbPositionConverter x:Key="RightThumbPositionConverter" />
|
||||
<tool:BottomThumbPositionConverter x:Key="BottomThumbPositionConverter" />
|
||||
<tool:VerticalCenterThumbPositionConverter x:Key="VerticalCenterThumbPositionConverter" />
|
||||
<tool:HorizontalCenterThumbPositionConverter x:Key="HorizontalCenterThumbPositionConverter" />
|
||||
<converter:RightThumbPositionConverter x:Key="RightThumbPositionConverter" />
|
||||
<converter:BottomThumbPositionConverter x:Key="BottomThumbPositionConverter" />
|
||||
<converter:VerticalCenterThumbPositionConverter x:Key="VerticalCenterThumbPositionConverter" />
|
||||
<converter:HorizontalCenterThumbPositionConverter x:Key="HorizontalCenterThumbPositionConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<DockPanel x:Name="FlowChartStackPanel"
|
||||
|
||||
@@ -87,6 +87,14 @@ namespace Serein.Workbench.Views
|
||||
FlowChartCanvas.Dispatcher.Invoke(() =>
|
||||
{
|
||||
FlowChartCanvas.Children.Add(nodeControl);
|
||||
if(nodeControl.ViewModel.NodeModel.ControlType == NodeControlType.UI)
|
||||
{
|
||||
// 需要切换到对应画布,尽可能让UI线程获取到适配器
|
||||
var edit = App.GetService<Locator>().FlowEditViewModel;
|
||||
var tab = edit.CanvasTabs.First(tab => tab.Content == this);
|
||||
App.GetService<Locator>().FlowEditViewModel.SelectedTab = tab;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
ConfigureNodeEvents(nodeControl); // 配置相关事件
|
||||
@@ -294,7 +302,7 @@ namespace Serein.Workbench.Views
|
||||
flowNodeService = App.GetService<FlowNodeService>();
|
||||
keyEventService = App.GetService<IKeyEventService>();
|
||||
flowNodeService.OnCreateNode += OnCreateNode;
|
||||
keyEventService.OnKeyDown += KeyEventService_OnKeyDown; ;
|
||||
keyEventService.OnKeyDown += KeyEventService_OnKeyDown;
|
||||
|
||||
// 缩放平移容器
|
||||
canvasTransformGroup = new TransformGroup();
|
||||
@@ -413,14 +421,25 @@ namespace Serein.Workbench.Views
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (key == Key.F5)
|
||||
{
|
||||
// F5 调试当前流程
|
||||
_ = flowEnvironment.StartFlowAsync([Guid]);
|
||||
}
|
||||
if (keyEventService.GetKeyState(Key.LeftCtrl) || keyEventService.GetKeyState(Key.RightCtrl))
|
||||
{
|
||||
// Ctrl + F5 调试当前流程
|
||||
_ = flowEnvironment.StartFlowAsync([flowNodeService.CurrentSelectCanvas.Guid]);
|
||||
}
|
||||
else if (selectNodeControls.Count == 1 )
|
||||
{
|
||||
// F5 调试当前选定节点
|
||||
var nodeModel = selectNodeControls[0].ViewModel.NodeModel;
|
||||
SereinEnv.WriteLine(InfoType.INFO, $"调试运行当前节点:{nodeModel.Guid}");
|
||||
_ = nodeModel.StartFlowAsync(new DynamicContext(flowEnvironment), new CancellationToken());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (key == Key.Escape)
|
||||
@@ -630,6 +649,7 @@ namespace Serein.Workbench.Views
|
||||
Type when typeof(GlobalDataControl).IsAssignableFrom(droppedType) => NodeControlType.GlobalData,
|
||||
Type when typeof(ScriptNodeControl).IsAssignableFrom(droppedType) => NodeControlType.Script,
|
||||
Type when typeof(NetScriptNodeControl).IsAssignableFrom(droppedType) => NodeControlType.NetScript,
|
||||
Type when typeof(FlowCallNodeControl).IsAssignableFrom(droppedType) => NodeControlType.FlowCall,
|
||||
_ => NodeControlType.None,
|
||||
};
|
||||
if (nodeControlType != NodeControlType.None)
|
||||
@@ -1146,7 +1166,7 @@ namespace Serein.Workbench.Views
|
||||
if (sender is NodeControlBase nodeControl)
|
||||
{
|
||||
//ChangeViewerObjOfNode(nodeControl); // 对象树
|
||||
if (nodeControl?.ViewModel?.NodeModel?.MethodDetails?.IsProtectionParameter == true) return;
|
||||
//if (nodeControl?.ViewModel?.NodeModel?.DebugSetting.IsProtectionParameter == true) return;
|
||||
IsControlDragging = true;
|
||||
startControlDragPoint = e.GetPosition(FlowChartCanvas); // 记录鼠标按下时的位置
|
||||
((UIElement)sender).CaptureMouse(); // 捕获鼠标
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Serein.Workbench.Views"
|
||||
xmlns:converters="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||
xmlns:converter="clr-namespace:Serein.Workbench.Converters"
|
||||
xmlns:vm="clr-namespace:Serein.Workbench.ViewModels"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
d:DataContext="{d:DesignInstance vm:FlowEditViewModel}"
|
||||
Background="#E7F0F6">
|
||||
<UserControl.Resources>
|
||||
<converters:InvertableBooleanToVisibilityConverter x:Key="InvertableBooleanToVisibilityConverter"/>
|
||||
<converter:InvertableBooleanToVisibilityConverter x:Key="InvertableBooleanToVisibilityConverter"/>
|
||||
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
|
||||
Reference in New Issue
Block a user