DLT_Splitter/Src/Workflow_Editor.cpp

938 lines
34 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_internal.h"
#include "Global_Variables.hpp"
extern "C"
{
#include "windows.h"
}
// 绘制节点编辑器
void Workflow_Editor::Show(void)
{
// 选区信息
int bounding_box_link_nums = ImNodes::NumSelectedLinks();
int bounding_box_node_nums = ImNodes::NumSelectedNodes();
// 操作标志位
bool config_load_flag = false; // 加载配置文件
bool clipboard_copy_flag = false; // 复制到剪切板
bool clipboard_paste_flag = false; // 粘贴剪切板内容
bool bounding_box_delete_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"复制 Ctrl + C", nullptr, nullptr, (bounding_box_link_nums > 0) || (bounding_box_node_nums > 0)))
clipboard_copy_flag = true;
// 剪切框选内容
if (ImGui::MenuItem(u8"剪切 Ctrl + X", nullptr, nullptr, (bounding_box_link_nums > 0) || (bounding_box_node_nums > 0)))
clipboard_copy_flag = bounding_box_delete_flag = true;
// 粘贴框选内容
if (ImGui::MenuItem(u8"粘贴 Ctrl + V", nullptr, nullptr, !this->Config_Clipboard.isEmpty()))
clipboard_paste_flag = true;
// 删除框选内容
if (ImGui::MenuItem(u8"删除 Delete", 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;
if (ImGui::MenuItem(u8"执行工作流Debug"))
if (this->Execute_Workflow() == true)
MessageBoxW(Main_Window_hWnd, L"工作流执行完成!!", L"", MB_OK);
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)
{
clipboard_copy_flag = true;
bounding_box_delete_flag = true;
}
// Ctrl + C 复制到剪切板
if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_C) || clipboard_copy_flag)
{
// 获取框选的节点
std::vector<std::shared_ptr<Abs_Node>> Target_Node_List;
{
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 ID : Target_ID_List)
for (auto pNode : this->Node_Pool)
if (pNode->Get_ID() == ID)
Target_Node_List.push_back(pNode);
}
// 获取框选的边
std::vector<Edge> Target_Edge_List;
{
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 ID : Target_Edge_ID_List)
for (auto Edge : this->Edge_Pool)
if (Edge.id == ID)
Target_Edge_List.push_back(Edge);
}
// 写入剪切板
this->Config_Clipboard = Generate_Config(Target_Node_List, Target_Edge_List);
}
// Ctrl + V 粘贴
if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_V) || clipboard_paste_flag)
{
this->Apply_Config(this->Config_Clipboard, ImGui::GetMousePos());
}
/**
* @todo 实现历史记录、重做功能
* 可能的做法是使用配置数组方式实现
* 但节点内选项更新可能需要向外暴露状态更新接口
*/
// Ctrl + Z 撤销
if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_Z))
{
}
// Ctrl + Y 撤销
if (ImGui::IsKeyChordPressed(ImGuiMod_Ctrl | ImGuiKey_Y))
{
}
// Delete 按键释放 或有删除请求
if (ImGui::IsKeyReleased(ImGuiKey_Delete) || bounding_box_delete_flag)
{
// 释放所有选中的边
{
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(Abs_Node::Node_Type_Enum type, ImVec2 initial_position)
{
// 新节点
std::shared_ptr<Abs_Node> p_New_Node;
// 记录节点
switch (type)
{
case Abs_Node::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 Abs_Node::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 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<std::shared_ptr<Abs_Node>>::iterator Workflow_Editor::Del_Node(std::vector<std::shared_ptr<Abs_Node>>::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<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)
{
// 检查下一步的连接是否会出现回环
{
// 工具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<Abs_Node *> 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<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)
{
// 释放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<std::shared_ptr<Abs_Node>> 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<Abs_Node>
{
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<std::shared_ptr<Abs_Node>> Process_Sequence_List; // 处理序列
std::vector<std::shared_ptr<Abs_Node>> pRelated_List; // 关联节点列表
// 构建相关节点列表
auto Lambda_Find_Related_List = [&](auto self, std::shared_ptr<Abs_Node> pTargetNode) -> void
{
// 记录自身到关联列表中
pRelated_List.push_back(pTargetNode);
// 查找当前节点的关联节点
std::vector<decltype(pTargetNode)> 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<std::shared_ptr<Abs_Node>> 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;
}
// 开始执行工作流
bool Workflow_Editor::Execute_Workflow(void)
{
/**
* @todo 线程分离
* 将任务单独分离到线程中,并跟随进度条
*/
bool status = this->Build_Process_Route();
if (status == false)
return status;
for (auto Route : this->Process_Route)
for (auto pNode : Route)
{
status = pNode->Execute_Process();
if (status == false)
return false;
}
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();
}
// 从节点列表构建配置对象
Json_Object Workflow_Editor::Generate_Config(std::vector<std::shared_ptr<Abs_Node>> Node_List, std::vector<Edge> Edge_List)
{
std::vector<Json_Value> Node_Info_List;
std::vector<Json_Value> Link_Info_List;
// 工具Lambda表达式查找接口id的所属节点
auto Lambda_Find_Owner = [&](int connector_id) -> std::shared_ptr<Abs_Node>
{
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 = Node_List.size();
for (size_t node_index = 0; node_index < Node_Count; node_index++)
{
// 存储节点相关信息
ImVec2 position = ImNodes::GetNodeGridSpacePos(Node_List[node_index]->Get_ID());
Node_Info_List.push_back(
Json_Object({{"index", (int)node_index}, //
{"type", Node_List[node_index]->Get_Type()}, //
{
"position", Json_Object({
{"x", position.x}, //
{"y", position.y} //
}) //
}, //
{"args", Node_List[node_index]->Get_Arguments()}} //
));
// 查询是有相关联的连接
for (auto edge : Edge_List)
{
// 存在关联连接时
if (Lambda_Find_Owner(edge.source_connector_id) == Node_List[node_index])
{
// 检查目标节点是否在传入的节点列表内
bool find_target = false;
auto pTarget_Node = Lambda_Find_Owner(edge.target_connector_id);
for (auto pNode : Node_List)
if (pNode == pTarget_Node)
{
find_target = true;
break;
}
// 源、目标节点均找到时
if (find_target)
{
int target_node_index = -1; // 目标节点索引
int source_connector_index = -1; // 源接口索引
int target_connector_index = -1; // 目标接口索引
// 查询源接口在源节点的索引
size_t list_size = Node_List[node_index]->Get_Connector_List().size();
for (size_t count = 0; count < list_size; count++)
if (Node_List[node_index]->Get_Connector_List()[count]->Get_ID() == edge.source_connector_id)
{
source_connector_index = count;
break;
}
// 查询目标节点索引
for (size_t count = 0; count < Node_Count; count++)
if (Node_List[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}, //
})} //
}));
}
}
}
}
return Json_Object({
{"Nodes", Json_Arry(Node_Info_List)}, //
{"Connections", Json_Arry(Link_Info_List)} //
});
}
// 从配置对象应用 true -> success / false -> failed
bool Workflow_Editor::Apply_Config(Json_Object Config_Object, ImVec2 initial_position)
{
decltype(this->Node_Pool) Created_Node_List;
// 创建节点
{
auto Node_Info_List = Config_Object.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));
// 应用配置参数
this->Node_Pool.back()->Apply_Arguments(Node_Info.asObject().get("args").asArry());
// 加入列表
Created_Node_List.push_back(this->Node_Pool.back());
}
}
// 创建连接关系
{
auto Link_Info_List = Config_Object.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::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();
// 应用配置
return Apply_Config(Config_Value.asObject(), initial_position);
}
// 存储配置文件 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::string err_str = Json_Export(file_path, Generate_Config(this->Node_Pool, this->Edge_Pool), 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;
}