DLT_Splitter/Src/Workflow-Editor.cpp

250 lines
7.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "Workflow-Editor.hpp"
#include "imgui.h"
#include "imgui_internal.h"
#include "imnodes.h"
#include <algorithm>
// 构造函数
Workflow_Editor_Class::Workflow_Editor_Class() {}
// 析构函数
Workflow_Editor_Class::~Workflow_Editor_Class()
{
// 释放资源
for (auto &pNode : this->Node_List)
delete pNode;
}
// 客制化圆形带X按钮
bool CircleButtonWithX(const char *id, float radius)
{
ImGuiWindow *window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return false;
// 创建ID
ImGuiID button_id = window->GetID(id);
// 计算按钮位置和大小
ImVec2 pos = window->DC.CursorPos;
ImVec2 size(radius * 2, radius * 2);
ImRect bb(pos, ImVec2(pos.x + size.x, pos.y + size.y));
// 处理交互
ImGui::ItemSize(bb);
if (!ImGui::ItemAdd(bb, button_id))
return false;
bool hovered, held;
bool pressed = ImGui::ButtonBehavior(bb, button_id, &hovered, &held);
// 绘制
ImU32 col = ImGui::GetColorU32(
held ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
: ImGuiCol_Button);
// 获取绘制列表
ImDrawList *draw_list = ImGui::GetWindowDrawList();
ImVec2 center = ImVec2(pos.x + radius, pos.y + radius);
// 绘制圆形
draw_list->AddCircleFilled(center, radius, col, 32);
// 绘制边框(可选)
draw_list->AddCircle(center, radius, ImGui::GetColorU32(ImGuiCol_Border), 32, 1.0f);
// 计算X的线条
float cross_radius = radius * 0.5f; // X的大小
float thickness = radius * 0.15f; // X的粗细
// 绘制X的两条线
draw_list->AddLine(
ImVec2(center.x - cross_radius, center.y - cross_radius),
ImVec2(center.x + cross_radius, center.y + cross_radius),
ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), // 白色X
thickness);
draw_list->AddLine(
ImVec2(center.x + cross_radius, center.y - cross_radius),
ImVec2(center.x - cross_radius, center.y + cross_radius),
ImGui::GetColorU32(ImVec4(1.0f, 1.0f, 1.0f, 1.0f)), // 白色X
thickness);
return pressed;
}
// 消息行输入节点绘制函数
bool MsgLine_Input_Node_Class::show_and_get_state()
{
// 节点宽度
const float node_width = 200.0f;
bool delete_flag = false;
// 初始化位置设定
if (this->initial_state)
{
ImNodes::SetNodeScreenSpacePos(this->id, this->initial_position);
this->initial_state = false;
}
// 绘制节点
ImNodes::BeginNode(this->id);
{
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, ImGui::GetStyle().ItemSpacing.y));
// 标题部分
ImNodes::BeginNodeTitleBar();
{
ImGui::TextUnformatted(u8"DLT-信息输入节点");
ImGui::SameLine();
ImGui::Dummy(ImVec2(node_width - ImGui::CalcTextSize(u8"DLT-信息输入节点").x - ImGui::GetTextLineHeight(), 0.0f));
ImGui::SameLine();
// 绘制关闭按钮
if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2))
delete_flag = true;
}
ImNodes::EndNodeTitleBar();
// // 正文部分
// ImGui::Text(u8"DLT消息输入流\n每次输出一条消息");
// ImGui::Text(u8"(节点ID : %d)", this->id);
// 链接点
ImNodes::BeginOutputAttribute(0, 1);
// const float label_width = ImGui::CalcTextSize(u8"DLT消息行->").x;
// ImGui::Indent(label_width);
ImGui::Dummy(ImVec2(node_width - ImGui::CalcTextSize("(?) DLT MSG ->").x, 0.0f));
ImGui::SameLine();
// Help Mark
{
ImGui::TextDisabled("(?) ");
if (ImGui::BeginItemTooltip())
{
ImGui::TextUnformatted(u8"每个处理流程开始时输出一条DLT消息\n每个此类节点输出的消息均会独立遍历所有输入文件;");
ImGui::EndTooltip();
}
}
ImGui::SameLine();
ImGui::TextUnformatted("DLT MSG ->");
ImNodes::EndOutputAttribute();
ImGui::PopStyleVar();
}
ImNodes::EndNode();
// 返回节点状态
return delete_flag;
}
// 显示工作流节点编辑器
void Workflow_Editor_Class::Show(void)
{
// 浅色主题
ImNodes::StyleColorsLight();
ImNodes::BeginNodeEditor();
ImGui::PopStyleVar();
{
// 显示所有节点
for (auto iterator = this->Node_List.begin(); iterator != this->Node_List.end(); iterator++)
{
if ((*iterator)->show_and_get_state())
{
delete *iterator;
// 迭代器删除后会返回下一个位置的迭代器
iterator = this->Node_List.erase(iterator);
iterator--;
}
}
// 右键菜单
{
const bool open_popup = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) &&
ImNodes::IsEditorHovered() &&
ImGui::IsMouseReleased(ImGuiMouseButton_Right);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8.f, 8.f));
if (!ImGui::IsAnyItemHovered() && open_popup)
{
ImGui::OpenPopup("RightClick_Popup");
}
if (ImGui::BeginPopup("RightClick_Popup"))
{
ImVec2 click_pos = ImGui::GetMousePosOnOpeningCurrentPopup();
// 节点添加菜单
if (ImGui::BeginMenu("Add Nodes"))
{
if (ImGui::MenuItem("Msg input node."))
this->Add_Node(NODE_TYPE_MSG_LINE_INPUT, click_pos);
ImGui::EndMenu();
}
ImGui::EndPopup();
}
}
{
// ImNodes::BeginNode(1);
// ImNodes::BeginNodeTitleBar();
// // ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 10.0f); // 绘制风格栈压入窗口圆角为0
// // ImGui::Button("X");
// // ImGui::PopStyleVar();
// if (CircleButtonWithX("#X", ImGui::GetTextLineHeight() / 2))
// {
// };
// ImGui::SameLine();
// ImGui::TextUnformatted("Output Node");
// ImNodes::EndNodeTitleBar();
// ImGui::Text("Test Format %%d :%d", 123);
// ImGui::Button("Click");
// ImGui::SameLine();
// static bool check = false;
// ImGui::Checkbox("", &check);
// ImNodes::EndNode();
}
}
ImNodes::MiniMap(0.2f, ImNodesMiniMapLocation_TopRight);
ImNodes::EndNodeEditor();
}
// 添加指定类型节点
void Workflow_Editor_Class::Add_Node(NodeType type, ImVec2 initial_position)
{
// 获取可用ID
auto get_id = [&]() -> int
{
int target_id = 0;
for (auto &pNode : this->Node_List)
if (target_id == pNode->getID())
target_id++;
else
break;
return target_id;
};
// 记录节点
switch (type)
{
case NODE_TYPE_MSG_LINE_INPUT: // 消息行输入
this->Node_List.push_back(new MsgLine_Input_Node_Class(get_id(), initial_position));
break;
case NODE_TYPE_CSV_EXPORTER: // CSV输出器
default:
break;
}
// 重新排序确保后续ID分配正常
std::sort(this->Node_List.begin(),
this->Node_List.end(),
[](Node_Class *a, Node_Class *b) -> bool
{ return a->getID() < b->getID(); });
}