aboutsummaryrefslogtreecommitdiff
path: root/core/src/Model/Assets.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2021-06-09 22:18:32 -0700
committerrtk0c <[email protected]>2021-06-09 22:18:32 -0700
commitdc09ba073744292a4d4af0445e5095f424fffa22 (patch)
tree999b3d641502805ddaa6291e95f0443113b8859a /core/src/Model/Assets.cpp
parent19d8aeb010ffc967bf82986b7586b161364ab82f (diff)
Refactor asset management UI into AssetList
Diffstat (limited to 'core/src/Model/Assets.cpp')
-rw-r--r--core/src/Model/Assets.cpp187
1 files changed, 171 insertions, 16 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();
+ }
+}