DLT_Splitter/Src/Workflow_Editor.cpp

342 lines
12 KiB
C++

#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<int> 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<int> 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<Abs_Node> p_New_Node;
// 记录节点
switch (type)
{
case NODE_TYPE_CONNECTOR_TEST: // 接口测试节点
p_New_Node = std::make_shared<Connector_Test_Node>(&this->Node_ID_Generator,
&this->Connector_ID_Generator,
initial_position);
break;
case NODE_TYPE_MSG_LINE_INPUT: // 消息行输入 (头节点)
// 创建节点
p_New_Node = std::make_shared<MSG_Input_Node>(&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<std::shared_ptr<Abs_Node>>::iterator Workflow_Editor::Del_Node(std::vector<std::shared_ptr<Abs_Node>>::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<Abs_Connector> p_source_connector;
std::shared_ptr<Abs_Connector> 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<Workflow_Editor::Edge>::iterator Workflow_Editor::Del_Link(std::vector<Edge>::iterator iterator)
{
// 查找接口
bool find = false;
std::shared_ptr<Abs_Connector> p_source_connector;
std::shared_ptr<Abs_Connector> 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;
}