diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/CMakeLists.txt | 32 | ||||
-rw-r--r-- | core/locale/zh_CN.json | 2 | ||||
-rw-r--r-- | core/src/UI/Localization.hpp | 24 | ||||
-rw-r--r-- | core/src/UI/UI_MainWindow.cpp | 63 | ||||
-rw-r--r-- | core/src/Utils/Dialog/Dialog.cpp | 18 | ||||
-rw-r--r-- | core/src/Utils/Dialog/Dialog.hpp | 52 | ||||
-rw-r--r-- | core/src/Utils/Dialog/Dialog_linux.cpp | 83 | ||||
-rw-r--r-- | core/src/Utils/Dialog/Dialog_macos.mm | 113 | ||||
-rw-r--r-- | core/src/Utils/Dialog/Dialog_win32.cpp | 64 | ||||
-rw-r--r-- | core/src/Utils/Dialog/fwd.hpp | 1 | ||||
-rw-r--r-- | core/src/Utils/fwd.hpp | 2 |
11 files changed, 56 insertions, 398 deletions
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index be089d8..d8e9db1 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -57,28 +57,6 @@ add_source_group(UTILS_MODULE_SOURCES src/Utils/String.cpp ) -# These files are compiled individually, hence no UNITY_GROUP property -# This is because the files here may contain non-c++ languages -set(UTILS_DIALOG_MODULE_SOURCES - src/Utils/Dialog/Dialog.cpp -) -if(APPLE) - find_library(COCOA_LIBRARY Cocoa) - list(APPEND UTILS_DIALOG_MODULE_SOURCES - src/Utils/Dialog/Dialog_macos.mm - ) -elseif(WIN32) - list(APPEND UTILS_DIALOG_MODULE_SOURCES - src/Utils/Dialog/Dialog_win32.cpp - ) -elseif(LINUX) - find_package(PkgConfig REQUIRED) - pkg_check_modules(GTK3 REQUIRED gtk+-3.0) - list(APPEND UTILS_DIALOG_MODULE_SOURCES - src/Utils/Dialog/Dialog_linux.cpp - ) -endif() - function(add_executable_variant TARGET_NAME) message("CpltCore: generating executable ${TARGET_NAME}") @@ -182,11 +160,7 @@ function(add_executable_variant TARGET_NAME) endif() endfunction() -if(BUILD_CORE_MAIN) - add_executable_variant(CpltCore_main) - target_compile_definitions(CpltCore_main PRIVATE DOCTEST_CONFIG_DISABLE=1) -endif() +add_executable_variant(CpltCore_main) +target_compile_definitions(CpltCore_main PRIVATE DOCTEST_CONFIG_DISABLE=1) -if(BUILD_CORE_TESTS) - add_executable_variant(CpltCore_test) -endif() +add_executable_variant(CpltCore_test) diff --git a/core/locale/zh_CN.json b/core/locale/zh_CN.json index 8550b1d..3b38f40 100644 --- a/core/locale/zh_CN.json +++ b/core/locale/zh_CN.json @@ -11,9 +11,11 @@ "Project.New.Cancel": "取消", "Project.New.Name": "项目名称", "Project.New.Path": "项目路径", + "Project.New.Path.DialogTitle": "项目路径", "Project.New.EmptyName": "项目名不能为空", "Project.New.InvalidPath": "无效路径", "Project.Open": "打开项目...", + "Project.Open.DialogTitle": "打开项目", "Project.Recents": "最近使用", "Project.Recents.Clear": "清空", "Project.Recents.NonePresent": "(暂无最近使用的项目)", diff --git a/core/src/UI/Localization.hpp b/core/src/UI/Localization.hpp index 7b401ef..e604165 100644 --- a/core/src/UI/Localization.hpp +++ b/core/src/UI/Localization.hpp @@ -19,19 +19,21 @@ public: BasicTranslation TabExport{ "MainWindow.Tab.Exports"sv }; BasicTranslation NewProject{ "Project.New"sv }; - BasicTranslation TitleNewProject{ "Project.New.DialogTitle"sv }; - BasicTranslation ActionNewProjectConfirm{ "Project.New.Confirm"sv }; - BasicTranslation ActionNewProjectCancel{ "Project.New.Cancel"sv }; - BasicTranslation HintNewProjectName{ "Project.New.Name"sv }; - BasicTranslation HintNewProjectPath{ "Project.New.Path"sv }; - BasicTranslation ErrorNewProjectEmptyName{ "Project.New.EmptyName"sv }; - BasicTranslation ErrorNewProjectInvalidPath{ "Project.New.InvalidPath"sv }; + BasicTranslation NewProjectTitle{ "Project.New.DialogTitle"sv }; + BasicTranslation ConfirmNewProject{ "Project.New.Confirm"sv }; + BasicTranslation CancelNewProject{ "Project.New.Cancel"sv }; + BasicTranslation NewProjectNameHint{ "Project.New.Name"sv }; + BasicTranslation NewProjectPathHint{ "Project.New.Path"sv }; + BasicTranslation NewProjectPathDialogTitle{ "Project.New.Path.DialogTitle"sv }; + BasicTranslation NewProjectEmptyNameError{ "Project.New.EmptyName"sv }; + BasicTranslation NewProjectInvalidPathError{ "Project.New.InvalidPath"sv }; BasicTranslation OpenProject{ "Project.Open"sv }; + BasicTranslation OpenProjectDialogTitle{ "Project.Open.DialogTitle"sv }; BasicTranslation RecentProjects{ "Project.Recents"sv }; - BasicTranslation ActionClearRecentProjects{ "Project.Recents.Clear"sv }; - BasicTranslation MessageNoRecentProjects{ "Project.Recents.NonePresent"sv }; - BasicTranslation TooltipOpenRecentProject{ "Project.Recents.Open.Tooltip"sv }; - BasicTranslation TooltipDeleteRecentProject{ "Project.Recents.Delete.Tooltip"sv }; + BasicTranslation ClearRecentProjects{ "Project.Recents.Clear"sv }; + BasicTranslation NoRecentProjectsMessage{ "Project.Recents.NonePresent"sv }; + BasicTranslation OpenRecentProjectTooltip{ "Project.Recents.Open.Tooltip"sv }; + BasicTranslation DeleteRecentProjectTooltip{ "Project.Recents.Delete.Tooltip"sv }; }; diff --git a/core/src/UI/UI_MainWindow.cpp b/core/src/UI/UI_MainWindow.cpp index 9b20550..de300e2 100644 --- a/core/src/UI/UI_MainWindow.cpp +++ b/core/src/UI/UI_MainWindow.cpp @@ -5,6 +5,8 @@ #include "UI/Localization.hpp" #include "UI/States.hpp" +#include <portable-file-dialogs.h> + #include <IconsFontAwesome.h> #include <imgui.h> #include <imgui_internal.h> @@ -18,9 +20,9 @@ void LoadProjectAt(const std::filesystem::path& path) { auto& uis = UIState::GetInstance(); auto& gs = GlobalStates::GetInstance(); - if (uis.CurrentProject) { - uis.CloseCurrentProject(); - } + auto project = Project::Load(path); + auto uptr = std::unique_ptr<Project>(new Project(std::move(project))); + uis.SetCurrentProject(std::move(uptr)); } void ProjectTab_Normal() { @@ -36,45 +38,52 @@ void ProjectTab_NoProject() { static std::string dirName; static fs::path dirPath; static bool dirNameIsValid = false; + + auto TrySelectPath = [&](fs::path newPath) { + if (fs::exists(newPath)) { + dirNameIsValid = true; + dirPath = std::move(newPath); + } else { + dirNameIsValid = false; + } + }; + if (ImGui::Button(ls->NewProject.Get())) { auto vs = ImGui::GetMainViewport()->Size; // Viewport Size ImGui::SetNextWindowSize({ vs.x * 0.5f, vs.y * 0.5f }); ImGui::SetNextWindowPos({ vs.x / 2, vs.y / 2 }, ImGuiCond_Always, { 0.5f, 0.5f }); // Center window initially - ImGui::OpenPopup(ls->TitleNewProject.Get()); + ImGui::OpenPopup(ls->NewProjectTitle.Get()); } // Make it so that the modal dialog has a close button bool newProjectDialogDummyTrue = true; - if (ImGui::BeginPopupModal(ls->TitleNewProject.Get(), &newProjectDialogDummyTrue)) { - ImGui::InputTextWithHint("##ProjectName", ls->HintNewProjectName.Get(), &projectName); + if (ImGui::BeginPopupModal(ls->NewProjectTitle.Get(), &newProjectDialogDummyTrue)) { + ImGui::InputTextWithHint("##ProjectName", ls->NewProjectNameHint.Get(), &projectName); - if (ImGui::InputTextWithHint("##ProjectPath", ls->HintNewProjectPath.Get(), &dirName)) { + if (ImGui::InputTextWithHint("##ProjectPath", ls->NewProjectPathHint.Get(), &dirName)) { // Changed, validate value - fs::path newPath(dirName); - if (fs::exists(newPath)) { - dirNameIsValid = true; - dirPath = std::move(newPath); - } else { - dirNameIsValid = false; - } + TrySelectPath(fs::path(dirName)); } ImGui::SameLine(); if (ImGui::Button("...")) { - // TODO file dialog + auto selection = pfd::select_folder(ls->NewProjectPathDialogTitle.Get()).result(); + if (!selection.empty()) { + TrySelectPath(fs::path(selection)); + } } if (projectName.empty()) { ImGui::ErrorIcon(); ImGui::SameLine(); - ImGui::Text(ls->ErrorNewProjectEmptyName.Get()); + ImGui::Text(ls->NewProjectEmptyNameError.Get()); } if (!dirNameIsValid) { ImGui::ErrorIcon(); ImGui::SameLine(); - ImGui::Text(ls->ErrorNewProjectInvalidPath.Get()); + ImGui::Text(ls->NewProjectInvalidPathError.Get()); } ImGui::Spacing(); @@ -85,7 +94,7 @@ void ProjectTab_NoProject() { ImGui::PushItemFlag(ImGuiItemFlags_Disabled, false); ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.5f * ImGui::GetStyle().Alpha); } - if (ImGui::Button(ls->ActionNewProjectConfirm.Get())) { + if (ImGui::Button(ls->ConfirmNewProject.Get())) { ImGui::CloseCurrentPopup(); auto project = Project::Create(std::move(projectName), dirPath); @@ -104,7 +113,7 @@ void ProjectTab_NoProject() { } ImGui::SameLine(); - if (ImGui::Button(ls->ActionNewProjectCancel.Get())) { + if (ImGui::Button(ls->CancelNewProject.Get())) { ImGui::CloseCurrentPopup(); } @@ -112,19 +121,23 @@ void ProjectTab_NoProject() { } if (ImGui::Button(ls->OpenProject.Get())) { - // TODO + auto selection = pfd::open_file(ls->OpenProjectDialogTitle.Get()).result(); + if (!selection.empty()) { + fs::path path(selection[0]); + LoadProjectAt(path); + } } ImGui::Separator(); ImGui::Text(ls->RecentProjects.Get()); ImGui::SameLine(); - if (ImGui::Button(ls->ActionClearRecentProjects.Get())) { + if (ImGui::Button(ls->ClearRecentProjects.Get())) { gs.ClearRecentProjects(); } auto& recentProjects = gs.GetRecentProjects(); if (recentProjects.empty()) { - ImGui::Text(ls->MessageNoRecentProjects.Get()); + ImGui::Text(ls->NoRecentProjectsMessage.Get()); } for (auto it = recentProjects.begin(); it != recentProjects.end(); ++it) { auto& [path, recent] = *it; @@ -135,7 +148,7 @@ void ProjectTab_NoProject() { LoadProjectAt(path); } if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(ls->TooltipOpenRecentProject.Get()); + ImGui::SetTooltip(ls->OpenRecentProjectTooltip.Get()); } ImGui::SameLine(); @@ -143,7 +156,7 @@ void ProjectTab_NoProject() { gs.RemoveRecentProject(std::distance(recentProjects.begin(), it)); } if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(ls->TooltipDeleteRecentProject.Get()); + ImGui::SetTooltip(ls->DeleteRecentProjectTooltip.Get()); } } } @@ -163,7 +176,7 @@ void UI::MainWindow() { ImGui::EndTabItem(); } - if (ImGui::BeginTabItem(ls->TabProject.Get(), nullptr, ImGuiTabItemFlags_SetSelected)) { + if (ImGui::BeginTabItem(ls->TabProject.Get(), nullptr)) { if (uis.CurrentProject) { ProjectTab_Normal(); } else { diff --git a/core/src/Utils/Dialog/Dialog.cpp b/core/src/Utils/Dialog/Dialog.cpp deleted file mode 100644 index c4459c0..0000000 --- a/core/src/Utils/Dialog/Dialog.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Adapted from https://github.com/aaronmjacobs/Boxer/blob/master/include/boxer/boxer.h
-#include "Dialog.hpp"
-
-namespace Dialog {
-
-Selection Show(const char* message, const char* title, Style style) {
- return Show(message, title, style, kDefaultButtons);
-}
-
-Selection Show(const char* message, const char* title, Buttons buttons) {
- return Show(message, title, kDefaultStyle, buttons);
-}
-
-Selection Show(const char* message, const char* title) {
- return Show(message, title, kDefaultStyle, kDefaultButtons);
-}
-
-} // namespace Dialog
diff --git a/core/src/Utils/Dialog/Dialog.hpp b/core/src/Utils/Dialog/Dialog.hpp deleted file mode 100644 index e8989e3..0000000 --- a/core/src/Utils/Dialog/Dialog.hpp +++ /dev/null @@ -1,52 +0,0 @@ -// Adapted from https://github.com/aaronmjacobs/Boxer/blob/master/include/boxer/boxer.h
-#pragma once
-
-namespace Dialog {
-
-/// Options for styles to apply to a message box.
-enum class Style {
- Info,
- Warning,
- Error,
- Question,
-};
-
-/// Options for buttons to provide on a message box.
-enum class Buttons {
- OK,
- OKCancel,
- YesNo,
- Quit,
-};
-
-/// Possible responses from a message box. 'None' signifies that no option was chosen, and 'Error' signifies that an
-/// error was encountered while creating the message box.
-enum class Selection {
- OK,
- Cancel,
- Yes,
- No,
- Quit,
- None,
- Error,
-};
-
-/// The default style to apply to a message box.
-constexpr Style kDefaultStyle = Style::Info;
-
-/// The default buttons to provide on a message box.
-constexpr Buttons kDefaultButtons = Buttons::OK;
-
-/// Blocking call to create a modal message box with the given message, title, style, and buttons.
-Selection Show(const char* message, const char* title, Style style, Buttons buttons);
-
-/// Convenience function to call show() with the default buttons.
-Selection Show(const char* message, const char* title, Style style);
-
-/// Convenience function to call show() with the default style.
-Selection Show(const char* message, const char* title, Buttons buttons);
-
-/// Convenience function to call show() with the default style and buttons.
-Selection Show(const char* message, const char* title);
-
-} // namespace Dialog
diff --git a/core/src/Utils/Dialog/Dialog_linux.cpp b/core/src/Utils/Dialog/Dialog_linux.cpp deleted file mode 100644 index 11c3cee..0000000 --- a/core/src/Utils/Dialog/Dialog_linux.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Adapted from https://github.com/aaronmjacobs/Boxer/blob/master/src/boxer_linux.cpp
-#include "Dialog.hpp"
-
-#include <gtk/gtk.h>
-
-namespace Dialog {
-namespace {
-
- GtkMessageType GetMessageType(Style style) {
- switch (style) {
- case Style::Info:
- return GTK_MESSAGE_INFO;
- case Style::Warning:
- return GTK_MESSAGE_WARNING;
- case Style::Error:
- return GTK_MESSAGE_ERROR;
- case Style::Question:
- return GTK_MESSAGE_QUESTION;
- default:
- return GTK_MESSAGE_INFO;
- }
- }
-
- GtkButtonsType GetButtonsType(Buttons buttons) {
- switch (buttons) {
- case Buttons::OK:
- return GTK_BUTTONS_OK;
- case Buttons::OKCancel:
- return GTK_BUTTONS_OK_CANCEL;
- case Buttons::YesNo:
- return GTK_BUTTONS_YES_NO;
- case Buttons::Quit:
- return GTK_BUTTONS_CLOSE;
- default:
- return GTK_BUTTONS_OK;
- }
- }
-
- Selection getSelection(gint response) {
- switch (response) {
- case GTK_RESPONSE_OK:
- return Selection::OK;
- case GTK_RESPONSE_CANCEL:
- return Selection::Cancel;
- case GTK_RESPONSE_YES:
- return Selection::Yes;
- case GTK_RESPONSE_NO:
- return Selection::No;
- case GTK_RESPONSE_CLOSE:
- return Selection::Quit;
- default:
- return Selection::None;
- }
- }
-
-} // namespace
-
-Selection Show(const char* message, const char* title, Style style, Buttons buttons) {
- if (!gtk_init_check(0, nullptr)) {
- return Selection::Error;
- }
-
- // Create a parent window to stop gtk_dialog_run from complaining
- GtkWidget* parent = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-
- GtkWidget* dialog = gtk_message_dialog_new(GTK_WINDOW(parent),
- GTK_DIALOG_MODAL,
- GetMessageType(style),
- GetButtonsType(buttons),
- "%s",
- message);
- gtk_window_set_title(GTK_WINDOW(dialog), title);
- Selection selection = getSelection(gtk_dialog_run(GTK_DIALOG(dialog)));
-
- gtk_widget_destroy(GTK_WIDGET(dialog));
- gtk_widget_destroy(GTK_WIDGET(parent));
- while (g_main_context_iteration(nullptr, false)) {
- // Do nothing
- }
-
- return selection;
-}
-} // namespace Dialog
diff --git a/core/src/Utils/Dialog/Dialog_macos.mm b/core/src/Utils/Dialog/Dialog_macos.mm deleted file mode 100644 index c0164a0..0000000 --- a/core/src/Utils/Dialog/Dialog_macos.mm +++ /dev/null @@ -1,113 +0,0 @@ -// Adapted from https://github.com/aaronmjacobs/Boxer/blob/master/src/boxer_osx.mm
-#include "Dialog.hpp"
-
-#import <Cocoa/Cocoa.h>
-
-namespace Dialog {
-namespace {
-
- NSString* const kOkStr = @"OK";
- NSString* const kCancelStr = @"Cancel";
- NSString* const kYesStr = @"Yes";
- NSString* const kNoStr = @"No";
- NSString* const kQuitStr = @"Quit";
-
- NSAlertStyle GetAlertStyle(Style style) {
-#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
- switch (style) {
- case Style::Info:
- return NSAlertStyleInformational;
- case Style::Warning:
- return NSAlertStyleWarning;
- case Style::Error:
- return NSAlertStyleCritical;
- case Style::Question:
- return NSAlertStyleWarning;
- default:
- return NSAlertStyleInformational;
- }
-#else
- switch (style) {
- case Style::Info:
- return NSInformationalAlertStyle;
- case Style::Warning:
- return NSWarningAlertStyle;
- case Style::Error:
- return NSCriticalAlertStyle;
- case Style::Question:
- return NSWarningAlertStyle;
- default:
- return NSInformationalAlertStyle;
- }
-#endif
- }
-
- void SetButtons(NSAlert* alert, Buttons buttons) {
- switch (buttons) {
- case Buttons::OK:
- [alert addButtonWithTitle:kOkStr];
- break;
- case Buttons::OKCancel:
- [alert addButtonWithTitle:kOkStr];
- [alert addButtonWithTitle:kCancelStr];
- break;
- case Buttons::YesNo:
- [alert addButtonWithTitle:kYesStr];
- [alert addButtonWithTitle:kNoStr];
- break;
- case Buttons::Quit:
- [alert addButtonWithTitle:kQuitStr];
- break;
- default:
- [alert addButtonWithTitle:kOkStr];
- }
- }
-
- Selection GetSelection(int index, Buttons buttons) {
- switch (buttons) {
- case Buttons::OK:
- return index == NSAlertFirstButtonReturn ? Selection::OK : Selection::None;
- case Buttons::OKCancel:
- if (index == NSAlertFirstButtonReturn) {
- return Selection::OK;
- } else if (index == NSAlertSecondButtonReturn) {
- return Selection::Cancel;
- } else {
- return Selection::None;
- }
- case Buttons::YesNo:
- if (index == NSAlertFirstButtonReturn) {
- return Selection::Yes;
- } else if (index == NSAlertSecondButtonReturn) {
- return Selection::No;
- } else {
- return Selection::None;
- }
- case Buttons::Quit:
- return index == NSAlertFirstButtonReturn ? Selection::Quit : Selection::None;
- default:
- return Selection::None;
- }
- }
-
-} // namespace
-
-Selection show(const char* message, const char* title, Style style, Buttons buttons) {
- NSAlert* alert = [[NSAlert alloc] init];
-
- [alert setMessageText:[NSString stringWithCString:title encoding:[NSString defaultCStringEncoding]]];
- [alert setInformativeText:[NSString stringWithCString:message encoding:[NSString defaultCStringEncoding]]];
-
- [alert setAlertStyle:GetAlertStyle(style)];
- SetButtons(alert, buttons);
-
- // Force the alert to appear on top of any other windows
- [[alert window] setLevel:NSModalPanelWindowLevel];
-
- Selection selection = GetSelection([alert runModal], buttons);
- [alert release];
-
- return selection;
-}
-
-} // namespace Dialog
diff --git a/core/src/Utils/Dialog/Dialog_win32.cpp b/core/src/Utils/Dialog/Dialog_win32.cpp deleted file mode 100644 index b82f382..0000000 --- a/core/src/Utils/Dialog/Dialog_win32.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Adapted from https://github.com/aaronmjacobs/Boxer/blob/master/src/boxer_win.cpp
-#include "Dialog.hpp"
-
-#define WIN32_LEAN_AND_MEAN
-#include <Windows.h>
-
-namespace Dialog {
-namespace {
-
- UINT GetIcon(Style style) {
- switch (style) {
- case Style::Info:
- return MB_ICONINFORMATION;
- case Style::Warning:
- return MB_ICONWARNING;
- case Style::Error:
- return MB_ICONERROR;
- case Style::Question:
- return MB_ICONQUESTION;
- default:
- return MB_ICONINFORMATION;
- }
- }
-
- UINT GetButtons(Buttons buttons) {
- switch (buttons) {
- case Buttons::OK:
- case Buttons::Quit: // There is no 'Quit' button on Windows :(
- return MB_OK;
- case Buttons::OKCancel:
- return MB_OKCANCEL;
- case Buttons::YesNo:
- return MB_YESNO;
- default:
- return MB_OK;
- }
- }
-
- Selection GetSelection(int response, Buttons buttons) {
- switch (response) {
- case IDOK:
- return buttons == Buttons::Quit ? Selection::Quit : Selection::OK;
- case IDCANCEL:
- return Selection::Cancel;
- case IDYES:
- return Selection::Yes;
- case IDNO:
- return Selection::No;
- default:
- return Selection::None;
- }
- }
-
-} // namespace
-
-Selection Show(const char* message, const char* title, Style style, Buttons buttons) {
- UINT flags = MB_TASKMODAL;
-
- flags |= GetIcon(style);
- flags |= GetButtons(buttons);
-
- return GetSelection(MessageBox(nullptr, message, title, flags), buttons);
-}
-} // namespace Dialog
diff --git a/core/src/Utils/Dialog/fwd.hpp b/core/src/Utils/Dialog/fwd.hpp deleted file mode 100644 index 50e9667..0000000 --- a/core/src/Utils/Dialog/fwd.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once
diff --git a/core/src/Utils/fwd.hpp b/core/src/Utils/fwd.hpp index 1949ca2..f33cb14 100644 --- a/core/src/Utils/fwd.hpp +++ b/core/src/Utils/fwd.hpp @@ -1,7 +1,5 @@ #pragma once
-#include "Dialog/fwd.hpp"
-
// Sigslot.hpp
class SignalStub;
template <class... TArgs>
|