summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/Model/Assets.cpp187
-rw-r--r--core/src/Model/Assets.hpp41
-rw-r--r--core/src/Model/Template/Template.hpp12
-rw-r--r--core/src/Model/Template/Template_Main.cpp96
-rw-r--r--core/src/Model/Workflow/Workflow.hpp11
-rw-r--r--core/src/Model/Workflow/Workflow_Main.cpp74
-rw-r--r--core/src/Model/fwd.hpp1
-rw-r--r--core/src/UI/UI_Templates.cpp168
-rw-r--r--core/src/UI/UI_Workflows.cpp107
9 files changed, 429 insertions, 268 deletions
diff --git a/core/src/Model/Assets.cpp b/core/src/Model/Assets.cpp
index a1e9730..0e53537 100644
--- a/core/src/Model/Assets.cpp
+++ b/core/src/Model/Assets.cpp
@@ -1,7 +1,13 @@
#include "Assets.hpp"
+#include "UI/Localization.hpp"
+#include "UI/UI.hpp"
+
#include <imgui.h>
+#include <imgui_stdlib.h>
+#include <tsl/array_map.h>
#include <fstream>
+#include <string>
#include <utility>
using namespace std::literals::string_view_literals;
@@ -11,6 +17,63 @@ Asset::Asset()
{
}
+class AssetList::Private
+{
+public:
+ tsl::array_map<char, SavedAsset> Assets;
+ tsl::array_map<char, std::unique_ptr<Asset>> Cache;
+ int CacheSizeLimit = 0;
+
+ struct
+ {
+ std::string NewName;
+ NameSelectionError NewNameError = NameSelectionError::Empty;
+
+ void ShowErrors() const
+ {
+ switch (NewNameError) {
+ case NameSelectionError::None: break;
+ case NameSelectionError::Duplicated:
+ ImGui::ErrorMessage("Duplicate template name");
+ break;
+ case NameSelectionError::Empty:
+ ImGui::ErrorMessage("Template name cannot be empty");
+ break;
+ }
+ }
+
+ bool HasErrors() const
+ {
+ return NewNameError != NameSelectionError::None;
+ }
+
+ void Validate(const AssetList& self)
+ {
+ if (NewName.empty()) {
+ NewNameError = NameSelectionError::Empty;
+ return;
+ }
+
+ if (self.FindByName(NewName)) {
+ NewNameError = NameSelectionError::Duplicated;
+ return;
+ }
+
+ NewNameError = NameSelectionError::None;
+ }
+ } PopupPrivateState;
+};
+
+AssetList::AssetList()
+ : mPrivate{ std::make_unique<Private>() }
+{
+}
+
+// Write an empty destructor here so std::unique_ptr's destructor can see AssetList::Private's implementation
+AssetList::~AssetList()
+{
+}
+
void AssetList::Reload()
{
DiscoverFiles([this](SavedAsset asset) -> void {
@@ -20,8 +83,8 @@ void AssetList::Reload()
const SavedAsset* AssetList::FindByName(std::string_view name) const
{
- auto iter = mAssets.find(name);
- if (iter != mAssets.end()) {
+ auto iter = mPrivate->Assets.find(name);
+ if (iter != mPrivate->Assets.end()) {
return &iter.value();
} else {
return nullptr;
@@ -30,7 +93,7 @@ const SavedAsset* AssetList::FindByName(std::string_view name) const
const SavedAsset& AssetList::Create(SavedAsset asset)
{
- auto [iter, DISCARD] = mAssets.insert(asset.Name, SavedAsset{});
+ auto [iter, DISCARD] = mPrivate->Assets.insert(asset.Name, SavedAsset{});
auto& savedAsset = iter.value();
savedAsset = std::move(asset);
@@ -67,57 +130,85 @@ std::unique_ptr<Asset> AssetList::Load(const SavedAsset& asset) const
const SavedAsset* AssetList::Rename(std::string_view oldName, std::string_view newName)
{
- auto iter = mAssets.find(oldName);
- if (iter == mAssets.end()) return nullptr;
+ auto iter = mPrivate->Assets.find(oldName);
+ if (iter == mPrivate->Assets.end()) return nullptr;
auto info = std::move(iter.value());
info.Name = newName;
- auto [newIter, DISCARD] = mAssets.insert(newName, std::move(info));
- mAssets.erase(iter);
+ auto [newIter, DISCARD] = mPrivate->Assets.insert(newName, std::move(info));
+ mPrivate->Assets.erase(iter);
return &newIter.value();
}
bool AssetList::Remove(std::string_view name)
{
- auto iter = mAssets.find(name);
- if (iter == mAssets.end()) {
+ auto iter = mPrivate->Assets.find(name);
+ if (iter == mPrivate->Assets.end()) {
return false;
}
auto& asset = iter.value();
fs::remove(RetrievePathFromAsset(asset));
- mAssets.erase(iter);
+ mPrivate->Assets.erase(iter);
return true;
}
int AssetList::GetCacheSizeLimit() const
{
- return mCacheSizeLimit;
+ return mPrivate->CacheSizeLimit;
}
void AssetList::SetCacheSizeLimit(int limit)
{
- mCacheSizeLimit = limit;
+ mPrivate->CacheSizeLimit = limit;
}
-void AssetList::DrawBigIcons(ListState& state)
+void AssetList::DisplayBigIconsList(ListState& state)
{
// TODO
}
-void AssetList::DrawDetails(ListState& state)
+void AssetList::DisplayDetailsTable(ListState& state)
{
SetupDetailsTable("AssetDetailsTable");
- for (auto& asset : mAssets) {
- DrawDetailsTableRow(asset);
+ for (auto& asset : mPrivate->Assets) {
+ DrawDetailsTableRow(state, asset);
ImGui::TableNextRow();
}
ImGui::EndTable();
}
+void AssetList::OpenBigIconsPopup()
+{
+ ImGui::OpenPopup("Manage assets##BigIcons");
+}
+
+void AssetList::DisplayBigIconsPopup(PopupState& state)
+{
+ if (ImGui::BeginPopupModal("Manage assets##BigIcons")) {
+ DisplayBigIconsList(state);
+ DisplayPopupControls(state);
+ ImGui::EndPopup();
+ }
+}
+
+void AssetList::OpenDetailsPopup()
+{
+ ImGui::OpenPopup("Manage assets##Details");
+}
+
+void AssetList::DisplayDetailsPopup(PopupState& state)
+{
+ if (ImGui::BeginPopupModal("Manage assets##Details")) {
+ DisplayBigIconsList(state);
+ DisplayPopupControls(state);
+ ImGui::EndPopup();
+ }
+}
+
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)) {
@@ -142,3 +233,67 @@ void AssetList::DiscoverFilesByHeader(const std::function<void(SavedAsset)>& cal
{
// TODO
}
+
+void AssetList::DisplayPopupControls(PopupState& state)
+{
+ auto& ps = mPrivate->PopupPrivateState;
+ auto ls = LocaleStrings::Instance.get();
+
+ bool openedDummy = false;
+
+ if (ImGui::Button(ls->Add.Get())) {
+ ImGui::OpenPopup("Create template");
+ }
+ if (ImGui::BeginPopupModal("Create template", &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
+ DisplayAssetCreator(state);
+ ImGui::EndPopup();
+ }
+
+ ImGui::SameLine();
+ if (ImGui::Button(ls->Rename.Get(), state.SelectedAsset == nullptr)) {
+ ImGui::OpenPopup("Rename template");
+ }
+ if (ImGui::BeginPopupModal("Rename template")) {
+ if (ImGui::InputText("New name", &ps.NewName)) {
+ ps.Validate(*this);
+ }
+
+ if (ImGui::Button(ls->DialogConfirm.Get(), ps.HasErrors())) {
+ ImGui::CloseCurrentPopup();
+
+ auto movedAsset = Rename(state.SelectedAsset->Name, ps.NewName);
+ // Update the selected pointer to the new location (we mutated the map, the pointer may be invalid now)
+ state.SelectedAsset = movedAsset;
+
+ ps = {};
+ }
+ ImGui::SameLine();
+ if (ImGui::Button(ls->DialogCancel.Get())) {
+ ImGui::CloseCurrentPopup();
+ }
+
+ ps.ShowErrors();
+
+ ImGui::EndPopup();
+ }
+
+ ImGui::SameLine();
+ if (ImGui::Button(ls->Delete.Get(), state.SelectedAsset == nullptr)) {
+ ImGui::OpenPopup("Delete confirmation");
+ }
+ if (ImGui::BeginPopupModal("Delete confirmation")) {
+ if (ImGui::Button(ls->DialogConfirm.Get())) {
+ ImGui::CloseCurrentPopup();
+
+ auto& assetName = state.SelectedAsset->Name;
+ Remove(assetName);
+
+ state.SelectedAsset = nullptr;
+ }
+ ImGui::SameLine();
+ if (ImGui::Button(ls->DialogCancel.Get())) {
+ ImGui::CloseCurrentPopup();
+ }
+ ImGui::EndPopup();
+ }
+}
diff --git a/core/src/Model/Assets.hpp b/core/src/Model/Assets.hpp
index feb4432..e035f51 100644
--- a/core/src/Model/Assets.hpp
+++ b/core/src/Model/Assets.hpp
@@ -1,8 +1,9 @@
-#pragma once
+#pragma once
#include "Utils/UUID.hpp"
-#include <tsl/array_map.h>
+#include "Assets.hpp"
+
#include <filesystem>
#include <iosfwd>
#include <memory>
@@ -27,15 +28,22 @@ public:
virtual ~Asset() = default;
};
+enum class NameSelectionError
+{
+ None,
+ Duplicated,
+ Empty,
+};
+
class AssetList
{
private:
- tsl::array_map<char, SavedAsset> mAssets;
- tsl::array_map<char, std::unique_ptr<Asset>> mCache;
- int mCacheSizeLimit = 0;
+ class Private;
+ std::unique_ptr<Private> mPrivate;
public:
- virtual ~AssetList() = default;
+ AssetList();
+ virtual ~AssetList();
// TODO support file watches
void Reload();
@@ -58,8 +66,16 @@ public:
{
const SavedAsset* SelectedAsset = nullptr;
};
- void DrawBigIcons(ListState& state);
- void DrawDetails(ListState& state);
+ void DisplayBigIconsList(ListState& state);
+ void DisplayDetailsTable(ListState& state);
+
+ struct PopupState : public ListState
+ {
+ };
+ void OpenBigIconsPopup();
+ void DisplayBigIconsPopup(PopupState& state);
+ void OpenDetailsPopup();
+ void DisplayDetailsPopup(PopupState& state);
protected:
virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const = 0;
@@ -77,10 +93,15 @@ protected:
virtual uuids::uuid RetrieveUuidFromFile(const std::filesystem::path& file) const = 0;
virtual std::filesystem::path RetrievePathFromAsset(const SavedAsset& asset) const = 0;
+ virtual void DisplayAssetCreator(PopupState& state) = 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;
+ virtual void DrawBigIcon(ListState& state, const SavedAsset& asset) const = 0;
+ virtual void DrawDetailsTableRow(ListState& state, const SavedAsset& asset) const = 0;
+
+private:
+ void DisplayPopupControls(PopupState& state);
};
template <class T>
diff --git a/core/src/Model/Template/Template.hpp b/core/src/Model/Template/Template.hpp
index 600bb26..fdac574 100644
--- a/core/src/Model/Template/Template.hpp
+++ b/core/src/Model/Template/Template.hpp
@@ -46,6 +46,12 @@ public:
class TemplateAssetList final : public AssetListTyped<Template>
{
+private:
+ // AC = Asset Creator
+ std::string mACNewName;
+ NameSelectionError mACNewNameError = NameSelectionError::Empty;
+ Template::Kind mACNewKind = Template::InvalidKind;
+
protected:
virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const override;
@@ -58,7 +64,9 @@ protected:
virtual Template* LoadImpl(const SavedAsset& diskForm) const override;
+ virtual void DisplayAssetCreator(PopupState& state) 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;
+ virtual void DrawBigIcon(ListState& state, const SavedAsset& asset) const override;
+ virtual void DrawDetailsTableRow(ListState& state, const SavedAsset& asset) const override;
};
diff --git a/core/src/Model/Template/Template_Main.cpp b/core/src/Model/Template/Template_Main.cpp
index 9bebc21..ebec490 100644
--- a/core/src/Model/Template/Template_Main.cpp
+++ b/core/src/Model/Template/Template_Main.cpp
@@ -2,9 +2,12 @@
#include "Model/GlobalStates.hpp"
#include "Model/Project.hpp"
+#include "UI/Localization.hpp"
+#include "UI/UI.hpp"
#include "Utils/UUID.hpp"
#include <imgui.h>
+#include <imgui_stdlib.h>
#include <fstream>
using namespace std::literals::string_view_literals;
@@ -86,30 +89,107 @@ Template* TemplateAssetList::LoadImpl(const SavedAsset& asset) const
return tmpl.release();
}
+void TemplateAssetList::DisplayAssetCreator(PopupState& state)
+{
+ auto ls = LocaleStrings::Instance.get();
+
+ 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("Duplicate template name");
+ break;
+ case NameSelectionError::Empty:
+ ImGui::ErrorMessage("Template name cannot be empty");
+ break;
+ }
+ };
+
+ auto ShowNewKindErrors = [&]() -> void {
+ if (mACNewKind == Template::InvalidKind) {
+ ImGui::ErrorMessage("Must select a valid template type");
+ }
+ };
+
+ auto IsInputValid = [&]() -> bool {
+ return mACNewNameError == NameSelectionError::None &&
+ mACNewKind != Template::InvalidKind;
+ };
+
+ auto ResetState = [&]() -> void {
+ mACNewName.clear();
+ mACNewKind = Template::InvalidKind;
+ ValidateNewName();
+ };
+
+ if (ImGui::InputText("Name", &mACNewName)) {
+ ValidateNewName();
+ }
+
+ if (ImGui::BeginCombo("Type", Template::FormatKind(mACNewKind))) {
+ for (int i = 0; i < Template::KindCount; ++i) {
+ auto kind = static_cast<Template::Kind>(i);
+ if (ImGui::Selectable(Template::FormatKind(kind), mACNewKind == kind)) {
+ mACNewKind = kind;
+ }
+ }
+ ImGui::EndCombo();
+ }
+
+ ShowNewNameErrors();
+ ShowNewKindErrors();
+
+ if (ImGui::Button(ls->DialogConfirm.Get(), !IsInputValid())) {
+ ImGui::CloseCurrentPopup();
+
+ Create(SavedAsset{
+ .Name = mACNewName,
+ .Payload = static_cast<uint64_t>(mACNewKind),
+ });
+ ResetState();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button(ls->DialogCancel.Get())) {
+ ImGui::CloseCurrentPopup();
+ }
+}
+
void TemplateAssetList::SetupDetailsTable(const char* tableId) const
{
- ImGui::BeginTable(tableId, 3);
+ ImGui::BeginTable(tableId, 2, ImGuiTableFlags_Borders);
ImGui::TableSetupColumn("Name");
ImGui::TableSetupColumn("Type");
- ImGui::TableSetupColumn("Modified time");
ImGui::TableHeadersRow();
}
-void TemplateAssetList::DrawBigIcon(const SavedAsset& asset) const
+void TemplateAssetList::DrawBigIcon(ListState& state, const SavedAsset& asset) const
{
// TODO
}
-void TemplateAssetList::DrawDetailsTableRow(const SavedAsset& asset) const
+void TemplateAssetList::DrawDetailsTableRow(ListState& state, const SavedAsset& asset) const
{
ImGui::TableNextColumn();
- ImGui::TextUnformatted(asset.Name.c_str());
+ if (ImGui::Selectable(asset.Name.c_str(), state.SelectedAsset == &asset, ImGuiSelectableFlags_SpanAllColumns)) {
+ state.SelectedAsset = &asset;
+ }
ImGui::TableNextColumn();
auto kind = static_cast<Template::Kind>(asset.Payload);
ImGui::TextUnformatted(Template::FormatKind(kind));
-
- ImGui::TableNextColumn();
- // TODO
}
diff --git a/core/src/Model/Workflow/Workflow.hpp b/core/src/Model/Workflow/Workflow.hpp
index e5e434a..95dcafe 100644
--- a/core/src/Model/Workflow/Workflow.hpp
+++ b/core/src/Model/Workflow/Workflow.hpp
@@ -277,6 +277,11 @@ private:
class WorkflowAssetList final : public AssetListTyped<Workflow>
{
+private:
+ // AC = Asset Creator
+ std::string mACNewName;
+ NameSelectionError mACNewNameError = NameSelectionError::Empty;
+
public:
virtual void DiscoverFiles(const std::function<void(SavedAsset)>& callback) const override;
@@ -289,7 +294,9 @@ public:
virtual Workflow* LoadImpl(const SavedAsset& diskForm) const override;
+ virtual void DisplayAssetCreator(PopupState& state) 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;
+ virtual void DrawBigIcon(ListState& state, const SavedAsset& asset) const override;
+ virtual void DrawDetailsTableRow(ListState& state, const SavedAsset& asset) const override;
};
diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp
index 131e0ae..99c70a7 100644
--- a/core/src/Model/Workflow/Workflow_Main.cpp
+++ b/core/src/Model/Workflow/Workflow_Main.cpp
@@ -2,10 +2,13 @@
#include "Model/GlobalStates.hpp"
#include "Model/Project.hpp"
+#include "UI/Localization.hpp"
+#include "UI/UI.hpp"
#include "Utils/UUID.hpp"
#include <imgui.h>
#include <imgui_node_editor.h>
+#include <imgui_stdlib.h>
#include <tsl/robin_set.h>
#include <cassert>
#include <fstream>
@@ -799,21 +802,82 @@ Workflow* WorkflowAssetList::LoadImpl(const SavedAsset& asset) const
return workflow.release();
}
+void WorkflowAssetList::DisplayAssetCreator(PopupState& state)
+{
+ auto ls = LocaleStrings::Instance.get();
+
+ 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("Duplicate template name");
+ break;
+ case NameSelectionError::Empty:
+ ImGui::ErrorMessage("Template name cannot be empty");
+ break;
+ }
+ };
+
+ auto IsInputValid = [&]() -> bool {
+ return mACNewNameError == NameSelectionError::None;
+ };
+
+ auto ResetState = [&]() -> void {
+ mACNewName.clear();
+ ValidateNewName();
+ };
+
+ if (ImGui::InputText("Name", &mACNewName)) {
+ ValidateNewName();
+ }
+
+ ShowNewNameErrors();
+
+ if (ImGui::Button(ls->DialogConfirm.Get(), !IsInputValid())) {
+ ImGui::CloseCurrentPopup();
+
+ Create(SavedAsset{
+ .Name = mACNewName,
+ });
+ ResetState();
+ }
+ ImGui::SameLine();
+ if (ImGui::Button(ls->DialogCancel.Get())) {
+ ImGui::CloseCurrentPopup();
+ }
+}
+
void WorkflowAssetList::SetupDetailsTable(const char* tableId) const
{
- ImGui::BeginTable(tableId, 2);
+ ImGui::BeginTable(tableId, 1, ImGuiTableFlags_Borders);
ImGui::TableSetupColumn("Name");
- ImGui::TableSetupColumn("Modified time");
ImGui::TableHeadersRow();
}
-void WorkflowAssetList::DrawBigIcon(const SavedAsset& asset) const
+void WorkflowAssetList::DrawBigIcon(ListState& state, const SavedAsset& asset) const
{
// TODO
}
-void WorkflowAssetList::DrawDetailsTableRow(const SavedAsset& asset) const
+void WorkflowAssetList::DrawDetailsTableRow(ListState& state, const SavedAsset& asset) const
{
- // TODO
+ ImGui::TableNextColumn();
+ if (ImGui::Selectable(asset.Name.c_str(), state.SelectedAsset == &asset, ImGuiSelectableFlags_SpanAllColumns)) {
+ state.SelectedAsset = &asset;
+ }
}
diff --git a/core/src/Model/fwd.hpp b/core/src/Model/fwd.hpp
index 2028cbb..358fc49 100644
--- a/core/src/Model/fwd.hpp
+++ b/core/src/Model/fwd.hpp
@@ -13,6 +13,7 @@ class MainDatabase;
// Assets.hpp
struct SavedAsset;
class Asset;
+enum class NameSelectionError;
class AssetList;
// Filter.hpp
diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp
index def50d9..d48e8bf 100644
--- a/core/src/UI/UI_Templates.cpp
+++ b/core/src/UI/UI_Templates.cpp
@@ -1,4 +1,4 @@
-#include "UI.hpp"
+#include "UI.hpp"
#include "Model/GlobalStates.hpp"
#include "Model/Project.hpp"
@@ -135,12 +135,18 @@ std::unique_ptr<TemplateUI> TemplateUI::CreateByKind(Template::Kind kind)
void UI::TemplatesTab()
{
auto ls = LocaleStrings::Instance.get();
- auto& gs = GlobalStates::GetInstance();
- auto& project = *gs.GetCurrentProject();
+ auto& project = *GlobalStates::GetInstance().GetCurrentProject();
+
+ enum class PopupType
+ {
+ None,
+ TemplateSelect,
+ Management,
+ };
- bool openedDummy = true;
static std::unique_ptr<TemplateUI> openTemplate;
- static AssetList::ListState state;
+ static AssetList::PopupState popup;
+ static PopupType popupType = PopupType::None;
// Toolbar item: close
if (ImGui::Button(ls->Close.Get(), openTemplate == nullptr)) {
@@ -150,153 +156,29 @@ void UI::TemplatesTab()
// Toolbar item: open...
ImGui::SameLine();
if (ImGui::Button("Open...")) {
- ImGui::OpenPopup("Open template");
- }
- if (ImGui::BeginPopupModal("Open template", &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- project.Templates.DrawDetails(state);
-
- if (state.SelectedAsset) {
- auto kind = static_cast<Template::Kind>(state.SelectedAsset->Payload);
- auto tmpl = project.Templates.Load(*state.SelectedAsset);
- openTemplate = TemplateUI::CreateByKind(kind, std::move(tmpl));
- }
-
- ImGui::EndPopup();
+ project.Templates.OpenDetailsPopup();
+ popupType = PopupType::TemplateSelect;
}
// Toolbar item: manage...
ImGui::SameLine();
if (ImGui::Button("Manage...")) {
- ImGui::OpenPopup("Manage templates");
+ project.Templates.OpenDetailsPopup();
+ popupType = PopupType::Management;
}
- if (ImGui::BeginPopupModal("Manage templates", &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- project.Templates.DrawDetails(state);
-
- enum class NameSelectionError
- {
- None,
- Duplicated,
- Empty,
- };
-
- static std::string newName;
- static NameSelectionError newNameError;
- auto ValidateNewName = [&]() -> void {
- if (newName.empty()) {
- newNameError = NameSelectionError::Empty;
- }
-
- if (project.Templates.FindByName(newName)) {
- newNameError = NameSelectionError::Duplicated;
- }
- };
- auto ShowNewNameErrors = [&]() -> void {
- switch (newNameError) {
- case NameSelectionError::None: break;
- case NameSelectionError::Duplicated:
- ImGui::ErrorMessage("Duplicate template name");
- break;
- case NameSelectionError::Empty:
- ImGui::ErrorMessage("Template name cannot be empty");
- break;
- }
- };
-
- static Template::Kind newKind = Template::InvalidKind;
- auto ShowNewKindErrors = [&]() -> void {
- if (newKind == Template::InvalidKind) {
- ImGui::ErrorMessage("Must select a valid template type");
- }
- };
-
- auto IsInputValid = [&]() -> bool {
- return newNameError == NameSelectionError::None && newKind != Template::InvalidKind;
- };
-
- if (ImGui::Button(ls->Add.Get())) {
- ImGui::OpenPopup("Create template");
- }
- if (ImGui::BeginPopupModal("Create template")) {
- if (ImGui::InputText("Name", &newName)) {
- ValidateNewName();
- }
-
- if (ImGui::BeginCombo("Type", Template::FormatKind(newKind))) {
- for (int i = 0; i < Template::KindCount; ++i) {
- auto kind = static_cast<Template::Kind>(i);
- if (ImGui::Selectable(Template::FormatKind(kind), newKind == kind)) {
- newKind = kind;
- }
- }
- ImGui::EndCombo();
- }
-
- if (ImGui::Button(ls->DialogConfirm.Get(), IsInputValid())) {
- project.Templates.Create(SavedAsset{
- .Name = newName,
- .Payload = static_cast<uint64_t>(newKind),
- });
- openTemplate = TemplateUI::CreateByKind(newKind);
+ switch (popupType) {
+ case PopupType::TemplateSelect:
+ if (ImGui::Button("Open", popup.SelectedAsset == nullptr)) {
+ auto kind = static_cast<Template::Kind>(popup.SelectedAsset->Payload);
+ openTemplate = TemplateUI::CreateByKind(kind);
}
- ImGui::SameLine();
- if (ImGui::Button(ls->DialogCancel.Get())) {
- ImGui::CloseCurrentPopup();
- }
-
- ShowNewNameErrors();
- ShowNewKindErrors();
-
- ImGui::EndPopup();
- }
-
- ImGui::SameLine();
- if (ImGui::Button(ls->Rename.Get(), state.SelectedAsset == nullptr)) {
- ImGui::OpenPopup("Rename template");
- newName.clear();
- }
- if (ImGui::BeginPopupModal("Rename template")) {
- if (ImGui::InputText("New name", &newName)) {
- ValidateNewName();
- }
-
- if (ImGui::Button(ls->DialogConfirm.Get(), IsInputValid())) {
- auto tmpl = project.Templates.Rename(
- state.SelectedAsset->Name,
- 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())) {
- ImGui::CloseCurrentPopup();
- }
-
- ShowNewNameErrors();
-
- ImGui::EndPopup();
- }
-
- ImGui::SameLine();
- if (ImGui::Button(ls->Delete.Get(), state.SelectedAsset == nullptr)) {
- ImGui::OpenPopup("Delete confirmation");
- }
- if (ImGui::BeginPopupModal("Delete confirmation")) {
- if (ImGui::Button(ls->DialogConfirm.Get())) {
- auto& assetName = state.SelectedAsset->Name;
- project.Templates.Remove(assetName);
-
- state.SelectedAsset = nullptr;
- }
- ImGui::SameLine();
- if (ImGui::Button(ls->DialogCancel.Get())) {
- ImGui::CloseCurrentPopup();
- }
- ImGui::EndPopup();
- }
+ project.Templates.DisplayDetailsPopup(popup);
+ break;
- ImGui::EndPopup();
+ default:
+ project.Templates.DisplayDetailsPopup(popup);
+ break;
}
if (openTemplate) {
diff --git a/core/src/UI/UI_Workflows.cpp b/core/src/UI/UI_Workflows.cpp
index 7b2de2a..3c23c30 100644
--- a/core/src/UI/UI_Workflows.cpp
+++ b/core/src/UI/UI_Workflows.cpp
@@ -363,12 +363,18 @@ public:
void UI::WorkflowsTab()
{
auto ls = LocaleStrings::Instance.get();
- auto& gs = GlobalStates::GetInstance();
- auto& project = *gs.GetCurrentProject();
+ auto& project = *GlobalStates::GetInstance().GetCurrentProject();
+
+ enum class PopupType
+ {
+ None,
+ WorkflowSelect,
+ Management,
+ };
- bool openedDummy = true;
static std::unique_ptr<WorkflowUI> openWorkflow;
- static AssetList::ListState state;
+ static AssetList::PopupState popup;
+ static PopupType popupType = PopupType::None;
// Toolbar item: close
if (ImGui::Button(ls->Close.Get(), openWorkflow == nullptr)) {
@@ -378,93 +384,30 @@ void UI::WorkflowsTab()
// Toolbar item: open...
ImGui::SameLine();
if (ImGui::Button(ls->OpenWorkflow.Get())) {
- ImGui::OpenPopup(ls->OpenWorkflowDialogTitle.Get());
- }
- if (ImGui::BeginPopupModal(ls->OpenWorkflowDialogTitle.Get(), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- project.Workflows.DrawDetails(state);
-
- if (state.SelectedAsset) {
- auto workflow = project.Workflows.Load(*state.SelectedAsset);
- openWorkflow = std::make_unique<WorkflowUI>(std::move(workflow));
- }
-
- ImGui::EndPopup();
+ project.Workflows.OpenDetailsPopup();
+ popupType = PopupType::WorkflowSelect;
}
// Toolbar item: manage...
ImGui::SameLine();
if (ImGui::Button(ls->ManageWorkflows.Get())) {
- ImGui::OpenPopup(ls->ManageWorkflowsDialogTitle.Get());
+ project.Workflows.OpenDetailsPopup();
+ popupType = PopupType::Management;
}
- if (ImGui::BeginPopupModal(ls->ManageWorkflowsDialogTitle.Get(), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) {
- project.Workflows.DrawDetails(state);
-
- enum class NameSelectionError
- {
- None,
- Duplicated,
- Empty,
- };
- static std::string newName;
- static NameSelectionError newNameError;
- if (ImGui::Button(ls->Rename.Get(), state.SelectedAsset == nullptr)) {
- ImGui::OpenPopup("Rename workflow");
- newName.clear();
- }
- if (ImGui::BeginPopupModal("Rename workflow")) {
- if (ImGui::InputText("New name", &newName)) {
- if (newName.empty()) {
- newNameError = NameSelectionError::Empty;
- }
-
- if (project.Workflows.FindByName(newName)) {
- newNameError = NameSelectionError::Duplicated;
- }
- }
-
- if (ImGui::Button(ls->DialogConfirm.Get(), newName.empty())) {
- auto workflow = project.Workflows.Rename(
- state.SelectedAsset->Name,
- newName);
- state.SelectedAsset = workflow;
+ project.Workflows.DisplayDetailsPopup(popup);
+ switch (popupType) {
+ case PopupType::WorkflowSelect:
+ if (ImGui::Button("Open", popup.SelectedAsset == nullptr)) {
+ auto workflow = project.Workflows.Load(*popup.SelectedAsset);
+ openWorkflow = std::make_unique<WorkflowUI>(std::move(workflow));
}
- ImGui::SameLine();
- if (ImGui::Button(ls->DialogCancel.Get())) {
- ImGui::CloseCurrentPopup();
- }
-
- switch (newNameError) {
- case NameSelectionError::None: break;
- case NameSelectionError::Duplicated:
- ImGui::ErrorMessage("Duplicate workflow name");
- break;
- case NameSelectionError::Empty:
- ImGui::ErrorMessage("Workflow name cannot be empty");
- break;
- }
-
- ImGui::EndPopup();
- }
-
- if (ImGui::Button(ls->Delete.Get(), state.SelectedAsset == nullptr)) {
- ImGui::OpenPopup("Delete confirmation");
- }
- if (ImGui::BeginPopupModal("Delete confirmation")) {
- if (ImGui::Button(ls->DialogConfirm.Get())) {
- auto& assetName = state.SelectedAsset->Name;
- project.Workflows.Remove(assetName);
-
- state.SelectedAsset = nullptr;
- }
- ImGui::SameLine();
- if (ImGui::Button(ls->DialogCancel.Get())) {
- ImGui::CloseCurrentPopup();
- }
- ImGui::EndPopup();
- }
+ project.Workflows.DisplayDetailsPopup(popup);
+ break;
- ImGui::EndPopup();
+ default:
+ project.Workflows.DisplayDetailsPopup(popup);
+ break;
}
if (openWorkflow) {