diff options
author | rtk0c <[email protected]> | 2022-06-30 21:38:53 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2022-06-30 21:38:53 -0700 |
commit | 7fe47a9d5b1727a61dc724523b530762f6d6ba19 (patch) | |
tree | e95be6e66db504ed06d00b72c579565bab873277 /app/source/Cplt/Model/Template/Template_Main.cpp | |
parent | 2cf952088d375ac8b2f45b144462af0953436cff (diff) |
Restructure project
Diffstat (limited to 'app/source/Cplt/Model/Template/Template_Main.cpp')
-rw-r--r-- | app/source/Cplt/Model/Template/Template_Main.cpp | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/app/source/Cplt/Model/Template/Template_Main.cpp b/app/source/Cplt/Model/Template/Template_Main.cpp new file mode 100644 index 0000000..d658231 --- /dev/null +++ b/app/source/Cplt/Model/Template/Template_Main.cpp @@ -0,0 +1,214 @@ +#include "Template.hpp" + +#include <Cplt/Model/GlobalStates.hpp> +#include <Cplt/Model/Project.hpp> +#include <Cplt/UI/UI.hpp> +#include <Cplt/Utils/I18n.hpp> +#include <Cplt/Utils/IO/Archive.hpp> +#include <Cplt/Utils/UUID.hpp> + +#include <imgui.h> +#include <imgui_stdlib.h> +#include <algorithm> +#include <cstdint> +#include <fstream> + +using namespace std::literals::string_view_literals; +namespace fs = std::filesystem; + +Template::Template(Kind kind) + : mKind{ kind } +{ +} + +Template::Kind Template::GetKind() const +{ + return mKind; +} + +void TemplateAssetList::DiscoverFiles(const std::function<void(SavedAsset)>& callback) const +{ + auto dir = GetConnectedProject().GetTemplatesDirectory(); + DiscoverFilesByExtension(callback, dir, ".cplt-template"sv); +} + +std::string TemplateAssetList::RetrieveNameFromFile(const fs::path& file) const +{ + auto res = DataArchive::LoadFile(file); + if (!res) return ""; + auto& stream = res.value(); + + SavedAsset assetInfo; + stream.ReadObject(assetInfo); + + return assetInfo.Name; +} + +uuids::uuid TemplateAssetList::RetrieveUuidFromFile(const fs::path& file) const +{ + return uuids::uuid::from_string(file.stem().string()); +} + +fs::path TemplateAssetList::RetrievePathFromAsset(const SavedAsset& asset) const +{ + auto fileName = uuids::to_string(asset.Uuid); + return GetConnectedProject().GetTemplatePath(fileName); +} + +bool TemplateAssetList::SaveInstance(const SavedAsset& assetInfo, const Asset* asset) const +{ + auto path = RetrievePathFromAsset(assetInfo); + auto res = DataArchive::SaveFile(path); + if (!res) return false; + auto& stream = res.value(); + + stream.WriteObject(assetInfo); + // This cast is fine: calls to this class will always be wrapped in TypedAssetList<T>, which will ensure `asset` points to some Template + if (auto tmpl = static_cast<const Template*>(asset)) { // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast) + stream.WriteObject(*tmpl); + } + + return true; +} + +static std::unique_ptr<Template> LoadTemplateFromFile(const fs::path& path) +{ + auto res = DataArchive::LoadFile(path); + if (!res) return nullptr; + auto& stream = res.value(); + + SavedAsset assetInfo; + stream.ReadObject(assetInfo); + + auto kind = static_cast<Template::Kind>(assetInfo.Payload); + auto tmpl = Template::CreateByKind(kind); + stream.ReadObject(*tmpl); + + return tmpl; +} + +Template* TemplateAssetList::LoadInstance(const SavedAsset& assetInfo) const +{ + return ::LoadTemplateFromFile(RetrievePathFromAsset(assetInfo)).release(); +} + +Template* TemplateAssetList::CreateInstance(const SavedAsset& assetInfo) const +{ + auto kind = static_cast<Template::Kind>(assetInfo.Payload); + return Template::CreateByKind(kind).release(); +} + +bool TemplateAssetList::RenameInstanceOnDisk(const SavedAsset& assetInfo, std::string_view oldName) const +{ + // Get asset path, which is only dependent on UUID + auto path = RetrievePathFromAsset(assetInfo); + + auto tmpl = ::LoadTemplateFromFile(path); + if (!tmpl) return false; + + // Rewrite the asset with the updated name (note the given assetInfo already has the update name) + SaveInstance(assetInfo, tmpl.get()); + + return true; +} + +void TemplateAssetList::DisplayAssetCreator(ListState& state) +{ + auto ValidateNewName = [&]() -> void { + if (mACNewName.empty()) { + mACNewNameError = NameSelectionError::Empty; + return; + } + + if (FindByName(mACNewName)) { + mACNewNameError = NameSelectionError::Duplicated; + return; + } + + mACNewNameError = NameSelectionError::None; + }; + + auto ShowNewNameErrors = [&]() -> void { + switch (mACNewNameError) { + case NameSelectionError::None: break; + case NameSelectionError::Duplicated: + ImGui::ErrorMessage(I18N_TEXT("Duplicate name", L10N_DUPLICATE_NAME_ERROR)); + break; + case NameSelectionError::Empty: + ImGui::ErrorMessage(I18N_TEXT("Name cannot be empty", L10N_EMPTY_NAME_ERROR)); + break; + } + }; + + auto ShowNewKindErrors = [&]() -> void { + if (mACNewKind == Template::InvalidKind) { + ImGui::ErrorMessage(I18N_TEXT("Invalid template type", L10N_TEMPLATE_INVALID_TYPE_ERROR)); + } + }; + + auto IsInputValid = [&]() -> bool { + return mACNewNameError == NameSelectionError::None && + mACNewKind != Template::InvalidKind; + }; + + auto ResetState = [&]() -> void { + mACNewName.clear(); + mACNewKind = Template::InvalidKind; + ValidateNewName(); + }; + + if (ImGui::InputText(I18N_TEXT("Name", L10N_NAME), &mACNewName)) { + ValidateNewName(); + } + + if (ImGui::BeginCombo(I18N_TEXT("Type", L10N_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(I18N_TEXT("OK", L10N_CONFIRM), !IsInputValid())) { + ImGui::CloseCurrentPopup(); + + Create(SavedAsset{ + .Name = mACNewName, + .Payload = static_cast<uint64_t>(mACNewKind), + }); + ResetState(); + } + ImGui::SameLine(); + if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) { + ImGui::CloseCurrentPopup(); + } +} + +void TemplateAssetList::DisplayDetailsTable(ListState& state) const +{ + ImGui::BeginTable("AssetDetailsTable", 2, ImGuiTableFlags_Borders); + + ImGui::TableSetupColumn(I18N_TEXT("Name", L10N_NAME)); + ImGui::TableSetupColumn(I18N_TEXT("Type", L10N_TYPE)); + ImGui::TableHeadersRow(); + + for (auto& asset : this->GetAssets()) { + ImGui::TableNextRow(); + + ImGui::TableNextColumn(); + if (ImGui::Selectable(asset.Name.c_str(), state.SelectedAsset == &asset, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_DontClosePopups)) { + state.SelectedAsset = &asset; + } + + ImGui::TableNextColumn(); + auto kind = static_cast<Template::Kind>(asset.Payload); + ImGui::TextUnformatted(Template::FormatKind(kind)); + } + + ImGui::EndTable(); +} |