#include "UI.hpp" #include "Model/Workflow/Nodes/DocumentNodes.hpp" #include "Model/Workflow/Nodes/NumericNodes.hpp" #include "Model/Workflow/Nodes/TextNodes.hpp" #include "Model/Workflow/Nodes/UserInputNodes.hpp" #include "Model/Workflow/Workflow.hpp" #include "UI/Localization.hpp" #include "Utils/Macros.hpp" #include #include #include #include #include namespace ImNodes = ax::NodeEditor; namespace { class WorkflowCreationMenu { private: using WorkflowNodeConstructor = std::unique_ptr (*)(); enum Category { NumericCategory, TextCategory, DocumentsCategory, UserInputCategory, SystemInputCategory, OutputCategory, }; struct Candidate { WorkflowNodeConstructor Constructor; std::string Name; Category Category; }; std::vector mCandidates; #define SUB_RANGE_ACCESS(Type, AccessorName, storage, begin, nextBegin) \ std::span AccessorName() \ { \ return { &storage[begin], (size_t)(nextBegin - begin) }; \ } int mTextOffset; int mDocumentOffset; int mUserInputOffset; int mSystemInputNodes; int mOutputOffset; SUB_RANGE_ACCESS(Candidate, GetNumericNodes, mCandidates, 0, mTextOffset); SUB_RANGE_ACCESS(Candidate, GetTextNodes, mCandidates, mTextOffset, mDocumentOffset); SUB_RANGE_ACCESS(Candidate, GetDocumentNodes, mCandidates, mDocumentOffset, mUserInputOffset); SUB_RANGE_ACCESS(Candidate, GetUserInputNodes, mCandidates, mUserInputOffset, mSystemInputNodes); SUB_RANGE_ACCESS(Candidate, GetSystemInputNodes, mCandidates, mSystemInputNodes, mOutputOffset); SUB_RANGE_ACCESS(Candidate, GetOutputNodes, mCandidates, mOutputOffset, mCandidates.size()); #undef SUB_RANGE_ACCESS public: WorkflowCreationMenu() { SetupCandidates(); } private: void SetupCandidates() { // Numeric nodes offset start at 0 mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(NumericOperationNode::Addition); }, .Name = "Add", .Category = NumericCategory, }); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(NumericOperationNode::Subtraction); }, .Name = "Subtract", .Category = NumericCategory, }); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(NumericOperationNode::Multiplication); }, .Name = "Multiply", .Category = NumericCategory, }); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(NumericOperationNode::Division); }, .Name = "Divide", .Category = NumericCategory, }); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(); }, .Name = "Evaluate expression", .Category = NumericCategory, }); mTextOffset = mCandidates.size(); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(); }, .Name = "Fill template text", .Category = TextCategory, }); mDocumentOffset = mCandidates.size(); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(); }, .Name = "Document template", .Category = Category::DocumentsCategory, }); /* Inputs */ mUserInputOffset = mCandidates.size(); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(); }, .Name = "Input: form", .Category = Category::UserInputCategory, }); mCandidates.push_back(Candidate{ .Constructor = []() -> std::unique_ptr { return std::make_unique(); }, .Name = "Input: database rows", .Category = Category::UserInputCategory, }); mSystemInputNodes = mCandidates.size(); /* Outputs */ mOutputOffset = mCandidates.size(); } }; class WorkflowUI { private: Workflow* mWorkflow; ImNodes::EditorContext* mContext; public: WorkflowUI() { mContext = ImNodes::CreateEditor(); } ~WorkflowUI() { ImNodes::DestroyEditor(mContext); } void Draw() { ImNodes::SetCurrentEditor(mContext); ImNodes::Begin(""); for (auto& node : mWorkflow->GetNodes()) { if (!node) continue; ImNodes::BeginNode(node->GetId()); node->Draw(); ImNodes::EndNode(); } for (auto& conn : mWorkflow->GetConnections()) { if (!conn.IsValid()) continue; // TODO create link } ImNodes::End(); } }; } // namespace void UI::WorkflowsTab() { static std::unique_ptr openWorkflow; // TODO }