#include "Workflow_Editor.hpp" #include "imgui_internal.h" #include "Global_Variables.hpp" #include "Json_Utilities.hpp" extern "C" { #include "windows.h" } // 绘制节点编辑器 void Workflow_Editor::Show(void) { // 选区信息 bool bounding_box_delete_flag = false; int bounding_box_link_nums = ImNodes::NumSelectedLinks(); int bounding_box_node_nums = ImNodes::NumSelectedNodes(); // 加载配置文件标志位 bool Config_Load_Flag = false; // 浅色主题节点编辑器窗体 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(Abs_Node::NODE_TYPE_CONNECTOR_TEST, click_pos); if (ImGui::MenuItem(u8"DLT信息输入节点")) this->Add_Node(Abs_Node::NODE_TYPE_MSG_LINE_INPUT, click_pos); ImGui::EndMenu(); } // 删除框选内容 if (ImGui::MenuItem(u8"删除所选内容", nullptr, nullptr, (bounding_box_link_nums > 0) || (bounding_box_node_nums > 0))) bounding_box_delete_flag = true; if (ImGui::MenuItem(u8"构建工作树(Debug)")) if (this->Build_Process_Route() == false) MessageBoxW(Main_Window_hWnd, L"构建工作树失败\n检查是否有合法的起始节点", L"", MB_OK | MB_ICONERROR); if (ImGui::MenuItem(u8"存储工作区(Debug)")) this->Store_Config("[Debug]Config.Json"); if (ImGui::MenuItem(u8"加载工作区(Debug)")) Config_Load_Flag = true; 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(); // 处理配置文件加载 if (Config_Load_Flag == true) this->Load_Config("[Debug]Config.Json", ImGui::GetMousePos()); // 处理连线 { int source_id = -1, target_id = -1; if (ImNodes::IsLinkCreated(&source_id, &target_id)) this->Add_Link(source_id, target_id); } // 处理键盘事件 { // Ctrl + A 全选 if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_A) == true) { for (auto Link : this->Edge_Pool) if (ImNodes::IsLinkSelected(Link.id) == false) ImNodes::SelectLink(Link.id); for (auto pNode : this->Node_Pool) if (ImNodes::IsNodeSelected(pNode->Get_ID()) == false) ImNodes::SelectNode(pNode->Get_ID()); } // Ctrl + X 剪切 if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_X) == true) { bounding_box_delete_flag = true; /** * @todo * 剪切板实现 */ } // Delete 按键释放 或有删除请求 if (ImGui::IsKeyReleased(ImGuiKey_Delete) || bounding_box_delete_flag) { // 释放所有选中的边 { 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(Abs_Node::Node_Type_Enum type, ImVec2 initial_position) { // 新节点 std::shared_ptr p_New_Node; // 记录节点 switch (type) { case Abs_Node::NODE_TYPE_CONNECTOR_TEST: // 接口测试节点 p_New_Node = std::make_shared(&this->Node_ID_Generator, &this->Connector_ID_Generator, initial_position); break; case Abs_Node::NODE_TYPE_MSG_LINE_INPUT: // 消息行输入 (头节点) // 创建节点 p_New_Node = std::make_shared(&this->Node_ID_Generator, &this->Connector_ID_Generator, initial_position); break; case Abs_Node::NODE_TYPE_CSV_EXPORTER: // CSV输出器 break; default: return false; } // 成功分配时 if (p_New_Node.get() != nullptr) { // 将新增的节点记录到接口池及散点池 this->Node_Pool.push_back(p_New_Node); return true; } return false; } // 删除节点 返回迭代器指定位置的下一个位置的迭代器,仅限内部使用 std::vector>::iterator Workflow_Editor::Del_Node(std::vector>::iterator iterator) { // 获取接口列表 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; } } } 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) { // 检查下一步的连接是否会出现回环 { // 工具Lambda表达式,查找接口id的所属节点 auto Lambda_Find_Owner = [&](int connector_id) -> Abs_Node * { for (auto pNode : this->Node_Pool) { for (auto pConnector : pNode->Get_Connector_List()) { if (pConnector->Get_ID() == connector_id) return pNode.get(); } } return nullptr; }; // 关联关系查找(递归Lambda) auto Lambda_Find_Related = [&](auto self, Abs_Node *pSource, Abs_Node *pTarget) -> bool { std::vector Sub_Node_List; for (auto pConnector : pSource->Get_Connector_List()) { // 检索所有OutPut类型的接口的下位节点 if (pConnector->Get_Type() == Abs_Connector::CONNECTOR_TYPE_OUTPUT) { for (auto pSubConnector : pConnector->Get_Related_List()) { auto pSubNode = Lambda_Find_Owner(pSubConnector->Get_ID()); bool duplicated = false; // 查重并加入子节点列表 for (auto pNode : Sub_Node_List) { if (pNode == pSubNode) { duplicated = true; break; } } if (!duplicated) Sub_Node_List.push_back(pSubNode); } } } // 递归出口 无子节点时直接返回 if (Sub_Node_List.size() == 0) return false; // 检索所有的下位节点 for (auto pNode : Sub_Node_List) { if (pNode == pTarget) return true; else if (self(self, pNode, pTarget) == true) return true; } return false; }; // 检查连接关系 if (Lambda_Find_Related(Lambda_Find_Related, Lambda_Find_Owner(target_connector_id), Lambda_Find_Owner(source_connector_id))) { MessageBoxW(Main_Window_hWnd, L"存在回环连线!!!", L"", MB_OK | MB_ICONERROR); return false; } } // 先尝试连接,成功后再进行边池操作 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}); } 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) { // 释放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; } // 创建工作路由 true -> success / false -> failed bool Workflow_Editor::Build_Process_Route(void) { this->Clear_Process_Route(); // 找出所有的头节点 std::vector> Head_List; for (auto pNode : this->Node_Pool) { if (pNode->Get_Type() == Abs_Node::NODE_TYPE_MSG_LINE_INPUT) Head_List.push_back(pNode); } // 没有可以构建的工作序列 if (Head_List.size() == 0) return false; // 工具Lambda表达式,查找接口id的所属节点 auto Lambda_Find_Owner = [&](int connector_id) -> std::shared_ptr { for (auto pNode : this->Node_Pool) { for (auto pConnector : pNode->Get_Connector_List()) { if (pConnector->Get_ID() == connector_id) return pNode; } } return nullptr; }; // 处理所有头节点工作流程 for (auto pNode : Head_List) { // 工作序列 std::vector> Process_Sequence_List; // 处理序列 std::vector> pRelated_List; // 关联节点列表 // 构建相关节点列表 auto Lambda_Find_Related_List = [&](auto self, std::shared_ptr pTargetNode) -> void { // 记录自身到关联列表中 pRelated_List.push_back(pTargetNode); // 查找当前节点的关联节点 std::vector Target_Related_Node_List; for (auto pConnector : pTargetNode->Get_Connector_List()) { for (auto pRelated_Connector : pConnector->Get_Related_List()) { auto pRelated_Node = Lambda_Find_Owner(pRelated_Connector->Get_ID()); bool duplicated = false; // 查重并加入子节点列表 for (auto pNode : Target_Related_Node_List) { if (pNode == pRelated_Node) { duplicated = true; break; } } if (!duplicated) Target_Related_Node_List.push_back(pRelated_Node); } } // 泛洪检查所有相邻的节点 for (auto pNode : Target_Related_Node_List) { bool find = false; for (auto pCheckedNode : pRelated_List) if (pCheckedNode == pNode) { find = true; break; } // 当前关联节点未被记录时,递归顺延泛洪 if (!find) self(self, pNode); } }; // 工具Lambda表达式,检查依赖节点 true -> ALL Dependency Find auto Lambda_Check_Dependency = [&](Abs_Node *pTargetNode) -> bool { // 查找目标节点的依赖节点列表 std::vector> Dependency_NodeList; for (auto pConnector : pTargetNode->Get_Connector_List()) { if (pConnector->Get_Type() == Abs_Connector::CONNECTOR_TYPE_INPUT) { for (auto pPreConnector : pConnector->Get_Related_List()) { auto pPreNode = Lambda_Find_Owner(pPreConnector->Get_ID()); bool duplicated = false; // 查重并加入依赖关系列表 for (auto pNode : Dependency_NodeList) { if (pNode == pPreNode) { duplicated = true; break; } } if (!duplicated) Dependency_NodeList.push_back(pPreNode); } } } // 比对依赖的节点和已处理的节点 bool all_find_flag = true; for (auto pDependencyNode : Dependency_NodeList) { bool find = false; for (auto pProcessedNode : Process_Sequence_List) { if (pDependencyNode == pProcessedNode) { find = true; break; } } if (!find) { all_find_flag = false; break; } } return all_find_flag; }; // 构建处理序列,遍历所有关联节点直到不存在散点,每次都加入已经满足依赖的所有节点 Lambda_Find_Related_List(Lambda_Find_Related_List, pNode); while (pRelated_List.size() > 0) { for (auto iterator = pRelated_List.begin(); iterator != pRelated_List.end(); iterator++) { if (Lambda_Check_Dependency(iterator->get()) == true) { Process_Sequence_List.push_back(*iterator); iterator = pRelated_List.erase(iterator) - 1; } } } // 工作序列中仅孤立节点时不加入工作路由表 if (Process_Sequence_List.size() > 1) this->Process_Route.push_back(Process_Sequence_List); } /** * @todo * 工作路由序列合法性检查 * 非法 -> return false */ return true; } // 清除工作路由 true -> success / false -> failed bool Workflow_Editor::Clear_Process_Route(void) { decltype(this->Process_Route) empty_route; this->Process_Route.swap(empty_route); return true; } // 清除整个工作区 void Workflow_Editor::Clear_All(void) { for (auto iterator = this->Node_Pool.begin(); iterator != this->Node_Pool.end(); iterator++) iterator = this->Del_Node(iterator) - 1; this->Clear_Process_Route(); } // 加载取配置文件 true -> success / false -> failed bool Workflow_Editor::Load_Config(const char *file_path, ImVec2 initial_position) { // 工具Lambda string 转 wstring auto Lambda_String_To_WString = [](const std::string &str) -> std::wstring { if (str.empty()) return std::wstring(); int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0); if (len <= 0) return std::wstring(); std::wstring wstr(len, L'\0'); MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], len); return wstr; }; Json_Value Config_Value; std::string err_str = JsonFile_Parse(file_path, &Config_Value); if (!err_str.empty()) { MessageBoxW(Main_Window_hWnd, (L"文件解析错误!!\n" + Lambda_String_To_WString(err_str)).c_str(), L"", MB_OK | MB_ICONERROR); return false; } // 清理工作区 this->Clear_All(); decltype(this->Node_Pool) Created_Node_List; // 创建节点 { auto Node_Info_List = Config_Value.asObject().get("Nodes").asArry().element_list; // 计算中心坐标 ImVec2 Position_Offset = {0, 0}; for (auto Node_Info : Node_Info_List) { Position_Offset.x += Node_Info.asObject().get("position").asObject().get("x").asFloat(); Position_Offset.y += Node_Info.asObject().get("position").asObject().get("y").asFloat(); } if (Node_Info_List.size() > 0) { Position_Offset.x /= Node_Info_List.size(); Position_Offset.y /= Node_Info_List.size(); } // 计算与初始位置的偏移量 Position_Offset.x = initial_position.x - Position_Offset.x; Position_Offset.y = initial_position.y - Position_Offset.y; // 依次新建节点 for (auto Node_Info : Node_Info_List) { this->Add_Node((Abs_Node::Node_Type_Enum)Node_Info.asObject().get("type").asInteger(), ImVec2(Node_Info.asObject().get("position").asObject().get("x").asFloat() + Position_Offset.x, Node_Info.asObject().get("position").asObject().get("y").asFloat() + Position_Offset.y)); Created_Node_List.push_back(this->Node_Pool.back()); } } // 创建连接关系 { auto Link_Info_List = Config_Value.asObject().get("Connections").asArry().element_list; for (auto Link_Info : Link_Info_List) { auto Source_Info = Link_Info.asObject().get("source").asObject(); auto Target_Info = Link_Info.asObject().get("target").asObject(); auto Source_Connector = Created_Node_List[Source_Info.get("owner").asInteger()]->Get_Connector_List()[Source_Info.get("index").asInteger()]; auto Target_Connector = Created_Node_List[Target_Info.get("owner").asInteger()]->Get_Connector_List()[Target_Info.get("index").asInteger()]; this->Add_Link(Source_Connector->Get_ID(), Target_Connector->Get_ID()); } } return true; } // 存储配置文件 true -> success / false -> failed bool Workflow_Editor::Store_Config(const char *file_path) { FILE *pFile = fopen(file_path, "wb"); if (pFile == nullptr) { MessageBoxW(Main_Window_hWnd, L"文件打开失败!!", L"", MB_OK | MB_ICONERROR); return false; } fclose(pFile); std::vector Node_Info_List; std::vector Link_Info_List; // 工具Lambda表达式,查找接口id的所属节点 auto Lambda_Find_Owner = [&](int connector_id) -> std::shared_ptr { for (auto pNode : this->Node_Pool) { for (auto pConnector : pNode->Get_Connector_List()) { if (pConnector->Get_ID() == connector_id) return pNode; } } return nullptr; }; // 遍历节点池,以遍历计数作为存储相对序列索引 size_t Node_Count = this->Node_Pool.size(); for (size_t node_index = 0; node_index < Node_Count; node_index++) { // 存储节点相关信息 ImVec2 position = ImNodes::GetNodeGridSpacePos(this->Node_Pool[node_index]->Get_ID()); Node_Info_List.push_back( Json_Object({{"index", (int)node_index}, // {"type", this->Node_Pool[node_index]->Get_Type()}, // { "position", Json_Object({ {"x", position.x}, // {"y", position.y} // }) // }, // {"args", Json_Arry()}} // )); // 查询是有相关联的连接 for (auto edge : this->Edge_Pool) { // 存在关联连接时 if (Lambda_Find_Owner(edge.source_connector_id) == this->Node_Pool[node_index]) { int target_node_index = -1; // 目标节点索引 int source_connector_index = -1; // 源接口索引 int target_connector_index = -1; // 目标接口索引 // 查询源接口在源节点的索引 size_t list_size = this->Node_Pool[node_index]->Get_Connector_List().size(); for (size_t count = 0; count < list_size; count++) if (this->Node_Pool[node_index]->Get_Connector_List()[count]->Get_ID() == edge.source_connector_id) { source_connector_index = count; break; } // 查询目标节点索引 auto pTarget_Node = Lambda_Find_Owner(edge.target_connector_id); for (size_t count = 0; count < Node_Count; count++) if (this->Node_Pool[count] == pTarget_Node) { target_node_index = count; break; } // 查询目标接口在目标节点的索引 list_size = pTarget_Node->Get_Connector_List().size(); for (size_t count = 0; count < list_size; count++) if (pTarget_Node->Get_Connector_List()[count]->Get_ID() == edge.target_connector_id) { target_connector_index = count; break; } Link_Info_List.push_back( Json_Object( { {"source", Json_Object({ {"owner", (int)node_index}, // {"index", source_connector_index}, // })}, // {"target", Json_Object({ {"owner", target_node_index}, // {"index", target_connector_index}, // })} // })); } } } std::string err_str = Json_Export(file_path, Json_Object({ {"Nodes", Json_Arry(Node_Info_List)}, // {"Connections", Json_Arry(Link_Info_List)} // }), true); // 输出错误信息 if (!err_str.empty()) { // 工具Lambda string 转 wstring auto Lambda_String_To_WString = [](const std::string &str) -> std::wstring { if (str.empty()) return std::wstring(); int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), nullptr, 0); if (len <= 0) return std::wstring(); std::wstring wstr(len, L'\0'); MultiByteToWideChar(CP_UTF8, 0, str.c_str(), (int)str.size(), &wstr[0], len); return wstr; }; MessageBoxW(Main_Window_hWnd, (L"存储配置文件失败!!\n" + Lambda_String_To_WString(err_str)).c_str(), L"", MB_OK | MB_ICONERROR); return false; } return true; }