mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-04-27 10:13:23 +08:00
web socket添加token验证能力(使用token+创建时设置验证回调);flowEnv添加WebSocket处理消息能力,下一步将开发远程登录登录工具。
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -34,14 +34,6 @@ namespace SereinFlowRemoteManagement
|
|||||||
public SereinFlowRemoteControl(IFlowEnvironment environment)
|
public SereinFlowRemoteControl(IFlowEnvironment environment)
|
||||||
{
|
{
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
//if (environment is FlowEnvironment env)
|
|
||||||
//{
|
|
||||||
// this.environment = env;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// throw new Exception();
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[NodeAction(NodeType.Init)]
|
[NodeAction(NodeType.Init)]
|
||||||
@@ -153,7 +145,7 @@ namespace SereinFlowRemoteManagement
|
|||||||
throw new InvalidOperationException("Guid错误");
|
throw new InvalidOperationException("Guid错误");
|
||||||
}
|
}
|
||||||
|
|
||||||
await environment.StartFlowInSelectNodeAsync(nodeGuid);
|
await environment.StartAsyncInSelectNode(nodeGuid);
|
||||||
|
|
||||||
await Send(new
|
await Send(new
|
||||||
{
|
{
|
||||||
@@ -172,7 +164,7 @@ namespace SereinFlowRemoteManagement
|
|||||||
return environment.GetProjectInfo();
|
return environment.GetProjectInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<Version>1.0.0</Version>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||||
<PublishSingleFile>true</PublishSingleFile>
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<Version>1.0.13</Version>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -33,6 +33,6 @@ using System.Runtime.InteropServices;
|
|||||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||||
//通过使用 "*",如下所示:
|
//通过使用 "*",如下所示:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.1.0")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.1.0")]
|
||||||
[assembly: NeutralResourcesLanguage("")]
|
[assembly: NeutralResourcesLanguage("")]
|
||||||
|
|||||||
@@ -80,6 +80,12 @@ namespace Serein.Library.Api
|
|||||||
/// <param name="eventArgs"></param>
|
/// <param name="eventArgs"></param>
|
||||||
public delegate void NodeLocatedHandler(NodeLocatedEventArgs eventArgs);
|
public delegate void NodeLocatedHandler(NodeLocatedEventArgs eventArgs);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点移动了(远程插件)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="eventArgs"></param>
|
||||||
|
public delegate void NodeMovedHandler(NodeMovedEventArgs eventArgs);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 环境事件签名
|
#region 环境事件签名
|
||||||
@@ -381,7 +387,9 @@ namespace Serein.Library.Api
|
|||||||
public object Instance { get; private set; }
|
public object Instance { get; private set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点需要定位
|
||||||
|
/// </summary>
|
||||||
public class NodeLocatedEventArgs : FlowEventArgs
|
public class NodeLocatedEventArgs : FlowEventArgs
|
||||||
{
|
{
|
||||||
public NodeLocatedEventArgs(string nodeGuid)
|
public NodeLocatedEventArgs(string nodeGuid)
|
||||||
@@ -391,6 +399,31 @@ namespace Serein.Library.Api
|
|||||||
public string NodeGuid { get; private set; }
|
public string NodeGuid { get; private set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点移动了
|
||||||
|
/// </summary>
|
||||||
|
public class NodeMovedEventArgs : FlowEventArgs
|
||||||
|
{
|
||||||
|
public NodeMovedEventArgs(string nodeGuid, double x, double y)
|
||||||
|
{
|
||||||
|
this.NodeGuid = nodeGuid;
|
||||||
|
this.X = x;
|
||||||
|
this.Y = y;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 节点唯一标识
|
||||||
|
/// </summary>
|
||||||
|
public string NodeGuid { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 画布上的x坐标
|
||||||
|
/// </summary>
|
||||||
|
public double X { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 画布上的y坐标
|
||||||
|
/// </summary>
|
||||||
|
public double Y { get; private set; }
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
@@ -492,11 +525,15 @@ namespace Serein.Library.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
event IOCMembersChangedHandler OnIOCMembersChanged;
|
event IOCMembersChangedHandler OnIOCMembersChanged;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 节点需要定位
|
/// 节点需要定位
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event NodeLocatedHandler OnNodeLocate;
|
event NodeLocatedHandler OnNodeLocated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点移动了(远程插件)
|
||||||
|
/// </summary>
|
||||||
|
event NodeMovedHandler OnNodeMoved;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -520,6 +557,15 @@ namespace Serein.Library.Api
|
|||||||
//bool TryGetNodeData(string methodName, out NodeData node);
|
//bool TryGetNodeData(string methodName, out NodeData node);
|
||||||
|
|
||||||
#region 环境基础接口
|
#region 环境基础接口
|
||||||
|
/// <summary>
|
||||||
|
/// 启动远程服务
|
||||||
|
/// </summary>
|
||||||
|
Task StartRemoteServerAsync(int port = 7525);
|
||||||
|
/// <summary>
|
||||||
|
/// 停止远程服务
|
||||||
|
/// </summary>
|
||||||
|
void StopRemoteServer();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 保存当前项目
|
/// 保存当前项目
|
||||||
@@ -532,7 +578,6 @@ namespace Serein.Library.Api
|
|||||||
/// <param name="projectFile"></param>
|
/// <param name="projectFile"></param>
|
||||||
/// <param name="filePath"></param>
|
/// <param name="filePath"></param>
|
||||||
void LoadProject(SereinProjectData projectFile, string filePath);
|
void LoadProject(SereinProjectData projectFile, string filePath);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载远程项目
|
/// 加载远程项目
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -556,8 +601,7 @@ namespace Serein.Library.Api
|
|||||||
/// 清理加载的DLL(待更改)
|
/// 清理加载的DLL(待更改)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ClearAll();
|
void ClearAll();
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始运行
|
/// 开始运行
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -567,18 +611,27 @@ namespace Serein.Library.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="startNodeGuid"></param>
|
/// <param name="startNodeGuid"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task StartFlowInSelectNodeAsync(string startNodeGuid);
|
Task StartAsyncInSelectNode(string startNodeGuid);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 结束运行
|
/// 结束运行
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Exit();
|
void ExitFlow();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移动了某个节点(远程插件使用)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nodeGuid"></param>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <param name="y"></param>
|
||||||
|
void MoveNode(string nodeGuid,double x, double y);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置流程起点节点
|
/// 设置流程起点节点
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeGuid"></param>
|
/// <param name="nodeGuid"></param>
|
||||||
void SetStartNode(string nodeGuid);
|
void SetStartNode(string nodeGuid);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 在两个节点之间创建连接关系
|
/// 在两个节点之间创建连接关系
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -586,6 +639,7 @@ namespace Serein.Library.Api
|
|||||||
/// <param name="toNodeGuid">目标节点Guid</param>
|
/// <param name="toNodeGuid">目标节点Guid</param>
|
||||||
/// <param name="connectionType">连接类型</param>
|
/// <param name="connectionType">连接类型</param>
|
||||||
void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
|
void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建节点/区域/基础控件
|
/// 创建节点/区域/基础控件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -601,6 +655,7 @@ namespace Serein.Library.Api
|
|||||||
/// <param name="toNodeGuid">目标节点</param>
|
/// <param name="toNodeGuid">目标节点</param>
|
||||||
/// <param name="connectionType">连接类型</param>
|
/// <param name="connectionType">连接类型</param>
|
||||||
void RemoveConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
|
void RemoveConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 移除节点/区域/基础控件
|
/// 移除节点/区域/基础控件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -612,6 +667,7 @@ namespace Serein.Library.Api
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeGuid"></param>
|
/// <param name="nodeGuid"></param>
|
||||||
void ActivateFlipflopNode(string nodeGuid);
|
void ActivateFlipflopNode(string nodeGuid);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 终结一个全局触发器,在它触发后将不会再次监听消息(表现为已经启动的触发器至少会再次处理一次消息,后面版本再修正这个非预期行为)
|
/// 终结一个全局触发器,在它触发后将不会再次监听消息(表现为已经启动的触发器至少会再次处理一次消息,后面版本再修正这个非预期行为)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -129,7 +129,15 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
|
|||||||
foreach ((var model, var method) in methods)
|
foreach ((var model, var method) in methods)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"theme value : {model.ThemeValue}");
|
Console.WriteLine($"theme value : {model.ThemeValue}");
|
||||||
handlemodule.AddHandleConfigs(model, socketControlBase, method, onExceptionTracking);
|
try
|
||||||
|
{
|
||||||
|
handlemodule.AddHandleConfigs(model, socketControlBase, method, onExceptionTracking);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
|
||||||
|
Console.WriteLine($"error in add method: {method.Name}{Environment.NewLine}{ex}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -147,7 +155,6 @@ namespace Serein.Library.Network.WebSocketCommunication.Handle
|
|||||||
{
|
{
|
||||||
foreach (var module in MyHandleModuleDict.Values)
|
foreach (var module in MyHandleModuleDict.Values)
|
||||||
{
|
{
|
||||||
|
|
||||||
module.HandleSocketMsg(RecoverAsync, json);
|
module.HandleSocketMsg(RecoverAsync, json);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Serein.Library.Attributes;
|
using Serein.Library.Attributes;
|
||||||
|
using Serein.Library.Network.WebSocketCommunication.Handle;
|
||||||
using Serein.Library.Web;
|
using Serein.Library.Web;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@@ -13,35 +14,58 @@ using System.Threading.Tasks;
|
|||||||
namespace Serein.Library.Network.WebSocketCommunication
|
namespace Serein.Library.Network.WebSocketCommunication
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket客户端
|
||||||
|
/// </summary>
|
||||||
[AutoRegister]
|
[AutoRegister]
|
||||||
public class WebSocketClient
|
public class WebSocketClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket客户端
|
||||||
|
/// </summary>
|
||||||
public WebSocketClient()
|
public WebSocketClient()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 消息处理
|
||||||
|
/// </summary>
|
||||||
|
public WebSocketMsgHandleHelper MsgHandleHelper { get; } = new WebSocketMsgHandleHelper();
|
||||||
|
|
||||||
private ClientWebSocket _client = new ClientWebSocket();
|
private ClientWebSocket _client = new ClientWebSocket();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接到指定WebSocket Server服务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uri"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task ConnectAsync(string uri)
|
public async Task ConnectAsync(string uri)
|
||||||
{
|
{
|
||||||
await _client.ConnectAsync(new Uri(uri), CancellationToken.None);
|
await _client.ConnectAsync(new Uri(uri), CancellationToken.None);
|
||||||
await ReceiveAsync();
|
await ReceiveAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public async Task SendAsync(WebSocket webSocket,string message)
|
/// 发送消息
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="webSocket"></param>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task SendAsync(string message)
|
||||||
{
|
{
|
||||||
var buffer = Encoding.UTF8.GetBytes(message);
|
var buffer = Encoding.UTF8.GetBytes(message);
|
||||||
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
await _client.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 开始处理消息
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
private async Task ReceiveAsync()
|
private async Task ReceiveAsync()
|
||||||
{
|
{
|
||||||
var buffer = new byte[1024];
|
var buffer = new byte[1024];
|
||||||
|
|
||||||
while (_client.State == WebSocketState.Open)
|
while (_client.State == WebSocketState.Open)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -54,8 +78,7 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
||||||
|
_ = MsgHandleHelper.HandleMsgAsync(SendAsync, message); // 处理消息
|
||||||
|
|
||||||
Debug.WriteLine($"Received: {message}");
|
Debug.WriteLine($"Received: {message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,9 +90,6 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Serein.Library.Attributes;
|
using Serein.Library.Attributes;
|
||||||
using Serein.Library.Network.WebSocketCommunication.Handle;
|
using Serein.Library.Network.WebSocketCommunication.Handle;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -14,6 +15,84 @@ using System.Threading.Tasks;
|
|||||||
|
|
||||||
namespace Serein.Library.Network.WebSocketCommunication
|
namespace Serein.Library.Network.WebSocketCommunication
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket JSON 消息授权管理
|
||||||
|
/// </summary>
|
||||||
|
public class WebSocketAuthorizedHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket JSON 消息授权管理
|
||||||
|
/// </summary>
|
||||||
|
public WebSocketAuthorizedHelper(string addresPort,string token, Func<dynamic, Task<bool>> inspectionAuthorizedFunc)
|
||||||
|
{
|
||||||
|
this.AddresPort = addresPort;
|
||||||
|
this.TokenKey = token;
|
||||||
|
this.InspectionAuthorizedFunc = inspectionAuthorizedFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 客户端地址
|
||||||
|
/// </summary>
|
||||||
|
public string AddresPort { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已经鉴权
|
||||||
|
/// </summary>
|
||||||
|
public bool IsAuthorized { get => isAuthorized; } //set => isAuthorized = value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已经鉴权
|
||||||
|
/// </summary>
|
||||||
|
private bool isAuthorized;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 授权字段
|
||||||
|
/// </summary>
|
||||||
|
private readonly string TokenKey;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理消息授权事件
|
||||||
|
/// </summary>
|
||||||
|
private readonly Func<dynamic, Task<bool>> InspectionAuthorizedFunc;
|
||||||
|
|
||||||
|
private SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理消息授权
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="message"></param>
|
||||||
|
public async Task HandleAuthorized(string message)
|
||||||
|
{
|
||||||
|
if(!isAuthorized && semaphoreSlim is null) // 需要重新授权
|
||||||
|
{
|
||||||
|
semaphoreSlim = new SemaphoreSlim(1);
|
||||||
|
}
|
||||||
|
await semaphoreSlim.WaitAsync(1);
|
||||||
|
if(isAuthorized) // 授权通过,无须再次检查授权
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
JObject json = JObject.Parse(message);
|
||||||
|
if(json.TryGetValue(TokenKey,out var token))
|
||||||
|
{
|
||||||
|
// 交给之前定义的授权方法进行判断
|
||||||
|
isAuthorized = await InspectionAuthorizedFunc?.Invoke(token);
|
||||||
|
if (isAuthorized)
|
||||||
|
{
|
||||||
|
// 授权通过,释放资源
|
||||||
|
semaphoreSlim.Release();
|
||||||
|
semaphoreSlim.Dispose();
|
||||||
|
semaphoreSlim = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
isAuthorized = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WebSocket服务类
|
/// WebSocket服务类
|
||||||
@@ -28,6 +107,36 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
|
|
||||||
private HttpListener listener;
|
private HttpListener listener;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建无须授权验证的WebSocket服务端
|
||||||
|
/// </summary>
|
||||||
|
public WebSocketServer()
|
||||||
|
{
|
||||||
|
this.AuthorizedClients = new ConcurrentDictionary<string, WebSocketAuthorizedHelper>();
|
||||||
|
this.InspectionAuthorizedFunc = (tokenObj) => Task.FromResult(true);
|
||||||
|
this.IsNeedInspectionAuthorized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 创建需要授权验证的WebSocket服务端
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tokenKey">token 字段</param>
|
||||||
|
/// <param name="inspectionAuthorizedFunc">验证token的方法</param>
|
||||||
|
public WebSocketServer(string tokenKey, Func<dynamic, Task<bool>> inspectionAuthorizedFunc)
|
||||||
|
{
|
||||||
|
this.TokenKey = tokenKey;
|
||||||
|
this.AuthorizedClients = new ConcurrentDictionary<string, WebSocketAuthorizedHelper>();
|
||||||
|
this.InspectionAuthorizedFunc = inspectionAuthorizedFunc;
|
||||||
|
this.IsNeedInspectionAuthorized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 授权
|
||||||
|
/// </summary>
|
||||||
|
public ConcurrentDictionary<string, WebSocketAuthorizedHelper> AuthorizedClients;
|
||||||
|
private readonly string TokenKey;
|
||||||
|
private readonly Func<dynamic, Task<bool>> InspectionAuthorizedFunc;
|
||||||
|
private bool IsNeedInspectionAuthorized = false;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 进行监听服务
|
/// 进行监听服务
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -37,6 +146,7 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
{
|
{
|
||||||
listener = new HttpListener();
|
listener = new HttpListener();
|
||||||
listener.Prefixes.Add(url);
|
listener.Prefixes.Add(url);
|
||||||
|
await Console.Out.WriteLineAsync($"WebSocket消息处理已启动[{url}]");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
listener.Start();
|
listener.Start();
|
||||||
@@ -46,7 +156,6 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
await Console.Out.WriteLineAsync(ex.Message);
|
await Console.Out.WriteLineAsync(ex.Message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
@@ -56,11 +165,20 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
string clientPoint = context.Request.RemoteEndPoint?.ToString();
|
string clientPoint = context.Request.RemoteEndPoint?.ToString();
|
||||||
|
|
||||||
await Console.Out.WriteLineAsync($"新的连接加入:{clientPoint}");
|
await Console.Out.WriteLineAsync($"新的连接加入:{clientPoint}");
|
||||||
|
|
||||||
if (context.Request.IsWebSocketRequest)
|
if (context.Request.IsWebSocketRequest)
|
||||||
{
|
{
|
||||||
var webSocketContext = await context.AcceptWebSocketAsync(null); //新连接
|
WebSocketAuthorizedHelper authorizedHelper = null;
|
||||||
|
if (IsNeedInspectionAuthorized)
|
||||||
|
{
|
||||||
|
if (AuthorizedClients.TryAdd(clientPoint, new WebSocketAuthorizedHelper(clientPoint, TokenKey, InspectionAuthorizedFunc)))
|
||||||
|
{
|
||||||
|
AuthorizedClients.TryGetValue(clientPoint, out authorizedHelper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_ = HandleWebSocketAsync(webSocketContext.WebSocket); // 处理消息
|
var webSocketContext = await context.AcceptWebSocketAsync(null); //新连接
|
||||||
|
_ = HandleWebSocketAsync(webSocketContext.WebSocket, authorizedHelper); // 处理消息
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -79,12 +197,21 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
listener?.Stop();
|
listener?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task HandleWebSocketAsync(WebSocket webSocket)
|
private async Task HandleWebSocketAsync(WebSocket webSocket, WebSocketAuthorizedHelper authorizedHelper)
|
||||||
{
|
{
|
||||||
Func<string,Task> SendAsync = async (text) =>
|
// 需要授权,却没有成功创建授权类,关闭连接
|
||||||
|
if (IsNeedInspectionAuthorized && authorizedHelper is null)
|
||||||
|
{
|
||||||
|
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Func<string, Task> SendAsync = async (text) =>
|
||||||
{
|
{
|
||||||
await WebSocketServer.SendAsync(webSocket, text);
|
await WebSocketServer.SendAsync(webSocket, text);
|
||||||
};
|
};
|
||||||
|
|
||||||
var buffer = new byte[1024];
|
var buffer = new byte[1024];
|
||||||
while (webSocket.State == WebSocketState.Open)
|
while (webSocket.State == WebSocketState.Open)
|
||||||
{
|
{
|
||||||
@@ -93,21 +220,45 @@ namespace Serein.Library.Network.WebSocketCommunication
|
|||||||
{
|
{
|
||||||
SendAsync = null;
|
SendAsync = null;
|
||||||
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
|
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", CancellationToken.None);
|
||||||
|
if (IsNeedInspectionAuthorized)
|
||||||
|
{
|
||||||
|
AuthorizedClients.TryRemove(authorizedHelper.AddresPort, out var _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
var message = Encoding.UTF8.GetString(buffer, 0, result.Count); // 序列为文本
|
||||||
|
if(!IsNeedInspectionAuthorized)
|
||||||
_ = MsgHandleHelper.HandleMsgAsync(SendAsync, message);
|
{
|
||||||
|
// 无须授权
|
||||||
//foreach (var item in HandldHelpers)
|
_ = MsgHandleHelper.HandleMsgAsync(SendAsync, message); // 处理消息
|
||||||
//{
|
|
||||||
// await item.HandleSocketMsg(webSocket, message);
|
}
|
||||||
//}
|
else
|
||||||
//Console.WriteLine($"Received: {message}");
|
{
|
||||||
//var echoMessage = Encoding.UTF8.GetBytes(message);
|
// 需要授权
|
||||||
//await webSocket.SendAsync(new ArraySegment<byte>(echoMessage, 0, echoMessage.Length), result.MessageType, result.EndOfMessage, CancellationToken.None);
|
if (!authorizedHelper.IsAuthorized)
|
||||||
|
{
|
||||||
|
// 该连接尚未验证授权,尝试检测授权
|
||||||
|
_ = SendAsync("正在授权");
|
||||||
|
await authorizedHelper.HandleAuthorized(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (authorizedHelper.IsAuthorized)
|
||||||
|
{
|
||||||
|
// 该连接通过了验证
|
||||||
|
_ = SendAsync("授权成功");
|
||||||
|
_ = MsgHandleHelper.HandleMsgAsync(SendAsync, message); // 处理消息
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ = SendAsync("授权失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ namespace Serein.Library.Attributes
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 注册顺序
|
||||||
|
/// </summary>
|
||||||
public enum RegisterSequence
|
public enum RegisterSequence
|
||||||
{ /// <summary>
|
{ /// <summary>
|
||||||
/// 不自动初始化
|
/// 不自动初始化
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<Version>1.0.13</Version>
|
||||||
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
<TargetFrameworks>net8.0;net462</TargetFrameworks>
|
||||||
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
<BaseOutputPath>D:\Project\C#\DynamicControl\SereinFlow\.Output</BaseOutputPath>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using Serein.Library.Api;
|
|||||||
using Serein.Library.Attributes;
|
using Serein.Library.Attributes;
|
||||||
using Serein.Library.Entity;
|
using Serein.Library.Entity;
|
||||||
using Serein.Library.Enums;
|
using Serein.Library.Enums;
|
||||||
|
using Serein.Library.Network.WebSocketCommunication;
|
||||||
using Serein.Library.Utils;
|
using Serein.Library.Utils;
|
||||||
using Serein.NodeFlow.Base;
|
using Serein.NodeFlow.Base;
|
||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
@@ -40,53 +41,144 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
public List<library> get(){
|
|
||||||
}
|
|
||||||
|
|
||||||
libray
|
public List<library> get(){
|
||||||
{
|
|
||||||
string dllname,
|
|
||||||
MethodInfo[] nodeinfos
|
|
||||||
}
|
|
||||||
|
|
||||||
methodInfo{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libray
|
||||||
|
{
|
||||||
*/
|
string dllname,
|
||||||
|
MethodInfo[] nodeinfos
|
||||||
|
}
|
||||||
|
|
||||||
|
methodInfo{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
void StopRemoteServer()//结束远程管理
|
||||||
|
async Task StartAsync()//异步运行
|
||||||
|
void ExitFlow()//退出
|
||||||
|
Task StartAsyncInSelectNode(string startNodeGuid)//从选定节点开始运行
|
||||||
|
void ActivateFlipflopNode(string nodeGuid)//激活全局触发器
|
||||||
|
void TerminateFlipflopNode(string nodeGuid)//关闭全局触发器
|
||||||
|
object GetEnvInfo() // 获取当前环境信息(远程连接)
|
||||||
|
void LoadProject(SereinProjectData project, string filePath) //加载项目文件
|
||||||
|
void LoadRemoteProject(string addres, int port, string token) //加载远程项目
|
||||||
|
SereinProjectData GetProjectInfo() // 序列化当前项目的依赖信息、节点信息
|
||||||
|
void LoadDll(string dllPath) //从文件路径中加载DLL
|
||||||
|
bool RemoteDll(string assemblyFullName) //移除DLL
|
||||||
|
NodeModelBase CreateNode(NodeControlType nodeControlType, Position position, MethodDetailsInfo? methodDetailsInfo = null) //流程正在运行时创建节点
|
||||||
|
void RemoveNode(string nodeGuid) //移除节点
|
||||||
|
void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType) // 连接节点
|
||||||
|
void RemoveConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType) //移除连接关系
|
||||||
|
|
||||||
|
void MoveNode(string nodeGuid,double x,double y) //移动了某个节点(远程插件使用)
|
||||||
|
void SetStartNode(string newNodeGuid) //设置起点控件
|
||||||
|
bool SetNodeInterrupt(string nodeGuid, InterruptClass interruptClass) //中断指定节点,并指定中断等级。
|
||||||
|
bool AddInterruptExpression(string key, string expression)//添加表达式中断
|
||||||
|
void SetMonitorObjState(string key, bool isMonitor) // 设置对象的监视状态
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 运行环境
|
/// 运行环境
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FlowEnvironment : IFlowEnvironment, ISereinIOC
|
[AutoSocketModule(ThemeKey = "theme", DataKey = "data")]
|
||||||
|
public class FlowEnvironment : IFlowEnvironment, ISereinIOC, ISocketHandleModule
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 流程运行环境
|
||||||
|
/// </summary>
|
||||||
public FlowEnvironment()
|
public FlowEnvironment()
|
||||||
{
|
{
|
||||||
sereinIOC = new SereinIOC();
|
sereinIOC = new SereinIOC();
|
||||||
ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
ChannelFlowInterrupt = new ChannelFlowInterrupt();
|
||||||
//LoadedAssemblyPaths = new List<string>();
|
|
||||||
//LoadedAssemblies = new List<Assembly>();
|
|
||||||
//MethodDetailss = new List<MethodDetails>();
|
|
||||||
//Nodes = new Dictionary<string, NodeModelBase>();
|
|
||||||
//FlipflopNodes = new List<SingleFlipflopNode>();
|
|
||||||
IsGlobalInterrupt = false;
|
IsGlobalInterrupt = false;
|
||||||
flowStarter = null;
|
flowStarter = null;
|
||||||
|
|
||||||
sereinIOC.OnIOCMembersChanged += e => this?.OnIOCMembersChanged?.Invoke(e) ; // 监听IOC容器的注册
|
sereinIOC.OnIOCMembersChanged += e => this?.OnIOCMembersChanged?.Invoke(e) ; // 监听IOC容器的注册
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket处理
|
||||||
|
/// </summary>
|
||||||
|
public Guid HandleGuid { get; } = new Guid();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程环境远程管理服务
|
||||||
|
/// </summary>
|
||||||
|
private WebSocketServer FlowEnvRemoteWebSocket;
|
||||||
|
|
||||||
|
|
||||||
|
private async Task<bool> InspectionAuthorized(dynamic token)
|
||||||
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
var tokenValue = token.ToString();
|
||||||
|
if ("123456".Equals(tokenValue))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 打开远程管理
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="port"></param>
|
||||||
|
public async Task StartRemoteServerAsync(int port = 7525)
|
||||||
|
{
|
||||||
|
FlowEnvRemoteWebSocket ??= new WebSocketServer("token", InspectionAuthorized);
|
||||||
|
FlowEnvRemoteWebSocket.MsgHandleHelper.AddModule(this,
|
||||||
|
(ex, send) =>
|
||||||
|
{
|
||||||
|
send(new
|
||||||
|
{
|
||||||
|
code = 400,
|
||||||
|
ex = ex.Message
|
||||||
|
});
|
||||||
|
});
|
||||||
|
var url = $"http://*:{port}/";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await FlowEnvRemoteWebSocket.StartAsync(url);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
FlowEnvRemoteWebSocket.MsgHandleHelper.RemoveModule(this);
|
||||||
|
Console.WriteLine("打开远程管理异常:" + ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 结束远程管理
|
||||||
|
/// </summary>
|
||||||
|
[AutoSocketHandle]
|
||||||
|
public void StopRemoteServer()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FlowEnvRemoteWebSocket.Stop();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("结束远程管理异常:" + ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 节点的命名空间
|
/// 节点的命名空间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const string SpaceName = $"{nameof(Serein)}.{nameof(Serein.NodeFlow)}.{nameof(Serein.NodeFlow.Model)}";
|
public const string SpaceName = $"{nameof(Serein)}.{nameof(Serein.NodeFlow)}.{nameof(Serein.NodeFlow.Model)}";
|
||||||
|
|
||||||
#region 环境接口事件
|
#region 环境运行事件
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 加载Dll
|
/// 加载Dll
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -150,7 +242,13 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 节点需要定位
|
/// 节点需要定位
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event NodeLocatedHandler? OnNodeLocate;
|
public event NodeLocatedHandler? OnNodeLocated;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 节点移动了(远程插件)
|
||||||
|
/// </summary>
|
||||||
|
public event NodeMovedHandler? OnNodeMoved;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 属性
|
#region 属性
|
||||||
@@ -268,14 +366,13 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 基础接口
|
#region 环境对外接口
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异步运行
|
/// 异步运行
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public async Task StartAsync()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
ChannelFlowInterrupt?.CancelAllTasks();
|
ChannelFlowInterrupt?.CancelAllTasks();
|
||||||
@@ -311,12 +408,18 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
if (this.FlipFlopState == RunState.Completion)
|
if (this.FlipFlopState == RunState.Completion)
|
||||||
{
|
{
|
||||||
this.Exit(); // 未运行触发器时,才会调用结束方法
|
this.ExitFlow(); // 未运行触发器时,才会调用结束方法
|
||||||
}
|
}
|
||||||
flowStarter = null;
|
flowStarter = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartFlowInSelectNodeAsync(string startNodeGuid)
|
/// <summary>
|
||||||
|
/// 从选定节点开始运行
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startNodeGuid"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
|
public async Task StartAsyncInSelectNode(string startNodeGuid)
|
||||||
{
|
{
|
||||||
if (flowStarter is null)
|
if (flowStarter is null)
|
||||||
{
|
{
|
||||||
@@ -340,7 +443,8 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 退出
|
/// 退出
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Exit()
|
[AutoSocketHandle]
|
||||||
|
public void ExitFlow()
|
||||||
{
|
{
|
||||||
ChannelFlowInterrupt?.CancelAllTasks();
|
ChannelFlowInterrupt?.CancelAllTasks();
|
||||||
flowStarter?.Exit();
|
flowStarter?.Exit();
|
||||||
@@ -359,6 +463,74 @@ namespace Serein.NodeFlow
|
|||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 激活全局触发器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nodeGuid"></param>
|
||||||
|
[AutoSocketHandle]
|
||||||
|
public void ActivateFlipflopNode(string nodeGuid)
|
||||||
|
{
|
||||||
|
var nodeModel = GuidToModel(nodeGuid);
|
||||||
|
if (nodeModel is null) return;
|
||||||
|
if (flowStarter is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
|
||||||
|
{
|
||||||
|
if (this.FlowState != RunState.Completion
|
||||||
|
&& flipflopNode.NotExitPreviousNode()) // 正在运行,且该触发器没有上游节点
|
||||||
|
{
|
||||||
|
_ = flowStarter.RunGlobalFlipflopAsync(this, flipflopNode);// 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 关闭全局触发器
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nodeGuid"></param>
|
||||||
|
[AutoSocketHandle]
|
||||||
|
public void TerminateFlipflopNode(string nodeGuid)
|
||||||
|
{
|
||||||
|
var nodeModel = GuidToModel(nodeGuid);
|
||||||
|
if (nodeModel is null) return;
|
||||||
|
if (flowStarter is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
|
||||||
|
{
|
||||||
|
flowStarter.TerminateGlobalFlipflopRuning(flipflopNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取当前环境信息(远程连接)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
|
public object GetEnvInfo()
|
||||||
|
{
|
||||||
|
Dictionary<NodeLibrary, List<MethodDetailsInfo>> LibraryMds = [];
|
||||||
|
|
||||||
|
foreach (var mdskv in this.MethodDetailsOfLibrarys)
|
||||||
|
{
|
||||||
|
var library = mdskv.Key;
|
||||||
|
var mds = mdskv.Value;
|
||||||
|
foreach (var md in mds)
|
||||||
|
{
|
||||||
|
if (!LibraryMds.TryGetValue(library, out var t_mds))
|
||||||
|
{
|
||||||
|
t_mds = new List<MethodDetailsInfo>();
|
||||||
|
LibraryMds[library] = t_mds;
|
||||||
|
}
|
||||||
|
var mdInfo = md.ToInfo();
|
||||||
|
mdInfo.LibraryName = library.Assembly.GetName().FullName;
|
||||||
|
t_mds.Add(mdInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var project = this.GetProjectInfo();
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
project = project,
|
||||||
|
envNode = LibraryMds.Values,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 清除所有
|
/// 清除所有
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -376,6 +548,7 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="project"></param>
|
/// <param name="project"></param>
|
||||||
/// <param name="filePath"></param>
|
/// <param name="filePath"></param>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void LoadProject(SereinProjectData project, string filePath)
|
public void LoadProject(SereinProjectData project, string filePath)
|
||||||
{
|
{
|
||||||
// 加载项目配置文件
|
// 加载项目配置文件
|
||||||
@@ -515,6 +688,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <param name="addres">远程项目地址</param>
|
/// <param name="addres">远程项目地址</param>
|
||||||
/// <param name="port">远程项目端口</param>
|
/// <param name="port">远程项目端口</param>
|
||||||
/// <param name="token">密码</param>
|
/// <param name="token">密码</param>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void LoadRemoteProject(string addres, int port, string token)
|
public void LoadRemoteProject(string addres, int port, string token)
|
||||||
{
|
{
|
||||||
// -- 第1种,直接从远程环境复制所有dll信息,项目信息,在本地打开?(安全问题)
|
// -- 第1种,直接从远程环境复制所有dll信息,项目信息,在本地打开?(安全问题)
|
||||||
@@ -543,6 +717,7 @@ namespace Serein.NodeFlow
|
|||||||
/// 序列化当前项目的依赖信息、节点信息
|
/// 序列化当前项目的依赖信息、节点信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public SereinProjectData GetProjectInfo()
|
public SereinProjectData GetProjectInfo()
|
||||||
{
|
{
|
||||||
var projectData = new SereinProjectData()
|
var projectData = new SereinProjectData()
|
||||||
@@ -560,6 +735,7 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dllPath"></param>
|
/// <param name="dllPath"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void LoadDll(string dllPath)
|
public void LoadDll(string dllPath)
|
||||||
{
|
{
|
||||||
LoadDllNodeInfo(dllPath);
|
LoadDllNodeInfo(dllPath);
|
||||||
@@ -570,6 +746,7 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="assemblyFullName"></param>
|
/// <param name="assemblyFullName"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public bool RemoteDll(string assemblyFullName)
|
public bool RemoteDll(string assemblyFullName)
|
||||||
{
|
{
|
||||||
var library = Librarys.Values.FirstOrDefault(nl => assemblyFullName.Equals(nl.Assembly.FullName));
|
var library = Librarys.Values.FirstOrDefault(nl => assemblyFullName.Equals(nl.Assembly.FullName));
|
||||||
@@ -624,6 +801,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <param name="nodeControlType"></param>
|
/// <param name="nodeControlType"></param>
|
||||||
/// <param name="position"></param>
|
/// <param name="position"></param>
|
||||||
/// <param name="methodDetailsInfo">如果是表达式节点条件节点,该项为null</param>
|
/// <param name="methodDetailsInfo">如果是表达式节点条件节点,该项为null</param>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void CreateNode(NodeControlType nodeControlType, Position position, MethodDetailsInfo? methodDetailsInfo = null)
|
public void CreateNode(NodeControlType nodeControlType, Position position, MethodDetailsInfo? methodDetailsInfo = null)
|
||||||
{
|
{
|
||||||
MethodDetails? methodDetails = null;
|
MethodDetails? methodDetails = null;
|
||||||
@@ -656,6 +834,7 @@ namespace Serein.NodeFlow
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeGuid"></param>
|
/// <param name="nodeGuid"></param>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void RemoveNode(string nodeGuid)
|
public void RemoveNode(string nodeGuid)
|
||||||
{
|
{
|
||||||
var remoteNode = GuidToModel(nodeGuid);
|
var remoteNode = GuidToModel(nodeGuid);
|
||||||
@@ -710,6 +889,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <param name="fromNodeGuid">起始节点</param>
|
/// <param name="fromNodeGuid">起始节点</param>
|
||||||
/// <param name="toNodeGuid">目标节点</param>
|
/// <param name="toNodeGuid">目标节点</param>
|
||||||
/// <param name="connectionType">连接关系</param>
|
/// <param name="connectionType">连接关系</param>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
|
public void ConnectNode(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
|
||||||
{
|
{
|
||||||
// 获取起始节点与目标节点
|
// 获取起始节点与目标节点
|
||||||
@@ -729,6 +909,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <param name="toNodeGuid">目标节点Guid</param>
|
/// <param name="toNodeGuid">目标节点Guid</param>
|
||||||
/// <param name="connectionType">连接关系</param>
|
/// <param name="connectionType">连接关系</param>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void RemoveConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
|
public void RemoveConnect(string fromNodeGuid, string toNodeGuid, ConnectionType connectionType)
|
||||||
{
|
{
|
||||||
// 获取起始节点与目标节点
|
// 获取起始节点与目标节点
|
||||||
@@ -740,11 +921,12 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取方法描述
|
/// 获取方法描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
||||||
public bool TryGetMethodDetailsInfo(string name, out MethodDetailsInfo? md)
|
public bool TryGetMethodDetailsInfo(string name, out MethodDetailsInfo? md)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(name))
|
if (!string.IsNullOrEmpty(name))
|
||||||
@@ -792,11 +974,23 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移动了某个节点(远程插件使用)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="nodeGuid"></param>
|
||||||
|
/// <param name="x"></param>
|
||||||
|
/// <param name="y"></param>
|
||||||
|
[AutoSocketHandle]
|
||||||
|
public void MoveNode(string nodeGuid,double x,double y)
|
||||||
|
{
|
||||||
|
this.OnNodeMoved?.Invoke(new NodeMovedEventArgs(nodeGuid, x, y));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置起点控件
|
/// 设置起点控件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="newNodeGuid"></param>
|
/// <param name="newNodeGuid"></param>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void SetStartNode(string newNodeGuid)
|
public void SetStartNode(string newNodeGuid)
|
||||||
{
|
{
|
||||||
var newStartNodeModel = GuidToModel(newNodeGuid);
|
var newStartNodeModel = GuidToModel(newNodeGuid);
|
||||||
@@ -810,6 +1004,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <param name="nodeGuid">被中断的目标节点Guid</param>
|
/// <param name="nodeGuid">被中断的目标节点Guid</param>
|
||||||
/// <param name="interruptClass">中断级别</param>
|
/// <param name="interruptClass">中断级别</param>
|
||||||
/// <returns>操作是否成功</returns>
|
/// <returns>操作是否成功</returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public bool SetNodeInterrupt(string nodeGuid, InterruptClass interruptClass)
|
public bool SetNodeInterrupt(string nodeGuid, InterruptClass interruptClass)
|
||||||
{
|
{
|
||||||
var nodeModel = GuidToModel(nodeGuid);
|
var nodeModel = GuidToModel(nodeGuid);
|
||||||
@@ -845,9 +1040,10 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加表达式中断
|
/// 添加表达式中断
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeGuid"></param>
|
/// <param name="key">如果是节点,传入Guid;如果是对象,传入类型FullName</param>
|
||||||
/// <param name="expression"></param>
|
/// <param name="expression">合法的条件表达式</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public bool AddInterruptExpression(string key, string expression)
|
public bool AddInterruptExpression(string key, string expression)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrEmpty(expression)) return false;
|
if(string.IsNullOrEmpty(expression)) return false;
|
||||||
@@ -874,9 +1070,10 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 设置对象的监视状态
|
/// 设置对象的监视状态
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="obj"></param>
|
/// <param name="key">如果是节点,传入Guid;如果是对象,传入类型FullName</param>
|
||||||
/// <param name="isMonitor"></param>
|
/// <param name="isMonitor">ture监视对象;false取消对象监视</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
[AutoSocketHandle]
|
||||||
public void SetMonitorObjState(string key, bool isMonitor)
|
public void SetMonitorObjState(string key, bool isMonitor)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(key)) { return; }
|
if (string.IsNullOrEmpty(key)) { return; }
|
||||||
@@ -900,8 +1097,8 @@ namespace Serein.NodeFlow
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检查一个对象是否处于监听状态,如果是,则传出与该对象相关的表达式(用于中断),如果不是,则返回false。
|
/// 检查一个对象是否处于监听状态,如果是,则传出与该对象相关的表达式(用于中断),如果不是,则返回false。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeGuid"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="obj"></param>
|
/// <param name="exps"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public bool CheckObjMonitorState(string key, out List<string>? exps)
|
public bool CheckObjMonitorState(string key, out List<string>? exps)
|
||||||
{
|
{
|
||||||
@@ -910,9 +1107,11 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 启动器调用,节点数据更新通知
|
/// 启动器调用,运行到某个节点时触发了监视对象的更新(对象预览视图将会自动更新)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeGuid"></param>
|
/// <param name="nodeGuid"></param>
|
||||||
|
/// <param name="monitorData"></param>
|
||||||
|
/// <param name="sourceType"></param>
|
||||||
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
|
public void MonitorObjectNotification(string nodeGuid, object monitorData, MonitorObjectEventArgs.ObjSourceType sourceType)
|
||||||
{
|
{
|
||||||
OnMonitorObjectChange?.Invoke(new MonitorObjectEventArgs(nodeGuid, monitorData, sourceType));
|
OnMonitorObjectChange?.Invoke(new MonitorObjectEventArgs(nodeGuid, monitorData, sourceType));
|
||||||
@@ -929,38 +1128,7 @@ namespace Serein.NodeFlow
|
|||||||
OnInterruptTrigger?.Invoke(new InterruptTriggerEventArgs(nodeGuid, expression, type));
|
OnInterruptTrigger?.Invoke(new InterruptTriggerEventArgs(nodeGuid, expression, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 激活全局触发器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="nodeGuid"></param>
|
|
||||||
public void ActivateFlipflopNode(string nodeGuid)
|
|
||||||
{
|
|
||||||
var nodeModel = GuidToModel(nodeGuid);
|
|
||||||
if (nodeModel is null) return;
|
|
||||||
if (flowStarter is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
|
|
||||||
{
|
|
||||||
if (this.FlowState != RunState.Completion
|
|
||||||
&& flipflopNode.NotExitPreviousNode()) // 正在运行,且该触发器没有上游节点
|
|
||||||
{
|
|
||||||
_ = flowStarter.RunGlobalFlipflopAsync(this, flipflopNode);// 被父节点移除连接关系的子节点若为触发器,且无上级节点,则当前流程正在运行,则加载到运行环境中
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// <summary>
|
|
||||||
/// 关闭全局触发器
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="nodeGuid"></param>
|
|
||||||
public void TerminateFlipflopNode(string nodeGuid)
|
|
||||||
{
|
|
||||||
var nodeModel = GuidToModel(nodeGuid);
|
|
||||||
if (nodeModel is null) return;
|
|
||||||
if (flowStarter is not null && nodeModel is SingleFlipflopNode flipflopNode) // 子节点为触发器
|
|
||||||
{
|
|
||||||
flowStarter.TerminateGlobalFlipflopRuning(flipflopNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 环境执行中断
|
/// 环境执行中断
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -971,37 +1139,6 @@ namespace Serein.NodeFlow
|
|||||||
return ChannelFlowInterrupt.GetOrCreateChannelAsync(this.EnvName);
|
return ChannelFlowInterrupt.GetOrCreateChannelAsync(this.EnvName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 获取当前环境信息(远程连接)
|
|
||||||
/// </summary>
|
|
||||||
/// <returns></returns>
|
|
||||||
public object GetEnvInfo()
|
|
||||||
{
|
|
||||||
Dictionary<NodeLibrary, List<MethodDetailsInfo>> LibraryMds = [];
|
|
||||||
|
|
||||||
foreach (var mdskv in this.MethodDetailsOfLibrarys)
|
|
||||||
{
|
|
||||||
var library = mdskv.Key;
|
|
||||||
var mds = mdskv.Value;
|
|
||||||
foreach (var md in mds)
|
|
||||||
{
|
|
||||||
if (!LibraryMds.TryGetValue(library, out var t_mds))
|
|
||||||
{
|
|
||||||
t_mds = new List<MethodDetailsInfo>();
|
|
||||||
LibraryMds[library] = t_mds;
|
|
||||||
}
|
|
||||||
var mdInfo = md.ToInfo();
|
|
||||||
mdInfo.LibraryName = library.Assembly.GetName().FullName;
|
|
||||||
t_mds.Add(mdInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var project = this.GetProjectInfo();
|
|
||||||
return new
|
|
||||||
{
|
|
||||||
project = project,
|
|
||||||
envNode = LibraryMds.Values,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Guid 转 NodeModel
|
/// Guid 转 NodeModel
|
||||||
@@ -1345,7 +1482,7 @@ namespace Serein.NodeFlow
|
|||||||
/// <param name="nodeGuid"></param>
|
/// <param name="nodeGuid"></param>
|
||||||
public void NodeLocated(string nodeGuid)
|
public void NodeLocated(string nodeGuid)
|
||||||
{
|
{
|
||||||
OnNodeLocate?.Invoke(new NodeLocatedEventArgs(nodeGuid));
|
OnNodeLocated?.Invoke(new NodeLocatedEventArgs(nodeGuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -1471,8 +1608,18 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 流程环境需要的扩展方法
|
||||||
|
/// </summary>
|
||||||
public static class FlowFunc
|
public static class FlowFunc
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 程序集封装依赖
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="assembly"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static Library.Entity.Library ToLibrary(this Assembly assembly)
|
public static Library.Entity.Library ToLibrary(this Assembly assembly)
|
||||||
{
|
{
|
||||||
var tmp = assembly.ManifestModule.Name;
|
var tmp = assembly.ManifestModule.Name;
|
||||||
@@ -1483,6 +1630,12 @@ namespace Serein.NodeFlow
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 触发器运行后状态转为对应的后继分支类别
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flowStateType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
public static ConnectionType ToContentType(this FlipflopStateType flowStateType)
|
public static ConnectionType ToContentType(this FlipflopStateType flowStateType)
|
||||||
{
|
{
|
||||||
return flowStateType switch
|
return flowStateType switch
|
||||||
@@ -1495,38 +1648,11 @@ namespace Serein.NodeFlow
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public static Type? ControlTypeToModel(this NodeControlType nodeControlType)
|
/// 判断 触发器节点 是否存在上游分支
|
||||||
{
|
/// </summary>
|
||||||
// 确定创建的节点类型
|
/// <param name="node"></param>
|
||||||
Type? nodeType = nodeControlType switch
|
/// <returns></returns>
|
||||||
{
|
|
||||||
NodeControlType.Action => typeof(SingleActionNode),
|
|
||||||
NodeControlType.Flipflop => typeof(SingleFlipflopNode),
|
|
||||||
|
|
||||||
NodeControlType.ExpOp => typeof(SingleExpOpNode),
|
|
||||||
NodeControlType.ExpCondition => typeof(SingleConditionNode),
|
|
||||||
NodeControlType.ConditionRegion => typeof(CompositeConditionNode),
|
|
||||||
_ => null
|
|
||||||
};
|
|
||||||
return nodeType;
|
|
||||||
}
|
|
||||||
public static NodeControlType ModelToControlType(this NodeControlType nodeControlType)
|
|
||||||
{
|
|
||||||
var type = nodeControlType.GetType();
|
|
||||||
NodeControlType controlType = type switch
|
|
||||||
{
|
|
||||||
Type when type == typeof(SingleActionNode) => NodeControlType.Action,
|
|
||||||
Type when type == typeof(SingleFlipflopNode) => NodeControlType.Flipflop,
|
|
||||||
|
|
||||||
Type when type == typeof(SingleExpOpNode) => NodeControlType.ExpOp,
|
|
||||||
Type when type == typeof(SingleConditionNode) => NodeControlType.ExpCondition,
|
|
||||||
Type when type == typeof(CompositeConditionNode) => NodeControlType.ConditionRegion,
|
|
||||||
_ => NodeControlType.None,
|
|
||||||
};
|
|
||||||
return controlType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool NotExitPreviousNode(this SingleFlipflopNode node)
|
public static bool NotExitPreviousNode(this SingleFlipflopNode node)
|
||||||
{
|
{
|
||||||
ConnectionType[] ct = [ConnectionType.IsSucceed,
|
ConnectionType[] ct = [ConnectionType.IsSucceed,
|
||||||
@@ -1542,6 +1668,43 @@ namespace Serein.NodeFlow
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///// <summary>
|
||||||
|
///// 从节点类型枚举中转为对应的 Model 类型
|
||||||
|
///// </summary>
|
||||||
|
///// <param name="nodeControlType"></param>
|
||||||
|
///// <returns></returns>
|
||||||
|
//public static Type? ControlTypeToModel(this NodeControlType nodeControlType)
|
||||||
|
//{
|
||||||
|
// // 确定创建的节点类型
|
||||||
|
// Type? nodeType = nodeControlType switch
|
||||||
|
// {
|
||||||
|
// NodeControlType.Action => typeof(SingleActionNode),
|
||||||
|
// NodeControlType.Flipflop => typeof(SingleFlipflopNode),
|
||||||
|
|
||||||
|
// NodeControlType.ExpOp => typeof(SingleExpOpNode),
|
||||||
|
// NodeControlType.ExpCondition => typeof(SingleConditionNode),
|
||||||
|
// NodeControlType.ConditionRegion => typeof(CompositeConditionNode),
|
||||||
|
// _ => null
|
||||||
|
// };
|
||||||
|
// return nodeType;
|
||||||
|
//}
|
||||||
|
//public static NodeControlType ModelToControlType(this NodeControlType nodeControlType)
|
||||||
|
//{
|
||||||
|
// var type = nodeControlType.GetType();
|
||||||
|
// NodeControlType controlType = type switch
|
||||||
|
// {
|
||||||
|
// Type when type == typeof(SingleActionNode) => NodeControlType.Action,
|
||||||
|
// Type when type == typeof(SingleFlipflopNode) => NodeControlType.Flipflop,
|
||||||
|
|
||||||
|
// Type when type == typeof(SingleExpOpNode) => NodeControlType.ExpOp,
|
||||||
|
// Type when type == typeof(SingleConditionNode) => NodeControlType.ExpCondition,
|
||||||
|
// Type when type == typeof(CompositeConditionNode) => NodeControlType.ConditionRegion,
|
||||||
|
// _ => NodeControlType.None,
|
||||||
|
// };
|
||||||
|
// return controlType;
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ namespace Serein.NodeFlow
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开始运行
|
/// 开始运行(需要准备好方法信息)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="env">运行环境</param>
|
/// <param name="env">运行环境</param>
|
||||||
/// <param name="nodes">环境中已加载的所有节点</param>
|
/// <param name="nodes">环境中已加载的所有节点</param>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
<Version>1.0.13</Version>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.9.34728.123
|
VisualStudioVersion = 17.9.34728.123
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.WorkBench", "WorkBench\Serein.WorkBench.csproj", "{EC933A9F-DAD3-4D26-BF27-DA9DE5263BCD}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Workbench", "WorkBench\Serein.Workbench.csproj", "{EC933A9F-DAD3-4D26-BF27-DA9DE5263BCD}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Library.Core", "Library.Core\Serein.Library.Core.csproj", "{4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Library.Core", "Library.Core\Serein.Library.Core.csproj", "{4A7D23E7-B05C-4B6D-A8B9-1A488DC356FD}"
|
||||||
EndProject
|
EndProject
|
||||||
@@ -22,10 +22,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net462DllTest", "Net462DllT
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Extend.RemoteControl", "Extend.FlowRemoteManagement\Serein.Extend.RemoteControl.csproj", "{3E568C47-74C6-4C28-9D43-C9BA29008DB7}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.Extend.RemoteControl", "Extend.FlowRemoteManagement\Serein.Extend.RemoteControl.csproj", "{3E568C47-74C6-4C28-9D43-C9BA29008DB7}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.WorkBench.Remote", "WorkBench.Remote\Serein.WorkBench.Remote.csproj", "{D550688A-4EAB-4872-8243-66D39FE3817D}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.WorkBench.ControlLibrary.Core", "WorkBench.ControlLibrary.Core\Serein.WorkBench.ControlLibrary.Core.csproj", "{789E3885-3D64-461B-BEF1-DC965E7CEF57}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.FlowStartTool", "FlowStartTool\Serein.FlowStartTool.csproj", "{38D0FA92-5139-4616-A41E-8186AA4C1532}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Serein.FlowStartTool", "FlowStartTool\Serein.FlowStartTool.csproj", "{38D0FA92-5139-4616-A41E-8186AA4C1532}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
@@ -62,14 +58,6 @@ Global
|
|||||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3E568C47-74C6-4C28-9D43-C9BA29008DB7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{D550688A-4EAB-4872-8243-66D39FE3817D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{D550688A-4EAB-4872-8243-66D39FE3817D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{D550688A-4EAB-4872-8243-66D39FE3817D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{D550688A-4EAB-4872-8243-66D39FE3817D}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{789E3885-3D64-461B-BEF1-DC965E7CEF57}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{789E3885-3D64-461B-BEF1-DC965E7CEF57}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{789E3885-3D64-461B-BEF1-DC965E7CEF57}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{789E3885-3D64-461B-BEF1-DC965E7CEF57}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{38D0FA92-5139-4616-A41E-8186AA4C1532}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Application x:Class="Serein.WorkBench.App"
|
<Application x:Class="Serein.Workbench.App"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench"
|
xmlns:local="clr-namespace:Serein.Workbench"
|
||||||
StartupUri="MainWindow.xaml"
|
StartupUri="MainWindow.xaml"
|
||||||
Startup="Application_Startup">
|
Startup="Application_Startup">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using Serein.NodeFlow.Tool;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace Serein.WorkBench
|
namespace Serein.Workbench
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interaction logic for App.xaml
|
/// Interaction logic for App.xaml
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Window x:Class="Serein.WorkBench.LogWindow"
|
<Window x:Class="Serein.Workbench.LogWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench"
|
xmlns:local="clr-namespace:Serein.Workbench"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Topmost="True"
|
Topmost="True"
|
||||||
Title="LogWindow" Height="600" Width="400"
|
Title="LogWindow" Height="600" Width="400"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace Serein.WorkBench
|
namespace Serein.Workbench
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DebugWindow.xaml 的交互逻辑
|
/// DebugWindow.xaml 的交互逻辑
|
||||||
@@ -23,7 +23,7 @@ namespace Serein.WorkBench
|
|||||||
private const int MaxLines = 1000; // 最大显示的行数
|
private const int MaxLines = 1000; // 最大显示的行数
|
||||||
private bool autoScroll = true; // 自动滚动标识
|
private bool autoScroll = true; // 自动滚动标识
|
||||||
private int flushThreshold = 1000; // 设置日志刷新阈值
|
private int flushThreshold = 1000; // 设置日志刷新阈值
|
||||||
private const int maxFlushSize = 10000; // 每次最大刷新字符数
|
private const int maxFlushSize = 1000; // 每次最大刷新字符数
|
||||||
|
|
||||||
public LogWindow()
|
public LogWindow()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<Window x:Class="Serein.WorkBench.MainWindow"
|
<Window x:Class="Serein.Workbench.MainWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench"
|
xmlns:local="clr-namespace:Serein.Workbench"
|
||||||
xmlns:tool="clr-namespace:Serein.WorkBench.Tool.Converters"
|
xmlns:tool="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||||
xmlns:nodeView="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:nodeView="clr-namespace:Serein.Workbench.Node.View"
|
||||||
xmlns:themes="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||||
Title="Dynamic Node Flow" Height="900" Width="1400"
|
Title="Dynamic Node Flow" Height="900" Width="1400"
|
||||||
AllowDrop="True" Drop="Window_Drop" DragOver="Window_DragOver"
|
AllowDrop="True" Drop="Window_Drop" DragOver="Window_DragOver"
|
||||||
Loaded="Window_Loaded"
|
Loaded="Window_Loaded"
|
||||||
@@ -36,11 +36,10 @@
|
|||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Menu DockPanel.Dock="Top" Grid.Row="0" Height="20">
|
<Menu DockPanel.Dock="Top" Grid.Row="0" Height="20">
|
||||||
<MenuItem Header="文件">
|
<MenuItem Header="项目">
|
||||||
<!--菜单项为MenuItem,文字使用属性 Header-->
|
<!--菜单项为MenuItem,文字使用属性 Header-->
|
||||||
<MenuItem Header="保存项目" Click="ButtonSaveFile_Click" ></MenuItem>
|
<MenuItem Header="保存项目" Click="ButtonSaveFile_Click" ></MenuItem>
|
||||||
<MenuItem Header="打开本地文件" Click="OpenLocalProject_Click"></MenuItem>
|
<MenuItem Header="打开本地文件" Click="ButtonOpenLocalProject_Click"></MenuItem>
|
||||||
<MenuItem Header="连接远程环境" Click="OpenRemoteProject_Click"></MenuItem>
|
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuItem Header="调试">
|
<MenuItem Header="调试">
|
||||||
<MenuItem Header="运行(从起始节点)" Click="ButtonDebugRun_Click"></MenuItem>
|
<MenuItem Header="运行(从起始节点)" Click="ButtonDebugRun_Click"></MenuItem>
|
||||||
@@ -51,6 +50,11 @@
|
|||||||
<MenuItem Header="输出窗口" Click="ButtonOpenConsoleOutWindow_Click"></MenuItem>
|
<MenuItem Header="输出窗口" Click="ButtonOpenConsoleOutWindow_Click"></MenuItem>
|
||||||
<MenuItem Header="重置画布" Click="ButtonResetCanvas_Click"></MenuItem>
|
<MenuItem Header="重置画布" Click="ButtonResetCanvas_Click"></MenuItem>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
|
<MenuItem Header="远程">
|
||||||
|
<MenuItem Header="启动远程服务" Click="ButtonStartRemoteServer_Click"></MenuItem>
|
||||||
|
|
||||||
|
<MenuItem Header="连接远程环境" Click="ButtonConnectionRemoteEnv_Click"></MenuItem>
|
||||||
|
</MenuItem>
|
||||||
<!--<MenuItem Header="说明"></MenuItem>-->
|
<!--<MenuItem Header="说明"></MenuItem>-->
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
@@ -107,8 +111,8 @@
|
|||||||
MouseLeftButtonDown ="FlowChartCanvas_MouseLeftButtonDown"
|
MouseLeftButtonDown ="FlowChartCanvas_MouseLeftButtonDown"
|
||||||
MouseLeftButtonUp="FlowChartCanvas_MouseLeftButtonUp"
|
MouseLeftButtonUp="FlowChartCanvas_MouseLeftButtonUp"
|
||||||
MouseDown="FlowChartCanvas_MouseDown"
|
MouseDown="FlowChartCanvas_MouseDown"
|
||||||
MouseMove="FlowChartCanvas_MouseMove"
|
|
||||||
MouseUp="FlowChartCanvas_MouseUp"
|
MouseUp="FlowChartCanvas_MouseUp"
|
||||||
|
MouseMove="FlowChartCanvas_MouseMove"
|
||||||
MouseWheel="FlowChartCanvas_MouseWheel"
|
MouseWheel="FlowChartCanvas_MouseWheel"
|
||||||
Drop="FlowChartCanvas_Drop"
|
Drop="FlowChartCanvas_Drop"
|
||||||
DragOver="FlowChartCanvas_DragOver">
|
DragOver="FlowChartCanvas_DragOver">
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ using Serein.NodeFlow.Base;
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.NodeFlow.Tool;
|
using Serein.NodeFlow.Tool;
|
||||||
using Serein.NodeFlow.Tool.SereinExpression;
|
using Serein.NodeFlow.Tool.SereinExpression;
|
||||||
using Serein.WorkBench.Node;
|
using Serein.Workbench.Node;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
using Serein.WorkBench.Themes;
|
using Serein.Workbench.Themes;
|
||||||
using Serein.WorkBench.tool;
|
using Serein.Workbench.tool;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
@@ -31,18 +32,21 @@ using System.Windows.Threading;
|
|||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using DataObject = System.Windows.DataObject;
|
using DataObject = System.Windows.DataObject;
|
||||||
|
|
||||||
namespace Serein.WorkBench
|
namespace Serein.Workbench
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 拖拽创建节点类型
|
/// 拖拽创建节点类型
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MouseNodeType
|
public static class MouseNodeType
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 创建来自DLL的节点
|
||||||
|
/// </summary>
|
||||||
public static string CreateDllNodeInCanvas { get; } = nameof(CreateDllNodeInCanvas);
|
public static string CreateDllNodeInCanvas { get; } = nameof(CreateDllNodeInCanvas);
|
||||||
|
/// <summary>
|
||||||
|
/// 创建基础节点
|
||||||
|
/// </summary>
|
||||||
public static string CreateBaseNodeInCanvas { get; } = nameof(CreateBaseNodeInCanvas);
|
public static string CreateBaseNodeInCanvas { get; } = nameof(CreateBaseNodeInCanvas);
|
||||||
//public static string RegionType { get; } = nameof(RegionType);
|
|
||||||
//public static string BaseNodeType { get; } = nameof(BaseNodeType);
|
|
||||||
//public static string DllNodeType { get; } = nameof(DllNodeType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -153,6 +157,7 @@ namespace Serein.WorkBench
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
logWindow = InitConsoleOut(); // 重定向 Console 输出
|
||||||
|
|
||||||
ViewModel = new MainWindowViewModel(this);
|
ViewModel = new MainWindowViewModel(this);
|
||||||
FlowEnvironment = ViewModel.FlowEnvironment;
|
FlowEnvironment = ViewModel.FlowEnvironment;
|
||||||
@@ -160,7 +165,6 @@ namespace Serein.WorkBench
|
|||||||
IOCObjectViewer.FlowEnvironment = FlowEnvironment;
|
IOCObjectViewer.FlowEnvironment = FlowEnvironment;
|
||||||
|
|
||||||
InitFlowEnvironmentEvent(); // 配置环境事件
|
InitFlowEnvironmentEvent(); // 配置环境事件
|
||||||
logWindow = InitConsoleOut(); // 重定向 Console 输出
|
|
||||||
|
|
||||||
canvasTransformGroup = new TransformGroup();
|
canvasTransformGroup = new TransformGroup();
|
||||||
scaleTransform = new ScaleTransform();
|
scaleTransform = new ScaleTransform();
|
||||||
@@ -199,10 +203,12 @@ namespace Serein.WorkBench
|
|||||||
|
|
||||||
FlowEnvironment.OnIOCMembersChanged += FlowEnvironment_OnIOCMembersChanged;
|
FlowEnvironment.OnIOCMembersChanged += FlowEnvironment_OnIOCMembersChanged;
|
||||||
|
|
||||||
FlowEnvironment.OnNodeLocate += FlowEnvironment_OnNodeLocate;
|
FlowEnvironment.OnNodeLocated += FlowEnvironment_OnNodeLocate;
|
||||||
|
FlowEnvironment.OnNodeMoved += FlowEnvironment_OnNodeMoved;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private LogWindow InitConsoleOut()
|
private LogWindow InitConsoleOut()
|
||||||
{
|
{
|
||||||
@@ -710,6 +716,26 @@ namespace Serein.WorkBench
|
|||||||
nodeControl.RenderTransform = null; // 或者重新设置为默认值
|
nodeControl.RenderTransform = null; // 或者重新设置为默认值
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
private void FlowEnvironment_OnNodeMoved(NodeMovedEventArgs eventArgs)
|
||||||
|
{
|
||||||
|
if (!TryGetControl(eventArgs.NodeGuid, out var nodeControl)) return;
|
||||||
|
|
||||||
|
var newLeft = eventArgs.X;
|
||||||
|
var newTop = eventArgs.Y;
|
||||||
|
|
||||||
|
// 限制控件不超出FlowChartCanvas的边界
|
||||||
|
if (newLeft >= 0 && newLeft + nodeControl.ActualWidth <= FlowChartCanvas.ActualWidth)
|
||||||
|
{
|
||||||
|
Canvas.SetLeft(nodeControl, newLeft);
|
||||||
|
}
|
||||||
|
if (newTop >= 0 && newTop + nodeControl.ActualHeight <= FlowChartCanvas.ActualHeight)
|
||||||
|
{
|
||||||
|
Canvas.SetTop(nodeControl, newTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Canvas.SetLeft(nodeControl,);
|
||||||
|
//Canvas.SetTop(nodeControl, );
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Guid 转 NodeControl
|
/// Guid 转 NodeControl
|
||||||
@@ -819,7 +845,7 @@ namespace Serein.WorkBench
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 配置节点事件
|
/// 配置节点事件(移动,点击相关)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="nodeControl"></param>
|
/// <param name="nodeControl"></param>
|
||||||
private void ConfigureNodeEvents(NodeControlBase nodeControl)
|
private void ConfigureNodeEvents(NodeControlBase nodeControl)
|
||||||
@@ -1295,87 +1321,65 @@ namespace Serein.WorkBench
|
|||||||
if (IsControlDragging) // 如果正在拖动控件
|
if (IsControlDragging) // 如果正在拖动控件
|
||||||
{
|
{
|
||||||
Point currentPosition = e.GetPosition(FlowChartCanvas); // 获取当前鼠标位置
|
Point currentPosition = e.GetPosition(FlowChartCanvas); // 获取当前鼠标位置
|
||||||
// 批量移动 与 单个节点控件移动
|
|
||||||
if (selectNodeControls.Count > 0 && sender is NodeControlBase element && selectNodeControls.Contains(element))
|
if (selectNodeControls.Count > 0 && sender is NodeControlBase nodeControlMain && selectNodeControls.Contains(nodeControlMain))
|
||||||
{
|
{
|
||||||
// 获取element控件的旧位置
|
// 进行批量移动
|
||||||
double oldLeft = Canvas.GetLeft(element);
|
// 获取旧位置
|
||||||
double oldTop = Canvas.GetTop(element);
|
var oldLeft = Canvas.GetLeft(nodeControlMain);
|
||||||
|
var oldTop = Canvas.GetTop(nodeControlMain);
|
||||||
|
|
||||||
// 计算被选择控件的偏移量
|
// 计算被选择控件的偏移量
|
||||||
double deltaX = (int)(currentPosition.X - startControlDragPoint.X);
|
var deltaX = /*(int)*/(currentPosition.X - startControlDragPoint.X);
|
||||||
double deltaY = (int)(currentPosition.Y - startControlDragPoint.Y);
|
var deltaY = /*(int)*/(currentPosition.Y - startControlDragPoint.Y);
|
||||||
|
|
||||||
// 移动被选择的控件
|
// 移动被选择的控件
|
||||||
double newLeft = oldLeft + deltaX;
|
var newLeft = oldLeft + deltaX;
|
||||||
double newTop = oldTop + deltaY;
|
var newTop = oldTop + deltaY;
|
||||||
|
|
||||||
// 限制控件不超出FlowChartCanvas的边界
|
this.FlowEnvironment.MoveNode(nodeControlMain.ViewModel.Node.Guid, newLeft, newTop); // 移动节点
|
||||||
if (newLeft >= 0 && newLeft + element.ActualWidth <= FlowChartCanvas.ActualWidth)
|
|
||||||
{
|
// 计算控件实际移动的距离
|
||||||
Canvas.SetLeft(element, newLeft);
|
var actualDeltaX = newLeft - oldLeft;
|
||||||
}
|
var actualDeltaY = newTop - oldTop;
|
||||||
if (newTop >= 0 && newTop + element.ActualHeight <= FlowChartCanvas.ActualHeight)
|
|
||||||
{
|
|
||||||
Canvas.SetTop(element, newTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 计算element实际移动的距离
|
|
||||||
double actualDeltaX = newLeft - oldLeft;
|
|
||||||
double actualDeltaY = newTop - oldTop;
|
|
||||||
// 移动其它选中的控件
|
// 移动其它选中的控件
|
||||||
foreach (var nodeControl in selectNodeControls)
|
foreach (var nodeControl in selectNodeControls)
|
||||||
{
|
{
|
||||||
if (nodeControl != element) // 跳过已经移动的控件
|
if (nodeControl != nodeControlMain) // 跳过已经移动的控件
|
||||||
{
|
{
|
||||||
double otherNewLeft = Canvas.GetLeft(nodeControl) + actualDeltaX;
|
var otherNewLeft = Canvas.GetLeft(nodeControl) + actualDeltaX;
|
||||||
double otherNewTop = Canvas.GetTop(nodeControl) + actualDeltaY;
|
var otherNewTop = Canvas.GetTop(nodeControl) + actualDeltaY;
|
||||||
|
this.FlowEnvironment.MoveNode(nodeControl.ViewModel.Node.Guid, otherNewLeft, otherNewTop); // 移动节点
|
||||||
// 限制控件不超出FlowChartCanvas的边界
|
|
||||||
if (otherNewLeft >= 0 && otherNewLeft + nodeControl.ActualWidth <= FlowChartCanvas.ActualWidth)
|
|
||||||
{
|
|
||||||
Canvas.SetLeft(nodeControl, otherNewLeft);
|
|
||||||
}
|
|
||||||
if (otherNewTop >= 0 && otherNewTop + nodeControl.ActualHeight <= FlowChartCanvas.ActualHeight)
|
|
||||||
{
|
|
||||||
Canvas.SetTop(nodeControl, otherNewTop);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新节点之间线的连接位置
|
||||||
foreach (var nodeControl in selectNodeControls)
|
foreach (var nodeControl in selectNodeControls)
|
||||||
{
|
{
|
||||||
UpdateConnections(nodeControl);
|
UpdateConnections(nodeControl);
|
||||||
}
|
}
|
||||||
startControlDragPoint = currentPosition; // 更新起始点位置
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // 获取引发事件的控件
|
{ // 单个节点移动
|
||||||
if (sender is not UserControl block)
|
if (sender is not NodeControlBase nodeControl)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
double deltaX = currentPosition.X - startControlDragPoint.X; // 计算X轴方向的偏移量
|
double deltaX = currentPosition.X - startControlDragPoint.X; // 计算X轴方向的偏移量
|
||||||
double deltaY = currentPosition.Y - startControlDragPoint.Y; // 计算Y轴方向的偏移量
|
double deltaY = currentPosition.Y - startControlDragPoint.Y; // 计算Y轴方向的偏移量
|
||||||
|
double newLeft = Canvas.GetLeft(nodeControl) + deltaX; // 新的左边距
|
||||||
double newLeft = Canvas.GetLeft(block) + deltaX; // 新的左边距
|
double newTop = Canvas.GetTop(nodeControl) + deltaY; // 新的上边距
|
||||||
double newTop = Canvas.GetTop(block) + deltaY; // 新的上边距
|
this.FlowEnvironment.MoveNode(nodeControl.ViewModel.Node.Guid, newLeft, newTop); // 移动节点
|
||||||
//Console.WriteLine((Canvas.GetLeft(block), Canvas.GetTop(block)));
|
UpdateConnections(nodeControl);
|
||||||
|
|
||||||
// 限制控件不超出FlowChartCanvas的边界
|
|
||||||
if (newLeft >= 0 && newLeft + block.ActualWidth <= FlowChartCanvas.ActualWidth)
|
|
||||||
{
|
|
||||||
Canvas.SetLeft(block, newLeft);
|
|
||||||
}
|
|
||||||
if (newTop >= 0 && newTop + block.ActualHeight <= FlowChartCanvas.ActualHeight)
|
|
||||||
{
|
|
||||||
Canvas.SetTop(block, newTop);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateConnections(block);
|
|
||||||
}
|
}
|
||||||
startControlDragPoint = currentPosition; // 更新起始点位置
|
startControlDragPoint = currentPosition; // 更新起始点位置
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void ChangeViewerObjOfNode(NodeControlBase nodeControl)
|
private void ChangeViewerObjOfNode(NodeControlBase nodeControl)
|
||||||
{
|
{
|
||||||
var node = nodeControl.ViewModel.Node;
|
var node = nodeControl.ViewModel.Node;
|
||||||
@@ -1755,7 +1759,6 @@ namespace Serein.WorkBench
|
|||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
private void FlowChartCanvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(1);
|
|
||||||
if (!IsSelectControl)
|
if (!IsSelectControl)
|
||||||
{
|
{
|
||||||
// 进入选取状态
|
// 进入选取状态
|
||||||
@@ -2352,7 +2355,7 @@ namespace Serein.WorkBench
|
|||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
private void ButtonDebugFlipflopNode_Click(object sender, RoutedEventArgs e)
|
private void ButtonDebugFlipflopNode_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
FlowEnvironment?.Exit(); // 在运行平台上点击了退出
|
FlowEnvironment?.ExitFlow(); // 在运行平台上点击了退出
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -2372,7 +2375,7 @@ namespace Serein.WorkBench
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
await this.FlowEnvironment.StartFlowInSelectNodeAsync(selectNodeControls[0].ViewModel.Node.Guid);
|
await this.FlowEnvironment.StartAsyncInSelectNode(selectNodeControls[0].ViewModel.Node.Guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2489,25 +2492,12 @@ namespace Serein.WorkBench
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender"></param>
|
/// <param name="sender"></param>
|
||||||
/// <param name="e"></param>
|
/// <param name="e"></param>
|
||||||
private void OpenLocalProject_Click(object sender, RoutedEventArgs e)
|
private void ButtonOpenLocalProject_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 连接远程运行环境
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sender"></param>
|
|
||||||
/// <param name="e"></param>
|
|
||||||
private void OpenRemoteProject_Click(object sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
var windowEnvRemoteLoginView = new WindowEnvRemoteLoginView((addres,port,token) =>
|
|
||||||
{
|
|
||||||
this.FlowEnvironment.LoadRemoteProject(addres, port, token);
|
|
||||||
});
|
|
||||||
windowEnvRemoteLoginView.Show();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -2531,6 +2521,26 @@ namespace Serein.WorkBench
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region 顶部菜单栏 - 远程管理
|
||||||
|
private async void ButtonStartRemoteServer_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
await this.FlowEnvironment.StartRemoteServerAsync();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 连接远程运行环境
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender"></param>
|
||||||
|
/// <param name="e"></param>
|
||||||
|
private void ButtonConnectionRemoteEnv_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var windowEnvRemoteLoginView = new WindowEnvRemoteLoginView((addres, port, token) =>
|
||||||
|
{
|
||||||
|
this.FlowEnvironment.LoadRemoteProject(addres, port, token);
|
||||||
|
});
|
||||||
|
windowEnvRemoteLoginView.Show();
|
||||||
|
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2636,6 +2646,7 @@ namespace Serein.WorkBench
|
|||||||
MessageBox.Show("所有DLL已卸载。", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
|
MessageBox.Show("所有DLL已卸载。", "信息", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region 创建两个控件之间的连接关系,在UI层面上显示为 带箭头指向的贝塞尔曲线
|
#region 创建两个控件之间的连接关系,在UI层面上显示为 带箭头指向的贝塞尔曲线
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using Serein.Library.Entity;
|
|||||||
using Serein.Library.Utils;
|
using Serein.Library.Utils;
|
||||||
using Serein.NodeFlow;
|
using Serein.NodeFlow;
|
||||||
using Serein.NodeFlow.Tool;
|
using Serein.NodeFlow.Tool;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -14,12 +14,24 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace Serein.WorkBench
|
namespace Serein.Workbench
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 工作台数据视图
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="window"></param>
|
||||||
public class MainWindowViewModel
|
public class MainWindowViewModel
|
||||||
{
|
{
|
||||||
private readonly MainWindow window ;
|
private readonly MainWindow window ;
|
||||||
|
/// <summary>
|
||||||
|
/// 运行环境
|
||||||
|
/// </summary>
|
||||||
public IFlowEnvironment FlowEnvironment { get; set; }
|
public IFlowEnvironment FlowEnvironment { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 工作台数据视图
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="window"></param>
|
||||||
public MainWindowViewModel(MainWindow window)
|
public MainWindowViewModel(MainWindow window)
|
||||||
{
|
{
|
||||||
FlowEnvironment = new FlowEnvironment();
|
FlowEnvironment = new FlowEnvironment();
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
public abstract class NodeControlViewModelBase : INotifyPropertyChanged
|
public abstract class NodeControlViewModelBase : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
<local:NodeControlBase x:Class="Serein.WorkBench.Node.View.ActionNodeControl"
|
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.ActionNodeControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
xmlns:vm="clr-namespace:Serein.WorkBench.Node.ViewModel"
|
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||||
xmlns:Converters="clr-namespace:Serein.WorkBench.Tool.Converters"
|
xmlns:Converters="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||||
xmlns:themes="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||||
MaxWidth="300">
|
MaxWidth="300">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
<!--<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />-->
|
<!--<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />-->
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ActionNode.xaml 的交互逻辑
|
/// ActionNode.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<local:NodeControlBase x:Class="Serein.WorkBench.Node.View.ActionRegionControl"
|
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.ActionRegionControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
MaxWidth="300">
|
MaxWidth="300">
|
||||||
<Grid>
|
<Grid>
|
||||||
<!--<Border BorderBrush="Black" BorderThickness="1" Padding="10">
|
<!--<Border BorderBrush="Black" BorderThickness="1" Padding="10">
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
using Serein.NodeFlow;
|
using Serein.NodeFlow;
|
||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
|
using Serein.Workbench.Node.View;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ActionRegion.xaml 的交互逻辑
|
/// ActionRegion.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<local:NodeControlBase x:Class="Serein.WorkBench.Node.View.ConditionNodeControl"
|
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.ConditionNodeControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
xmlns:vm="clr-namespace:Serein.WorkBench.Node.ViewModel"
|
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||||
xmlns:themes="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||||
MaxWidth="300">
|
MaxWidth="300">
|
||||||
|
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ConditionNode.xaml 的交互逻辑
|
/// ConditionNode.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<local:NodeControlBase x:Class="Serein.WorkBench.Node.View.ConditionRegionControl"
|
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.ConditionRegionControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
MaxWidth="300">
|
MaxWidth="300">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Border BorderBrush="Black" BorderThickness="1" Padding="10">
|
<Border BorderBrush="Black" BorderThickness="1" Padding="10">
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ConditionRegion.xaml 的交互逻辑
|
/// ConditionRegion.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<UserControl x:Class="Serein.WorkBench.Node.View.DllControl"
|
<UserControl x:Class="Serein.Workbench.Node.View.DllControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
MaxWidth="300"
|
MaxWidth="300"
|
||||||
>
|
>
|
||||||
<DockPanel>
|
<DockPanel>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<ColumnDefinition Width="*" />
|
<ColumnDefinition Width="*" />
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<GroupBox x:Name="ActionNodes" Grid.Row="0" Header="动作" Margin="5">
|
<GroupBox x:Name="Ac" Grid.Row="0" Header="动作" Margin="5">
|
||||||
<ListBox x:Name="ActionsListBox" Background="#D0F1F9"/>
|
<ListBox x:Name="ActionsListBox" Background="#D0F1F9"/>
|
||||||
</GroupBox>
|
</GroupBox>
|
||||||
<GroupBox x:Name="FlipflopNodes" Grid.Row="1" Header="触发器" Margin="5" >
|
<GroupBox x:Name="FlipflopNodes" Grid.Row="1" Header="触发器" Margin="5" >
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ using System.Windows.Automation;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<local:NodeControlBase x:Class="Serein.WorkBench.Node.View.ExpOpNodeControl"
|
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.ExpOpNodeControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
MaxWidth="300">
|
MaxWidth="300">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ExprOpNodeControl.xaml 的交互逻辑
|
/// ExprOpNodeControl.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<local:NodeControlBase x:Class="Serein.WorkBench.Node.View.FlipflopNodeControl"
|
<local:NodeControlBase x:Class="Serein.Workbench.Node.View.FlipflopNodeControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:Converters="clr-namespace:Serein.WorkBench.Tool.Converters"
|
xmlns:Converters="clr-namespace:Serein.Workbench.Tool.Converters"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Node.View"
|
xmlns:local="clr-namespace:Serein.Workbench.Node.View"
|
||||||
xmlns:vm="clr-namespace:Serein.WorkBench.Node.ViewModel"
|
xmlns:vm="clr-namespace:Serein.Workbench.Node.ViewModel"
|
||||||
xmlns:themes="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:themes="clr-namespace:Serein.Workbench.Themes"
|
||||||
MaxWidth="300">
|
MaxWidth="300">
|
||||||
|
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// StateNode.xaml 的交互逻辑
|
/// StateNode.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.Library.Api;
|
using Serein.Library.Api;
|
||||||
using Serein.Library.Entity;
|
using Serein.Library.Entity;
|
||||||
using Serein.NodeFlow.Base;
|
using Serein.NodeFlow.Base;
|
||||||
using Serein.WorkBench.Node.ViewModel;
|
using Serein.Workbench.Node.ViewModel;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@@ -9,7 +9,7 @@ using System.Runtime.CompilerServices;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.View
|
namespace Serein.Workbench.Node.View
|
||||||
{
|
{
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -34,24 +34,19 @@ namespace Serein.WorkBench.Node.View
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//public class FLowNodeObObservableCollection<T> : ObservableCollection<T>
|
||||||
|
//{
|
||||||
|
|
||||||
|
// public void AddRange(IEnumerable<T> items)
|
||||||
|
// {
|
||||||
|
// foreach (var item in items)
|
||||||
|
// {
|
||||||
public class FLowNodeObObservableCollection<T> : ObservableCollection<T>
|
// this.Items.Add(item);
|
||||||
{
|
// }
|
||||||
|
// OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
|
||||||
public void AddRange(IEnumerable<T> items)
|
// }
|
||||||
{
|
//}
|
||||||
foreach (var item in items)
|
|
||||||
{
|
|
||||||
this.Items.Add(item);
|
|
||||||
}
|
|
||||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
public class ActionNodeControlViewModel : NodeControlViewModelBase
|
public class ActionNodeControlViewModel : NodeControlViewModelBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 条件节点
|
||||||
|
/// </summary>
|
||||||
public class ConditionNodeControlViewModel : NodeControlViewModelBase
|
public class ConditionNodeControlViewModel : NodeControlViewModelBase
|
||||||
{
|
{
|
||||||
private readonly SingleConditionNode singleConditionNode;
|
private readonly SingleConditionNode singleConditionNode;
|
||||||
@@ -32,6 +35,10 @@ namespace Serein.WorkBench.Node.ViewModel
|
|||||||
set { singleConditionNode.Expression = value; OnPropertyChanged(); }
|
set { singleConditionNode.Expression = value; OnPropertyChanged(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 条件节点
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node"></param>
|
||||||
public ConditionNodeControlViewModel(SingleConditionNode node) : base(node)
|
public ConditionNodeControlViewModel(SingleConditionNode node) : base(node)
|
||||||
{
|
{
|
||||||
this.singleConditionNode = node;
|
this.singleConditionNode = node;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
public class ConditionRegionNodeControlViewModel : NodeControlViewModelBase
|
public class ConditionRegionNodeControlViewModel : NodeControlViewModelBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
public class ExpOpNodeViewModel: NodeControlViewModelBase
|
public class ExpOpNodeViewModel: NodeControlViewModelBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using Serein.NodeFlow.Model;
|
using Serein.NodeFlow.Model;
|
||||||
using Serein.WorkBench.Node.View;
|
using Serein.Workbench.Node.View;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
public class FlipflopNodeControlViewModel : NodeControlViewModelBase
|
public class FlipflopNodeControlViewModel : NodeControlViewModelBase
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Node.ViewModel
|
namespace Serein.Workbench.Node.ViewModel
|
||||||
{
|
{
|
||||||
public class TypeToStringConverter : IValueConverter
|
public class TypeToStringConverter : IValueConverter
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<UserControl x:Class="Serein.WorkBench.Themes.IOCObjectViewControl"
|
<UserControl x:Class="Serein.Workbench.Themes.IOCObjectViewControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ using System.Windows.Navigation;
|
|||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IOCObjectViewControl.xaml 的交互逻辑
|
/// IOCObjectViewControl.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Window x:Class="Serein.WorkBench.Themes.InputDialog"
|
<Window x:Class="Serein.Workbench.Themes.InputDialog"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="InputDialog" Height="450" Width="800">
|
Title="InputDialog" Height="450" Width="800">
|
||||||
<StackPanel Margin="10">
|
<StackPanel Margin="10">
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// InputDialog.xaml 的交互逻辑
|
/// InputDialog.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<ResourceDictionary
|
<ResourceDictionary
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
xmlns:sys="clr-namespace:System;assembly=mscorlib">
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ using System.Windows;
|
|||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
public class MultiConditionConverter : IMultiValueConverter
|
public class MultiConditionConverter : IMultiValueConverter
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<UserControl x:Class="Serein.WorkBench.Themes.NodeTreeItemViewControl"
|
<UserControl x:Class="Serein.Workbench.Themes.NodeTreeItemViewControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="400" d:DesignWidth="200">
|
d:DesignHeight="400" d:DesignWidth="200">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ using System.Windows.Media.Imaging;
|
|||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using static Serein.WorkBench.Themes.TypeViewerWindow;
|
using static Serein.Workbench.Themes.TypeViewerWindow;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NodeTreeVIewControl.xaml 的交互逻辑
|
/// NodeTreeVIewControl.xaml 的交互逻辑
|
||||||
@@ -156,7 +156,7 @@ namespace Serein.WorkBench.Themes
|
|||||||
var contextMenu = new ContextMenu();
|
var contextMenu = new ContextMenu();
|
||||||
contextMenu.Items.Add(MainWindow.CreateMenuItem("从此节点执行", (s, e) =>
|
contextMenu.Items.Add(MainWindow.CreateMenuItem("从此节点执行", (s, e) =>
|
||||||
{
|
{
|
||||||
flowEnvironment.StartFlowInSelectNodeAsync(tmpNodeTreeModel.RootNode.Guid);
|
flowEnvironment.StartAsyncInSelectNode(tmpNodeTreeModel.RootNode.Guid);
|
||||||
}));
|
}));
|
||||||
contextMenu.Items.Add(MainWindow.CreateMenuItem("定位", (s, e) => flowEnvironment.NodeLocated(tmpNodeTreeModel.RootNode.Guid)));
|
contextMenu.Items.Add(MainWindow.CreateMenuItem("定位", (s, e) => flowEnvironment.NodeLocated(tmpNodeTreeModel.RootNode.Guid)));
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<UserControl x:Class="Serein.WorkBench.Themes.NodeTreeViewControl"
|
<UserControl x:Class="Serein.Workbench.Themes.NodeTreeViewControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ using System.Windows.Media.Imaging;
|
|||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// NodeTreeViewControl.xaml 的交互逻辑
|
/// NodeTreeViewControl.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<UserControl x:Class="Serein.WorkBench.Themes.ObjectViewerControl"
|
<UserControl x:Class="Serein.Workbench.Themes.ObjectViewerControl"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="400" d:DesignWidth="400">
|
d:DesignHeight="400" d:DesignWidth="400">
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ using System.Windows.Media.Imaging;
|
|||||||
using System.Windows.Navigation;
|
using System.Windows.Navigation;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using static Serein.WorkBench.Themes.TypeViewerWindow;
|
using static Serein.Workbench.Themes.TypeViewerWindow;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
|
|
||||||
public class FlowDataDetails
|
public class FlowDataDetails
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Window x:Class="Serein.WorkBench.Themes.TypeViewerWindow"
|
<Window x:Class="Serein.Workbench.Themes.TypeViewerWindow"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Topmost="True"
|
Topmost="True"
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// TypeViewerWindow.xaml 的交互逻辑
|
/// TypeViewerWindow.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<Window x:Class="Serein.WorkBench.Themes.WindowEnvRemoteLoginView"
|
<Window x:Class="Serein.Workbench.Themes.WindowEnvRemoteLoginView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:Serein.WorkBench.Themes"
|
xmlns:local="clr-namespace:Serein.Workbench.Themes"
|
||||||
Title="登录远程环境" Height="150" Width="200">
|
Title="登录远程环境" Height="150" Width="200">
|
||||||
<Grid Margin="0,10,0,0">
|
<Grid Margin="0,10,0,0">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Windows.Media;
|
|||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Shapes;
|
using System.Windows.Shapes;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Themes
|
namespace Serein.Workbench.Themes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WindowDialogInput.xaml 的交互逻辑
|
/// WindowDialogInput.xaml 的交互逻辑
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
|||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Tool.Converters
|
namespace Serein.Workbench.Tool.Converters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据bool类型控制可见性
|
/// 根据bool类型控制可见性
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Text;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Tool.Converters
|
namespace Serein.Workbench.Tool.Converters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 画布拉动范围距离计算器
|
/// 画布拉动范围距离计算器
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.Globalization;
|
|||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
namespace Serein.WorkBench.Tool.Converters
|
namespace Serein.Workbench.Tool.Converters
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据控件类型切换颜色
|
/// 根据控件类型切换颜色
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ using System.IO;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Channels;
|
using System.Threading.Channels;
|
||||||
|
|
||||||
namespace Serein.WorkBench.tool
|
namespace Serein.Workbench.tool
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可以捕获类库输出的打印输出
|
/// 可以捕获类库输出的打印输出
|
||||||
|
|||||||
Reference in New Issue
Block a user