aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Workflow
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/Model/Workflow')
-rw-r--r--core/src/Model/Workflow/Evaluation.cpp174
-rw-r--r--core/src/Model/Workflow/Evaluation.hpp67
-rw-r--r--core/src/Model/Workflow/Nodes/DocumentNodes.cpp18
-rw-r--r--core/src/Model/Workflow/Nodes/DocumentNodes.hpp13
-rw-r--r--core/src/Model/Workflow/Nodes/NumericNodes.cpp94
-rw-r--r--core/src/Model/Workflow/Nodes/NumericNodes.hpp44
-rw-r--r--core/src/Model/Workflow/Nodes/TextNodes.cpp231
-rw-r--r--core/src/Model/Workflow/Nodes/TextNodes.hpp53
-rw-r--r--core/src/Model/Workflow/Nodes/UserInputNodes.cpp32
-rw-r--r--core/src/Model/Workflow/Nodes/UserInputNodes.hpp23
-rw-r--r--core/src/Model/Workflow/Nodes/fwd.hpp15
-rw-r--r--core/src/Model/Workflow/Value.hpp94
-rw-r--r--core/src/Model/Workflow/ValueInternals.hpp21
-rw-r--r--core/src/Model/Workflow/Value_Main.cpp35
-rw-r--r--core/src/Model/Workflow/Value_RTTI.cpp174
-rw-r--r--core/src/Model/Workflow/Values/Basic.cpp111
-rw-r--r--core/src/Model/Workflow/Values/Basic.hpp67
-rw-r--r--core/src/Model/Workflow/Values/Database.cpp88
-rw-r--r--core/src/Model/Workflow/Values/Database.hpp51
-rw-r--r--core/src/Model/Workflow/Values/Dictionary.cpp49
-rw-r--r--core/src/Model/Workflow/Values/Dictionary.hpp25
-rw-r--r--core/src/Model/Workflow/Values/List.cpp100
-rw-r--r--core/src/Model/Workflow/Values/List.hpp50
-rw-r--r--core/src/Model/Workflow/Values/fwd.hpp17
-rw-r--r--core/src/Model/Workflow/Workflow.hpp316
-rw-r--r--core/src/Model/Workflow/Workflow_Main.cpp846
-rw-r--r--core/src/Model/Workflow/Workflow_RTTI.cpp143
-rw-r--r--core/src/Model/Workflow/fwd.hpp22
28 files changed, 0 insertions, 2973 deletions
diff --git a/core/src/Model/Workflow/Evaluation.cpp b/core/src/Model/Workflow/Evaluation.cpp
deleted file mode 100644
index 7035bf9..0000000
--- a/core/src/Model/Workflow/Evaluation.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-#include "Evaluation.hpp"
-
-#include <queue>
-
-const char* WorkflowEvaluationError::FormatMessageType(enum MessageType messageType)
-{
- switch (messageType) {
- case Error: return "Error";
- case Warning: return "Warning";
- }
-}
-
-const char* WorkflowEvaluationError::FormatPinType(enum PinType pinType)
-{
- switch (pinType) {
- case NoPin: return nullptr;
- case InputPin: return "Input pin";
- case OutputPin: return "Output pin";
- }
-}
-
-std::string WorkflowEvaluationError::Format() const
-{
- // TODO convert to std::format
-
- std::string result;
- result += FormatMessageType(this->Type);
- result += " at ";
- result += NodeId;
- if (auto pinText = FormatPinType(this->PinType)) {
- result += "/";
- result += pinText;
- result += " ";
- result += PinId;
- }
- result += ": ";
- result += this->Message;
-
- return result;
-}
-
-struct WorkflowEvaluationContext::RuntimeNode
-{
- enum EvaluationStatus
- {
- ST_Unevaluated,
- ST_Success,
- ST_Failed,
- };
-
- EvaluationStatus Status = ST_Unevaluated;
-};
-
-struct WorkflowEvaluationContext::RuntimeConnection
-{
- std::unique_ptr<BaseValue> Value;
-
- bool IsAvailableValue() const
- {
- return Value != nullptr;
- }
-};
-
-WorkflowEvaluationContext::WorkflowEvaluationContext(Workflow& workflow)
- : mWorkflow{ &workflow }
-{
- mRuntimeNodes.resize(workflow.mNodes.size());
- mRuntimeConnections.resize(workflow.mConnections.size());
-}
-
-BaseValue* WorkflowEvaluationContext::GetConnectionValue(size_t id, bool constant)
-{
- if (constant) {
- return mWorkflow->GetConstantById(id);
- } else {
- return mRuntimeConnections[id].Value.get();
- }
-}
-
-BaseValue* WorkflowEvaluationContext::GetConnectionValue(const WorkflowNode::InputPin& inputPin)
-{
- if (inputPin.IsConnected()) {
- return GetConnectionValue(inputPin.Connection, inputPin.IsConstantConnection());
- } else {
- return nullptr;
- }
-}
-
-void WorkflowEvaluationContext::SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value)
-{
- mRuntimeConnections[id].Value = std::move(value);
-}
-
-void WorkflowEvaluationContext::SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value)
-{
- if (outputPin.IsConnected()) {
- SetConnectionValue(outputPin.Connection, std::move(value));
- }
-}
-
-void WorkflowEvaluationContext::Run()
-{
- int evaluatedCount = 0;
- int erroredCount = 0;
-
- for (auto& depthGroup : mWorkflow->GetDepthGroups()) {
- for (size_t idx : depthGroup) {
- auto& rn = mRuntimeNodes[idx];
- auto& n = *mWorkflow->mNodes[idx];
-
- // TODO
-
- int preEvalErrors = mErrors.size();
- n.Evaluate(*this);
- if (preEvalErrors != mErrors.size()) {
- erroredCount++;
- } else {
- evaluatedCount++;
- }
- }
- }
-
- for (size_t i = 0; i < mRuntimeNodes.size(); ++i) {
- auto& rn = mRuntimeNodes[i];
- auto& n = *mWorkflow->mNodes[i];
- if (n.GetType() == WorkflowNode::OutputType) {
- // TODO record outputs
- }
- }
-}
-
-void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin)
-{
- mErrors.push_back(WorkflowEvaluationError{
- .Message = std::move(message),
- .NodeId = node.GetId(),
- .PinId = pinId,
- .PinType = inputPin ? WorkflowEvaluationError::InputPin : WorkflowEvaluationError::OutputPin,
- .Type = WorkflowEvaluationError::Error,
- });
-}
-
-void WorkflowEvaluationContext::ReportError(std::string message, const WorkflowNode& node)
-{
- mErrors.push_back(WorkflowEvaluationError{
- .Message = std::move(message),
- .NodeId = node.GetId(),
- .PinId = -1,
- .PinType = WorkflowEvaluationError::NoPin,
- .Type = WorkflowEvaluationError::Error,
- });
-}
-
-void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin)
-{
- mErrors.push_back(WorkflowEvaluationError{
- .Message = std::move(message),
- .NodeId = node.GetId(),
- .PinId = pinId,
- .PinType = inputPin ? WorkflowEvaluationError::InputPin : WorkflowEvaluationError::OutputPin,
- .Type = WorkflowEvaluationError::Warning,
- });
-}
-
-void WorkflowEvaluationContext::ReportWarning(std::string message, const WorkflowNode& node)
-{
- mErrors.push_back(WorkflowEvaluationError{
- .Message = std::move(message),
- .NodeId = node.GetId(),
- .PinId = -1,
- .PinType = WorkflowEvaluationError::NoPin,
- .Type = WorkflowEvaluationError::Warning,
- });
-}
diff --git a/core/src/Model/Workflow/Evaluation.hpp b/core/src/Model/Workflow/Evaluation.hpp
deleted file mode 100644
index 4d78872..0000000
--- a/core/src/Model/Workflow/Evaluation.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Workflow.hpp"
-
-#include <cstddef>
-#include <cstdint>
-#include <string>
-#include <vector>
-
-class WorkflowEvaluationError
-{
-public:
- enum MessageType : int16_t
- {
- Error,
- Warning,
- };
-
- enum PinType : int16_t
- {
- NoPin,
- InputPin,
- OutputPin,
- };
-
-public:
- std::string Message;
- size_t NodeId;
- int PinId;
- PinType PinType;
- MessageType Type;
-
-public:
- static const char* FormatMessageType(enum MessageType messageType);
- static const char* FormatPinType(enum PinType pinType);
-
- std::string Format() const;
-};
-
-class WorkflowEvaluationContext
-{
-private:
- struct RuntimeNode;
- struct RuntimeConnection;
-
- Workflow* mWorkflow;
- std::vector<RuntimeNode> mRuntimeNodes;
- std::vector<RuntimeConnection> mRuntimeConnections;
- std::vector<WorkflowEvaluationError> mErrors;
- std::vector<WorkflowEvaluationError> mWarnings;
-
-public:
- WorkflowEvaluationContext(Workflow& workflow);
-
- BaseValue* GetConnectionValue(size_t id, bool constant);
- BaseValue* GetConnectionValue(const WorkflowNode::InputPin& inputPin);
- void SetConnectionValue(size_t id, std::unique_ptr<BaseValue> value);
- void SetConnectionValue(const WorkflowNode::OutputPin& outputPin, std::unique_ptr<BaseValue> value);
-
- void ReportError(std::string message, const WorkflowNode& node, int pinId, bool inputPin);
- void ReportError(std::string message, const WorkflowNode& node);
- void ReportWarning(std::string message, const WorkflowNode& node, int pinId, bool inputPin);
- void ReportWarning(std::string message, const WorkflowNode& node);
-
- /// Run until all possible paths have been evaluated.
- void Run();
-};
diff --git a/core/src/Model/Workflow/Nodes/DocumentNodes.cpp b/core/src/Model/Workflow/Nodes/DocumentNodes.cpp
deleted file mode 100644
index 6729c63..0000000
--- a/core/src/Model/Workflow/Nodes/DocumentNodes.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "DocumentNodes.hpp"
-
-#include "Model/Workflow/Evaluation.hpp"
-#include "Model/Workflow/Values/Basic.hpp"
-
-bool DocumentTemplateExpansionNode::IsInstance(const WorkflowNode* node)
-{
- return node->GetKind() == KD_DocumentTemplateExpansion;
-}
-
-DocumentTemplateExpansionNode::DocumentTemplateExpansionNode()
- : WorkflowNode(KD_DocumentTemplateExpansion, false)
-{
-}
-
-void DocumentTemplateExpansionNode::Evaluate(WorkflowEvaluationContext& ctx)
-{
-}
diff --git a/core/src/Model/Workflow/Nodes/DocumentNodes.hpp b/core/src/Model/Workflow/Nodes/DocumentNodes.hpp
deleted file mode 100644
index 85bba9e..0000000
--- a/core/src/Model/Workflow/Nodes/DocumentNodes.hpp
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Workflow.hpp"
-
-class DocumentTemplateExpansionNode : public WorkflowNode
-{
-public:
- static bool IsInstance(const WorkflowNode* node);
- DocumentTemplateExpansionNode();
-
- // TODO
- virtual void Evaluate(WorkflowEvaluationContext& ctx) override;
-};
diff --git a/core/src/Model/Workflow/Nodes/NumericNodes.cpp b/core/src/Model/Workflow/Nodes/NumericNodes.cpp
deleted file mode 100644
index 3a81979..0000000
--- a/core/src/Model/Workflow/Nodes/NumericNodes.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#include "NumericNodes.hpp"
-
-#include "Model/Workflow/Evaluation.hpp"
-#include "Model/Workflow/Values/Basic.hpp"
-#include "Utils/I18n.hpp"
-#include "Utils/Macros.hpp"
-#include "Utils/RTTI.hpp"
-
-#include <cassert>
-#include <utility>
-
-WorkflowNode::Kind NumericOperationNode::OperationTypeToNodeKind(OperationType type)
-{
- switch (type) {
- case Addition: return KD_NumericAddition;
- case Subtraction: return KD_NumericSubtraction;
- case Multiplication: return KD_NumericMultiplication;
- case Division: return KD_NumericDivision;
- default: return InvalidKind;
- }
-}
-
-NumericOperationNode::OperationType NumericOperationNode::NodeKindToOperationType(Kind kind)
-{
- switch (kind) {
- case KD_NumericAddition: return Addition;
- case KD_NumericSubtraction: return Subtraction;
- case KD_NumericMultiplication: return Multiplication;
- case KD_NumericDivision: return Division;
- default: return InvalidType;
- }
-}
-
-bool NumericOperationNode::IsInstance(const WorkflowNode* node)
-{
- return node->GetKind() >= KD_NumericAddition && node->GetKind() <= KD_NumericDivision;
-}
-
-NumericOperationNode::NumericOperationNode(OperationType type)
- : WorkflowNode(OperationTypeToNodeKind(type), false)
- , mType{ type }
-{
- mInputs.resize(2);
- mInputs[0].MatchingType = BaseValue::KD_Numeric;
- mInputs[1].MatchingType = BaseValue::KD_Numeric;
-
- mOutputs.resize(1);
- mOutputs[0].MatchingType = BaseValue::KD_Numeric;
-}
-
-void NumericOperationNode::Evaluate(WorkflowEvaluationContext& ctx)
-{
- auto lhsVal = dyn_cast<NumericValue>(ctx.GetConnectionValue(mInputs[0]));
- if (!lhsVal) return;
- double lhs = lhsVal->GetValue();
-
- auto rhsVal = dyn_cast<NumericValue>(ctx.GetConnectionValue(mInputs[1]));
- if (!rhsVal) return;
- double rhs = rhsVal->GetValue();
-
- double res;
- switch (mType) {
- case Addition: res = lhs + rhs; break;
- case Subtraction: res = lhs - rhs; break;
- case Multiplication: res = lhs * rhs; break;
- case Division: {
- if (rhs == 0.0) {
- ctx.ReportError(I18N_TEXT("Error: division by 0", L10N_WORKFLOW_RTERROR_DIV_BY_0), *this);
- return;
- }
- res = lhs / rhs;
- } break;
-
- default: return;
- }
-
- auto value = std::make_unique<NumericValue>();
- value->SetValue(res);
- ctx.SetConnectionValue(mOutputs[0], std::move(value));
-}
-
-bool NumericExpressionNode::IsInstance(const WorkflowNode* node)
-{
- return node->GetKind() == KD_NumericExpression;
-}
-
-NumericExpressionNode::NumericExpressionNode()
- : WorkflowNode(KD_NumericExpression, false)
-{
-}
-
-void NumericExpressionNode::Evaluate(WorkflowEvaluationContext& ctx)
-{
-}
diff --git a/core/src/Model/Workflow/Nodes/NumericNodes.hpp b/core/src/Model/Workflow/Nodes/NumericNodes.hpp
deleted file mode 100644
index 56c0313..0000000
--- a/core/src/Model/Workflow/Nodes/NumericNodes.hpp
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Workflow.hpp"
-
-#include <cstddef>
-#include <memory>
-#include <variant>
-#include <vector>
-
-class NumericOperationNode : public WorkflowNode
-{
-public:
- enum OperationType
- {
- Addition,
- Subtraction,
- Multiplication,
- Division,
-
- InvalidType,
- TypeCount = InvalidType,
- };
-
-private:
- OperationType mType;
-
-public:
- static Kind OperationTypeToNodeKind(OperationType type);
- static OperationType NodeKindToOperationType(Kind kind);
- static bool IsInstance(const WorkflowNode* node);
- NumericOperationNode(OperationType type);
-
- virtual void Evaluate(WorkflowEvaluationContext& ctx) override;
-};
-
-class NumericExpressionNode : public WorkflowNode
-{
-public:
- static bool IsInstance(const WorkflowNode* node);
- NumericExpressionNode();
-
- // TODO
- virtual void Evaluate(WorkflowEvaluationContext& ctx) override;
-}; \ No newline at end of file
diff --git a/core/src/Model/Workflow/Nodes/TextNodes.cpp b/core/src/Model/Workflow/Nodes/TextNodes.cpp
deleted file mode 100644
index 4628dd3..0000000
--- a/core/src/Model/Workflow/Nodes/TextNodes.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-#include "TextNodes.hpp"
-
-#include "Model/Workflow/Evaluation.hpp"
-#include "Model/Workflow/Values/Basic.hpp"
-#include "Utils/Macros.hpp"
-#include "Utils/RTTI.hpp"
-#include "Utils/Variant.hpp"
-
-#include <cassert>
-#include <utility>
-#include <variant>
-#include <vector>
-
-class TextFormatterNode::Impl
-{
-public:
- template <class TFunction>
- static void ForArguments(std::vector<Element>::iterator begin, std::vector<Element>::iterator end, const TFunction& func)
- {
- for (auto it = begin; it != end; ++it) {
- auto& elm = *it;
- if (auto arg = std::get_if<Argument>(&elm)) {
- func(*arg);
- }
- }
- }
-
- /// Find the pin index that the \c elmIdx -th element should have, based on the elements coming before it.
- static int FindPinForElement(const std::vector<Element>& vec, int elmIdx)
- {
- for (int i = elmIdx; i >= 0; --i) {
- auto& elm = vec[i];
- if (auto arg = std::get_if<Argument>(&elm)) {
- return arg->PinIdx + 1;
- }
- }
- return 0;
- }
-};
-
-BaseValue::Kind TextFormatterNode::ArgumentTypeToValueKind(TextFormatterNode::ArgumentType arg)
-{
- switch (arg) {
- case NumericArgument: return BaseValue::KD_Numeric;
- case TextArgument: return BaseValue::KD_Text;
- case DateTimeArgument: return BaseValue::KD_DateTime;
- }
-}
-
-bool TextFormatterNode::IsInstance(const WorkflowNode* node)
-{
- return node->GetKind() == KD_TextFormatting;
-}
-
-TextFormatterNode::TextFormatterNode()
- : WorkflowNode(KD_TextFormatting, false)
-{
-}
-
-int TextFormatterNode::GetElementCount() const
-{
- return mElements.size();
-}
-
-const TextFormatterNode::Element& TextFormatterNode::GetElement(int idx) const
-{
- return mElements[idx];
-}
-
-void TextFormatterNode::SetElement(int idx, std::string text)
-{
- assert(idx >= 0 && idx < mElements.size());
-
- std::visit(
- Overloaded{
- [&](const std::string& original) { mMinOutputChars -= original.size(); },
- [&](const Argument& original) { PreRemoveElement(idx); },
- },
- mElements[idx]);
-
- mMinOutputChars += text.size();
- mElements[idx] = std::move(text);
-}
-
-void TextFormatterNode::SetElement(int idx, ArgumentType argument)
-{
- assert(idx >= 0 && idx < mElements.size());
-
- std::visit(
- Overloaded{
- [&](const std::string& original) {
- mMinOutputChars -= original.size();
-
- mElements[idx] = Argument{
- .Type = argument,
- .PinIdx = Impl::FindPinForElement(mElements, idx),
- };
- /* `original` is invalid from this point */
- },
- [&](const Argument& original) {
- int pinIdx = original.PinIdx;
-
- // Create pin
- auto& pin = mInputs[pinIdx];
- pin.MatchingType = ArgumentTypeToValueKind(argument);
-
- // Create element
- mElements[idx] = Argument{
- .Type = argument,
- .PinIdx = pinIdx,
- };
- /* `original` is invalid from this point */
- },
- },
- mElements[idx]);
-}
-
-void TextFormatterNode::InsertElement(int idx, std::string text)
-{
- assert(idx >= 0);
- if (idx >= mElements.size()) AppendElement(std::move(text));
-
- mMinOutputChars += text.size();
- mElements.insert(mElements.begin() + idx, std::move(text));
-}
-
-void TextFormatterNode::InsertElement(int idx, ArgumentType argument)
-{
- assert(idx >= 0);
- if (idx >= mElements.size()) AppendElement(argument);
-
- int pinIdx = Impl::FindPinForElement(mElements, idx);
-
- // Create pin
- auto& pin = InsertInputPin(pinIdx);
- pin.MatchingType = ArgumentTypeToValueKind(argument);
-
- // Create element
- mElements.insert(
- mElements.begin() + idx,
- Argument{
- .Type = argument,
- .PinIdx = pinIdx,
- });
-}
-
-void TextFormatterNode::AppendElement(std::string text)
-{
- mMinOutputChars += text.size();
- mElements.push_back(std::move(text));
-}
-
-void TextFormatterNode::AppendElement(ArgumentType argument)
-{
- int pinIdx = mInputs.size();
- // Create pin
- mInputs.push_back(InputPin{});
- mInputs.back().MatchingType = ArgumentTypeToValueKind(argument);
- // Creat eelement
- mElements.push_back(Argument{
- .Type = argument,
- .PinIdx = pinIdx,
- });
-}
-
-void TextFormatterNode::RemoveElement(int idx)
-{
- assert(idx >= 0 && idx < mElements.size());
-
- PreRemoveElement(idx);
- if (auto arg = std::get_if<Argument>(&mElements[idx])) {
- RemoveInputPin(arg->PinIdx);
- }
- mElements.erase(mElements.begin() + idx);
-}
-
-void TextFormatterNode::Evaluate(WorkflowEvaluationContext& ctx)
-{
- std::string result;
- result.reserve((size_t)(mMinOutputChars * 1.5f));
-
- auto HandleText = [&](const std::string& str) {
- result += str;
- };
- auto HandleArgument = [&](const Argument& arg) {
- switch (arg.Type) {
- case NumericArgument: {
- if (auto val = dyn_cast<NumericValue>(ctx.GetConnectionValue(mInputs[arg.PinIdx]))) {
- result += val->GetString();
- } else {
- // TODO localize
- ctx.ReportError("Non-numeric value connected to a numeric text format parameter.", *this);
- }
- } break;
- case TextArgument: {
- if (auto val = dyn_cast<TextValue>(ctx.GetConnectionValue(mInputs[arg.PinIdx]))) {
- result += val->GetValue();
- } else {
- // TODO localize
- ctx.ReportError("Non-text value connected to a textual text format parameter.", *this);
- }
- } break;
- case DateTimeArgument: {
- if (auto val = dyn_cast<DateTimeValue>(ctx.GetConnectionValue(mInputs[arg.PinIdx]))) {
- result += val->GetString();
- } else {
- // TODO localize
- ctx.ReportError("Non-date/time value connected to a date/time text format parameter.", *this);
- }
- } break;
- }
- };
-
- for (auto& elm : mElements) {
- std::visit(Overloaded{ HandleText, HandleArgument }, elm);
- }
-}
-
-void TextFormatterNode::PreRemoveElement(int idx)
-{
- auto& elm = mElements[idx];
- if (auto arg = std::get_if<Argument>(&elm)) {
- RemoveInputPin(arg->PinIdx);
- Impl::ForArguments(
- mElements.begin() + idx + 1,
- mElements.end(),
- [&](Argument& arg) {
- arg.PinIdx--;
- });
- }
-}
diff --git a/core/src/Model/Workflow/Nodes/TextNodes.hpp b/core/src/Model/Workflow/Nodes/TextNodes.hpp
deleted file mode 100644
index c33854c..0000000
--- a/core/src/Model/Workflow/Nodes/TextNodes.hpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Workflow.hpp"
-
-#include <cstddef>
-#include <memory>
-#include <variant>
-#include <vector>
-
-class TextFormatterNode : public WorkflowNode
-{
-public:
- enum ArgumentType
- {
- NumericArgument,
- TextArgument,
- DateTimeArgument,
- };
-
-private:
- class Impl;
-
- struct Argument
- {
- ArgumentType Type;
- int PinIdx;
- };
- using Element = std::variant<std::string, Argument>;
-
- std::vector<Element> mElements;
- int mMinOutputChars;
-
-public:
- static BaseValue::Kind ArgumentTypeToValueKind(ArgumentType arg);
- static bool IsInstance(const WorkflowNode* node);
- TextFormatterNode();
-
- int GetElementCount() const;
- const Element& GetElement(int idx) const;
-
- void SetElement(int idx, std::string text);
- void SetElement(int idx, ArgumentType argument);
- void InsertElement(int idx, std::string text);
- void InsertElement(int idx, ArgumentType argument);
- void AppendElement(std::string text);
- void AppendElement(ArgumentType argument);
- void RemoveElement(int idx);
-
- virtual void Evaluate(WorkflowEvaluationContext& ctx) override;
-
-private:
- void PreRemoveElement(int idx);
-};
diff --git a/core/src/Model/Workflow/Nodes/UserInputNodes.cpp b/core/src/Model/Workflow/Nodes/UserInputNodes.cpp
deleted file mode 100644
index 0b6d471..0000000
--- a/core/src/Model/Workflow/Nodes/UserInputNodes.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "UserInputNodes.hpp"
-
-#include "Model/Workflow/Evaluation.hpp"
-#include "Model/Workflow/Values/Basic.hpp"
-
-bool FormInputNode::IsInstance(const WorkflowNode* node)
-{
- return node->GetKind() == KD_FormInput;
-}
-
-FormInputNode::FormInputNode()
- : WorkflowNode(KD_FormInput, false)
-{
-}
-
-void FormInputNode::Evaluate(WorkflowEvaluationContext& ctx)
-{
-}
-
-bool DatabaseRowsInputNode::IsInstance(const WorkflowNode* node)
-{
- return node->GetKind() == KD_DatabaseRowsInput;
-}
-
-DatabaseRowsInputNode::DatabaseRowsInputNode()
- : WorkflowNode(KD_DatabaseRowsInput, false)
-{
-}
-
-void DatabaseRowsInputNode::Evaluate(WorkflowEvaluationContext& ctx)
-{
-}
diff --git a/core/src/Model/Workflow/Nodes/UserInputNodes.hpp b/core/src/Model/Workflow/Nodes/UserInputNodes.hpp
deleted file mode 100644
index 10ea95d..0000000
--- a/core/src/Model/Workflow/Nodes/UserInputNodes.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Workflow.hpp"
-
-class FormInputNode : public WorkflowNode
-{
-public:
- static bool IsInstance(const WorkflowNode* node);
- FormInputNode();
-
- // TODO
- virtual void Evaluate(WorkflowEvaluationContext& ctx) override;
-};
-
-class DatabaseRowsInputNode : public WorkflowNode
-{
-public:
- static bool IsInstance(const WorkflowNode* node);
- DatabaseRowsInputNode();
-
- // TODO
- virtual void Evaluate(WorkflowEvaluationContext& ctx) override;
-};
diff --git a/core/src/Model/Workflow/Nodes/fwd.hpp b/core/src/Model/Workflow/Nodes/fwd.hpp
deleted file mode 100644
index 4153825..0000000
--- a/core/src/Model/Workflow/Nodes/fwd.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-// DocumentNodes.hpp
-class DocumentTemplateExpansionNode;
-
-// InputNodes.hpp
-class FormInputNode;
-class DatabaseRowsInputNode;
-
-// NumericNodes.hpp
-class NumericOperationNode;
-class NumericExpressionNode;
-
-// TextNodes.hpp
-class TextFormatterNode;
diff --git a/core/src/Model/Workflow/Value.hpp b/core/src/Model/Workflow/Value.hpp
deleted file mode 100644
index 2198674..0000000
--- a/core/src/Model/Workflow/Value.hpp
+++ /dev/null
@@ -1,94 +0,0 @@
-#pragma once
-
-#include "Utils/Color.hpp"
-#include "cplt_fwd.hpp"
-
-#include <iosfwd>
-#include <memory>
-#include <string>
-#include <vector>
-
-class BaseValue
-{
-public:
- enum Kind
- {
- KD_Numeric,
- KD_Text,
- KD_DateTime,
- KD_DatabaseRowId,
- KD_List,
- KD_Dictionary,
-
- KD_BaseObject,
- KD_SaleDatabaseRow,
- KD_PurchaseDatabaseRow,
- KD_BaseObjectLast = KD_PurchaseDatabaseRow,
-
- /// An unspecified type, otherwise known as "any" in some contexts.
- InvalidKind,
- KindCount = InvalidKind,
- };
-
- struct KindInfo
- {
- ImGui::IconType PinIcon;
- RgbaColor PinColor;
- };
-
-private:
- Kind mKind;
-
-public:
- static const KindInfo& QueryInfo(Kind kind);
- static const char* Format(Kind kind);
- static std::unique_ptr<BaseValue> CreateByKind(Kind kind);
-
- static bool IsInstance(const BaseValue* value);
-
- BaseValue(Kind kind);
- virtual ~BaseValue() = default;
-
- BaseValue(const BaseValue&) = delete;
- BaseValue& operator=(const BaseValue&) = delete;
- BaseValue(BaseValue&&) = default;
- BaseValue& operator=(BaseValue&&) = default;
-
- Kind GetKind() const;
-
- // TODO get constant editor
-
- /// The functions \c ReadFrom, \c WriteTo will only be valid to call if this function returns true.
- virtual bool SupportsConstant() const;
- virtual void ReadFrom(std::istream& stream);
- virtual void WriteTo(std::ostream& stream);
-};
-
-class BaseObjectDescription
-{
-public:
- struct Property
- {
- std::string Name;
- BaseValue::Kind Kind;
- bool Mutatable = true;
- };
-
-public:
- std::vector<Property> Properties;
-};
-
-class BaseObjectValue : public BaseValue
-{
-public:
- /// \param kind A value kind enum, within the range of KD_BaseObject and KD_BaseObjectLast (both inclusive).
- static const BaseObjectDescription& QueryObjectInfo(Kind kind);
-
- static bool IsInstance(const BaseValue* value);
- BaseObjectValue(Kind kind);
-
- const BaseObjectDescription& GetObjectDescription() const;
-
- virtual const BaseValue* GetProperty(int idx) const = 0;
- virtual bool SetProperty(int idx, std::unique_ptr<BaseValue> value) = 0;
-};
diff --git a/core/src/Model/Workflow/ValueInternals.hpp b/core/src/Model/Workflow/ValueInternals.hpp
deleted file mode 100644
index 49981f0..0000000
--- a/core/src/Model/Workflow/ValueInternals.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-// This file contains utility classes and macros for implementing values
-// As consumers, you should not include this header as it contains unnecessary symbols and can pollute your files
-// for this reason, classes here aren't forward-declared in fwd.hpp either.
-
-#pragma once
-
-#include "Utils/RTTI.hpp"
-
-#include <utility>
-
-#define CHECK_VALUE_TYPE(Type, value) \
- if (!is_a<Type>(value)) { \
- return false; \
- }
-
-#define CHECK_VALUE_TYPE_AND_MOVE(Type, dest, value) \
- if (auto ptr = dyn_cast<Type>(value)) { \
- dest = std::move(*ptr); \
- } else { \
- return false; \
- }
diff --git a/core/src/Model/Workflow/Value_Main.cpp b/core/src/Model/Workflow/Value_Main.cpp
deleted file mode 100644
index ca972c4..0000000
--- a/core/src/Model/Workflow/Value_Main.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#include "Value.hpp"
-
-BaseValue::BaseValue(Kind kind)
- : mKind{ kind }
-{
-}
-
-BaseValue::Kind BaseValue::GetKind() const
-{
- return mKind;
-}
-
-bool BaseValue::SupportsConstant() const
-{
- return false;
-}
-
-void BaseValue::ReadFrom(std::istream& stream)
-{
-}
-
-void BaseValue::WriteTo(std::ostream& stream)
-{
-}
-
-BaseObjectValue::BaseObjectValue(Kind kind)
- : BaseValue(kind)
-{
- assert(kind >= KD_BaseObject && kind <= KD_BaseObjectLast);
-}
-
-const BaseObjectDescription& BaseObjectValue::GetObjectDescription() const
-{
- return QueryObjectInfo(this->GetKind());
-}
diff --git a/core/src/Model/Workflow/Value_RTTI.cpp b/core/src/Model/Workflow/Value_RTTI.cpp
deleted file mode 100644
index 0561239..0000000
--- a/core/src/Model/Workflow/Value_RTTI.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-#include "Value.hpp"
-
-#include "Model/Workflow/Values/Basic.hpp"
-#include "Model/Workflow/Values/Database.hpp"
-#include "Model/Workflow/Values/Dictionary.hpp"
-#include "Model/Workflow/Values/List.hpp"
-#include "UI/UI.hpp"
-#include "Utils/I18n.hpp"
-
-constexpr BaseValue::KindInfo kEmptyInfo{
- .PinIcon = ImGui::IconType::Circle,
- .PinColor = RgbaColor(),
-};
-
-constexpr BaseValue::KindInfo kNumericInfo{
- .PinIcon = ImGui::IconType::Circle,
- .PinColor = RgbaColor(147, 226, 74),
-};
-
-constexpr BaseValue::KindInfo kTextInfo{
- .PinIcon = ImGui::IconType::Circle,
- .PinColor = RgbaColor(124, 21, 153),
-};
-
-constexpr BaseValue::KindInfo kDateTimeInfo{
- .PinIcon = ImGui::IconType::Circle,
- .PinColor = RgbaColor(147, 226, 74),
-};
-
-constexpr BaseValue::KindInfo kDatabaseRowIdInfo{
- .PinIcon = ImGui::IconType::Circle,
- .PinColor = RgbaColor(216, 42, 221),
-};
-
-constexpr BaseValue::KindInfo kListInfo{
- .PinIcon = ImGui::IconType::Diamond,
- .PinColor = RgbaColor(58, 154, 214),
-};
-
-constexpr BaseValue::KindInfo kDictionaryInfo{
- .PinIcon = ImGui::IconType::Diamond,
- .PinColor = RgbaColor(240, 240, 34),
-};
-
-constexpr BaseValue::KindInfo kDatabaseRowInfo{
- .PinIcon = ImGui::IconType::Square,
- .PinColor = RgbaColor(15, 124, 196),
-};
-
-constexpr BaseValue::KindInfo kObjectInfo{
- .PinIcon = ImGui::IconType::Square,
- .PinColor = RgbaColor(161, 161, 161),
-};
-
-const BaseValue::KindInfo& BaseValue::QueryInfo(BaseValue::Kind kind)
-{
- switch (kind) {
- case KD_Numeric: return kNumericInfo;
- case KD_Text: return kTextInfo;
- case KD_DateTime: return kDateTimeInfo;
- case KD_DatabaseRowId: return kDatabaseRowIdInfo;
- case KD_List: return kListInfo;
- case KD_Dictionary: return kDictionaryInfo;
-
- case KD_BaseObject: return kObjectInfo;
- case KD_SaleDatabaseRow:
- case KD_PurchaseDatabaseRow:
- return kDatabaseRowInfo;
-
- case InvalidKind: break;
- }
- return kEmptyInfo;
-}
-
-const char* BaseValue::Format(Kind kind)
-{
- switch (kind) {
- case KD_Numeric: return I18N_TEXT("Numeric", L10N_VALUE_NUMERIC);
- case KD_Text: return I18N_TEXT("Text", L10N_VALUE_TEXT);
- case KD_DateTime: return I18N_TEXT("Date/time", L10N_VALUE_DATE_TIME);
- case KD_DatabaseRowId: return I18N_TEXT("Row id", L10N_VALUE_ROW_ID);
- case KD_List: return I18N_TEXT("List", L10N_VALUE_LIST);
- case KD_Dictionary: return I18N_TEXT("Dictionary", L10N_VALUE_DICT);
-
- case KD_BaseObject: return I18N_TEXT("Object", L10N_VALUE_OBJECT);
- case KD_SaleDatabaseRow: return I18N_TEXT("Sale record", L10N_VALUE_SALE_RECORD);
- case KD_PurchaseDatabaseRow: return I18N_TEXT("Purchase record", L10N_VALUE_PURCHASE_RECORD);
-
- case InvalidKind: break;
- }
- return "";
-}
-
-std::unique_ptr<BaseValue> BaseValue::CreateByKind(BaseValue::Kind kind)
-{
- switch (kind) {
- case KD_Numeric: return std::make_unique<NumericValue>();
- case KD_Text: return std::make_unique<TextValue>();
- case KD_DateTime: return std::make_unique<DateTimeValue>();
- case KD_DatabaseRowId: return std::make_unique<DatabaseRowIdValue>();
- case KD_List: return std::make_unique<ListValue>();
- case KD_Dictionary: return std::make_unique<DictionaryValue>();
-
- case KD_BaseObject: return nullptr;
- case KD_SaleDatabaseRow: return std::make_unique<SaleDatabaseRowValue>();
- case KD_PurchaseDatabaseRow: return std::make_unique<PurchaseDatabaseRowValue>();
-
- case InvalidKind: break;
- }
- return nullptr;
-}
-
-bool BaseValue::IsInstance(const BaseValue* value)
-{
- return true;
-}
-
-const BaseObjectDescription kEmptyObjectInfo{
- .Properties = {},
-};
-
-const BaseObjectDescription kSaleDbRowObject{
- .Properties = {
- {
- .Name = I18N_TEXT("Customer", L10N_VALUE_PROPERTY_CUSTOMER),
- .Kind = BaseValue::KD_Text,
- .Mutatable = false,
- },
- {
- .Name = I18N_TEXT("Deadline", L10N_VALUE_PROPERTY_DEADLINE),
- .Kind = BaseValue::KD_DateTime,
- },
- {
- .Name = I18N_TEXT("Delivery time", L10N_VALUE_PROPERTY_DELIVERY_TIME),
- .Kind = BaseValue::KD_DateTime,
- },
- },
-};
-
-const BaseObjectDescription kPurchaseDbRowObject{
- .Properties = {
- {
- .Name = I18N_TEXT("Factory", L10N_VALUE_PROPERTY_FACTORY),
- .Kind = BaseValue::KD_Text,
- .Mutatable = false,
- },
- {
- .Name = I18N_TEXT("Order time", L10N_VALUE_PROPERTY_ORDER_TIME),
- .Kind = BaseValue::KD_DateTime,
- },
- {
- .Name = I18N_TEXT("Delivery time", L10N_VALUE_PROPERTY_DELIVERY_TIME),
- .Kind = BaseValue::KD_DateTime,
- },
- },
-};
-
-const BaseObjectDescription& BaseObjectValue::QueryObjectInfo(Kind kind)
-{
- switch (kind) {
- case KD_BaseObject: return kEmptyObjectInfo;
- case KD_SaleDatabaseRow: return kSaleDbRowObject;
- case KD_PurchaseDatabaseRow: return kPurchaseDbRowObject;
-
- default: break;
- }
- return kEmptyObjectInfo;
-}
-
-bool BaseObjectValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() >= KD_BaseObject &&
- value->GetKind() <= KD_BaseObjectLast;
-}
diff --git a/core/src/Model/Workflow/Values/Basic.cpp b/core/src/Model/Workflow/Values/Basic.cpp
deleted file mode 100644
index 198387c..0000000
--- a/core/src/Model/Workflow/Values/Basic.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-#include "Basic.hpp"
-
-#include <charconv>
-#include <cmath>
-#include <limits>
-
-bool NumericValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_Numeric;
-}
-
-NumericValue::NumericValue()
- : BaseValue(BaseValue::KD_Numeric)
-{
-}
-
-template <class T, int kMaxSize>
-static std::string NumberToString(T value)
-{
- char buf[kMaxSize];
- auto res = std::to_chars(buf, buf + kMaxSize, value);
- if (res.ec == std::errc()) {
- return std::string(buf, res.ptr);
- } else {
- return "<err>";
- }
-}
-
-std::string NumericValue::GetTruncatedString() const
-{
- constexpr auto kMaxSize = std::numeric_limits<int64_t>::digits10;
- return ::NumberToString<int64_t, kMaxSize>((int64_t)mValue);
-}
-
-std::string NumericValue::GetRoundedString() const
-{
- constexpr auto kMaxSize = std::numeric_limits<int64_t>::digits10;
- return ::NumberToString<int64_t, kMaxSize>((int64_t)std::round(mValue));
-}
-
-std::string NumericValue::GetString() const
-{
- constexpr auto kMaxSize = std::numeric_limits<double>::max_digits10;
- return ::NumberToString<double, kMaxSize>(mValue);
-}
-
-int64_t NumericValue::GetInt() const
-{
- return static_cast<int64_t>(mValue);
-}
-
-double NumericValue::GetValue() const
-{
- return mValue;
-}
-
-void NumericValue::SetValue(double value)
-{
- mValue = value;
-}
-
-bool TextValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_Text;
-}
-
-TextValue::TextValue()
- : BaseValue(BaseValue::KD_Text)
-{
-}
-
-const std::string& TextValue::GetValue() const
-{
- return mValue;
-}
-
-void TextValue::SetValue(const std::string& value)
-{
- mValue = value;
-}
-
-bool DateTimeValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_DateTime;
-}
-
-DateTimeValue::DateTimeValue()
- : BaseValue(BaseValue::KD_DateTime)
-{
-}
-
-std::string DateTimeValue::GetString() const
-{
- namespace chrono = std::chrono;
- auto t = chrono::system_clock::to_time_t(mValue);
-
- char data[32];
- std::strftime(data, sizeof(data), "%Y-%m-%d %H:%M:%S", std::localtime(&t));
-
- return std::string(data);
-}
-
-const std::chrono::time_point<std::chrono::system_clock>& DateTimeValue::GetValue() const
-{
- return mValue;
-}
-
-void DateTimeValue::SetValue(const std::chrono::time_point<std::chrono::system_clock>& value)
-{
- mValue = value;
-}
diff --git a/core/src/Model/Workflow/Values/Basic.hpp b/core/src/Model/Workflow/Values/Basic.hpp
deleted file mode 100644
index 38e0531..0000000
--- a/core/src/Model/Workflow/Values/Basic.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Value.hpp"
-
-#include <chrono>
-#include <cstdint>
-#include <string>
-
-class NumericValue : public BaseValue
-{
-private:
- double mValue;
-
-public:
- static bool IsInstance(const BaseValue* value);
- NumericValue();
-
- NumericValue(const NumericValue&) = delete;
- NumericValue& operator=(const NumericValue&) = delete;
- NumericValue(NumericValue&&) = default;
- NumericValue& operator=(NumericValue&&) = default;
-
- std::string GetTruncatedString() const;
- std::string GetRoundedString() const;
- std::string GetString() const;
-
- int64_t GetInt() const;
- double GetValue() const;
- void SetValue(double value);
-};
-
-class TextValue : public BaseValue
-{
-private:
- std::string mValue;
-
-public:
- static bool IsInstance(const BaseValue* value);
- TextValue();
-
- TextValue(const TextValue&) = delete;
- TextValue& operator=(const TextValue&) = delete;
- TextValue(TextValue&&) = default;
- TextValue& operator=(TextValue&&) = default;
-
- const std::string& GetValue() const;
- void SetValue(const std::string& value);
-};
-
-class DateTimeValue : public BaseValue
-{
-private:
- std::chrono::time_point<std::chrono::system_clock> mValue;
-
-public:
- static bool IsInstance(const BaseValue* value);
- DateTimeValue();
-
- DateTimeValue(const DateTimeValue&) = delete;
- DateTimeValue& operator=(const DateTimeValue&) = delete;
- DateTimeValue(DateTimeValue&&) = default;
- DateTimeValue& operator=(DateTimeValue&&) = default;
-
- std::string GetString() const;
- const std::chrono::time_point<std::chrono::system_clock>& GetValue() const;
- void SetValue(const std::chrono::time_point<std::chrono::system_clock>& value);
-};
diff --git a/core/src/Model/Workflow/Values/Database.cpp b/core/src/Model/Workflow/Values/Database.cpp
deleted file mode 100644
index cdc2b4f..0000000
--- a/core/src/Model/Workflow/Values/Database.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "Database.hpp"
-
-#include "Model/Database.hpp"
-#include "Model/Workflow/ValueInternals.hpp"
-
-#include <limits>
-
-TableKind DatabaseRowIdValue::GetTable() const
-{
- return mTable;
-}
-
-int64_t DatabaseRowIdValue::GetRowId() const
-{
- return mRowId;
-}
-
-bool DatabaseRowIdValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_DatabaseRowId;
-}
-
-DatabaseRowIdValue::DatabaseRowIdValue()
- : BaseValue(KD_DatabaseRowId)
- , mTable{ TableKind::Sales }
- , mRowId{ std::numeric_limits<int64_t>::max() }
-{
-}
-
-bool SaleDatabaseRowValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_SaleDatabaseRow;
-}
-
-SaleDatabaseRowValue::SaleDatabaseRowValue()
- : BaseObjectValue(KD_SaleDatabaseRow)
-{
-}
-
-const BaseValue* SaleDatabaseRowValue::GetProperty(int idx) const
-{
- switch (idx) {
- case 0: return &mCustomerName;
- case 1: return &mDeadline;
- case 2: return &mDeliveryTime;
- default: return nullptr;
- }
-}
-
-bool SaleDatabaseRowValue::SetProperty(int idx, std::unique_ptr<BaseValue> value)
-{
- switch (idx) {
- case 0: return false;
- case 1: CHECK_VALUE_TYPE_AND_MOVE(DateTimeValue, mDeadline, value.get()); break;
- case 2: CHECK_VALUE_TYPE_AND_MOVE(DateTimeValue, mDeliveryTime, value.get()); break;
- }
- return true;
-}
-
-bool PurchaseDatabaseRowValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_PurchaseDatabaseRow;
-}
-
-PurchaseDatabaseRowValue::PurchaseDatabaseRowValue()
- : BaseObjectValue(KD_PurchaseDatabaseRow)
-{
-}
-
-const BaseValue* PurchaseDatabaseRowValue::GetProperty(int idx) const
-{
- switch (idx) {
- case 0: return &mFactoryName;
- case 1: return &mOrderTime;
- case 2: return &mDeliveryTime;
- default: return nullptr;
- }
-}
-
-bool PurchaseDatabaseRowValue::SetProperty(int idx, std::unique_ptr<BaseValue> value)
-{
- switch (idx) {
- case 0: return false;
- case 1: CHECK_VALUE_TYPE_AND_MOVE(DateTimeValue, mOrderTime, value.get()); break;
- case 2: CHECK_VALUE_TYPE_AND_MOVE(DateTimeValue, mDeliveryTime, value.get()); break;
- }
- return true;
-}
diff --git a/core/src/Model/Workflow/Values/Database.hpp b/core/src/Model/Workflow/Values/Database.hpp
deleted file mode 100644
index e8a4f83..0000000
--- a/core/src/Model/Workflow/Values/Database.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Value.hpp"
-#include "Model/Workflow/Values/Basic.hpp"
-#include "cplt_fwd.hpp"
-
-class DatabaseRowIdValue : public BaseValue
-{
-private:
- TableKind mTable;
- int64_t mRowId;
-
-public:
- static bool IsInstance(const BaseValue* value);
- DatabaseRowIdValue();
-
- TableKind GetTable() const;
- int64_t GetRowId() const;
-};
-
-class SaleDatabaseRowValue : public BaseObjectValue
-{
-private:
- int mCustomerId;
- TextValue mCustomerName;
- DateTimeValue mDeadline;
- DateTimeValue mDeliveryTime;
-
-public:
- static bool IsInstance(const BaseValue* value);
- SaleDatabaseRowValue();
-
- virtual const BaseValue* GetProperty(int idx) const;
- virtual bool SetProperty(int idx, std::unique_ptr<BaseValue> value);
-};
-
-class PurchaseDatabaseRowValue : public BaseObjectValue
-{
-private:
- int mFactoryId;
- TextValue mFactoryName;
- DateTimeValue mOrderTime;
- DateTimeValue mDeliveryTime;
-
-public:
- static bool IsInstance(const BaseValue* value);
- PurchaseDatabaseRowValue();
-
- virtual const BaseValue* GetProperty(int idx) const;
- virtual bool SetProperty(int idx, std::unique_ptr<BaseValue> value);
-};
diff --git a/core/src/Model/Workflow/Values/Dictionary.cpp b/core/src/Model/Workflow/Values/Dictionary.cpp
deleted file mode 100644
index 106e48d..0000000
--- a/core/src/Model/Workflow/Values/Dictionary.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "Dictionary.hpp"
-
-#include "Utils/Macros.hpp"
-
-bool DictionaryValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_Dictionary;
-}
-
-DictionaryValue::DictionaryValue()
- : BaseValue(KD_Dictionary)
-{
-}
-
-int DictionaryValue::GetCount() const
-{
- return mElements.size();
-}
-
-BaseValue* DictionaryValue::Find(std::string_view key)
-{
- auto iter = mElements.find(key);
- if (iter != mElements.end()) {
- return iter.value().get();
- } else {
- return nullptr;
- }
-}
-
-BaseValue* DictionaryValue::Insert(std::string_view key, std::unique_ptr<BaseValue>& value)
-{
- auto [iter, success] = mElements.insert(key, std::move(value));
- if (success) {
- return iter.value().get();
- } else {
- return nullptr;
- }
-}
-
-BaseValue& DictionaryValue::InsertOrReplace(std::string_view key, std::unique_ptr<BaseValue> value)
-{
- auto [iter, DISCARD] = mElements.emplace(key, std::move(value));
- return *iter.value();
-}
-
-void DictionaryValue::Remove(std::string_view key)
-{
- mElements.erase(mElements.find(key));
-}
diff --git a/core/src/Model/Workflow/Values/Dictionary.hpp b/core/src/Model/Workflow/Values/Dictionary.hpp
deleted file mode 100644
index 65ea82f..0000000
--- a/core/src/Model/Workflow/Values/Dictionary.hpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Value.hpp"
-
-#include <tsl/array_map.h>
-#include <memory>
-#include <string>
-#include <string_view>
-
-class DictionaryValue : public BaseValue
-{
-private:
- tsl::array_map<char, std::unique_ptr<BaseValue>> mElements;
-
-public:
- static bool IsInstance(const BaseValue* value);
- DictionaryValue();
-
- int GetCount() const;
- BaseValue* Find(std::string_view key);
-
- BaseValue* Insert(std::string_view key, std::unique_ptr<BaseValue>& value);
- BaseValue& InsertOrReplace(std::string_view key, std::unique_ptr<BaseValue> value);
- void Remove(std::string_view key);
-};
diff --git a/core/src/Model/Workflow/Values/List.cpp b/core/src/Model/Workflow/Values/List.cpp
deleted file mode 100644
index 9fd6bfd..0000000
--- a/core/src/Model/Workflow/Values/List.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "List.hpp"
-
-#include <utility>
-
-BaseValue* ListValue::Iterator::operator*() const
-{
- return mIter->get();
-}
-
-BaseValue* ListValue::Iterator::operator->() const
-{
- return mIter->get();
-}
-
-ListValue::Iterator& ListValue::Iterator::operator++()
-{
- ++mIter;
- return *this;
-}
-
-ListValue::Iterator ListValue::Iterator::operator++(int) const
-{
- return Iterator(mIter + 1);
-}
-
-ListValue::Iterator& ListValue::Iterator::operator--()
-{
- --mIter;
- return *this;
-}
-
-ListValue::Iterator ListValue::Iterator::operator--(int) const
-{
- return Iterator(mIter - 1);
-}
-
-bool operator==(const ListValue::Iterator& a, const ListValue::Iterator& b)
-{
- return a.mIter == b.mIter;
-}
-
-ListValue::Iterator::Iterator(decltype(mIter) iter)
- : mIter{ iter }
-{
-}
-
-bool ListValue::IsInstance(const BaseValue* value)
-{
- return value->GetKind() == KD_List;
-}
-
-ListValue::ListValue()
- : BaseValue(KD_List)
-{
-}
-
-int ListValue::GetCount() const
-{
- return mElements.size();
-}
-
-BaseValue* ListValue::GetElement(int i) const
-{
- return mElements[i].get();
-}
-
-void ListValue::Append(std::unique_ptr<BaseValue> element)
-{
- mElements.push_back(std::move(element));
-}
-
-void ListValue::Insert(int i, std::unique_ptr<BaseValue> element)
-{
- mElements.insert(mElements.begin() + i, std::move(element));
-}
-
-void ListValue::Insert(Iterator iter, std::unique_ptr<BaseValue> element)
-{
- mElements.insert(iter.mIter, std::move(element));
-}
-
-void ListValue::Remove(int i)
-{
- mElements.erase(mElements.begin() + i);
-}
-
-void ListValue::Remove(Iterator iter)
-{
- mElements.erase(iter.mIter);
-}
-
-ListValue::Iterator ListValue::begin()
-{
- return Iterator(mElements.begin());
-}
-
-ListValue::Iterator ListValue::end()
-{
- return Iterator(mElements.end());
-}
diff --git a/core/src/Model/Workflow/Values/List.hpp b/core/src/Model/Workflow/Values/List.hpp
deleted file mode 100644
index 706a95c..0000000
--- a/core/src/Model/Workflow/Values/List.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Value.hpp"
-
-#include <memory>
-#include <vector>
-
-class ListValue : public BaseValue
-{
-public:
- class Iterator
- {
- private:
- std::vector<std::unique_ptr<BaseValue>>::iterator mIter;
-
- public:
- BaseValue* operator*() const;
- BaseValue* operator->() const;
-
- Iterator& operator++();
- Iterator operator++(int) const;
- Iterator& operator--();
- Iterator operator--(int) const;
-
- friend bool operator==(const Iterator& a, const Iterator& b);
-
- private:
- friend class ListValue;
- Iterator(decltype(mIter) iter);
- };
-
-private:
- std::vector<std::unique_ptr<BaseValue>> mElements;
-
-public:
- static bool IsInstance(const BaseValue* value);
- ListValue();
-
- int GetCount() const;
- BaseValue* GetElement(int i) const;
-
- void Append(std::unique_ptr<BaseValue> element);
- void Insert(int i, std::unique_ptr<BaseValue> element);
- void Insert(Iterator iter, std::unique_ptr<BaseValue> element);
- void Remove(int i);
- void Remove(Iterator iter);
-
- Iterator begin();
- Iterator end();
-};
diff --git a/core/src/Model/Workflow/Values/fwd.hpp b/core/src/Model/Workflow/Values/fwd.hpp
deleted file mode 100644
index 51a04e9..0000000
--- a/core/src/Model/Workflow/Values/fwd.hpp
+++ /dev/null
@@ -1,17 +0,0 @@
-#pragma once
-
-// Basic.hpp
-class NumericValue;
-class TextValue;
-class DateTimeValue;
-
-// Database.hpp
-class DatabaseRowIdValue;
-class SaleDatabaseRowValue;
-class PurchaseDatabaseRowValue;
-
-// Dictionary.hpp
-class DictionaryValue;
-
-// List.hpp
-class ListValue;
diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp
deleted file mode 100644
index 3c4d320..0000000
--- a/core/src/Model/Workflow/Workflow.hpp
+++ /dev/null
@@ -1,316 +0,0 @@
-#pragma once
-
-#include "Model/Assets.hpp"
-#include "Model/Workflow/Value.hpp"
-#include "Utils/Vector.hpp"
-#include "cplt_fwd.hpp"
-
-#include <imgui_node_editor.h>
-#include <cstddef>
-#include <cstdint>
-#include <filesystem>
-#include <functional>
-#include <iosfwd>
-#include <limits>
-#include <memory>
-#include <span>
-#include <string>
-#include <variant>
-#include <vector>
-
-namespace ImNodes = ax::NodeEditor;
-
-class WorkflowConnection
-{
-public:
- static constexpr auto kInvalidId = std::numeric_limits<uint32_t>::max();
-
- uint32_t Id;
- uint32_t SourceNode;
- uint32_t SourcePin;
- uint32_t DestinationNode;
- uint32_t DestinationPin;
-
-public:
- WorkflowConnection();
-
- bool IsValid() const;
-
- /// Used for `LinkId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading).
- ImNodes::LinkId GetLinkId() const;
-
- void DrawDebugInfo() const;
- void ReadFrom(std::istream& stream);
- void WriteTo(std::ostream& stream) const;
-};
-
-class WorkflowNode
-{
-public:
- static constexpr auto kInvalidId = std::numeric_limits<uint32_t>::max();
- static constexpr auto kInvalidPinId = std::numeric_limits<uint32_t>::max();
-
- enum Type
- {
- InputType,
- TransformType,
- OutputType,
- };
-
- enum Kind
- {
- KD_NumericAddition,
- KD_NumericSubtraction,
- KD_NumericMultiplication,
- KD_NumericDivision,
- KD_NumericExpression,
- KD_TextFormatting,
- KD_DocumentTemplateExpansion,
- KD_FormInput,
- KD_DatabaseRowsInput,
-
- InvalidKind,
- KindCount = InvalidKind,
- };
-
- enum Category
- {
- CG_Numeric,
- CG_Text,
- CG_Document,
- CG_UserInput,
- CG_SystemInput,
- CG_Output,
-
- InvalidCategory,
- CategoryCount = InvalidCategory,
- };
-
- struct InputPin
- {
- uint32_t Connection = WorkflowConnection::kInvalidId;
- BaseValue::Kind MatchingType = BaseValue::InvalidKind;
- bool ConnectionToConst = false;
-
- /// A constant connection connects from a user-specified constant value, feeding to a valid \c DestinationNode and \c DestinationPin (i.e. input pins).
- bool IsConstantConnection() const;
- bool IsConnected() const;
- BaseValue::Kind GetMatchingType() const;
- };
-
- struct OutputPin
- {
- uint32_t Connection = WorkflowConnection::kInvalidId;
- BaseValue::Kind MatchingType = BaseValue::InvalidKind;
-
- bool IsConnected() const;
- BaseValue::Kind GetMatchingType() const;
- };
-
-protected:
- friend class Workflow;
- friend class WorkflowEvaluationContext;
-
- Workflow* mWorkflow;
- std::vector<InputPin> mInputs;
- std::vector<OutputPin> mOutputs;
- Vec2i mPosition;
- uint32_t mId;
- Kind mKind;
- int mDepth;
- bool mLocked;
-
-public:
- static const char* FormatKind(Kind kind);
- static const char* FormatCategory(Category category);
- static const char* FormatType(Type type);
- static Category QueryCategory(Kind kind);
- static std::span<const Kind> QueryCategoryMembers(Category category);
- static std::unique_ptr<WorkflowNode> CreateByKind(Kind kind);
-
- static bool IsInstance(const WorkflowNode* node);
-
- WorkflowNode(Kind kind, bool locked);
- virtual ~WorkflowNode() = default;
-
- WorkflowNode(const WorkflowNode&) = delete;
- WorkflowNode& operator=(const WorkflowNode&) = delete;
- WorkflowNode(WorkflowNode&&) = default;
- WorkflowNode& operator=(WorkflowNode&&) = default;
-
- void SetPosition(const Vec2i& position);
- Vec2i GetPosition() const;
-
- uint32_t GetId() const;
- /// Used for `NodeId` when interfacing with imgui node editor. Runtime only (not saved to disk and generated when loading).
- ImNodes::NodeId GetNodeId() const;
- Kind GetKind() const;
- int GetDepth() const;
- bool IsLocked() const;
-
- Type GetType() const;
- bool IsInputNode() const;
- bool IsOutputNode() const;
-
- void ConnectInput(uint32_t pinId, WorkflowNode& srcNode, uint32_t srcPinId);
- void DisconnectInput(uint32_t pinId);
-
- void DrawInputPinDebugInfo(uint32_t pinId) const;
- const InputPin& GetInputPin(uint32_t pinId) const;
- ImNodes::PinId GetInputPinUniqueId(uint32_t pinId) const;
-
- void ConnectOutput(uint32_t pinId, WorkflowNode& dstNode, uint32_t dstPinId);
- void DisconnectOutput(uint32_t pinId);
-
- void DrawOutputPinDebugInfo(uint32_t pinId) const;
- const OutputPin& GetOutputPin(uint32_t pinId) const;
- ImNodes::PinId GetOutputPinUniqueId(uint32_t pinId) const;
-
- virtual void Evaluate(WorkflowEvaluationContext& ctx) = 0;
-
- void Draw();
- virtual void DrawExtra() {}
-
- void DrawDebugInfo() const;
- virtual void DrawExtraDebugInfo() const {}
-
- virtual void ReadFrom(std::istream& istream);
- virtual void WriteTo(std::ostream& ostream);
-
-protected:
- InputPin& InsertInputPin(int atIdx);
- void RemoveInputPin(int pin);
- void SwapInputPin(int a, int b);
- OutputPin& InsertOutputPin(int atIdx);
- void RemoveOutputPin(int pin);
- void SwapOutputPin(int a, int b);
-
- /* For \c Workflow to invoke, override by implementations */
-
- void OnAttach(Workflow& workflow, uint32_t newId);
- void OnDetach();
-};
-
-class Workflow : public Asset
-{
- friend class WorkflowNode;
- friend class WorkflowEvaluationContext;
- class Private;
-
-public:
- using CategoryType = WorkflowAssetList;
- static constinit const WorkflowAssetList Category;
-
-private:
- std::vector<WorkflowConnection> mConnections;
- std::vector<std::unique_ptr<WorkflowNode>> mNodes;
- std::vector<std::unique_ptr<BaseValue>> mConstants;
- std::vector<std::vector<uint32_t>> mDepthGroups;
- int mConnectionCount;
- int mNodeCount;
- int mConstantCount;
- bool mDepthsDirty = true;
-
-public:
- /* Graph access */
-
- const std::vector<WorkflowConnection>& GetConnections() const;
- std::vector<WorkflowConnection>& GetConnections();
- const std::vector<std::unique_ptr<WorkflowNode>>& GetNodes() const;
- std::vector<std::unique_ptr<WorkflowNode>>& GetNodes();
- const std::vector<std::unique_ptr<BaseValue>>& GetConstants() const;
- std::vector<std::unique_ptr<BaseValue>>& GetConstants();
-
- WorkflowConnection* GetConnectionById(uint32_t id);
- WorkflowConnection* GetConnectionByLinkId(ImNodes::LinkId linkId);
- WorkflowNode* GetNodeById(uint32_t id);
- WorkflowNode* GetNodeByNodeId(ImNodes::NodeId nodeId);
- BaseValue* GetConstantById(uint32_t id);
-
- struct GlobalPinId
- {
- WorkflowNode* Node;
- uint32_t PinId;
- /// true => input pin
- /// false => output pin
- bool IsOutput;
- };
-
- /// `pinId` should be the `UniqueId` of a pin from a node that's within this workflow.
- GlobalPinId DisassembleGlobalPinId(ImNodes::PinId id);
- ImNodes::PinId FabricateGlobalPinId(const WorkflowNode& node, uint32_t pinId, bool isOutput) const;
-
- const std::vector<std::vector<uint32_t>>& GetDepthGroups() const;
- bool DoesDepthNeedsUpdate() const;
-
- /* Graph mutation */
-
- void AddNode(std::unique_ptr<WorkflowNode> step);
- void RemoveNode(uint32_t id);
-
- void RemoveConnection(uint32_t id);
-
- bool Connect(WorkflowNode& sourceNode, uint32_t sourcePin, WorkflowNode& destinationNode, uint32_t destinationPin);
- bool DisconnectBySource(WorkflowNode& sourceNode, uint32_t sourcePin);
- bool DisconnectByDestination(WorkflowNode& destinationNode, uint32_t destinationPin);
-
- /* Graph rebuild */
-
- enum GraphUpdateResult
- {
- /// Successfully rebuilt graph dependent data.
- /// Details: nothing is written.
- GUR_Success,
- /// Nothing has changed since last time UpdateGraph() was called.
- /// Details: nothing is written.
- GUR_NoWorkToDo,
- /// Details: list of nodes is written.
- GUR_UnsatisfiedDependencies,
- /// Details: list of nodes is written.
- GUR_UnreachableNodes,
- };
-
- using GraphUpdateDetails = std::variant<
- // Case: nothing
- std::monostate,
- // Case: list of nodes (ids)
- std::vector<uint32_t>>;
-
- GraphUpdateResult UpdateGraph(GraphUpdateDetails* details = nullptr);
-
- /* Serialization */
-
- void ReadFromDataStream(InputDataStream& stream);
- void WriteToDataStream(OutputDataStream& stream) const;
-
-private:
- std::pair<WorkflowConnection&, uint32_t> AllocWorkflowConnection();
- std::pair<std::unique_ptr<WorkflowNode>&, uint32_t> AllocWorkflowStep();
-};
-
-class WorkflowAssetList final : public AssetListTyped<Workflow>
-{
-private:
- // AC = Asset Creator
- std::string mACNewName;
- NameSelectionError mACNewNameError = NameSelectionError::Empty;
-
-public:
- // Inherit constructors
- using AssetListTyped::AssetListTyped;
-
-protected:
- void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const override;
-
- std::string RetrieveNameFromFile(const std::filesystem::path& file) const override;
- uuids::uuid RetrieveUuidFromFile(const std::filesystem::path& file) const override;
- std::filesystem::path RetrievePathFromAsset(const SavedAsset& asset) const override;
-
- bool SaveInstance(const SavedAsset& assetInfo, const Asset* asset) const override;
- Workflow* LoadInstance(const SavedAsset& assetInfo) const override;
- Workflow* CreateInstance(const SavedAsset& assetInfo) const override;
- bool RenameInstanceOnDisk(const SavedAsset& assetInfo, std::string_view oldName) const override;
-
- void DisplayAssetCreator(ListState& state) override;
- void DisplayDetailsTable(ListState& state) const override;
-};
diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp
deleted file mode 100644
index 3be2d4d..0000000
--- a/core/src/Model/Workflow/Workflow_Main.cpp
+++ /dev/null
@@ -1,846 +0,0 @@
-#include "Workflow.hpp"
-
-#include "Model/GlobalStates.hpp"
-#include "Model/Project.hpp"
-#include "UI/UI.hpp"
-#include "Utils/I18n.hpp"
-#include "Utils/IO/Archive.hpp"
-#include "Utils/UUID.hpp"
-
-#include <imgui.h>
-#include <imgui_node_editor.h>
-#include <imgui_stdlib.h>
-#include <tsl/robin_set.h>
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <fstream>
-#include <iostream>
-#include <queue>
-#include <utility>
-
-using namespace std::literals::string_view_literals;
-namespace fs = std::filesystem;
-namespace ImNodes = ax::NodeEditor;
-
-WorkflowConnection::WorkflowConnection()
- : Id{ 0 }
- , SourceNode{ WorkflowNode::kInvalidId }
- , SourcePin{ WorkflowNode::kInvalidPinId }
- , DestinationNode{ WorkflowNode::kInvalidId }
- , DestinationPin{ WorkflowNode::kInvalidPinId }
-{
-}
-
-bool WorkflowConnection::IsValid() const
-{
- return Id != 0;
-}
-
-ImNodes::LinkId WorkflowConnection::GetLinkId() const
-{
- // Our id is 0-based (represents an index directly)
- // but imgui-node-editor uses the value 0 to represent a null id, so we need to offset by 1
- return Id + 1;
-}
-
-void WorkflowConnection::DrawDebugInfo() const
-{
- ImGui::Text("Source (node with output pin):");
- ImGui::Text("{ Node = %u, Pin = %u }", SourceNode, SourcePin);
- ImGui::Text("Destination (node with input pin):");
- ImGui::Text("{ Node = %u, Pin = %u }", DestinationNode, DestinationPin);
-}
-
-void WorkflowConnection::ReadFrom(std::istream& stream)
-{
- stream >> SourceNode >> SourcePin;
- stream >> DestinationNode >> DestinationPin;
-}
-
-void WorkflowConnection::WriteTo(std::ostream& stream) const
-{
- stream << SourceNode << SourcePin;
- stream << DestinationNode << DestinationPin;
-}
-
-bool WorkflowNode::InputPin::IsConstantConnection() const
-{
- return ConnectionToConst && IsConnected();
-}
-
-bool WorkflowNode::InputPin::IsConnected() const
-{
- return Connection != WorkflowConnection::kInvalidId;
-}
-
-BaseValue::Kind WorkflowNode::InputPin::GetMatchingType() const
-{
- return MatchingType;
-}
-
-bool WorkflowNode::OutputPin::IsConnected() const
-{
- return Connection != WorkflowConnection::kInvalidId;
-}
-
-BaseValue::Kind WorkflowNode::OutputPin::GetMatchingType() const
-{
- return MatchingType;
-}
-
-WorkflowNode::WorkflowNode(Kind kind, bool locked)
- : mKind{ kind }
- , mDepth{ -1 }
- , mLocked(locked)
-{
-}
-
-Vec2i WorkflowNode::GetPosition() const
-{
- return mPosition;
-}
-
-void WorkflowNode::SetPosition(const Vec2i& position)
-{
- mPosition = position;
-}
-
-uint32_t WorkflowNode::GetId() const
-{
- return mId;
-}
-
-ImNodes::NodeId WorkflowNode::GetNodeId() const
-{
- // See WorkflowConnection::GetLinkId for the rationale
- return mId + 1;
-}
-
-WorkflowNode::Kind WorkflowNode::GetKind() const
-{
- return mKind;
-}
-
-int WorkflowNode::GetDepth() const
-{
- return mDepth;
-}
-
-bool WorkflowNode::IsLocked() const
-{
- return mLocked;
-}
-
-WorkflowNode::Type WorkflowNode::GetType() const
-{
- if (IsInputNode()) {
- return InputType;
- } else if (IsOutputNode()) {
- return OutputType;
- } else {
- return TransformType;
- }
-}
-
-bool WorkflowNode::IsInputNode() const
-{
- return mInputs.size() == 0;
-}
-
-bool WorkflowNode::IsOutputNode() const
-{
- return mOutputs.size() == 0;
-}
-
-void WorkflowNode::ConnectInput(uint32_t pinId, WorkflowNode& srcNode, uint32_t srcPinId)
-{
- mWorkflow->Connect(*this, pinId, srcNode, srcPinId);
-}
-
-void WorkflowNode::DisconnectInput(uint32_t pinId)
-{
- mWorkflow->DisconnectByDestination(*this, pinId);
-}
-
-void WorkflowNode::DrawInputPinDebugInfo(uint32_t pinId) const
-{
- ImGui::Text("Node ID: %d", mId);
- ImGui::Text("Pin ID: (input) %d", pinId);
-}
-
-const WorkflowNode::InputPin& WorkflowNode::GetInputPin(uint32_t pinId) const
-{
- return mInputs[pinId];
-}
-
-ImNodes::PinId WorkflowNode::GetInputPinUniqueId(uint32_t pinId) const
-{
- return mWorkflow->FabricateGlobalPinId(*this, pinId, false);
-}
-
-void WorkflowNode::ConnectOutput(uint32_t pinId, WorkflowNode& dstNode, uint32_t dstPinId)
-{
- mWorkflow->Connect(dstNode, dstPinId, *this, pinId);
-}
-
-void WorkflowNode::DisconnectOutput(uint32_t pinId)
-{
- mWorkflow->DisconnectBySource(*this, pinId);
-}
-
-void WorkflowNode::DrawOutputPinDebugInfo(uint32_t pinId) const
-{
- ImGui::Text("Node ID: %d", mId);
- ImGui::Text("Pin ID: (output) %d", pinId);
-}
-
-const WorkflowNode::OutputPin& WorkflowNode::GetOutputPin(uint32_t pinId) const
-{
- return mOutputs[pinId];
-}
-
-ImNodes::PinId WorkflowNode::GetOutputPinUniqueId(uint32_t pinId) const
-{
- return mWorkflow->FabricateGlobalPinId(*this, pinId, true);
-}
-
-void WorkflowNode::Draw()
-{
- for (uint32_t i = 0; i < mInputs.size(); ++i) {
- auto& pin = mInputs[i];
- auto& typeInfo = BaseValue::QueryInfo(pin.MatchingType);
- ImNodes::BeginPin(GetInputPinUniqueId(i), ImNodes::PinKind::Input);
- // TODO
- ImNodes::EndPin();
- }
- for (uint32_t i = 0; i < mOutputs.size(); ++i) {
- auto& pin = mOutputs[i];
- auto& typeInfo = BaseValue::QueryInfo(pin.MatchingType);
- ImNodes::BeginPin(GetOutputPinUniqueId(i), ImNodes::PinKind::Output);
- // TODO
- ImNodes::EndPin();
- }
-}
-
-void WorkflowNode::DrawDebugInfo() const
-{
- ImGui::Text("Node kind: %s", FormatKind(mKind));
- ImGui::Text("Node type: %s", FormatType(GetType()));
- ImGui::Text("Node ID: %u", mId);
- ImGui::Text("Depth: %d", mDepth);
- DrawExtraDebugInfo();
-}
-
-void WorkflowNode::ReadFrom(std::istream& stream)
-{
- stream >> mId;
- stream >> mPosition.x >> mPosition.y;
-}
-
-void WorkflowNode::WriteTo(std::ostream& stream)
-{
- stream << mId;
- stream << mPosition.x << mPosition.y;
-}
-
-WorkflowNode::InputPin& WorkflowNode::InsertInputPin(int atIdx)
-{
- assert(atIdx >= 0 && atIdx < mInputs.size());
-
- mInputs.push_back(InputPin{});
- for (int i = (int)mInputs.size() - 1, end = atIdx + 1; i >= end; --i) {
- SwapInputPin(i, i + 1);
- }
-
- return mInputs[atIdx];
-}
-
-void WorkflowNode::RemoveInputPin(int pin)
-{
- DisconnectInput(pin);
- for (int i = 0, end = (int)mInputs.size() - 1; i < end; ++i) {
- SwapInputPin(i, i + 1);
- }
- mInputs.resize(mInputs.size() - 1);
-}
-
-void WorkflowNode::SwapInputPin(int a, int b)
-{
- auto& pinA = mInputs[a];
- auto& pinB = mInputs[b];
-
- if (mWorkflow) {
- if (pinA.IsConnected() && !pinA.IsConstantConnection()) {
- auto& conn = *mWorkflow->GetConnectionById(pinA.Connection);
- conn.DestinationPin = b;
- }
- if (pinB.IsConnected() && !pinB.IsConstantConnection()) {
- auto& conn = *mWorkflow->GetConnectionById(pinB.Connection);
- conn.DestinationPin = a;
- }
- }
-
- std::swap(pinA, pinB);
-}
-
-WorkflowNode::OutputPin& WorkflowNode::InsertOutputPin(int atIdx)
-{
- assert(atIdx >= 0 && atIdx < mOutputs.size());
-
- mOutputs.push_back(OutputPin{});
- for (int i = (int)mOutputs.size() - 1, end = atIdx + 1; i >= end; --i) {
- SwapOutputPin(i, i + 1);
- }
-
- return mOutputs[atIdx];
-}
-
-void WorkflowNode::RemoveOutputPin(int pin)
-{
- DisconnectOutput(pin);
- for (int i = 0, end = (int)mOutputs.size() - 1; i < end; ++i) {
- SwapInputPin(i, i + 1);
- }
- mOutputs.resize(mOutputs.size() - 1);
-}
-
-void WorkflowNode::SwapOutputPin(int a, int b)
-{
- auto& pinA = mOutputs[a];
- auto& pinB = mOutputs[b];
-
- if (mWorkflow) {
- if (pinA.IsConnected()) {
- auto& conn = *mWorkflow->GetConnectionById(pinA.Connection);
- conn.SourcePin = b;
- }
- if (pinB.IsConnected()) {
- auto& conn = *mWorkflow->GetConnectionById(pinB.Connection);
- conn.SourcePin = a;
- }
- }
-
- std::swap(pinA, pinB);
-}
-
-void WorkflowNode::OnAttach(Workflow& workflow, uint32_t newId)
-{
-}
-
-void WorkflowNode::OnDetach()
-{
-}
-
-const std::vector<WorkflowConnection>& Workflow::GetConnections() const
-{
- return mConnections;
-}
-
-std::vector<WorkflowConnection>& Workflow::GetConnections()
-{
- return mConnections;
-}
-
-const std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes() const
-{
- return mNodes;
-}
-
-std::vector<std::unique_ptr<WorkflowNode>>& Workflow::GetNodes()
-{
- return mNodes;
-}
-
-const std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants() const
-{
- return mConstants;
-}
-
-std::vector<std::unique_ptr<BaseValue>>& Workflow::GetConstants()
-{
- return mConstants;
-}
-
-WorkflowConnection* Workflow::GetConnectionById(uint32_t id)
-{
- return &mConnections[id];
-}
-
-WorkflowConnection* Workflow::GetConnectionByLinkId(ImNodes::LinkId id)
-{
- return &mConnections[(uint32_t)(size_t)id - 1];
-}
-
-WorkflowNode* Workflow::GetNodeById(uint32_t id)
-{
- return mNodes[id].get();
-}
-
-WorkflowNode* Workflow::GetNodeByNodeId(ImNodes::NodeId id)
-{
- return mNodes[(uint32_t)(size_t)id - 1].get();
-}
-
-BaseValue* Workflow::GetConstantById(uint32_t id)
-{
- return mConstants[id].get();
-}
-
-Workflow::GlobalPinId Workflow::DisassembleGlobalPinId(ImNodes::PinId pinId)
-{
- // imgui-node-editor requires all pins to have a global, unique id
- // but in our model the pin are typed (input vs output) and associated with a node: there is no built-in global id
- // Therefore we encode one ourselves
-
- // Global pin id format
- // nnnnnnnn nnnnnnnn nnnnnnnn nnnnnnnn Tppppppp ppppppppp pppppppp pppppppp
- // <------- (32 bits) node id -------> ^<------ (31 bits) pin id -------->
- // | (1 bit) input (false) vs output (true)
-
- // 1 is added to pin id to prevent the 0th node's 0th input pin resulting in a 0 global pin id
- // (this is problematic because imgui-node-editor use 0 to represent null)
-
- auto id = static_cast<uint64_t>(pinId);
- GlobalPinId result;
-
- result.Node = mNodes[id >> 32].get();
- result.PinId = (uint32_t)(id & 0x000000001FFFFFFF) - 1;
- result.IsOutput = id >> 31;
-
- return result;
-}
-
-ImNodes::PinId Workflow::FabricateGlobalPinId(const WorkflowNode& node, uint32_t pinId, bool isOutput) const
-{
- // See this->DisassembleGlobalPinId for format details and rationale
-
- uint64_t id = 0;
- id |= ((uint64_t)node.GetId() << 32);
- id |= (isOutput << 31);
- id |= ((pinId + 1) & 0x1FFFFFFF);
-
- return id;
-}
-
-const std::vector<std::vector<uint32_t>>& Workflow::GetDepthGroups() const
-{
- return mDepthGroups;
-}
-
-bool Workflow::DoesDepthNeedsUpdate() const
-{
- return mDepthsDirty;
-}
-
-void Workflow::AddNode(std::unique_ptr<WorkflowNode> step)
-{
- auto [storage, id] = AllocWorkflowStep();
- storage = std::move(step);
- storage->OnAttach(*this, id);
- storage->mWorkflow = this;
- storage->mId = id;
-}
-
-void Workflow::RemoveNode(uint32_t id)
-{
- auto& step = mNodes[id];
- if (step == nullptr) return;
-
- step->OnDetach();
- step->mWorkflow = nullptr;
- step->mId = WorkflowNode::kInvalidId;
-}
-
-void Workflow::RemoveConnection(uint32_t id)
-{
- auto& conn = mConnections[id];
- if (!conn.IsValid()) return;
-
- mNodes[conn.SourceNode]->mInputs[conn.SourcePin].Connection = WorkflowNode::kInvalidId;
- mNodes[conn.DestinationNode]->mInputs[conn.DestinationPin].Connection = WorkflowNode::kInvalidId;
-
- conn = {};
- mDepthsDirty = true;
-}
-
-bool Workflow::Connect(WorkflowNode& sourceNode, uint32_t sourcePin, WorkflowNode& destinationNode, uint32_t destinationPin)
-{
- auto& src = sourceNode.mOutputs[sourcePin];
- auto& dst = destinationNode.mInputs[destinationPin];
-
- // TODO report error to user?
- if (src.GetMatchingType() != dst.GetMatchingType()) {
- return false;
- }
-
- if (src.IsConnected()) {
- DisconnectBySource(sourceNode, sourcePin);
- }
-
- auto [conn, id] = AllocWorkflowConnection();
- conn.SourceNode = sourceNode.GetId();
- conn.SourcePin = sourcePin;
- conn.DestinationNode = destinationNode.GetId();
- conn.DestinationPin = destinationPin;
-
- src.Connection = id;
- dst.Connection = id;
-
- mDepthsDirty = true;
- return true;
-}
-
-bool Workflow::DisconnectBySource(WorkflowNode& sourceNode, uint32_t sourcePin)
-{
- auto& sn = sourceNode.mOutputs[sourcePin];
- if (!sn.IsConnected()) return false;
-
- auto& conn = mConnections[sn.Connection];
- auto& dn = mNodes[conn.DestinationNode]->mInputs[conn.DestinationPin];
-
- sn.Connection = WorkflowConnection::kInvalidId;
- dn.Connection = WorkflowConnection::kInvalidId;
- conn = {};
-
- mDepthsDirty = true;
- return true;
-}
-
-bool Workflow::DisconnectByDestination(WorkflowNode& destinationNode, uint32_t destinationPin)
-{
- auto& dn = destinationNode.mOutputs[destinationPin];
- if (!dn.IsConnected()) return false;
-
- auto& conn = mConnections[dn.Connection];
- auto& sn = mNodes[conn.SourceNode]->mInputs[conn.SourcePin];
-
- sn.Connection = WorkflowConnection::kInvalidId;
- dn.Connection = WorkflowConnection::kInvalidId;
- conn = {};
-
- mDepthsDirty = true;
- return true;
-}
-
-Workflow::GraphUpdateResult Workflow::UpdateGraph(GraphUpdateDetails* details)
-{
- if (!mDepthsDirty) {
- return GUR_NoWorkToDo;
- }
-
- // Terminology:
- // - Dependency = nodes its input pins are connected to
- // - Dependents = nodes its output pins are connected to
-
- struct WorkingNode
- {
- // The max depth out of all dependency nodes, maintained during the traversal and committed as the actual depth
- // when all dependencies of this node has been resolved. Add 1 to get the depth that will be assigned to the node.
- int MaximumDepth = 0;
- int FulfilledInputCount = 0;
- };
-
- std::vector<WorkingNode> workingNodes;
- std::queue<uint32_t> q;
-
- // Check if all dependencies of this node is satisfied
- auto CheckNodeDependencies = [&](WorkflowNode& node) -> bool {
- for (auto& pin : node.mInputs) {
- if (!pin.IsConnected()) {
- return false;
- }
- }
- return true;
- };
-
- workingNodes.reserve(mNodes.size());
- {
- std::vector<uint32_t> unsatisfiedNodes;
- for (uint32_t i = 0; i < mNodes.size(); ++i) {
- auto& node = mNodes[i];
- workingNodes.push_back(WorkingNode{});
-
- if (!node) continue;
-
- if (!CheckNodeDependencies(*node)) {
- unsatisfiedNodes.push_back(i);
- }
-
- node->mDepth = -1;
-
- // Start traversing with the input nodes
- if (node->GetType() == WorkflowNode::InputType) {
- q.push(i);
- }
- }
-
- if (!unsatisfiedNodes.empty()) {
- if (details) {
- details->emplace<decltype(unsatisfiedNodes)>(std::move(unsatisfiedNodes));
- }
- return GUR_UnsatisfiedDependencies;
- }
- }
-
- auto ProcessNode = [&](WorkflowNode& node) -> void {
- for (auto& pin : node.mOutputs) {
- if (!pin.IsConnected()) continue;
- auto& conn = mConnections[pin.Connection];
-
- auto& wn = workingNodes[conn.DestinationNode];
- auto& n = *mNodes[conn.DestinationPin].get();
-
- wn.FulfilledInputCount++;
- wn.MaximumDepth = std::max(node.mDepth, wn.MaximumDepth);
-
- // Node's dependency is fulfilled, we can process its dependents next
- // We use >= here because for a many-to-one pin, the dependency is an "or" relation ship, i.e. any of the nodes firing before this will fulfill the requirement
- if (n.mInputs.size() >= wn.FulfilledInputCount) {
- n.mDepth = wn.MaximumDepth + 1;
- }
- }
- };
-
- int processedNodes = 0;
- while (!q.empty()) {
- auto& wn = workingNodes[q.front()];
- auto& n = *mNodes[q.front()];
- q.pop();
- processedNodes++;
-
- ProcessNode(n);
- }
-
- if (processedNodes < mNodes.size()) {
- // There is unreachable nodes, collect them and report to the caller
-
- std::vector<uint32_t> unreachableNodes;
- for (uint32_t i = 0; i < mNodes.size(); ++i) {
- auto& wn = workingNodes[i];
- auto& n = *mNodes[i];
-
- // This is a reachable node
- if (n.mDepth != -1) continue;
-
- unreachableNodes.push_back(i);
- }
-
- if (details) {
- details->emplace<decltype(unreachableNodes)>(std::move(unreachableNodes));
- }
- return GUR_UnreachableNodes;
- }
-
- return GUR_Success;
-}
-
-class Workflow::Private
-{
-public:
- template <class TSelf, class TProxy>
- static void OperateStream(TSelf& self, TProxy& proxy)
- {
- // TODO
- }
-};
-
-void Workflow::ReadFromDataStream(InputDataStream& stream)
-{
- Private::OperateStream(*this, stream);
-}
-
-void Workflow::WriteToDataStream(OutputDataStream& stream) const
-{
- Private::OperateStream(*this, stream);
-}
-
-std::pair<WorkflowConnection&, uint32_t> Workflow::AllocWorkflowConnection()
-{
- for (size_t idx = 0; idx < mConnections.size(); ++idx) {
- auto& elm = mConnections[idx];
- if (!elm.IsValid()) {
- return { elm, (uint32_t)idx };
- }
- }
-
- auto id = (uint32_t)mConnections.size();
- auto& conn = mConnections.emplace_back(WorkflowConnection{});
- conn.Id = id;
-
- return { conn, id };
-}
-
-std::pair<std::unique_ptr<WorkflowNode>&, uint32_t> Workflow::AllocWorkflowStep()
-{
- for (size_t idx = 0; idx < mNodes.size(); ++idx) {
- auto& elm = mNodes[idx];
- if (elm == nullptr) {
- return { elm, (uint32_t)idx };
- }
- }
-
- auto id = (uint32_t)mNodes.size();
- auto& node = mNodes.emplace_back(std::unique_ptr<WorkflowNode>());
-
- return { node, id };
-}
-
-void WorkflowAssetList::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const
-{
- auto dir = GetConnectedProject().GetWorkflowsDirectory();
- DiscoverFilesByExtension(callback, dir, ".cplt-workflow"sv);
-}
-
-std::string WorkflowAssetList::RetrieveNameFromFile(const fs::path& file) const
-{
- auto res = DataArchive::LoadFile(file);
- if (!res) return "";
- auto& stream = res.value();
-
- SavedAsset assetInfo;
- stream.ReadObject(assetInfo);
-
- return assetInfo.Name;
-}
-
-uuids::uuid WorkflowAssetList::RetrieveUuidFromFile(const fs::path& file) const
-{
- return uuids::uuid::from_string(file.stem().string());
-}
-
-fs::path WorkflowAssetList::RetrievePathFromAsset(const SavedAsset& asset) const
-{
- auto fileName = uuids::to_string(asset.Uuid);
- return GetConnectedProject().GetWorkflowPath(fileName);
-}
-
-bool WorkflowAssetList::SaveInstance(const SavedAsset& assetInfo, const Asset* asset) const
-{
- auto path = RetrievePathFromAsset(assetInfo);
- auto res = DataArchive::SaveFile(path);
- if (!res) return false;
- auto& stream = res.value();
-
- stream.WriteObject(assetInfo);
- // This cast is fine: calls to this class will always be wrapped in TypedAssetList<T>, which will ensure `asset` points to some Workflow
- if (auto workflow = static_cast<const Workflow*>(asset)) { // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
- stream.WriteObject(*workflow);
- }
-
- return true;
-}
-
-static std::unique_ptr<Workflow> LoadWorkflowFromFile(const fs::path& path)
-{
- auto res = DataArchive::LoadFile(path);
- if (!res) return nullptr;
- auto& stream = res.value();
-
- // TODO this is currently unused
- SavedAsset assetInfo;
- stream.ReadObject(assetInfo);
-
- auto workflow = std::make_unique<Workflow>();
- stream.ReadObject(*workflow);
-
- return workflow;
-}
-
-Workflow* WorkflowAssetList::LoadInstance(const SavedAsset& assetInfo) const
-{
- return ::LoadWorkflowFromFile(RetrievePathFromAsset(assetInfo)).release();
-}
-
-Workflow* WorkflowAssetList::CreateInstance(const SavedAsset& assetInfo) const
-{
- return new Workflow();
-}
-
-bool WorkflowAssetList::RenameInstanceOnDisk(const SavedAsset& assetInfo, std::string_view oldName) const
-{
- auto path = RetrievePathFromAsset(assetInfo);
-
- auto workflow = ::LoadWorkflowFromFile(path);
- if (!workflow) return false;
-
- SaveInstance(assetInfo, workflow.get());
-
- return true;
-}
-
-void WorkflowAssetList::DisplayAssetCreator(ListState& state)
-{
- auto ValidateNewName = [&]() -> void {
- if (mACNewName.empty()) {
- mACNewNameError = NameSelectionError::Empty;
- return;
- }
-
- if (FindByName(mACNewName)) {
- mACNewNameError = NameSelectionError::Duplicated;
- return;
- }
-
- mACNewNameError = NameSelectionError::None;
- };
-
- auto ShowNewNameErrors = [&]() -> void {
- switch (mACNewNameError) {
- case NameSelectionError::None: break;
- case NameSelectionError::Duplicated:
- ImGui::ErrorMessage(I18N_TEXT("Duplicate name", L10N_DUPLICATE_NAME_ERROR));
- break;
- case NameSelectionError::Empty:
- ImGui::ErrorMessage(I18N_TEXT("Name cannot be empty", L10N_EMPTY_NAME_ERROR));
- break;
- }
- };
-
- auto IsInputValid = [&]() -> bool {
- return mACNewNameError == NameSelectionError::None;
- };
-
- auto ResetState = [&]() -> void {
- mACNewName.clear();
- ValidateNewName();
- };
-
- if (ImGui::InputText(I18N_TEXT("Name", L10N_NAME), &mACNewName)) {
- ValidateNewName();
- }
-
- ShowNewNameErrors();
-
- if (ImGui::Button(I18N_TEXT("OK", L10N_CONFIRM), !IsInputValid())) {
- ImGui::CloseCurrentPopup();
-
- Create(SavedAsset{
- .Name = mACNewName,
- });
- ResetState();
- }
- ImGui::SameLine();
- if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) {
- ImGui::CloseCurrentPopup();
- }
-}
-
-void WorkflowAssetList::DisplayDetailsTable(ListState& state) const
-{
- ImGui::BeginTable("AssetDetailsTable", 1, ImGuiTableFlags_Borders);
-
- ImGui::TableSetupColumn(I18N_TEXT("Name", L10N_NAME));
- ImGui::TableHeadersRow();
-
- for (auto& asset : this->GetAssets()) {
- ImGui::TableNextRow();
-
- ImGui::TableNextColumn();
- if (ImGui::Selectable(asset.Name.c_str(), state.SelectedAsset == &asset, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_DontClosePopups)) {
- state.SelectedAsset = &asset;
- }
- }
-
- ImGui::EndTable();
-}
diff --git a/core/src/Model/Workflow/Workflow_RTTI.cpp b/core/src/Model/Workflow/Workflow_RTTI.cpp
deleted file mode 100644
index cb66c69..0000000
--- a/core/src/Model/Workflow/Workflow_RTTI.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "Workflow.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 "Utils/I18n.hpp"
-#include "Utils/Macros.hpp"
-
-#include <memory>
-
-const char* WorkflowNode::FormatKind(Kind kind)
-{
- switch (kind) {
- case KD_NumericAddition: return I18N_TEXT("Add", L10N_WORKFLOW_ADD);
- case KD_NumericSubtraction: return I18N_TEXT("Subtract", L10N_WORKFLOW_SUB);
- case KD_NumericMultiplication: return I18N_TEXT("Multiply", L10N_WORKFLOW_MUL);
- case KD_NumericDivision: return I18N_TEXT("Divide", L10N_WORKFLOW_DIV);
- case KD_NumericExpression: return I18N_TEXT("Evaluate expression", L10N_WORKFLOW_EVAL);
- case KD_TextFormatting: return I18N_TEXT("Format text", L10N_WORKFLOW_FMT);
- case KD_DocumentTemplateExpansion: return I18N_TEXT("Expand template", L10N_WORKFLOW_INSTANTIATE_TEMPLATE);
- case KD_FormInput: return I18N_TEXT("Form input", L10N_WORKFLOW_FORM_INPUT);
- case KD_DatabaseRowsInput: return I18N_TEXT("Database input", L10N_WORKFLOW_DB_INPUT);
-
- case InvalidKind: break;
- }
- return "";
-}
-
-const char* WorkflowNode::FormatCategory(WorkflowNode::Category category)
-{
- switch (category) {
- case CG_Numeric: return I18N_TEXT("Numeric", L10N_WORKFLOW_CATEGORY_NUMERIC);
- case CG_Text: return I18N_TEXT("Text", L10N_WORKFLOW_CATEGORY_TEXT);
- case CG_Document: return I18N_TEXT("Document", L10N_WORKFLOW_CATEGORY_DOCUMENT);
- case CG_UserInput: return I18N_TEXT("User input", L10N_WORKFLOW_CATEGORY_USER_INPUT);
- case CG_SystemInput: return I18N_TEXT("System input", L10N_WORKFLOW_CATEGORY_SYS_INPUT);
- case CG_Output: return I18N_TEXT("Output", L10N_WORKFLOW_CATEGORY_OUTPUT);
-
- case InvalidCategory: break;
- }
- return "";
-}
-
-const char* WorkflowNode::FormatType(Type type)
-{
- switch (type) {
- case InputType: return I18N_TEXT("Input", L10N_WORKFLOW_KIND_INPUT);
- case TransformType: return I18N_TEXT("Transform", L10N_WORKFLOW_KIND_TRANSFORM);
- case OutputType: return I18N_TEXT("Output", L10N_WORKFLOW_KIND_OUTPUT);
- }
- return "";
-}
-
-WorkflowNode::Category WorkflowNode::QueryCategory(Kind kind)
-{
- switch (kind) {
- case KD_NumericAddition:
- case KD_NumericSubtraction:
- case KD_NumericMultiplication:
- case KD_NumericDivision:
- case KD_NumericExpression:
- return CG_Numeric;
- case KD_TextFormatting:
- return CG_Text;
- case KD_DocumentTemplateExpansion:
- return CG_Document;
- case KD_FormInput:
- case KD_DatabaseRowsInput:
- return CG_UserInput;
-
- case InvalidKind: break;
- }
- return InvalidCategory;
-}
-
-std::span<const WorkflowNode::Kind> WorkflowNode::QueryCategoryMembers(Category category)
-{
- constexpr WorkflowNode::Kind kNumeric[] = {
- KD_NumericAddition,
- KD_NumericSubtraction,
- KD_NumericMultiplication,
- KD_NumericDivision,
- KD_NumericExpression,
- };
-
- constexpr WorkflowNode::Kind kText[] = {
- KD_TextFormatting,
- };
-
- constexpr WorkflowNode::Kind kDocument[] = {
- KD_DocumentTemplateExpansion,
- };
-
- constexpr WorkflowNode::Kind kUserInput[] = {
- KD_FormInput,
- KD_DatabaseRowsInput,
- };
-
- // TODO remove invalid kinds after we have nodes of these categories
- constexpr WorkflowNode::Kind kSystemInput[] = {
- InvalidKind,
- };
-
- constexpr WorkflowNode::Kind kOutput[] = {
- InvalidKind,
- };
-
- switch (category) {
- case CG_Numeric: return kNumeric;
- case CG_Text: return kText;
- case CG_Document: return kDocument;
- case CG_UserInput: return kUserInput;
- case CG_SystemInput: return kSystemInput;
- case CG_Output: return kOutput;
-
- case InvalidCategory: break;
- }
- return {};
-}
-
-std::unique_ptr<WorkflowNode> WorkflowNode::CreateByKind(WorkflowNode::Kind kind)
-{
- switch (kind) {
- case KD_NumericAddition: return std::make_unique<NumericOperationNode>(NumericOperationNode::Addition);
- case KD_NumericSubtraction: return std::make_unique<NumericOperationNode>(NumericOperationNode::Subtraction);
- case KD_NumericMultiplication: return std::make_unique<NumericOperationNode>(NumericOperationNode::Multiplication);
- case KD_NumericDivision: return std::make_unique<NumericOperationNode>(NumericOperationNode::Division);
- case KD_NumericExpression: return std::make_unique<NumericExpressionNode>();
- case KD_TextFormatting: return std::make_unique<TextFormatterNode>();
- case KD_DocumentTemplateExpansion: return std::make_unique<DocumentTemplateExpansionNode>();
- case KD_FormInput: return std::make_unique<FormInputNode>();
- case KD_DatabaseRowsInput: return std::make_unique<DatabaseRowsInputNode>();
-
- case InvalidKind: break;
- }
- return nullptr;
-}
-
-bool WorkflowNode::IsInstance(const WorkflowNode* node)
-{
- return true;
-}
diff --git a/core/src/Model/Workflow/fwd.hpp b/core/src/Model/Workflow/fwd.hpp
deleted file mode 100644
index ed39bdb..0000000
--- a/core/src/Model/Workflow/fwd.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#pragma once
-
-#include "Model/Workflow/Nodes/fwd.hpp"
-#include "Model/Workflow/Values/fwd.hpp"
-
-// Evaluation.hpp
-class WorkflowEvaluationError;
-class WorkflowEvaluationContext;
-
-// SavedWorkflow.hpp
-class SavedWorkflowCache;
-class SavedWorkflow;
-
-// Value.hpp
-class BaseValue;
-class BaseObjectValue;
-
-// Workflow.hpp
-class WorkflowConnection;
-class WorkflowNode;
-class Workflow;
-class WorkflowAssetList;