diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/src/Model/Assets.cpp | 187 | ||||
-rw-r--r-- | core/src/Model/Assets.hpp | 41 | ||||
-rw-r--r-- | core/src/Model/Template/Template.hpp | 12 | ||||
-rw-r--r-- | core/src/Model/Template/Template_Main.cpp | 96 | ||||
-rw-r--r-- | core/src/Model/Workflow/Workflow.hpp | 11 | ||||
-rw-r--r-- | core/src/Model/Workflow/Workflow_Main.cpp | 74 | ||||
-rw-r--r-- | core/src/Model/fwd.hpp | 1 | ||||
-rw-r--r-- | core/src/UI/UI_Templates.cpp | 168 | ||||
-rw-r--r-- | core/src/UI/UI_Workflows.cpp | 107 |
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) { |