优化了Workbench画布节点创建相关的代码逻辑

This commit is contained in:
fengjiayi
2025-06-01 12:21:38 +08:00
parent 84390b574f
commit 401c0e42d9
13 changed files with 119 additions and 114 deletions

4
.gitignore vendored
View File

@@ -20,7 +20,9 @@ obj/
# 排除发布文件夹
.Output/
/.git1
doc
WorkBench.ControlLibrary.Core
WorkBench.Remote
Serein.FlowStartTool
Serein.CloudWorkbench
Serein.CloudWorkbench
Serein.CollaborationSync

View File

@@ -873,8 +873,6 @@ namespace Serein.Library.Api
/// </summary>
void ExitRemoteEnv();
/// <summary>
/// (用于远程)通知节点属性变更
/// </summary>

View File

@@ -8,7 +8,6 @@ using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Serein.Library
{
@@ -118,6 +117,11 @@ namespace Serein.Library
public partial class ParameterDetails
{
/// <summary>
/// 用于创建元数据

View File

@@ -28,6 +28,8 @@ namespace Serein.Library
// IOC节点对象信息
}
/// <summary>
/// 程序集相关的方法信息
/// </summary>
@@ -64,12 +66,6 @@ namespace Serein.Library
public NodeLibraryInfo[] Librarys { get; set; }
///// <summary>
///// 起始节点GUID
///// </summary>
//public string StartNode { get; set; }
/// <summary>
/// 画布集合
/// </summary>
@@ -100,45 +96,7 @@ namespace Serein.Library
}
/* /// <summary>
/// 画布信息,项目文件相关
/// </summary>
public class FlowCanvasInfo
{
public string Guid { get; set; }
public string Name { get; set; }
/// <summary>
/// 宽度
/// </summary>
public double Width { get; set; }
/// <summary>
/// 高度
/// </summary>
public double Height { get; set; }
/// <summary>
/// 预览位置X
/// </summary>
public double ViewX { get; set; }
/// <summary>
/// 预览位置Y
/// </summary>
public double ViewY { get; set; }
/// <summary>
/// 缩放比例X
/// </summary>
public double ScaleX { get; set; }
/// <summary>
/// 缩放比例Y
/// </summary>
public double ScaleY { get; set; }
}*/
/// <summary>
/// 项目依赖的程序集,项目文件相关
/// </summary>
@@ -161,27 +119,7 @@ namespace Serein.Library
public string AssemblyName { get; set; }
}
#region
/*public class LibraryInfo
{
/// <summary>
/// 文件名称
/// </summary>
public string FileName { get; set; }
/// <summary>
/// 文件路径
/// </summary>
public string FilePath { get; set; }
/// <summary>
/// 程序集名称
/// </summary>
public string AssemblyName { get; set; }
}*/
#endregion
/// <summary>
/// 节点信息,项目文件相关
/// </summary>
@@ -291,6 +229,8 @@ namespace Serein.Library
public dynamic CustomData { get; set; }
}
/// <summary>
/// 参数信息,项目文件相关
/// </summary>

View File

@@ -2,10 +2,8 @@
<PropertyGroup>
<Version>1.2.0</Version>
<!--<TargetFrameworks>net8.0</TargetFrameworks>-->
<TargetFrameworks>net8.0;net462</TargetFrameworks>
<BaseOutputPath>..\.\.Output</BaseOutputPath>
<!--<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>-->
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Title>SereinFow</Title>
<Description>动态节点流、可视化编辑的基本依赖支持导入C# DLL生成自定义节点提供二次开发支持适合用于可视化编程和流程设计</Description>

View File

@@ -18,6 +18,8 @@ namespace Serein.Library
public class SereinBaseFunction
{
[NodeAction(NodeType.Action, "键值对组装")]
private Dictionary<string, object> SereinKvDataCollectionNode(string argName,
params object[] value)

View File

@@ -150,7 +150,7 @@ namespace Serein.Library.Utils
/// <summary>
/// 对象转换(好像没啥用)
/// 对象转换为对应类型
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="data"></param>

View File

@@ -77,14 +77,12 @@ namespace Serein.NodeFlow.Env
private MsgControllerOfServer clientMsgManage;
/// <summary>
/// <para>表示是否正在控制远程</para>
/// <para>Local control remote env</para>
/// </summary>
public bool IsControlRemoteEnv { get; set; }
/// <summary>
/// 打开远程管理
/// </summary>
@@ -1521,10 +1519,13 @@ namespace Serein.NodeFlow.Env
/// <returns></returns>
public Task NotificationNodeValueChangeAsync(string nodeGuid, string path, object value)
{
// "NodeModel.Path"
if (TryGetNodeModel(nodeGuid, out var nodeModel))
{
SerinExpressionEvaluator.Evaluate($"@Set .{path} = {value}", nodeModel, out _); // 更改对应的数据
}
return Task.CompletedTask;
//if (NodeValueChangeLogger.Remove((nodeGuid, path, value)))
//{

View File

@@ -20,11 +20,10 @@ namespace Serein.NodeFlow
/// <returns></returns>
public static bool IsBaseNode(this NodeControlType nodeControlType)
{
var nodeDesc = EnumHelper.GetAttribute<NodeControlType, DescriptionAttribute>(nodeControlType);
if("base".Equals(nodeDesc?.Description, StringComparison.OrdinalIgnoreCase))
if("base".Equals(nodeDesc?.Description, StringComparison.OrdinalIgnoreCase))
{
return true;
return true;
}
return false;
}

View File

@@ -125,11 +125,10 @@ namespace Serein.Library.NodeGenerator
sb.AppendLine($"using System.Collections.Generic;");
sb.AppendLine($"using Serein.Library;");
sb.AppendLine($"using Serein.Library.Api;");
//sb.AppendLine($"using static Serein.Library.Utils.ChannelFlowInterrupt;");
sb.AppendLine($"");
sb.AppendLine($"namespace {namespaceName}");
sb.AppendLine($"namespace {namespaceName}"); // 命名空间
sb.AppendLine("{");
sb.AppendLine($" public partial class {className} : System.ComponentModel.INotifyPropertyChanged");
sb.AppendLine($" public partial class {className} : global::System.ComponentModel.INotifyPropertyChanged"); // 类名
sb.AppendLine(" {");
//object path = null ;
@@ -143,10 +142,6 @@ namespace Serein.Library.NodeGenerator
// "ParameterDetails";
// "MethodDetails";
try
{
var expInfo = MyAttributeResolver.BuildCacheOfField(classSyntax.Members.OfType<FieldDeclarationSyntax>());
@@ -158,35 +153,46 @@ namespace Serein.Library.NodeGenerator
continue;
}
var leadingTrivia = field.GetLeadingTrivia().InsertSummaryComment("(此属性为自动生成)").ToString(); // 获取注释
//var leadingTrivia = field.GetLeadingTrivia().InsertSummaryComment("(此属性为自动生成)").ToString(); // 获取注释
var fieldName = field.Declaration.Variables.First().Identifier.Text; // 获取字段名称
var fieldType = field.Declaration.Type.ToString(); // 获取字段类型
var propertyName = field.ToPropertyName(); // 转为合适的属性名称
var attributeInfo = fieldKV.Value; // 缓存的特性信息
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(leadingTrivia);
sb.AppendLine($" partial void On{propertyName}Changed({fieldType} oldValue, {fieldType} newValue);");
sb.AppendLine($" partial void On{propertyName}Changed({fieldType} value);");
sb.AppendLine();
// 生成 getter / setter
sb.AppendLine(leadingTrivia);
sb.AppendLine($" /// <inheritdoc cref=\"{fieldName}\"/>");
sb.AppendLine( " [global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]");
sb.AppendLine($" public {fieldType} {propertyName}");
sb.AppendLine(" {");
sb.AppendLine($" get => {fieldName};"); // getter方法
sb.AppendLine(" set");
sb.AppendLine(" {");
sb.AppendLine( " set");
sb.AppendLine( " {");
sb.AppendLine($" if ({fieldName} {(isProtection ? "== default" : "!= value")})"); // 非保护的Setter
sb.AppendLine(" {");
sb.AppendLine( " {");
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))) // 是否打印
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsPrint), value => bool.Parse(value)))
{
sb.AddCode(5, $"Console.WriteLine({fieldName});");
}
} // 是否打印
// private void ValueChangedNotificationRemoteEnv(string nodeGuid, string nodeValuePath, string proprtyName, string fieldType, string otherData = null)
// NodeValuePath.Node 作用在节点
// NodeValuePath.DebugSetting 节点 → 参数信息
// NodeValuePath.Method 节点 → 方法描述
// NodeValuePath.Parameter 节点 → 方法描述 → 参数描述
if (attributeInfo.Search(nameof(PropertyInfo), nameof(PropertyInfo.IsNotification), value => bool.Parse(value))) // 是否通知
{
if (classInfo.ExitsPath(nameof(NodeValuePath.Node))) // 节点 or 自定义节点
{
sb.AddCode(5, $"if (this?.Env?.IsControlRemoteEnv == true) // 正在控制远程环境时才触发");
@@ -214,9 +220,9 @@ namespace Serein.Library.NodeGenerator
}
sb.AddCode(5, $"}}");
}
}
} // 是否通知
sb.AppendLine(" }");
sb.AppendLine(" }");
sb.AppendLine(" }"); // 属性的结尾大括号
@@ -250,6 +256,11 @@ namespace Serein.Library.NodeGenerator
sb.AppendLine(" ");
sb.AppendLine(" ");
sb.AppendLine(" ");
// 生成变量修改
//sb.AppendLine(" /// <summary> ");
//sb.AppendLine(" /// 略 ");
//sb.AppendLine(" /// <para>此方法为自动生成</para> ");
@@ -272,11 +283,40 @@ namespace Serein.Library.NodeGenerator
return sb.ToString(); // 返回生成的代码
}
/*private void ModifyValue(string path, string value)
{
if (string.IsNullOrWhiteSpace(path))
{
return;
}
else if (path.Equals(nameof(MaxChildrenCount), StringComparison.OrdinalIgnoreCase))
{
if (typeof(int) == typeof(string))
{
this.MaxChildrenCount = value;
}
else
{
this.MaxChildrenCount = ConvertHelper.ValueParse<int>(value);
}
}
else if (path.Equals(nameof(Guid), StringComparison.OrdinalIgnoreCase))
{
if (typeof(string) == typeof(string))
{
this.Guid = value;
}
else
{
this.Guid = ConvertHelper.ValueParse<string>(value);
}
}
}*/
/// <summary>
/// 获取类所在的命名空间。
/// </summary>
@@ -310,7 +350,7 @@ namespace Serein.Library.NodeGenerator
/// <summary>
/// 为 XML 文档注释中的 <summary> 标签插入指定的文本
/// 为 XML 文档注释中的 summary 标签插入指定的文本
/// </summary>
/// <param name="triviaList">语法节点的 LeadingTrivia 或 TrailingTrivia 列表</param>
/// <param name="comment">要插入的注释文本</param>
@@ -348,14 +388,19 @@ namespace Serein.Library.NodeGenerator
var paraElement = SyntaxFactory.XmlElement(
SyntaxFactory.XmlElementStartTag(SyntaxFactory.XmlName("para")), // 起始标签 <para>
SyntaxFactory.SingletonList<XmlNodeSyntax>( // 内容
SyntaxFactory.XmlText(comment).WithLeadingTrivia(SyntaxFactory.Whitespace(" "))
SyntaxFactory.XmlText(comment)
),
SyntaxFactory.XmlElementEndTag(SyntaxFactory.XmlName("para")) // 结束标签 </para>
);
// WithLeadingTrivia(SyntaxFactory.Whitespace(""))
// .AddContent(SyntaxFactory.XmlNewLine("123")
// 将 <para> 插入到 <summary> 中
var updatedSummaryNode = summaryNode.AddContent(paraElement);
var updatedSummaryNode = summaryNode.AddContent(paraElement).AddContent();
// 用新的 <summary> 标签替换原来的
var updatedStructuredTrivia = structuredTrivia.ReplaceNode(summaryNode, updatedSummaryNode);

View File

@@ -26,6 +26,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Workbench.Avalonia",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Workbench.Avalonia.Desktop", "Serein.Workbench.Avalonia.Desktop\Serein.Workbench.Avalonia.Desktop.csproj", "{D46C9E9E-9994-45E6-8084-A8A9497B1DC2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Serein.CollaborationSync", "Serein.CollaborationSync\Serein.CollaborationSync.csproj", "{913AAB34-7383-4F9D-A7DF-A5E6191DDB3D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -68,6 +70,10 @@ Global
{D46C9E9E-9994-45E6-8084-A8A9497B1DC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D46C9E9E-9994-45E6-8084-A8A9497B1DC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D46C9E9E-9994-45E6-8084-A8A9497B1DC2}.Release|Any CPU.Build.0 = Release|Any CPU
{913AAB34-7383-4F9D-A7DF-A5E6191DDB3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{913AAB34-7383-4F9D-A7DF-A5E6191DDB3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{913AAB34-7383-4F9D-A7DF-A5E6191DDB3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{913AAB34-7383-4F9D-A7DF-A5E6191DDB3D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -35,11 +35,6 @@ namespace Serein.Workbench.Services
/// </summary>
public Action<FlowCanvasView> OnRemoveFlowCanvasView { get; set; }
/// <summary>
/// 添加了节点
/// </summary>
public Action<NodeControlBase> OnCreateNode { get; set; }
/// <summary>
/// 查看的画布发生改变
/// </summary>
@@ -356,7 +351,11 @@ namespace Serein.Workbench.Services
nodeMVVM.ViewModelType, // 控件VIewModel类型
nodeModel, // 控件数据实体
nodeCanvas); // 所在画布
OnCreateNode.Invoke(nodeControl); // 创建节点
if(nodeCanvas is IFlowCanvas flowCanvas)
{
flowCanvas.Add(nodeControl); // 创建节点
}
}
catch (Exception ex)
{

View File

@@ -173,7 +173,6 @@ namespace Serein.Workbench.Views
private void InitEvent()
{
flowNodeService.OnCreateNode += OnCreateNode;
keyEventService.OnKeyDown += KeyEventService_OnKeyDown;
flowEEForwardingService.OnNodeLocated += FlowEEForwardingService_OnNodeLocated;
}
@@ -273,7 +272,7 @@ namespace Serein.Workbench.Views
/// 当前画布创建了节点
/// </summary>
/// <param name="nodeControl"></param>
private void OnCreateNode(NodeControlBase nodeControl)
/* private void OnCreateNode(NodeControlBase nodeControl)
{
if (!nodeControl.FlowCanvas.Guid.Equals(Guid)) // 防止事件传播到其它画布
{
@@ -295,7 +294,7 @@ namespace Serein.Workbench.Views
}
}
}*/
/// <summary>
/// 尝试判断是否为区域,如果是,将节点放置在区域中
@@ -367,6 +366,18 @@ namespace Serein.Workbench.Views
}
void IFlowCanvas.Add(NodeControlBase nodeControl)
{
var p = nodeControl.ViewModel.NodeModel.Position;
PositionOfUI position = new PositionOfUI(p.X, p.Y);
if (TryPlaceNodeInRegion(nodeControl, position, out var regionControl)) // 判断添加到区域容器
{
// 通知运行环境调用加载节点子项的方法
_ = flowEnvironment.PlaceNodeToContainerAsync(Guid,
nodeControl.ViewModel.NodeModel.Guid, // 待移动的节点
regionControl.ViewModel.NodeModel.Guid); // 目标的容器节点
return;
}
// 并非添加在容器中,直接放置节点
ViewModel.NodeControls.TryAdd(nodeControl.ViewModel.NodeModel.Guid, nodeControl);