diff --git a/Inc/Nodes_And_Connectors.hpp b/Inc/Nodes_And_Connectors.hpp index e501e06..9fbaefa 100644 --- a/Inc/Nodes_And_Connectors.hpp +++ b/Inc/Nodes_And_Connectors.hpp @@ -26,9 +26,8 @@ protected: Connector_Type_Enum type; // 类型标识 const char *socket_str; // 套接字字符串 - Abs_Connector *provider; // 提供者 - std::vector receiver_list; // 接收方 - void *product; // 产物 + std::vector related_connector_list; // 关联列表 + void *product; // 产物(仅输出类节点持有) public: // 显式禁用默认构造 @@ -43,14 +42,17 @@ public: // 连接到目标连接点 virtual bool Connect_To(Abs_Connector *target); - // 断开连接 - virtual void Disconnect(void); + // 断开所有连接 + virtual void Disconnect_All(void); + + // 与指定的接口断开连接 + virtual bool Disconnect_To(Abs_Connector *target); // 注册产物 virtual bool Register_Product(void *product, size_t size); - // 获取上级节点 - virtual Abs_Connector *Get_Provider(void); + // 获取关联接口列表 + virtual std::vector Get_Related_List(void); // 获取产物 virtual void *Get_Product(void); @@ -70,6 +72,7 @@ protected: typedef enum { NODE_TYPE_UNKNOWN, // 未知节点类型 + NODE_TYPE_CONNECTOR_TEST, // 接口测试节点 NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点 NODE_TYPE_CSV_EXPORTER, // CSV输出节点 } Node_Type_Enum; // 节点类型枚举 @@ -106,6 +109,9 @@ public: // 执行处理流程 virtual bool Execute_Process(void) = 0; + // 获取ID + virtual int Get_ID(void); + // 获取关闭信号 virtual bool Get_CloseFlag(void); diff --git a/Inc/Workflow_Editor.hpp b/Inc/Workflow_Editor.hpp index 9cf7484..7f10959 100644 --- a/Inc/Workflow_Editor.hpp +++ b/Inc/Workflow_Editor.hpp @@ -15,6 +15,7 @@ protected: typedef enum { NODE_TYPE_UNKNOWN, // 未知节点类型 + NODE_TYPE_CONNECTOR_TEST, // 接口测试节点 NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点 NODE_TYPE_CSV_EXPORTER, // CSV输出节点 } Node_Type_Enum; // 节点类型枚举 @@ -46,13 +47,33 @@ protected: std::vector>>> Process_Route; // 工作层级路由 std::vector> Separate_Node_List; // 散点列表 - // =====================================函数声明================================================= - // 新增节点 true -> success / false -> failed - bool Add_Node(Node_Type_Enum type, ImVec2 initial_position = ImVec2(0, 0)); + // 删除节点 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用 + std::vector>::iterator Del_Node(std::vector>::iterator iterator); + + // 删除边 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用 + std::vector::iterator Del_Link(std::vector::iterator iterator); public: // 绘制节点编辑器 void Show(void); + + // 新增节点 true -> success / false -> failed + bool Add_Node(Node_Type_Enum type, ImVec2 initial_position = ImVec2(0, 0)); + + // 删除节点 true -> success / false -> failed + bool Del_Node(int target_node_id); + + // 新增连接 true -> success / false -> failed + bool Add_Link(int source_connector_id, int target_connector_id); + + // 删除连接 true -> success / false -> failed + bool Del_Link(int source_connector_id, int target_connector_id); + + // 读取配置文件 + bool Read_Config(const char *file_path); + + // 存储配置文件 + bool Store_Config(const char *file_path); }; #endif \ No newline at end of file diff --git a/Src/Nodes_And_Connectors.cpp b/Src/Nodes_And_Connectors.cpp index f4ecb49..6c8ab72 100644 --- a/Src/Nodes_And_Connectors.cpp +++ b/Src/Nodes_And_Connectors.cpp @@ -77,7 +77,6 @@ Abs_Connector::Abs_Connector(Independent_ID_Generator *ID_Generator, // 指针初始化 this->product = nullptr; - this->provider = nullptr; }; // 析构 @@ -86,8 +85,8 @@ Abs_Connector::~Abs_Connector() // 释放产物 if (this->product != nullptr) free(product); - // 断开连接 - this->Disconnect(); + // 断开所有连接 + this->Disconnect_All(); // 释放ID this->ID_Generator->Release_ID(this->id); } @@ -98,53 +97,61 @@ bool Abs_Connector::Connect_To(Abs_Connector *target) // 判定接口是否匹配 if (strcmp(target->socket_str, this->socket_str) == 0) { - // 写连接关系 - if ((this->type == CONNECTOR_TYPE_OUTPUT) && (target->type == CONNECTOR_TYPE_INPUT)) + // 写连接关系 必须是一收一发 + if (((this->type == CONNECTOR_TYPE_OUTPUT) && (target->type == CONNECTOR_TYPE_INPUT)) || ((this->type == CONNECTOR_TYPE_INPUT) && (target->type == CONNECTOR_TYPE_OUTPUT))) { - target->provider = this; - this->receiver_list.push_back(target); - return true; - } - if ((this->type == CONNECTOR_TYPE_INPUT) && (target->type == CONNECTOR_TYPE_OUTPUT)) - { - target->receiver_list.push_back(this); - this->provider = target; + // 向双方写入关联信息 + target->related_connector_list.push_back(this); + this->related_connector_list.push_back(target); return true; } } return false; } -// 断开连接 -void Abs_Connector::Disconnect(void) +// 断开所有连接 +void Abs_Connector::Disconnect_All(void) { - // 受点断开供方连接 - if (this->type == CONNECTOR_TYPE_INPUT) + for (auto target : this->related_connector_list) { - // 断开供方对自身的记录 - for (auto iterator = this->provider->receiver_list.begin(); iterator != this->provider->receiver_list.end(); iterator++) - { - // 供方断开自身列表记录 - if ((*iterator) == this) + // 删除连接点对自己的记录 + for (auto iterator = target->related_connector_list.begin(); iterator != target->related_connector_list.end(); iterator++) + if (*iterator == this) { - this->provider->receiver_list.erase(iterator); + iterator = target->related_connector_list.erase(iterator); break; } - } - // 断开自身对供方的记录 - this->provider = nullptr; } - // 供方断开所有受点的供方记录 - if (this->type == CONNECTOR_TYPE_OUTPUT) - { - // 断开受点的供方记录 - for (auto receiver : this->receiver_list) - receiver->provider = nullptr; - // 清空受点列表 - decltype(this->receiver_list) empty_list; - this->receiver_list.swap(empty_list); + // 清空自身列表 + decltype(this->related_connector_list) empty_list; + this->related_connector_list.swap(empty_list); +} + +// 与指定的接口断开连接 +bool Abs_Connector::Disconnect_To(Abs_Connector *target) +{ + // 查找目标接口 + for (auto iterator = this->related_connector_list.begin(); iterator != this->related_connector_list.end(); iterator++) + { + if (*iterator == target) + { + // 删除目标连接点对自己的记录 + for (auto iterator = target->related_connector_list.begin(); iterator != target->related_connector_list.end(); iterator++) + if (*iterator == this) + { + iterator = target->related_connector_list.erase(iterator); + break; + } + + // 自身删除对目标点的记录 + iterator = this->related_connector_list.erase(iterator); + return true; + } } + + // 未成功查找 + return false; } // 注册产物 @@ -169,9 +176,9 @@ bool Abs_Connector::Register_Product(void *product, size_t size) } // 获取上级节点 -Abs_Connector *Abs_Connector::Get_Provider(void) +std::vector Abs_Connector::Get_Related_List(void) { - return this->provider; + return this->related_connector_list; } // 获取产物 @@ -181,15 +188,7 @@ void *Abs_Connector::Get_Product(void) if (this->type == CONNECTOR_TYPE_OUTPUT) return this->product; - // 输入节点返回间接产物(提供者方产物) - if (this->type == CONNECTOR_TYPE_INPUT) - { - if (this->provider == nullptr) - return nullptr; - return this->provider->product; - } - - // 未知类型 + // 其它情况返回空值 return nullptr; } @@ -232,6 +231,12 @@ Abs_Node::~Abs_Node() this->Node_ID_Generator->Release_ID(this->id); } +// 获取ID +int Abs_Node::Get_ID(void) +{ + return this->id; +} + // 获取关闭信号 bool Abs_Node::Get_CloseFlag(void) { @@ -246,17 +251,6 @@ std::vector> &Abs_Node::Get_Connector_List(void) // ================================================================================================= -// 必要构造 -MSG_OutPut_Connector::MSG_OutPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_OUTPUT, "DLT MSG") {} - -// 绘制接口 -void MSG_OutPut_Connector::Show(void) -{ - // 输出接口点 - ImNodes::BeginOutputAttribute(this->id, 1); - ImNodes::EndOutputAttribute(); -} - // 必要构造 MSG_InPut_Connector::MSG_InPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_INPUT, "DLT MSG") {} @@ -264,12 +258,168 @@ MSG_InPut_Connector::MSG_InPut_Connector(Independent_ID_Generator *ID_Generator) void MSG_InPut_Connector::Show(void) { // 输出接口点 - ImNodes::BeginInputAttribute(this->id, 1); + ImNodes::BeginInputAttribute(this->id, ImNodesPinShape_CircleFilled); + // 填充占位 + ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight())); ImNodes::EndInputAttribute(); } +// 必要构造 +MSG_OutPut_Connector::MSG_OutPut_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_OUTPUT, "DLT MSG") {} + +// 绘制接口 +void MSG_OutPut_Connector::Show(void) +{ + // 输出接口点 + ImNodes::BeginOutputAttribute(this->id, ImNodesPinShape_CircleFilled); + // 填充占位 + ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight())); + ImNodes::EndOutputAttribute(); +} + +// 必要构造 +CSV_Column_Input_Connector::CSV_Column_Input_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_INPUT, "CSV Column") {} + +// 绘制接口 +void CSV_Column_Input_Connector::Show() +{ + // 输出接口点 + ImNodes::BeginInputAttribute(this->id, ImNodesPinShape_TriangleFilled); + // 填充占位 + ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight())); + ImNodes::EndInputAttribute(); +} + +// 必要构造 +CSV_Column_Output_Connector::CSV_Column_Output_Connector(Independent_ID_Generator *ID_Generator) : Abs_Connector(ID_Generator, CONNECTOR_TYPE_OUTPUT, "CSV Column") {} + +// 绘制接口 +void CSV_Column_Output_Connector::Show() +{ + // 输出接口点 + ImNodes::BeginOutputAttribute(this->id, ImNodesPinShape_TriangleFilled); + // 填充占位 + ImGui::Dummy(ImVec2(0.0f, ImGui::GetTextLineHeight())); + ImNodes::EndOutputAttribute(); +} // ================================================================================================= +// 必要构造 +Connector_Test_Node::Connector_Test_Node(Independent_ID_Generator *Node_ID_Generator, + Independent_ID_Generator *Connector_ID_Generator, + ImVec2 initial_position) + : Abs_Node(Node_ID_Generator, + Connector_ID_Generator, + NODE_TYPE_CONNECTOR_TEST, + initial_position) +{ + // 判定是否成功申请ID , 后加载测试用节点列表 + if (this->id != -1) + { + // DLT MSG 相关接口 + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [0] -> MSG + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [1] MSG -> + + // CSV 相关接口 + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [2] -> Column + this->Connector_List.push_back(std::make_shared(Connector_ID_Generator)); // [3] -> Column + } +} + +// 绘制节点 +void Connector_Test_Node::Show(void) +{ + + if (this->close_flag == true) + return; + + // 初始化位置设定 + if ((this->initial_position.x != 0) || (this->initial_position.y != 0)) + { + ImNodes::SetNodeScreenSpacePos(this->id, this->initial_position); + this->initial_position = ImVec2(0, 0); + } + + // 绘制节点 + ImNodes::BeginNode(this->id); + { + + // 标题部分 + ImNodes::BeginNodeTitleBar(); + { + ImGui::Text(u8"接口测试用节点"); + ImGui::SameLine(); + { + ImGui::TextDisabled(u8"(?)"); + // 上下边距为调整 + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f)); + + if (ImGui::BeginItemTooltip()) + { + ImGui::Text("Node ID : %d\n", this->id); + ImGui::Separator(); + ImGui::Text(u8"注意!仅供接口测试使用!\n该节点不会进行任何处理操作,且不会生成任何产物"); + ImGui::EndTooltip(); + } + + ImGui::PopStyleVar(); + } + ImGui::SameLine(); + + // 节点宽度调整 + ImGui::Dummy(ImVec2(120.0f, 0.0f)); + + ImGui::SameLine(); + // 绘制关闭按钮 + if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2)) + this->close_flag = true; + } + ImNodes::EndNodeTitleBar(); + + // 绘制DLT相关接口组 + { + + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y)); + + this->Connector_List[0]->Show(); + ImGui::SameLine(); + ImGui::Text("-> DLT-In"); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(ImNodes::GetNodeDimensions(this->id).x - ImGui::CalcTextSize("-> DLT-In").x - ImGui::CalcTextSize("DLT-Out ->").x - (ImNodes::GetStyle().NodePadding.x + ImGui::GetStyle().ItemSpacing.x) * 2, 0.0f)); + ImGui::SameLine(); + ImGui::Text("DLT-Out ->"); + ImGui::SameLine(); + this->Connector_List[1]->Show(); + + ImGui::PopStyleVar(); + } + + // 绘制CSV列相关接口组 + { + ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y)); + + this->Connector_List[2]->Show(); + ImGui::SameLine(); + ImGui::Text("-> CSV-Column-In"); + ImGui::SameLine(); + ImGui::Dummy(ImVec2(ImNodes::GetNodeDimensions(this->id).x - ImGui::CalcTextSize("-> CSV-Column-In").x - ImGui::CalcTextSize("CSV-Column-Out ->").x - (ImNodes::GetStyle().NodePadding.x + ImGui::GetStyle().ItemSpacing.x) * 2, 0.0f)); + ImGui::SameLine(); + ImGui::Text("CSV-Column-Out ->"); + ImGui::SameLine(); + this->Connector_List[3]->Show(); + + ImGui::PopStyleVar(); + } + } + ImNodes::EndNode(); +} + +// 执行处理流程 +bool Connector_Test_Node::Execute_Process(void) +{ + return true; +} + // 必要构造 MSG_Input_Node::MSG_Input_Node(Independent_ID_Generator *Node_ID_Generator, Independent_ID_Generator *Connector_ID_Generator, diff --git a/Src/Workflow_Editor.cpp b/Src/Workflow_Editor.cpp index c174c59..be45914 100644 --- a/Src/Workflow_Editor.cpp +++ b/Src/Workflow_Editor.cpp @@ -1,63 +1,6 @@ #include "Workflow_Editor.hpp" #include "imgui_internal.h" -// 新增节点 -bool Workflow_Editor::Add_Node(Node_Type_Enum type, ImVec2 initial_position) -{ - // 新节点 - std::shared_ptr p_New_Node; - - // 记录节点 - switch (type) - { - case NODE_TYPE_MSG_LINE_INPUT: // 消息行输入 (头节点) - - // 创建节点 - p_New_Node = std::make_shared(&this->Node_ID_Generator, - &this->Connector_ID_Generator, - initial_position); - break; - - // // 记录到节点池和接口池 - // this->Node_Pool.push_back(p_New_Node); - // for (auto p_Connector : p_New_Node->Get_Connector_List()) - // this->Connector_Pool.push_back(p_Connector); - - // // 编辑工作路由 - // { - // // 起始层级只有起始节点 - // std::vector> Begin_Layer; - // Begin_Layer.push_back(p_New_Node); - - // // 层级列表仅有起始层级 - // std::vector>> Layer_List; - // Layer_List.push_back(Begin_Layer); - - // // 插入工作路由表 - // this->Process_Route.push_back(Layer_List); - // } - // return true; - - case NODE_TYPE_CSV_EXPORTER: // CSV输出器 - break; - default: - return false; - } - - if (p_New_Node.get() != nullptr) - { - // 将新增的节点及其接口记录到对应的池 - this->Node_Pool.push_back(p_New_Node); - for (auto p_Connector : p_New_Node->Get_Connector_List()) - this->Connector_Pool.push_back(p_Connector); - - // 记录到散点池 - this->Separate_Node_List.push_back(p_New_Node); - return true; - } - return false; -} - // 绘制节点编辑器 void Workflow_Editor::Show(void) { @@ -68,45 +11,10 @@ void Workflow_Editor::Show(void) // 显示所有节点 for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++) { - auto Connector_List = (*iterator)->Get_Connector_List(); if ((*iterator)->Get_CloseFlag() == true) { - // 删除列表中所有与该节点接口相关的边并从接口池中删除 - for (auto pConnector : Connector_List) - { - int connector_id = pConnector->Get_ID(); - // 遍历边池 - for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++) - { - if ((iterator->source_connector_id == connector_id) || (iterator->target_connector_id == connector_id)) - { - // 注销边ID - this->Edge_ID_Generator.Release_ID(connector_id); - // 注销边记录,迭代器删除后会返回下一个位置的迭代器 - iterator = this->Edge_Pool.erase(iterator); - iterator--; - } - } - - // 从接口池中移除 - for (auto iterator = this->Connector_Pool.begin(); iterator != this->Connector_Pool.end(); iterator++) - { - if (*iterator == pConnector) - { - // 注销节点记录 - iterator = this->Connector_Pool.erase(iterator); - break; - } - } - } - - /** - * @todo 从工作路由中删除该节点并调整工作路由层级顺序 - * @todo 可能不需要对外暴露接口池 - */ - - // 从节点池中删除该节点,迭代器删除后会返回下一个位置的迭代器 - iterator = this->Node_Pool.erase(iterator); + // 处理节点删除 + iterator = this->Del_Node(iterator); iterator--; } else @@ -135,6 +43,8 @@ void Workflow_Editor::Show(void) // 节点添加菜单 if (ImGui::BeginMenu(u8"创建节点")) { + if (ImGui::MenuItem(u8"接口测试节点")) + this->Add_Node(NODE_TYPE_CONNECTOR_TEST, click_pos); if (ImGui::MenuItem(u8"DLT信息输入节点")) this->Add_Node(NODE_TYPE_MSG_LINE_INPUT, click_pos); ImGui::EndMenu(); @@ -158,60 +68,274 @@ void Workflow_Editor::Show(void) { int source_id = -1, target_id = -1; if (ImNodes::IsLinkCreated(&source_id, &target_id)) - { + this->Add_Link(source_id, target_id); + } - // 查找接口 - bool find = false; - std::shared_ptr p_source_connector; - std::shared_ptr p_target_connector; - for (auto pNode : this->Node_Pool) + // 处理键盘事件 + { + // Delete 按键释放 + if (ImGui::IsKeyReleased(ImGuiKey_Delete)) + { + // 释放所有选中的边 { - for (auto pConnector : pNode->Get_Connector_List()) + std::vector target_edge_id_list; + target_edge_id_list.resize(ImNodes::NumSelectedLinks()); + if (target_edge_id_list.size() > 0) { - if (pConnector->Get_ID() == source_id) - p_source_connector = pConnector; - if (pConnector->Get_ID() == target_id) - p_target_connector = pConnector; - if ((p_source_connector.get() != nullptr) && (p_target_connector.get() != nullptr)) + ImNodes::GetSelectedLinks(&target_edge_id_list[0]); + for (auto edge_iterator = this->Edge_Pool.begin(); edge_iterator != this->Edge_Pool.end(); edge_iterator++) { - find = true; - break; + if (target_edge_id_list.size() > 0) + for (auto target_id_iterator = target_edge_id_list.begin(); target_id_iterator != target_edge_id_list.end(); target_id_iterator++) + { + if (*target_id_iterator == edge_iterator->id) + { + target_edge_id_list.erase(target_id_iterator); + edge_iterator = this->Del_Link(edge_iterator) - 1; + break; + } + } + else + break; } } - - if (find) - break; } - // 判定查找结果 - if (find) + // 释放所有选中的节点 { - // 输入类型节点只允许一个父接口,输出类型节点可以有多个子接口 - if (p_target_connector->Get_Provider() != nullptr) - { - int origin_source_id = p_target_connector->Get_Provider()->Get_ID(); - for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++) - { - if (iterator->source_connector_id == origin_source_id && iterator->target_connector_id == target_id) - { - this->Edge_ID_Generator.Release_ID(iterator->id); - this->Edge_Pool.erase(iterator); - break; - } - } - } - - // 尝试连接 - if (p_source_connector->Connect_To(p_target_connector.get()) == true) - { - // 记录到边池 - this->Edge_Pool.push_back({this->Edge_ID_Generator.Request_ID(), source_id, target_id}); - - /** - * @todo 调整工作路由层级 - */ - } + std::vector target_id_list; + target_id_list.resize(ImNodes::NumSelectedNodes()); + if (target_id_list.size() > 0) + ImNodes::GetSelectedNodes(&target_id_list[0]); + for (auto target_id : target_id_list) + this->Del_Node(target_id); } } } } + +// 新增节点 true -> success / false -> failed +bool Workflow_Editor::Add_Node(Node_Type_Enum type, ImVec2 initial_position) +{ + // 新节点 + std::shared_ptr p_New_Node; + + // 记录节点 + switch (type) + { + + case NODE_TYPE_CONNECTOR_TEST: // 接口测试节点 + p_New_Node = std::make_shared(&this->Node_ID_Generator, + &this->Connector_ID_Generator, + initial_position); + break; + case NODE_TYPE_MSG_LINE_INPUT: // 消息行输入 (头节点) + + // 创建节点 + p_New_Node = std::make_shared(&this->Node_ID_Generator, + &this->Connector_ID_Generator, + initial_position); + break; + + case NODE_TYPE_CSV_EXPORTER: // CSV输出器 + break; + default: + return false; + } + + // 成功分配时 + if (p_New_Node.get() != nullptr) + { + // 将新增的节点记录到接口池及散点池 + this->Node_Pool.push_back(p_New_Node); + this->Separate_Node_List.push_back(p_New_Node); + + /** + * @todo + * 考量接口列表是否有必要存在,遍历时可以通过遍历节点所含的接口列表来定位 + * 如果有节点需要动态扩充接口,此时接口列表遍历方式存在问题 + */ + + // 记录节点内含的接口列表 + for (auto p_Connector : p_New_Node->Get_Connector_List()) + this->Connector_Pool.push_back(p_Connector); + + // 记录到散点池 + return true; + } + return false; +} + +// 删除节点 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用 +std::vector>::iterator Workflow_Editor::Del_Node(std::vector>::iterator iterator) +{ + + // 散点删除 + int node_id = (*iterator)->Get_ID(); + for (auto iterator = this->Separate_Node_List.begin(); iterator != this->Separate_Node_List.end(); iterator++) + if ((*iterator)->Get_ID() == node_id) + { + iterator = this->Separate_Node_List.erase(iterator); + break; + } + + // 获取接口列表 + auto Connector_List = (*iterator)->Get_Connector_List(); + + // 删除列表中所有与该节点接口相关的边并从接口池中删除 + for (auto pConnector : Connector_List) + { + int connector_id = pConnector->Get_ID(); + // 遍历边池 + for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++) + { + if ((iterator->source_connector_id == connector_id) || (iterator->target_connector_id == connector_id)) + { + // 注销边ID + this->Edge_ID_Generator.Release_ID(connector_id); + // 注销边记录,迭代器删除后会返回下一个位置的迭代器 + iterator = this->Edge_Pool.erase(iterator) - 1; + } + } + + // 从接口池中移除 + for (auto iterator = this->Connector_Pool.begin(); iterator != this->Connector_Pool.end(); iterator++) + if (*iterator == pConnector) + { + iterator = this->Connector_Pool.erase(iterator); + break; + } + } + + /** + * @todo 从工作路由中删除该节点并调整工作路由层级顺序 + * @todo 可能不需要对外暴露接口池 + */ + + iterator = this->Node_Pool.erase(iterator); + + return iterator; +} + +// 删除节点 true -> success / false -> failed +bool Workflow_Editor::Del_Node(int target_node_id) +{ + // 查找ID + for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++) + { + // 从节点池删除对应的节点 + if ((*iterator)->Get_ID() == target_node_id) + { + this->Del_Node(iterator); + return true; + } + } + + // 未成功查找 + return false; +} + +// 新增连接 true -> success / false -> failed +bool Workflow_Editor::Add_Link(int source_connector_id, int target_connector_id) +{ + // 查找接口 + bool find = false; + std::shared_ptr p_source_connector; + std::shared_ptr p_target_connector; + for (auto pNode : this->Node_Pool) + { + for (auto pConnector : pNode->Get_Connector_List()) + { + if (pConnector->Get_ID() == source_connector_id) + p_source_connector = pConnector; + if (pConnector->Get_ID() == target_connector_id) + p_target_connector = pConnector; + if ((p_source_connector.get() != nullptr) && (p_target_connector.get() != nullptr)) + { + find = true; + break; + } + } + + if (find) + break; + } + + // 判定查找结果 + if (find) + { + // 先尝试连接,成功后再进行边池操作 + if (p_source_connector->Connect_To(p_target_connector.get()) == true) + { + // 记录到边池 + this->Edge_Pool.push_back({this->Edge_ID_Generator.Request_ID(), source_connector_id, target_connector_id}); + + /** + * @todo 调整工作路由层级 + */ + } + + return true; + } + + return false; +} + +// 删除边 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用 +std::vector::iterator Workflow_Editor::Del_Link(std::vector::iterator iterator) +{ + // 查找接口 + bool find = false; + std::shared_ptr p_source_connector; + std::shared_ptr p_target_connector; + for (auto pNode : this->Node_Pool) + { + for (auto pConnector : pNode->Get_Connector_List()) + { + if (pConnector->Get_ID() == iterator->source_connector_id) + p_source_connector = pConnector; + if (pConnector->Get_ID() == iterator->target_connector_id) + p_target_connector = pConnector; + if ((p_source_connector.get() != nullptr) && (p_target_connector.get() != nullptr)) + { + find = true; + break; + } + } + + if (find) + break; + } + + // 判定查找结果 + if (find) + { + // 成功删除连接关系 + if (p_source_connector->Disconnect_To(p_target_connector.get()) == true) + { + /** + * @todo 调整工作路由层级 + */ + + // 释放ID并销毁容器 + this->Edge_ID_Generator.Release_ID(iterator->id); + return this->Edge_Pool.erase(iterator); + } + } + + return iterator--; +} + +// 删除连接 true -> success / false -> failed +bool Workflow_Editor::Del_Link(int source_connector_id, int target_connector_id) +{ + // 遍历边池,删除对应的边 + for (auto iterator = this->Edge_Pool.begin(); iterator != this->Edge_Pool.end(); iterator++) + if ((iterator->source_connector_id == source_connector_id) && (iterator->target_connector_id == target_connector_id)) + { + this->Del_Link(iterator); + return true; + } + + return false; +}