diff options
Diffstat (limited to 'app/source/Cplt/UI/UI_MainWindow.cpp')
-rw-r--r-- | app/source/Cplt/UI/UI_MainWindow.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/app/source/Cplt/UI/UI_MainWindow.cpp b/app/source/Cplt/UI/UI_MainWindow.cpp new file mode 100644 index 0000000..4653f79 --- /dev/null +++ b/app/source/Cplt/UI/UI_MainWindow.cpp @@ -0,0 +1,237 @@ +#include "UI.hpp" + +#include <Cplt/Model/GlobalStates.hpp> +#include <Cplt/Model/Project.hpp> +#include <Cplt/Utils/I18n.hpp> + +#include <IconsFontAwesome.h> +#include <imgui.h> +#include <imgui_stdlib.h> +#include <portable-file-dialogs.h> +#include <filesystem> +#include <memory> + +namespace fs = std::filesystem; + +namespace CPLT_UNITY_ID { +void ProjectTab_Normal() +{ + auto& gs = GlobalStates::GetInstance(); + + if (ImGui::Button(ICON_FA_TIMES " " I18N_TEXT("Close", L10N_CLOSE))) { + gs.SetCurrentProject(nullptr); + return; + } + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_FOLDER " " I18N_TEXT("Open in filesystem", L10N_PROJECT_OPEN_IN_FILESYSTEM))) { + // TODO + } + + ImGui::Text("%s %s", I18N_TEXT("Project name", L10N_PROJECT_NAME), gs.GetCurrentProject()->GetName().c_str()); + ImGui::Text("%s %s", I18N_TEXT("Project path", L10N_PROJECT_PATH), gs.GetCurrentProject()->GetPathString().c_str()); +} + +void ProjectTab_NoProject() +{ + auto& gs = GlobalStates::GetInstance(); + + bool openedDummy = true; + bool openErrorDialog = false; + static std::string projectName; + static std::string dirName; + static fs::path dirPath; + static bool dirNameIsValid = false; + + auto TrySelectPath = [&](fs::path newPath) { + if (fs::exists(newPath)) { + dirNameIsValid = true; + dirName = newPath.string(); + dirPath = std::move(newPath); + } else { + dirNameIsValid = false; + } + }; + + if (ImGui::Button(I18N_TEXT("Create project....", L10N_PROJECT_NEW))) { + ImGui::SetNextWindowCentered(); + ImGui::OpenPopup(I18N_TEXT("Create project wizard", L10N_PROJECT_NEW_DIALOG_TITLE)); + } + + // Make it so that the modal dialog has a close button + if (ImGui::BeginPopupModal(I18N_TEXT("Create project wizard", L10N_PROJECT_NEW_DIALOG_TITLE), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::InputTextWithHint("##ProjectName", I18N_TEXT("Project name", L10N_PROJECT_NAME), &projectName); + + if (ImGui::InputTextWithHint("##ProjectPath", I18N_TEXT("Project path", L10N_PROJECT_PATH), &dirName)) { + // Changed, validate value + TrySelectPath(fs::path(dirName)); + } + ImGui::SameLine(); + if (ImGui::Button("...")) { + auto selection = pfd::select_folder(I18N_TEXT("Project path", L10N_PROJECT_NEW_PATH_DIALOG_TITLE)).result(); + if (!selection.empty()) { + TrySelectPath(fs::path(selection)); + } + } + + if (projectName.empty()) { + ImGui::ErrorMessage("%s", I18N_TEXT("Name cannot be empty", L10N_EMPTY_NAME_ERROR)); + } + if (!dirNameIsValid) { + ImGui::ErrorMessage("%s", I18N_TEXT("Invalid path", L10N_INVALID_PATH_ERROR)); + } + + ImGui::Spacing(); + + if (ImGui::Button(I18N_TEXT("Confirm", L10N_CONFIRM), !dirNameIsValid || projectName.empty())) { + ImGui::CloseCurrentPopup(); + + gs.SetCurrentProject(std::make_unique<Project>(std::move(dirPath), std::move(projectName))); + + // Dialog just got closed, reset states + projectName.clear(); + dirName.clear(); + dirPath.clear(); + dirNameIsValid = false; + } + + ImGui::SameLine(); + if (ImGui::Button(I18N_TEXT("Cancel", L10N_CANCEL))) { + ImGui::CloseCurrentPopup(); + } + + ImGui::EndPopup(); + } + + ImGui::SameLine(); + if (ImGui::Button(I18N_TEXT("Open project...", L10N_PROJECT_OPEN))) { + auto selection = pfd::open_file(I18N_TEXT("Open project", L10N_PROJECT_OPEN_DIALOG_TITLE)).result(); + if (!selection.empty()) { + fs::path path(selection[0]); + + try { + // Project's constructor wants a path to directory containing cplt_project.json + gs.SetCurrentProject(std::make_unique<Project>(path.parent_path())); + openErrorDialog = false; + } catch (const std::exception& e) { + openErrorDialog = true; + } + } + } + + // TODO cleanup UI + // Recent projects + + ImGui::Separator(); + ImGui::TextUnformatted(I18N_TEXT("Recent projects", L10N_PROJECT_RECENTS)); + + ImGui::SameLine(); + if (ImGui::Button(I18N_TEXT("Clear", L10N_PROJECT_RECENTS_CLEAR))) { + gs.ClearRecentProjects(); + } + + auto& rp = gs.GetRecentProjects(); + // End of vector is the most recently used, so that appending has less overhead + size_t toRemoveIdx = rp.size(); + + if (rp.empty()) { + ImGui::TextUnformatted(I18N_TEXT("No recent projects", L10N_PROJECT_RECENTS_NONE_PRESENT)); + } else { + for (auto it = rp.rbegin(); it != rp.rend(); ++it) { + auto& [path, recent] = *it; + ImGui::TextUnformatted(recent.c_str()); + + size_t idx = std::distance(it, rp.rend()) - 1; + ImGui::PushID(idx); + + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_FOLDER_OPEN)) { + try { + gs.SetCurrentProject(std::make_unique<Project>(path)); + openErrorDialog = false; + } catch (const std::exception& e) { + openErrorDialog = true; + } + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(I18N_TEXT("Open this project", L10N_PROJECT_RECENTS_OPEN_TOOLTIP)); + } + + ImGui::SameLine(); + if (ImGui::Button(ICON_FA_TRASH)) { + toRemoveIdx = idx; + } + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(I18N_TEXT("Delete this project from the Recent Projects list, the project itself will not be affected", L10N_PROJECT_RECENTS_DELETE_TOOLTIP)); + } + + ImGui::PopID(); + } + } + + if (toRemoveIdx != rp.size()) { + gs.RemoveRecentProject(toRemoveIdx); + } + + if (openErrorDialog) { + ImGui::SetNextWindowCentered(); + ImGui::OpenPopup(I18N_TEXT("Error", L10N_ERROR)); + } + if (ImGui::BeginPopupModal(I18N_TEXT("Error", L10N_ERROR), &openedDummy, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::ErrorMessage("%s", I18N_TEXT("Invalid project file", L10N_PROJECT_INVALID_PROJECT_FORMAT)); + ImGui::EndPopup(); + } +} +} // namespace CPLT_UNITY_ID + +void UI::MainWindow() +{ + auto& gs = GlobalStates::GetInstance(); + + auto windowSize = ImGui::GetMainViewport()->Size; + ImGui::SetNextWindowSize({ windowSize.x, windowSize.y }); + ImGui::SetNextWindowPos({ 0, 0 }); + ImGui::Begin("##MainWindow", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize); + if (ImGui::BeginTabBar("MainWindowTabs")) { + if (ImGui::BeginTabItem(ICON_FA_COGS " " I18N_TEXT("Settings", L10N_MAIN_TAB_SETTINGS))) { + UI::SettingsTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem(ICON_FA_FILE " " I18N_TEXT("Project", L10N_MAIN_WINDOW_TAB_PROJECT), nullptr)) { + if (gs.HasCurrentProject()) { + CPLT_UNITY_ID::ProjectTab_Normal(); + } else { + CPLT_UNITY_ID::ProjectTab_NoProject(); + } + ImGui::EndTabItem(); + } + if (!gs.HasCurrentProject()) { + // No project open, simply skip all project specific tabs + goto endTab; + } + + if (ImGui::BeginTabItem(ICON_FA_DATABASE " " I18N_TEXT("Data", L10N_MAIN_WINDOW_TAB_DATABASE_VIEW))) { + UI::DatabaseViewTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem(ICON_FA_BOX " " I18N_TEXT("Items", L10N_MAIN_WINDOW_TAB_ITEMS))) { + UI::ItemsTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem(ICON_FA_SCROLL " " I18N_TEXT("Workflows", L10N_MAIN_WINDOW_TAB_WORKFLOWS))) { + UI::WorkflowsTab(); + ImGui::EndTabItem(); + } + + if (ImGui::BeginTabItem(ICON_FA_TABLE " " I18N_TEXT("Templates", L10N_MAIN_WINDOW_TAB_TEMPLATES))) { + UI::TemplatesTab(); + ImGui::EndTabItem(); + } + + endTab: + ImGui::EndTabBar(); + } + ImGui::End(); +} |