summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2021-06-07 12:19:51 -0700
committerrtk0c <[email protected]>2021-06-07 12:19:51 -0700
commitd7ee2efaca226fc478e3f0c78abdbe86a887f17a (patch)
tree81670fefb7cdba3c5fa0ab890f7d84e24c194bdb /core
parenta180e1b56025c6b7d81d2e587ad90531d29de44c (diff)
Complete asset loading/saving and UI management logic
Diffstat (limited to 'core')
-rw-r--r--core/src/Model/Assets.cpp116
-rw-r--r--core/src/Model/Assets.hpp97
-rw-r--r--core/src/Model/Project.hpp4
-rw-r--r--core/src/Model/Template/Template.hpp19
-rw-r--r--core/src/Model/Template/Template_Main.cpp62
-rw-r--r--core/src/Model/Template/fwd.hpp2
-rw-r--r--core/src/Model/Workflow/Workflow.hpp18
-rw-r--r--core/src/Model/Workflow/Workflow_Main.cpp134
-rw-r--r--core/src/Model/Workflow/fwd.hpp2
-rw-r--r--core/src/Model/fwd.hpp3
-rw-r--r--core/src/UI/UI_Templates.cpp41
-rw-r--r--core/src/UI/UI_Workflows.cpp54
12 files changed, 309 insertions, 243 deletions
diff --git a/core/src/Model/Assets.cpp b/core/src/Model/Assets.cpp
index e4eee54..a1e9730 100644
--- a/core/src/Model/Assets.cpp
+++ b/core/src/Model/Assets.cpp
@@ -4,54 +4,16 @@
#include <fstream>
#include <utility>
+using namespace std::literals::string_view_literals;
namespace fs = std::filesystem;
Asset::Asset()
{
}
-std::unique_ptr<Asset> AssetCategory::CreateEmptyUnique(const SavedAsset& diskForm) const
-{
- return std::unique_ptr<Asset>(CreateEmpty(diskForm));
-}
-
-std::unique_ptr<Asset> AssetCategory::LoadUnique(const SavedAsset& diskForm) const
-{
- return std::unique_ptr<Asset>(Load(diskForm));
-}
-
-void AssetCategory::DiscoverFilesByExtension(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, std::string_view extension)
-{
- for (auto entry : fs::directory_iterator(containerDir)) {
- if (!entry.is_regular_file()) continue;
-
- // If the caller provided an extension to match against, and it doesn't equal to current file extension, skip
- if (!extension.empty() &&
- entry.path().extension() != extension)
- {
- continue;
- }
-
- callback(SavedAsset{
- .Path = entry.path(),
- .Name = entry.path().stem().string(),
- });
- }
-}
-
-void AssetCategory::DiscoverFilesByHeader(const std::function<void(SavedAsset)>& callback, const std::filesystem::__cxx11::path& containerDir, const std::function<bool(std::istream&)>& validater)
-{
- // TODO
-}
-
-AssetList::AssetList(const AssetCategory& loader)
- : mLoader{ &loader }
-{
-}
-
void AssetList::Reload()
{
- mLoader->DiscoverFiles([this](SavedAsset asset) -> void {
+ DiscoverFiles([this](SavedAsset asset) -> void {
Create(std::move(asset));
});
}
@@ -71,8 +33,12 @@ const SavedAsset& AssetList::Create(SavedAsset asset)
auto [iter, DISCARD] = mAssets.insert(asset.Name, SavedAsset{});
auto& savedAsset = iter.value();
- mLoader->CreateEmpty(asset);
savedAsset = std::move(asset);
+ if (savedAsset.Uuid.is_nil()) {
+ savedAsset.Uuid = uuids::uuid_random_generator{}();
+ }
+
+ SaveEmptyInstance(savedAsset);
return savedAsset;
}
@@ -80,24 +46,51 @@ const SavedAsset& AssetList::Create(SavedAsset asset)
std::unique_ptr<Asset> AssetList::CreateAndLoad(SavedAsset assetIn)
{
auto& savedAsset = Create(std::move(assetIn));
- auto asset = std::unique_ptr<Asset>(mLoader->CreateEmpty(savedAsset));
+ auto asset = std::unique_ptr<Asset>(CreateEmptyInstance(savedAsset));
return asset;
}
-std::unique_ptr<Asset> AssetList::LoadFromDisk(std::string_view name) const
+std::unique_ptr<Asset> AssetList::Load(std::string_view name) const
{
if (auto savedAsset = FindByName(name)) {
- auto asset = mLoader->LoadUnique(*savedAsset);
+ auto asset = Load(*savedAsset);
return asset;
+ } else {
+ return nullptr;
}
}
-bool AssetList::Rename(std::string_view oldName, std::string_view newName)
+std::unique_ptr<Asset> AssetList::Load(const SavedAsset& asset) const
+{
+ return std::unique_ptr<Asset>(LoadImpl(asset));
+}
+
+const SavedAsset* AssetList::Rename(std::string_view oldName, std::string_view newName)
{
+ auto iter = mAssets.find(oldName);
+ if (iter == mAssets.end()) return nullptr;
+
+ auto info = std::move(iter.value());
+ info.Name = newName;
+
+ auto [newIter, DISCARD] = mAssets.insert(newName, std::move(info));
+ mAssets.erase(iter);
+
+ return &newIter.value();
}
bool AssetList::Remove(std::string_view name)
{
+ auto iter = mAssets.find(name);
+ if (iter == mAssets.end()) {
+ return false;
+ }
+ auto& asset = iter.value();
+
+ fs::remove(RetrievePathFromAsset(asset));
+ mAssets.erase(iter);
+
+ return true;
}
int AssetList::GetCacheSizeLimit() const
@@ -110,17 +103,42 @@ void AssetList::SetCacheSizeLimit(int limit)
mCacheSizeLimit = limit;
}
-void AssetList::DrawBigIcons(DrawState& state)
+void AssetList::DrawBigIcons(ListState& state)
{
// TODO
}
-void AssetList::DrawDetails(DrawState& state)
+void AssetList::DrawDetails(ListState& state)
{
- mLoader->SetupDetailsTable("AssetDetailsTable");
+ SetupDetailsTable("AssetDetailsTable");
for (auto& asset : mAssets) {
- mLoader->DrawDetailsTableRow(asset);
+ DrawDetailsTableRow(asset);
ImGui::TableNextRow();
}
ImGui::EndTable();
}
+
+void AssetList::DiscoverFilesByExtension(const std::function<void(SavedAsset)>& callback, const fs::path& containerDir, std::string_view extension) const
+{
+ for (auto entry : fs::directory_iterator(containerDir)) {
+ if (!entry.is_regular_file()) continue;
+
+ // If the caller provided an extension to match against, and it doesn't equal to current file extension, skip
+ if (!extension.empty() &&
+ entry.path().extension() != extension)
+ {
+ continue;
+ }
+
+ callback(SavedAsset{
+ .Name = RetrieveNameFromFile(entry.path()),
+ .Uuid = RetrieveUuidFromFile(entry.path()),
+ // TODO load payload
+ });
+ }
+}
+
+void AssetList::DiscoverFilesByHeader(const std::function<void(SavedAsset)>& callback, const fs::path& containerDir, const std::function<bool(std::istream&)>& validater) const
+{
+ // TODO
+}
diff --git a/core/src/Model/Assets.hpp b/core/src/Model/Assets.hpp
index bc5219d..3401e42 100644
--- a/core/src/Model/Assets.hpp
+++ b/core/src/Model/Assets.hpp
@@ -1,18 +1,22 @@
#pragma once
#include <tsl/array_map.h>
+#include <uuid.h>
#include <filesystem>
#include <iosfwd>
#include <memory>
#include <string_view>
/// A structure representing a ready-to-be-loaded asset, locating on the disk.
+/// Each asset should be identified by a unique uuid within the asset category (i.e. a workflow and a template can share the same uuid),
+/// generated on insertion to an asset list if not given by the caller.
struct SavedAsset
{
- std::filesystem::path Path;
std::string Name;
- /// `Path`'s string form, encoded in UTF-8.
- std::string PathString = Path.string();
+ /// UUID of this asset. This field is generated as a random UUID v4 upon insertion into an AssetList, if not already provided by the caller (indicated by !is_nil()).
+ uuids::uuid Uuid;
+ /// Extra data to be used by the AssetList/Asset implementation.
+ uint64_t Payload;
};
class Asset
@@ -22,40 +26,15 @@ public:
virtual ~Asset() = default;
};
-class AssetCategory
-{
-public:
- virtual ~AssetCategory() = default;
-
- virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const = 0;
-
- virtual Asset* CreateEmpty(const SavedAsset& diskForm) const = 0;
- std::unique_ptr<Asset> CreateEmptyUnique(const SavedAsset& diskForm) const;
- virtual Asset* Load(const SavedAsset& diskForm) const = 0;
- std::unique_ptr<Asset> LoadUnique(const SavedAsset& diskForm) const;
-
- /// This should call ImGui::BeginTable() along with other accessories such as setting up the header row.
- virtual void SetupDetailsTable(const char* tableId) const = 0;
- virtual void DrawBigIcon(const SavedAsset& asset) const = 0;
- virtual void DrawDetailsTableRow(const SavedAsset& asset) const = 0;
-
-protected:
- /* Helper loader functions */
-
- static void DiscoverFilesByExtension(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, std::string_view extension);
- static void DiscoverFilesByHeader(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, const std::function<bool(std::istream&)>& validater);
-};
-
class AssetList
{
private:
- const AssetCategory* mLoader;
tsl::array_map<char, SavedAsset> mAssets;
tsl::array_map<char, std::unique_ptr<Asset>> mCache;
int mCacheSizeLimit = 0;
public:
- AssetList(const AssetCategory& loader);
+ virtual ~AssetList() = default;
// TODO support file watches
void Reload();
@@ -63,42 +42,62 @@ public:
const SavedAsset* FindByName(std::string_view name) const;
const SavedAsset& Create(SavedAsset asset);
std::unique_ptr<Asset> CreateAndLoad(SavedAsset asset);
- std::unique_ptr<Asset> LoadFromDisk(std::string_view name) const;
- bool Rename(std::string_view oldName, std::string_view newName);
+ /// Load the asset on disk by its name.
+ std::unique_ptr<Asset> Load(std::string_view name) const;
+ /// Load the asset on disk by a reference to its SavedAsset instance. This function assumes that the given SavedAsset
+ /// is stored in AssetList, otherwise the behavior is undefined.
+ std::unique_ptr<Asset> Load(const SavedAsset& asset) const;
+ const SavedAsset* Rename(std::string_view oldName, std::string_view newName);
bool Remove(std::string_view name);
int GetCacheSizeLimit() const;
void SetCacheSizeLimit(int limit);
- struct DrawState
+ struct ListState
{
const SavedAsset* SelectedAsset = nullptr;
};
- void DrawBigIcons(DrawState& state);
- void DrawDetails(DrawState& state);
+ void DrawBigIcons(ListState& state);
+ void DrawDetails(ListState& state);
+
+protected:
+ virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const = 0;
+
+ // Helper
+ void DiscoverFilesByExtension(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, std::string_view extension) const;
+ void DiscoverFilesByHeader(const std::function<void(SavedAsset)>& callback, const std::filesystem::path& containerDir, const std::function<bool(std::istream&)>& validater) const;
+
+ virtual void SaveEmptyInstance(const SavedAsset& asset) const = 0;
+ virtual Asset* CreateEmptyInstance(const SavedAsset& asset) const = 0;
+
+ virtual Asset* LoadImpl(const SavedAsset& asset) const = 0;
+
+ virtual std::string RetrieveNameFromFile(const std::filesystem::path& file) const = 0;
+ virtual uuids::uuid RetrieveUuidFromFile(const std::filesystem::path& file) const = 0;
+ virtual std::filesystem::path RetrievePathFromAsset(const SavedAsset& asset) const = 0;
+
+ /// This should call ImGui::BeginTable() along with other accessories such as setting up the header row.
+ virtual void SetupDetailsTable(const char* tableId) const = 0;
+ virtual void DrawBigIcon(const SavedAsset& asset) const = 0;
+ virtual void DrawDetailsTableRow(const SavedAsset& asset) const = 0;
};
-template <class TAsset>
-class TypedAssetList : public AssetList
+template <class T>
+class AssetListTyped : public AssetList
{
public:
- using Asset = TAsset;
- using AssetType = typename TAsset::CategoryType;
-
-public:
- // Import constructor
- using AssetList::AssetList;
-
- Asset* FindByName(std::string_view name) const
+ std::unique_ptr<T> CreateAndLoad(SavedAsset asset)
{
- return static_cast<TAsset*>(AssetList::FindByName(name));
+ return std::unique_ptr<T>(static_cast<T*>(AssetList::CreateAndLoad(asset).release()));
}
- std::unique_ptr<Asset> Create(std::string_view name)
+
+ std::unique_ptr<T> Load(std::string_view name) const
{
- return std::unique_ptr<TAsset>(static_cast<TAsset*>(AssetList::Create(name).release()));
+ return std::unique_ptr<T>(static_cast<T*>(AssetList::Load(name).release()));
}
- std::unique_ptr<Asset> LoadFromDisk(std::string_view name) const
+
+ std::unique_ptr<T> Load(const SavedAsset& asset) const
{
- return std::unique_ptr<TAsset>(static_cast<TAsset>(AssetList::LoadFromDisk(name)));
+ return std::unique_ptr<T>(static_cast<T*>(AssetList::Load(asset).release()));
}
};
diff --git a/core/src/Model/Project.hpp b/core/src/Model/Project.hpp
index fea148d..8cf3483 100644
--- a/core/src/Model/Project.hpp
+++ b/core/src/Model/Project.hpp
@@ -15,8 +15,8 @@
class Project
{
public:
- TypedAssetList<Workflow> Workflows;
- TypedAssetList<Template> Templates;
+ WorkflowAssetList Workflows;
+ TemplateAssetList Templates;
ItemList<ProductItem> Products;
ItemList<FactoryItem> Factories;
ItemList<CustomerItem> Customers;
diff --git a/core/src/Model/Template/Template.hpp b/core/src/Model/Template/Template.hpp
index d876650..600bb26 100644
--- a/core/src/Model/Template/Template.hpp
+++ b/core/src/Model/Template/Template.hpp
@@ -19,8 +19,7 @@ public:
KindCount = InvalidKind,
};
- using CategoryType = TemplateAssetCategory;
- static constinit const TemplateAssetCategory Category;
+ using CategoryType = TemplateAssetList;
private:
Kind mKind;
@@ -45,12 +44,20 @@ public:
virtual void WriteTo(std::ostream& stream) const = 0;
};
-class TemplateAssetCategory : public AssetCategory
+class TemplateAssetList final : public AssetListTyped<Template>
{
-public:
+protected:
virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const override;
- virtual Template* CreateEmpty(const SavedAsset& diskForm) const override;
- virtual Template* Load(const SavedAsset& diskForm) const override;
+
+ virtual std::string RetrieveNameFromFile(const std::filesystem::path& file) const override;
+ virtual uuids::uuid RetrieveUuidFromFile(const std::filesystem::path& file) const override;
+ virtual std::filesystem::path RetrievePathFromAsset(const SavedAsset& asset) const override;
+
+ virtual void SaveEmptyInstance(const SavedAsset& asset) const override;
+ virtual Template* CreateEmptyInstance(const SavedAsset& diskForm) const override;
+
+ virtual Template* LoadImpl(const SavedAsset& diskForm) const override;
+
virtual void SetupDetailsTable(const char* tableId) const override;
virtual void DrawBigIcon(const SavedAsset& asset) const override;
virtual void DrawDetailsTableRow(const SavedAsset& asset) const override;
diff --git a/core/src/Model/Template/Template_Main.cpp b/core/src/Model/Template/Template_Main.cpp
index 9efbeae..92ad050 100644
--- a/core/src/Model/Template/Template_Main.cpp
+++ b/core/src/Model/Template/Template_Main.cpp
@@ -4,11 +4,11 @@
#include "Model/Project.hpp"
#include <imgui.h>
+#include <uuid.h>
#include <fstream>
using namespace std::literals::string_view_literals;
-
-constinit const TemplateAssetCategory Template::Category{};
+namespace fs = std::filesystem;
Template::Template(Kind kind)
: mKind{ kind }
@@ -20,26 +20,62 @@ Template::Kind Template::GetKind() const
return mKind;
}
-void TemplateAssetCategory::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const
+void TemplateAssetList::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const
{
auto& gs = GlobalStates::GetInstance();
DiscoverFilesByExtension(callback, gs.GetCurrentProject()->GetTemplatesDirectory(), ".cplt-template"sv);
}
-Template* TemplateAssetCategory::CreateEmpty(const SavedAsset& diskForm) const
+std::string TemplateAssetList::RetrieveNameFromFile(const fs::path& file) const
{
- // TODO
+ std::ifstream ifs(file);
+ if (!ifs) return "";
+
+ std::string name;
+ ifs >> name;
+ return name;
+}
+
+uuids::uuid TemplateAssetList::RetrieveUuidFromFile(const fs::path& file) const
+{
+ return uuids::uuid::from_string(file.stem().string());
}
-Template* TemplateAssetCategory::Load(const SavedAsset& diskForm) const
+fs::path TemplateAssetList::RetrievePathFromAsset(const SavedAsset& asset) const
{
- std::ifstream ifs(diskForm.Path);
+ auto uuid = uuids::uuid_random_generator{}();
+ auto fileName = uuids::to_string(uuid);
+ fileName.append(".cplt-template");
+
+ auto& gs = GlobalStates::GetInstance();
+ return gs.GetCurrentProject()->GetTemplatePath(fileName);
+}
+
+void TemplateAssetList::SaveEmptyInstance(const SavedAsset& asset) const
+{
+ auto path = RetrievePathFromAsset(asset);
+
+ std::ofstream ofs(path);
+ if (!ofs) return;
+ ofs << asset.Name;
+ ofs << static_cast<Template::Kind>(asset.Payload);
+}
+
+Template* TemplateAssetList::CreateEmptyInstance(const SavedAsset& asset) const
+{
+ auto kind = static_cast<Template::Kind>(asset.Payload);
+ return Template::CreateByKind(kind).release();
+}
+
+Template* TemplateAssetList::LoadImpl(const SavedAsset& asset) const
+{
+ std::ifstream ifs(RetrievePathFromAsset(asset));
if (!ifs) return nullptr;
uint32_t iKind;
ifs >> iKind;
- auto kind = (Template::Kind)iKind;
+ auto kind = static_cast<Template::Kind>(iKind);
auto tmpl = Template::CreateByKind(kind);
auto res = tmpl->ReadFrom(ifs);
@@ -50,7 +86,7 @@ Template* TemplateAssetCategory::Load(const SavedAsset& diskForm) const
return tmpl.release();
}
-void TemplateAssetCategory::SetupDetailsTable(const char* tableId) const
+void TemplateAssetList::SetupDetailsTable(const char* tableId) const
{
ImGui::BeginTable(tableId, 3);
@@ -60,19 +96,19 @@ void TemplateAssetCategory::SetupDetailsTable(const char* tableId) const
ImGui::TableHeadersRow();
}
-void TemplateAssetCategory::DrawBigIcon(const SavedAsset& asset) const
+void TemplateAssetList::DrawBigIcon(const SavedAsset& asset) const
{
// TODO
}
-void TemplateAssetCategory::DrawDetailsTableRow(const SavedAsset& asset) const
+void TemplateAssetList::DrawDetailsTableRow(const SavedAsset& asset) const
{
ImGui::TableNextColumn();
ImGui::TextUnformatted(asset.Name.c_str());
ImGui::TableNextColumn();
- // TODO
- //ImGui::TextUnformatted(Template::FormatKind(asset.));
+ auto kind = static_cast<Template::Kind>(asset.Payload);
+ ImGui::TextUnformatted(Template::FormatKind(kind));
ImGui::TableNextColumn();
// TODO
diff --git a/core/src/Model/Template/fwd.hpp b/core/src/Model/Template/fwd.hpp
index aad9f14..b0acb28 100644
--- a/core/src/Model/Template/fwd.hpp
+++ b/core/src/Model/Template/fwd.hpp
@@ -8,4 +8,4 @@ class TableTemplate;
// Template.hpp
class Template;
-class TemplateAssetCategory;
+class TemplateAssetList;
diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp
index 51596e5..8b3db8a 100644
--- a/core/src/Model/Workflow/Workflow.hpp
+++ b/core/src/Model/Workflow/Workflow.hpp
@@ -178,8 +178,8 @@ protected:
class Workflow : public Asset
{
public:
- using CategoryType = WorkflowAssetCategory;
- static constinit const WorkflowAssetCategory Category;
+ using CategoryType = WorkflowAssetList;
+ static constinit const WorkflowAssetList Category;
private:
friend class WorkflowNode;
@@ -276,12 +276,20 @@ private:
std::pair<std::unique_ptr<WorkflowNode>&, size_t> AllocWorkflowStep();
};
-class WorkflowAssetCategory : public AssetCategory
+class WorkflowAssetList final : public AssetListTyped<Workflow>
{
public:
virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const override;
- virtual Workflow* CreateEmpty(const SavedAsset& diskForm) const override;
- virtual Workflow* Load(const SavedAsset& diskForm) const override;
+
+ virtual std::string RetrieveNameFromFile(const std::filesystem::path& file) const override;
+ virtual uuids::uuid RetrieveUuidFromFile(const std::filesystem::path& file) const override;
+ virtual std::filesystem::path RetrievePathFromAsset(const SavedAsset& asset) const override;
+
+ virtual void SaveEmptyInstance(const SavedAsset& asset) const override;
+ virtual Workflow* CreateEmptyInstance(const SavedAsset& diskForm) const override;
+
+ virtual Workflow* LoadImpl(const SavedAsset& diskForm) const override;
+
virtual void SetupDetailsTable(const char* tableId) const override;
virtual void DrawBigIcon(const SavedAsset& asset) const override;
virtual void DrawDetailsTableRow(const SavedAsset& asset) const override;
diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp
index 0875f11..202818f 100644
--- a/core/src/Model/Workflow/Workflow_Main.cpp
+++ b/core/src/Model/Workflow/Workflow_Main.cpp
@@ -6,6 +6,7 @@
#include <imgui.h>
#include <imgui_node_editor.h>
#include <tsl/robin_set.h>
+#include <uuid.h>
#include <cassert>
#include <fstream>
#include <iostream>
@@ -13,6 +14,7 @@
#include <utility>
using namespace std::literals::string_view_literals;
+namespace fs = std::filesystem;
namespace ImNodes = ax::NodeEditor;
WorkflowConnection::WorkflowConnection()
@@ -324,51 +326,6 @@ void WorkflowNode::OnDetach()
{
}
-constinit const WorkflowAssetCategory Workflow::Category{};
-
-void WorkflowAssetCategory::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const
-{
- auto& gs = GlobalStates::GetInstance();
- DiscoverFilesByExtension(callback, gs.GetCurrentProject()->GetWorkflowsDirectory(), ".cplt-workflow"sv);
-}
-
-Workflow* WorkflowAssetCategory::CreateEmpty(const SavedAsset& diskForm) const
-{
- // TODO
-}
-
-Workflow* WorkflowAssetCategory::Load(const SavedAsset& diskForm) const
-{
- std::ifstream ifs(diskForm.Path);
- if (!ifs) return nullptr;
-
- auto workflow = std::make_unique<Workflow>();
- if (workflow->ReadFrom(ifs) != Workflow::RR_Success) {
- return nullptr;
- }
-
- return workflow.release();
-}
-
-void WorkflowAssetCategory::SetupDetailsTable(const char* tableId) const
-{
- ImGui::BeginTable(tableId, 2);
-
- ImGui::TableSetupColumn("Name");
- ImGui::TableSetupColumn("Modified time");
- ImGui::TableHeadersRow();
-}
-
-void WorkflowAssetCategory::DrawBigIcon(const SavedAsset& asset) const
-{
- // TODO
-}
-
-void WorkflowAssetCategory::DrawDetailsTableRow(const SavedAsset& asset) const
-{
- // TODO
-}
-
const std::vector<WorkflowConnection>& Workflow::GetConnections() const
{
return mConnections;
@@ -753,16 +710,6 @@ void Workflow::WriteTo(std::ostream& stream)
}
}
-void Workflow::DrawBigIcon() const
-{
- // TODO
-}
-
-void Workflow::DrawDetailTableRow() const
-{
- // TODO
-}
-
std::pair<WorkflowConnection&, size_t> Workflow::AllocWorkflowConnection()
{
for (size_t idx = 0; idx < mConnections.size(); ++idx) {
@@ -793,3 +740,80 @@ std::pair<std::unique_ptr<WorkflowNode>&, size_t> Workflow::AllocWorkflowStep()
return { node, id };
}
+
+void WorkflowAssetList::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const
+{
+ auto& gs = GlobalStates::GetInstance();
+ DiscoverFilesByExtension(callback, gs.GetCurrentProject()->GetWorkflowsDirectory(), ".cplt-workflow"sv);
+}
+
+std::string WorkflowAssetList::RetrieveNameFromFile(const fs::path& file) const
+{
+ std::ifstream ifs(file);
+ if (!ifs) return "";
+
+ std::string name;
+ ifs >> name;
+ return 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 uuid = uuids::uuid_random_generator{}();
+ auto fileName = uuids::to_string(uuid);
+ fileName.append(".cplt-workflow");
+
+ auto& gs = GlobalStates::GetInstance();
+ return gs.GetCurrentProject()->GetTemplatePath(fileName);
+}
+
+void WorkflowAssetList::SaveEmptyInstance(const SavedAsset& asset) const
+{
+ auto path = RetrievePathFromAsset(asset);
+
+ std::ofstream ofs(path);
+ if (!ofs) return;
+ ofs << asset.Name;
+}
+
+Workflow* WorkflowAssetList::CreateEmptyInstance(const SavedAsset& asset) const
+{
+ return new Workflow();
+}
+
+Workflow* WorkflowAssetList::LoadImpl(const SavedAsset& asset) const
+{
+ std::ifstream ifs(RetrievePathFromAsset(asset));
+ if (!ifs) return nullptr;
+
+ auto workflow = std::make_unique<Workflow>();
+ if (workflow->ReadFrom(ifs) != Workflow::RR_Success) {
+ return nullptr;
+ }
+
+ return workflow.release();
+}
+
+void WorkflowAssetList::SetupDetailsTable(const char* tableId) const
+{
+ ImGui::BeginTable(tableId, 2);
+
+ ImGui::TableSetupColumn("Name");
+ ImGui::TableSetupColumn("Modified time");
+ ImGui::TableHeadersRow();
+}
+
+void WorkflowAssetList::DrawBigIcon(const SavedAsset& asset) const
+{
+ // TODO
+}
+
+void WorkflowAssetList::DrawDetailsTableRow(const SavedAsset& asset) const
+{
+ // TODO
+}
diff --git a/core/src/Model/Workflow/fwd.hpp b/core/src/Model/Workflow/fwd.hpp
index 8f0263d..ed39bdb 100644
--- a/core/src/Model/Workflow/fwd.hpp
+++ b/core/src/Model/Workflow/fwd.hpp
@@ -19,4 +19,4 @@ class BaseObjectValue;
class WorkflowConnection;
class WorkflowNode;
class Workflow;
-class WorkflowAssetCategory;
+class WorkflowAssetList;
diff --git a/core/src/Model/fwd.hpp b/core/src/Model/fwd.hpp
index ba7b156..2028cbb 100644
--- a/core/src/Model/fwd.hpp
+++ b/core/src/Model/fwd.hpp
@@ -13,10 +13,7 @@ class MainDatabase;
// Assets.hpp
struct SavedAsset;
class Asset;
-class AssetCategory;
class AssetList;
-template <class T>
-class TypedAssetList;
// Filter.hpp
class TableRowsFilter;
diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp
index 7ebb9e1..def50d9 100644
--- a/core/src/UI/UI_Templates.cpp
+++ b/core/src/UI/UI_Templates.cpp
@@ -140,7 +140,7 @@ void UI::TemplatesTab()
bool openedDummy = true;
static std::unique_ptr<TemplateUI> openTemplate;
- static AssetList::DrawState state;
+ static AssetList::ListState state;
// Toolbar item: close
if (ImGui::Button(ls->Close.Get(), openTemplate == nullptr)) {
@@ -156,8 +156,8 @@ void UI::TemplatesTab()
project.Templates.DrawDetails(state);
if (state.SelectedAsset) {
- auto kind = state.SelectedAsset->Kind;
- auto tmpl = state.SelectedAsset->LoadFromDisk();
+ auto kind = static_cast<Template::Kind>(state.SelectedAsset->Payload);
+ auto tmpl = project.Templates.Load(*state.SelectedAsset);
openTemplate = TemplateUI::CreateByKind(kind, std::move(tmpl));
}
@@ -186,8 +186,7 @@ void UI::TemplatesTab()
newNameError = NameSelectionError::Empty;
}
- auto& templates = gs.GetCurrentProject()->GetTemplates();
- if (templates.find(newName) != templates.end()) {
+ if (project.Templates.FindByName(newName)) {
newNameError = NameSelectionError::Duplicated;
}
};
@@ -233,13 +232,10 @@ void UI::TemplatesTab()
}
if (ImGui::Button(ls->DialogConfirm.Get(), IsInputValid())) {
- project.InsertTemplate(
- newName,
- TemplateInfo{
- .Path = project.GetTemplatePath(newName),
- .Name = newName, // Don't std::move here because evaluation order of `newName` (as parameter of InsertTemplate()) and this is unspecified
- .Kind = newKind,
- });
+ project.Templates.Create(SavedAsset{
+ .Name = newName,
+ .Payload = static_cast<uint64_t>(newKind),
+ });
openTemplate = TemplateUI::CreateByKind(newKind);
}
@@ -255,7 +251,7 @@ void UI::TemplatesTab()
}
ImGui::SameLine();
- if (ImGui::Button(ls->Rename.Get(), state.SelectedTemplate == nullptr)) {
+ if (ImGui::Button(ls->Rename.Get(), state.SelectedAsset == nullptr)) {
ImGui::OpenPopup("Rename template");
newName.clear();
}
@@ -265,14 +261,12 @@ void UI::TemplatesTab()
}
if (ImGui::Button(ls->DialogConfirm.Get(), IsInputValid())) {
- auto& project = *gs.GetCurrentProject();
-
- project.Templates.Rename(
- state.SelectedTemplate->Name,
+ auto tmpl = project.Templates.Rename(
+ state.SelectedAsset->Name,
newName);
- // We mutated the map, the pointer may be invalid now
- state.SelectedTemplate = &project.GetTemplates().at(newName);
+ // Update the selected pointer to the new location (we mutated the map, the pointer may be invalid now)
+ state.SelectedAsset = tmpl;
}
ImGui::SameLine();
if (ImGui::Button(ls->DialogCancel.Get())) {
@@ -285,14 +279,15 @@ void UI::TemplatesTab()
}
ImGui::SameLine();
- if (ImGui::Button(ls->Delete.Get(), state.SelectedTemplate == nullptr)) {
+ if (ImGui::Button(ls->Delete.Get(), state.SelectedAsset == nullptr)) {
ImGui::OpenPopup("Delete confirmation");
}
if (ImGui::BeginPopupModal("Delete confirmation")) {
- assert(state.SelectedTemplate != nullptr);
-
if (ImGui::Button(ls->DialogConfirm.Get())) {
- gs.GetCurrentProject()->RemoveTemplate(state.SelectedTemplate->Name);
+ auto& assetName = state.SelectedAsset->Name;
+ project.Templates.Remove(assetName);
+
+ state.SelectedAsset = nullptr;
}
ImGui::SameLine();
if (ImGui::Button(ls->DialogCancel.Get())) {
diff --git a/core/src/UI/UI_Workflows.cpp b/core/src/UI/UI_Workflows.cpp
index 51cc4f8..7b2de2a 100644
--- a/core/src/UI/UI_Workflows.cpp
+++ b/core/src/UI/UI_Workflows.cpp
@@ -358,39 +358,17 @@ public:
ImNodes::End();
}
};
-
-struct DrawTemplateList_State
-{
- const WorkflowInfo* SelectedWorkflow = nullptr;
-};
-
-void DrawTemplateList(DrawTemplateList_State& state)
-{
- auto& gs = GlobalStates::GetInstance();
- auto& workflows = gs.GetCurrentProject()->GetWorkflows();
-
- // TODO sort the list
- for (auto& info : workflows) {
- if (ImGui::Selectable(info.Name.c_str(), state.SelectedWorkflow == &info)) {
- state.SelectedWorkflow = &info;
- }
- if (ImGui::IsItemHovered()) {
- ImGui::BeginTooltip();
- ImGui::Text("Path: %s", info.PathStringCache.c_str());
- ImGui::EndTooltip();
- }
- }
-}
} // namespace
void UI::WorkflowsTab()
{
auto ls = LocaleStrings::Instance.get();
auto& gs = GlobalStates::GetInstance();
+ auto& project = *gs.GetCurrentProject();
bool openedDummy = true;
static std::unique_ptr<WorkflowUI> openWorkflow;
- static DrawTemplateList_State state;
+ static AssetList::ListState state;
// Toolbar item: close
if (ImGui::Button(ls->Close.Get(), openWorkflow == nullptr)) {
@@ -403,10 +381,10 @@ void UI::WorkflowsTab()
ImGui::OpenPopup(ls->OpenWorkflowDialogTitle.Get());
}
if (ImGui::BeginPopupModal(ls->OpenWorkflowDialogTitle.Get(), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- DrawTemplateList(state);
+ project.Workflows.DrawDetails(state);
- if (state.SelectedWorkflow) {
- auto workflow = state.SelectedWorkflow->LoadFromDisk();
+ if (state.SelectedAsset) {
+ auto workflow = project.Workflows.Load(*state.SelectedAsset);
openWorkflow = std::make_unique<WorkflowUI>(std::move(workflow));
}
@@ -419,7 +397,7 @@ void UI::WorkflowsTab()
ImGui::OpenPopup(ls->ManageWorkflowsDialogTitle.Get());
}
if (ImGui::BeginPopupModal(ls->ManageWorkflowsDialogTitle.Get(), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- DrawTemplateList(state);
+ project.Workflows.DrawDetails(state);
enum class NameSelectionError
{
@@ -429,7 +407,7 @@ void UI::WorkflowsTab()
};
static std::string newName;
static NameSelectionError newNameError;
- if (ImGui::Button(ls->Rename.Get(), state.SelectedWorkflow == nullptr)) {
+ if (ImGui::Button(ls->Rename.Get(), state.SelectedAsset == nullptr)) {
ImGui::OpenPopup("Rename workflow");
newName.clear();
}
@@ -439,16 +417,17 @@ void UI::WorkflowsTab()
newNameError = NameSelectionError::Empty;
}
- auto& workflows = gs.GetCurrentProject()->GetWorkflows();
- if (workflows.find(newName) != workflows.end()) {
+ if (project.Workflows.FindByName(newName)) {
newNameError = NameSelectionError::Duplicated;
}
}
if (ImGui::Button(ls->DialogConfirm.Get(), newName.empty())) {
- auto project = gs.GetCurrentProject();
- project->RenameWorkflow(state.SelectedWorkflow->Name, newName);
- state.SelectedWorkflow = &project->GetWorkflows().at(newName);
+ auto workflow = project.Workflows.Rename(
+ state.SelectedAsset->Name,
+ newName);
+
+ state.SelectedAsset = workflow;
}
ImGui::SameLine();
if (ImGui::Button(ls->DialogCancel.Get())) {
@@ -468,12 +447,15 @@ void UI::WorkflowsTab()
ImGui::EndPopup();
}
- if (ImGui::Button(ls->Delete.Get(), state.SelectedWorkflow == nullptr)) {
+ if (ImGui::Button(ls->Delete.Get(), state.SelectedAsset == nullptr)) {
ImGui::OpenPopup("Delete confirmation");
}
if (ImGui::BeginPopupModal("Delete confirmation")) {
if (ImGui::Button(ls->DialogConfirm.Get())) {
- gs.GetCurrentProject()->RemoveWorkflow(state.SelectedWorkflow->Name);
+ auto& assetName = state.SelectedAsset->Name;
+ project.Workflows.Remove(assetName);
+
+ state.SelectedAsset = nullptr;
}
ImGui::SameLine();
if (ImGui::Button(ls->DialogCancel.Get())) {