aboutsummaryrefslogtreecommitdiff
path: root/app/source/Cplt/UI/UI_MainWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/source/Cplt/UI/UI_MainWindow.cpp')
-rw-r--r--app/source/Cplt/UI/UI_MainWindow.cpp237
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();
+}