diff --git a/.gitignore b/.gitignore index ced4e34..16ea43e 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,9 @@ obj/ # 排除发布文件夹 .Output/ /.git1 +doc WorkBench.ControlLibrary.Core WorkBench.Remote Serein.FlowStartTool -Serein.CloudWorkbench \ No newline at end of file +Serein.CloudWorkbench +Serein.CollaborationSync \ No newline at end of file diff --git a/Library/Api/IFlowEnvironment.cs b/Library/Api/IFlowEnvironment.cs index a5d85c3..d095342 100644 --- a/Library/Api/IFlowEnvironment.cs +++ b/Library/Api/IFlowEnvironment.cs @@ -873,8 +873,6 @@ namespace Serein.Library.Api /// void ExitRemoteEnv(); - - /// /// (用于远程)通知节点属性变更 /// diff --git a/Library/FlowNode/ParameterDetails.cs b/Library/FlowNode/ParameterDetails.cs index c7864b2..908b5d0 100644 --- a/Library/FlowNode/ParameterDetails.cs +++ b/Library/FlowNode/ParameterDetails.cs @@ -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 { + + + + + /// /// 用于创建元数据 diff --git a/Library/FlowNode/SereinProjectData.cs b/Library/FlowNode/SereinProjectData.cs index 8d7944f..8b7a3f0 100644 --- a/Library/FlowNode/SereinProjectData.cs +++ b/Library/FlowNode/SereinProjectData.cs @@ -28,6 +28,8 @@ namespace Serein.Library // IOC节点对象信息 } + + /// /// 程序集相关的方法信息 /// @@ -64,12 +66,6 @@ namespace Serein.Library public NodeLibraryInfo[] Librarys { get; set; } - ///// - ///// 起始节点GUID - ///// - - //public string StartNode { get; set; } - /// /// 画布集合 /// @@ -100,45 +96,7 @@ namespace Serein.Library } - /* /// - /// 画布信息,项目文件相关 - /// - public class FlowCanvasInfo - { - public string Guid { get; set; } - - public string Name { get; set; } - - /// - /// 宽度 - /// - public double Width { get; set; } - /// - /// 高度 - /// - public double Height { get; set; } - - /// - /// 预览位置X - /// - public double ViewX { get; set; } - - /// - /// 预览位置Y - /// - public double ViewY { get; set; } - - /// - /// 缩放比例X - /// - public double ScaleX { get; set; } - - /// - /// 缩放比例Y - /// - public double ScaleY { get; set; } - }*/ - + /// /// 项目依赖的程序集,项目文件相关 /// @@ -161,27 +119,7 @@ namespace Serein.Library public string AssemblyName { get; set; } } - #region 暂时注释 - /*public class LibraryInfo -{ - /// - /// 文件名称 - /// - - public string FileName { get; set; } - - /// - /// 文件路径 - /// - public string FilePath { get; set; } - - /// - /// 程序集名称 - /// - public string AssemblyName { get; set; } -}*/ - #endregion - + /// /// 节点信息,项目文件相关 /// @@ -291,6 +229,8 @@ namespace Serein.Library public dynamic CustomData { get; set; } } + + /// /// 参数信息,项目文件相关 /// diff --git a/Library/Serein.Library.csproj b/Library/Serein.Library.csproj index f8baeb8..c54d5e4 100644 --- a/Library/Serein.Library.csproj +++ b/Library/Serein.Library.csproj @@ -2,10 +2,8 @@ 1.2.0 - net8.0;net462 ..\.\.Output - True SereinFow 动态节点流、可视化编辑的基本依赖,支持导入C# DLL生成自定义节点,提供二次开发支持,适合用于可视化编程和流程设计 diff --git a/Library/SereinBaseFunction.cs b/Library/SereinBaseFunction.cs index c0d8961..6be3ab2 100644 --- a/Library/SereinBaseFunction.cs +++ b/Library/SereinBaseFunction.cs @@ -18,6 +18,8 @@ namespace Serein.Library public class SereinBaseFunction { + + [NodeAction(NodeType.Action, "键值对组装")] private Dictionary SereinKvDataCollectionNode(string argName, params object[] value) diff --git a/Library/Utils/ConvertHelper.cs b/Library/Utils/ConvertHelper.cs index ba9b238..c3ac1c6 100644 --- a/Library/Utils/ConvertHelper.cs +++ b/Library/Utils/ConvertHelper.cs @@ -150,7 +150,7 @@ namespace Serein.Library.Utils /// - /// 对象转换(好像没啥用) + /// 对象转换为对应类型 /// /// /// diff --git a/NodeFlow/Env/FlowEnvironment.cs b/NodeFlow/Env/FlowEnvironment.cs index 8e1075a..493953f 100644 --- a/NodeFlow/Env/FlowEnvironment.cs +++ b/NodeFlow/Env/FlowEnvironment.cs @@ -77,14 +77,12 @@ namespace Serein.NodeFlow.Env private MsgControllerOfServer clientMsgManage; - /// /// 表示是否正在控制远程 /// Local control remote env /// public bool IsControlRemoteEnv { get; set; } - /// /// 打开远程管理 /// @@ -1521,10 +1519,13 @@ namespace Serein.NodeFlow.Env /// 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))) //{ diff --git a/NodeFlow/FlowNodeExtension.cs b/NodeFlow/FlowNodeExtension.cs index 21e3212..1b63c82 100644 --- a/NodeFlow/FlowNodeExtension.cs +++ b/NodeFlow/FlowNodeExtension.cs @@ -20,11 +20,10 @@ namespace Serein.NodeFlow /// public static bool IsBaseNode(this NodeControlType nodeControlType) { - var nodeDesc = EnumHelper.GetAttribute(nodeControlType); - if("base".Equals(nodeDesc?.Description, StringComparison.OrdinalIgnoreCase)) + if("base".Equals(nodeDesc?.Description, StringComparison.OrdinalIgnoreCase)) { - return true; + return true; } return false; } diff --git a/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs b/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs index e4c5229..433c661 100644 --- a/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs +++ b/Serein.Library.MyGenerator/ParameterDetailsPropertyGenerator.cs @@ -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()); @@ -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($" /// "); + 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(" /// "); //sb.AppendLine(" /// 略 "); //sb.AppendLine(" /// 此方法为自动生成 "); @@ -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(value); + } + } + else if (path.Equals(nameof(Guid), StringComparison.OrdinalIgnoreCase)) + { + if (typeof(string) == typeof(string)) + { + this.Guid = value; + } + else + { + this.Guid = ConvertHelper.ValueParse(value); + } + } + }*/ + + /// /// 获取类所在的命名空间。 /// @@ -310,7 +350,7 @@ namespace Serein.Library.NodeGenerator /// - /// 为 XML 文档注释中的 标签插入指定的文本 + /// 为 XML 文档注释中的 summary 标签插入指定的文本 /// /// 语法节点的 LeadingTrivia 或 TrailingTrivia 列表 /// 要插入的注释文本 @@ -348,14 +388,19 @@ namespace Serein.Library.NodeGenerator var paraElement = SyntaxFactory.XmlElement( SyntaxFactory.XmlElementStartTag(SyntaxFactory.XmlName("para")), // 起始标签 SyntaxFactory.SingletonList( // 内容 - SyntaxFactory.XmlText(comment).WithLeadingTrivia(SyntaxFactory.Whitespace(" ")) + SyntaxFactory.XmlText(comment) ), SyntaxFactory.XmlElementEndTag(SyntaxFactory.XmlName("para")) // 结束标签 ); + // WithLeadingTrivia(SyntaxFactory.Whitespace("")) + + // .AddContent(SyntaxFactory.XmlNewLine("123") // 将 插入到 中 - var updatedSummaryNode = summaryNode.AddContent(paraElement); + var updatedSummaryNode = summaryNode.AddContent(paraElement).AddContent(); + + // 用新的 标签替换原来的 var updatedStructuredTrivia = structuredTrivia.ReplaceNode(summaryNode, updatedSummaryNode); diff --git a/SereinFlow.sln b/SereinFlow.sln index 7a2ba7c..aaa40ec 100644 --- a/SereinFlow.sln +++ b/SereinFlow.sln @@ -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 diff --git a/Workbench/Services/FlowNodeService.cs b/Workbench/Services/FlowNodeService.cs index e5b2ea2..25841f1 100644 --- a/Workbench/Services/FlowNodeService.cs +++ b/Workbench/Services/FlowNodeService.cs @@ -35,11 +35,6 @@ namespace Serein.Workbench.Services /// public Action OnRemoveFlowCanvasView { get; set; } - /// - /// 添加了节点 - /// - public Action OnCreateNode { get; set; } - /// /// 查看的画布发生改变 /// @@ -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) { diff --git a/Workbench/Views/FlowCanvasView.xaml.cs b/Workbench/Views/FlowCanvasView.xaml.cs index 5aff73a..a070243 100644 --- a/Workbench/Views/FlowCanvasView.xaml.cs +++ b/Workbench/Views/FlowCanvasView.xaml.cs @@ -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 /// 当前画布创建了节点 /// /// - private void OnCreateNode(NodeControlBase nodeControl) + /* private void OnCreateNode(NodeControlBase nodeControl) { if (!nodeControl.FlowCanvas.Guid.Equals(Guid)) // 防止事件传播到其它画布 { @@ -295,7 +294,7 @@ namespace Serein.Workbench.Views } - } + }*/ /// /// 尝试判断是否为区域,如果是,将节点放置在区域中 @@ -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);