aboutsummaryrefslogtreecommitdiff
path: root/app/source/Cplt/Model/Template/Template_Main.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-30 21:38:53 -0700
committerrtk0c <[email protected]>2022-06-30 21:38:53 -0700
commit7fe47a9d5b1727a61dc724523b530762f6d6ba19 (patch)
treee95be6e66db504ed06d00b72c579565bab873277 /app/source/Cplt/Model/Template/Template_Main.cpp
parent2cf952088d375ac8b2f45b144462af0953436cff (diff)
Restructure project
Diffstat (limited to 'app/source/Cplt/Model/Template/Template_Main.cpp')
-rw-r--r--app/source/Cplt/Model/Template/Template_Main.cpp214
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();
+}