Compare commits
No commits in common. "dev" and "main" have entirely different histories.
@ -145,13 +145,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
size_t get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list));
|
size_t get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list));
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief 将消息列表按时间戳排序
|
|
||||||
* @param null
|
|
||||||
* @return DLT_Type::DLT_Err 错误类型枚举
|
|
||||||
*/
|
|
||||||
DLT_Type::DLT_Err sort_msg_list(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 导出为CSV
|
* @brief 导出为CSV
|
||||||
* @param file_name_str 目标文件名
|
* @param file_name_str 目标文件名
|
||||||
|
|||||||
@ -12,7 +12,6 @@ extern "C"
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "Type_Descriptions.hpp"
|
#include "Type_Descriptions.hpp"
|
||||||
#include "Workflow-Editor.hpp"
|
|
||||||
|
|
||||||
// 主窗体句柄
|
// 主窗体句柄
|
||||||
extern HWND Main_Window_hWnd;
|
extern HWND Main_Window_hWnd;
|
||||||
@ -30,7 +29,4 @@ extern ID3D11RenderTargetView *g_mainRenderTargetView; // D3D11 渲染目标
|
|||||||
extern Input_File_Node *input_dlt_file_list_head;
|
extern Input_File_Node *input_dlt_file_list_head;
|
||||||
extern size_t input_dlt_file_count;
|
extern size_t input_dlt_file_count;
|
||||||
|
|
||||||
// 节点编辑器
|
|
||||||
extern Workflow_Editor_Class Workflow_Editor;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -1,89 +0,0 @@
|
|||||||
#ifndef __WORKFLOW_NODES_HPP__
|
|
||||||
#define __WORKFLOW_NODES_HPP__
|
|
||||||
|
|
||||||
#include "imgui.h"
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "stdint.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
// // 并行工作链
|
|
||||||
// class Parallel_Working_List
|
|
||||||
// {
|
|
||||||
// private:
|
|
||||||
// // 节点计数
|
|
||||||
// size_t node_count;
|
|
||||||
|
|
||||||
// // 内部迭代器
|
|
||||||
// class iterator
|
|
||||||
// {
|
|
||||||
// };
|
|
||||||
|
|
||||||
// public:
|
|
||||||
// iterator begin() { return iterator(arr); }
|
|
||||||
// iterator end() { return iterator(arr + SIZE); }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// 节点类型枚举
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
NODE_TYPE_MSG_LINE_INPUT, // 消息输入节点
|
|
||||||
NODE_TYPE_CSV_EXPORTER, // CSV输出节点
|
|
||||||
} NodeType;
|
|
||||||
|
|
||||||
// 节点基类
|
|
||||||
class Node_Class
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
int id; // 节点ID
|
|
||||||
bool initial_state; // 初始状态
|
|
||||||
ImVec2 initial_position; // 初始位置
|
|
||||||
|
|
||||||
public:
|
|
||||||
// 初始化列表构造
|
|
||||||
explicit Node_Class(int id, ImVec2 initial_position = ImVec2(0, 0)) : id(id), initial_state(true), initial_position(initial_position) {}
|
|
||||||
int getID() { return this->id; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示节点并获取状态(子类必须实现)
|
|
||||||
* @param null
|
|
||||||
* @return 0 -> normal : 1-> close
|
|
||||||
*/
|
|
||||||
virtual bool show_and_get_state(void) = 0;
|
|
||||||
|
|
||||||
virtual ~Node_Class() = default; // 抽象基类必须有虚析构函数
|
|
||||||
};
|
|
||||||
|
|
||||||
// 消息输出节点
|
|
||||||
class MsgLine_Input_Node_Class : public Node_Class
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit MsgLine_Input_Node_Class(int id, ImVec2 initial_position = ImVec2(0, 0)) : Node_Class(id, initial_position) {};
|
|
||||||
bool show_and_get_state(void) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 节点编辑器类
|
|
||||||
class Workflow_Editor_Class
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
// 节点列表
|
|
||||||
std::vector<Node_Class *> Node_List;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// 构造函数
|
|
||||||
Workflow_Editor_Class();
|
|
||||||
|
|
||||||
// 析构函数
|
|
||||||
~Workflow_Editor_Class();
|
|
||||||
|
|
||||||
// 显示工作流节点编辑器
|
|
||||||
void Show(void);
|
|
||||||
|
|
||||||
// 新增节点
|
|
||||||
void Add_Node(NodeType type, ImVec2 initial_position = ImVec2(0, 0));
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -285,82 +285,6 @@ size_t DLT_Log::get_msg_list(DLT_Type::DLT_Msg_Node *(&p_msg_list))
|
|||||||
return this->loaded_msg_count;
|
return this->loaded_msg_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLT_Type::DLT_Err DLT_Log::sort_msg_list(void)
|
|
||||||
{
|
|
||||||
// 临时分配的排序用指针数组
|
|
||||||
DLT_Type::DLT_Msg_Node **Node_P_Arr = (DLT_Type::DLT_Msg_Node **)malloc(sizeof(DLT_Type::DLT_Msg_Node *) * this->loaded_msg_count);
|
|
||||||
if (Node_P_Arr == nullptr)
|
|
||||||
return DLT_Type::DLT_ERROR_MEM_ALLOCATE_FAILED;
|
|
||||||
|
|
||||||
// 填充地址数组
|
|
||||||
{
|
|
||||||
DLT_Type::DLT_Msg_Node *p_target_node = this->Msg_List_Head;
|
|
||||||
for (size_t count = 0; count < loaded_msg_count; count++)
|
|
||||||
{
|
|
||||||
Node_P_Arr[count] = p_target_node;
|
|
||||||
p_target_node = p_target_node->p_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// qsort排序
|
|
||||||
qsort(Node_P_Arr,
|
|
||||||
loaded_msg_count,
|
|
||||||
sizeof(DLT_Type::DLT_Msg_Node *),
|
|
||||||
|
|
||||||
// 升序,小时间戳在前
|
|
||||||
[](const void *param1, const void *param2) -> int
|
|
||||||
{
|
|
||||||
DLT_Type::DLT_Msg_Node *Node1 = *(DLT_Type::DLT_Msg_Node **)param1;
|
|
||||||
DLT_Type::DLT_Msg_Node *Node2 = *(DLT_Type::DLT_Msg_Node **)param2;
|
|
||||||
if (Node1->Msg.storage_header.seconds > Node2->Msg.storage_header.seconds)
|
|
||||||
return 1;
|
|
||||||
else if (Node1->Msg.storage_header.seconds == Node2->Msg.storage_header.seconds)
|
|
||||||
{
|
|
||||||
if (Node1->Msg.storage_header.microseconds > Node2->Msg.storage_header.microseconds)
|
|
||||||
return 1;
|
|
||||||
else if (Node1->Msg.storage_header.microseconds == Node2->Msg.storage_header.microseconds)
|
|
||||||
{
|
|
||||||
// 存在0.1ms时间戳
|
|
||||||
if (Node1->Msg.standard_header.htyp.WTMS && Node2->Msg.standard_header.htyp.WTMS)
|
|
||||||
{
|
|
||||||
if (Node1->Msg.standard_header_extra.tmsp > Node2->Msg.standard_header_extra.tmsp)
|
|
||||||
return 1;
|
|
||||||
else if (Node1->Msg.standard_header_extra.tmsp == Node2->Msg.standard_header_extra.tmsp)
|
|
||||||
return 0;
|
|
||||||
else if (Node1->Msg.standard_header_extra.tmsp < Node2->Msg.standard_header_extra.tmsp)
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 重新连接消息列表
|
|
||||||
{
|
|
||||||
this->Msg_List_Head = Node_P_Arr[0];
|
|
||||||
this->Msg_List_End = Node_P_Arr[this->loaded_msg_count - 1];
|
|
||||||
this->Msg_List_End->p_next = nullptr;
|
|
||||||
|
|
||||||
DLT_Type::DLT_Msg_Node *p_target = Node_P_Arr[0];
|
|
||||||
for (size_t count = 1; count < this->loaded_msg_count; count++)
|
|
||||||
{
|
|
||||||
p_target->p_next = Node_P_Arr[count];
|
|
||||||
p_target = p_target->p_next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 释放空间
|
|
||||||
free(Node_P_Arr);
|
|
||||||
return DLT_Type::DLT_ERROR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
||||||
{
|
{
|
||||||
FILE *p_file = fopen(file_name_str, "wb");
|
FILE *p_file = fopen(file_name_str, "wb");
|
||||||
@ -403,23 +327,13 @@ DLT_Type::DLT_Err DLT_Log::export_to_csv(const char *file_name_str)
|
|||||||
/**< Timestamp since system start in 0.1 milliseconds */
|
/**< Timestamp since system start in 0.1 milliseconds */
|
||||||
char time_str[20];
|
char time_str[20];
|
||||||
sprintf(time_str, "%d", p_msg->Msg.standard_header_extra.tmsp);
|
sprintf(time_str, "%d", p_msg->Msg.standard_header_extra.tmsp);
|
||||||
if (strlen(time_str) > 4)
|
char *p_sec_end = time_str + strlen(time_str) - 4;
|
||||||
{
|
|
||||||
char *p_sec_end = time_str + strlen(time_str) - 4;
|
|
||||||
|
|
||||||
// 输出秒
|
// 输出秒
|
||||||
for (char *p = time_str; p < p_sec_end; p++)
|
for (char *p = time_str; p < p_sec_end; p++)
|
||||||
fputc(*p, p_file);
|
fputc(*p, p_file);
|
||||||
// 输出剩余的时间
|
// 输出剩余的时间
|
||||||
fprintf(p_file, ".%s,", p_sec_end);
|
fprintf(p_file, ".%s,", p_sec_end);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(p_file, "0.");
|
|
||||||
for (int count = 4 - strlen(time_str); count > 0; count--)
|
|
||||||
fputc('0', p_file);
|
|
||||||
fprintf(p_file, "%s,", time_str);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
fprintf(p_file, "N/A,");
|
fprintf(p_file, "N/A,");
|
||||||
|
|||||||
@ -15,6 +15,3 @@ ID3D11RenderTargetView *g_mainRenderTargetView = nullptr; // D3D11 渲染目标
|
|||||||
// 文件输入相关
|
// 文件输入相关
|
||||||
Input_File_Node *input_dlt_file_list_head;
|
Input_File_Node *input_dlt_file_list_head;
|
||||||
size_t input_dlt_file_count;
|
size_t input_dlt_file_count;
|
||||||
|
|
||||||
// 节点编辑器
|
|
||||||
Workflow_Editor_Class Workflow_Editor;
|
|
||||||
@ -36,62 +36,24 @@ void UI_Layout()
|
|||||||
// 设置窗体相关属性,不允许停靠
|
// 设置窗体相关属性,不允许停靠
|
||||||
window_flags |= ImGuiWindowFlags_NoDocking;
|
window_flags |= ImGuiWindowFlags_NoDocking;
|
||||||
|
|
||||||
// 临时设置一下窗体大小,动态扩张窗体
|
|
||||||
{
|
|
||||||
static size_t Width = MAIN_FRAME_SIZE_WIDTH_MIN;
|
|
||||||
static size_t Height = MAIN_FRAME_SIZE_HEIGHT_MIN;
|
|
||||||
if (!(Width >= 1400 && Height >= 700))
|
|
||||||
{
|
|
||||||
SetWindowPos(
|
|
||||||
Main_Window_hWnd,
|
|
||||||
NULL,
|
|
||||||
(GetSystemMetrics(SM_CXSCREEN) - (Width)) / 2,
|
|
||||||
(GetSystemMetrics(SM_CYSCREEN) - (Height)) / 2,
|
|
||||||
Width,
|
|
||||||
Height,
|
|
||||||
SWP_NOZORDER);
|
|
||||||
|
|
||||||
if (Height < 700)
|
|
||||||
Height += 5;
|
|
||||||
if (Width < 1400)
|
|
||||||
Width += 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::Begin("Main Panel", NULL, window_flags); // 创建主面板
|
ImGui::Begin("Main Panel", NULL, window_flags); // 创建主面板
|
||||||
ImGui::PopStyleVar(2); // 退出绘制风格栈中的设置项
|
ImGui::PopStyleVar(2); // 退出绘制风格栈中的设置项
|
||||||
{
|
{
|
||||||
const ImGuiStyle &style = ImGui::GetStyle();
|
const ImGuiStyle &style = ImGui::GetStyle();
|
||||||
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY));
|
float main_scale = ImGui_ImplWin32_GetDpiScaleForMonitor(MonitorFromPoint(POINT{0, 0}, MONITOR_DEFAULTTOPRIMARY));
|
||||||
|
|
||||||
// 左半部分
|
// 拖拽输入区域
|
||||||
ImGui::BeginChild("Left Part", ImVec2(MAIN_FRAME_SIZE_WIDTH_MIN, ImGui::GetContentRegionAvail().y));
|
Widgets::Drag_Input_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().x / 2 > MAIN_FRAME_SIZE_WIDTH_MIN / 2 ? MAIN_FRAME_SIZE_WIDTH_MIN / 2 : ImGui::GetContentRegionAvail().x / 2));
|
||||||
{
|
|
||||||
|
|
||||||
// 拖拽输入区域
|
// 文件列表组件
|
||||||
Widgets::Drag_Input_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().x / 2 > MAIN_FRAME_SIZE_WIDTH_MIN * main_scale / 2 ? MAIN_FRAME_SIZE_WIDTH_MIN * main_scale / 2 : ImGui::GetContentRegionAvail().x / 2));
|
Widgets::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y)));
|
||||||
|
|
||||||
// 文件列表组件
|
// 导出文件
|
||||||
Widgets::File_List_Area(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y - (ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale + style.ItemSpacing.y)));
|
Widgets::Control_Panel(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale));
|
||||||
|
|
||||||
// 导出文件
|
|
||||||
Widgets::Control_Panel(ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetTextLineHeightWithSpacing() + 20 * main_scale));
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
|
|
||||||
ImGui::SameLine();
|
|
||||||
|
|
||||||
// 右半部分
|
|
||||||
ImGui::BeginChild("Right Part", ImVec2(0, 0));
|
|
||||||
{
|
|
||||||
// 工作流节点编辑器
|
|
||||||
Workflow_Editor.Show();
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
ImGui::ShowDemoWindow(nullptr);
|
// ImGui::ShowDemoWindow(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widgets::Drag_Input_Area(const ImVec2 &size)
|
void Widgets::Drag_Input_Area(const ImVec2 &size)
|
||||||
@ -433,8 +395,6 @@ void Widgets::Control_Panel(const ImVec2 &size)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 排序后导出
|
|
||||||
Log.sort_msg_list();
|
|
||||||
err = Log.export_to_csv(export_file_path_str);
|
err = Log.export_to_csv(export_file_path_str);
|
||||||
|
|
||||||
if (err == DLT_Type::DLT_ERROR_NONE)
|
if (err == DLT_Type::DLT_ERROR_NONE)
|
||||||
|
|||||||
@ -1,250 +0,0 @@
|
|||||||
#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(); });
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user