#include "Workflow_Editor.hpp" #include "imgui_internal.h" // 绘制节点编辑器 void Workflow_Editor::Show(void) { // 浅色主题节点编辑器窗体 ImNodes::StyleColorsLight(); ImNodes::BeginNodeEditor(); { // 显示所有节点 for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++) { if ((*iterator)->Get_CloseFlag() == true) { // 处理节点删除 iterator = this->Del_Node(iterator); iterator--; } else // 绘制节点 (*iterator)->Show(); } // 右键菜单 { const bool open_popup = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && ImNodes::IsEditorHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Right); // 设置弹窗周边Padding ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f)); // if (!ImGui::IsAnyItemHovered() && open_popup) if (open_popup) { ImGui::OpenPopup("RightClick_Popup"); } if (ImGui::BeginPopup("RightClick_Popup")) { ImVec2 click_pos = ImGui::GetMousePosOnOpeningCurrentPopup(); // 节点添加菜单 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(); } ImGui::EndPopup(); } ImGui::PopStyleVar(); } // 显示所有的连线 for (auto Edge : this->Edge_Pool) ImNodes::Link(Edge.id, Edge.source_connector_id, Edge.target_connector_id); // 缩略图 ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_TopRight); } ImNodes::EndNodeEditor(); // 处理连线 { int source_id = -1, target_id = -1; if (ImNodes::IsLinkCreated(&source_id, &target_id)) this->Add_Link(source_id, target_id); } // 处理键盘事件 { // Delete 按键释放 if (ImGui::IsKeyReleased(ImGuiKey_Delete)) { // 释放所有选中的边 { std::vector target_edge_id_list; target_edge_id_list.resize(ImNodes::NumSelectedLinks()); if (target_edge_id_list.size() > 0) { ImNodes::GetSelectedLinks(&target_edge_id_list[0]); for (auto edge_iterator = this->Edge_Pool.begin(); edge_iterator != this->Edge_Pool.end(); edge_iterator++) { 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; } } } // 释放所有选中的节点 { 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; }