From 88cc7363c6aa29363c596317e6d54c29b50e47a3 Mon Sep 17 00:00:00 2001 From: Maximilian Kueffner Date: Sun, 17 Aug 2025 21:30:00 +0200 Subject: [PATCH] Factor out AppGLFW base class The intention here is to get rid of scaffolding in the consumer application class and allow to focus on the "important bits". --- CMakeLists.txt | 20 ++--- lib/CMakeLists.txt | 1 + {src => lib/app}/AppGLFW.cpp | 74 ++++++++----------- lib/app/AppGLFW.hpp | 38 ++++++++++ lib/app/CMakeLists.txt | 36 +++++++++ .../app/uiresources_app.h.in | 4 +- src/AppGLFW.hpp | 55 -------------- src/CMakeLists.txt | 6 +- src/MyApp.cpp | 58 +++++++++++++++ src/MyApp.hpp | 40 ++++++++++ src/main.cpp | 6 +- src/uiresources_local.h.in | 10 +++ 12 files changed, 225 insertions(+), 123 deletions(-) rename {src => lib/app}/AppGLFW.cpp (77%) create mode 100644 lib/app/AppGLFW.hpp create mode 100644 lib/app/CMakeLists.txt rename src/uiresources.h.in => lib/app/uiresources_app.h.in (75%) delete mode 100644 src/AppGLFW.hpp create mode 100644 src/MyApp.cpp create mode 100644 src/MyApp.hpp create mode 100644 src/uiresources_local.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 9dd6ce4..e786fd8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,14 +6,12 @@ set(CMAKE_VERBOSE_MAKEFILE ON) set(CXX_STANDARD 20) set(CXX_STANDARD_REQUIRED true) -set(imgui_DIR ${PROJECT_SOURCE_DIR}/modules/imgui) set(glfw_DIR ${PROJECT_SOURCE_DIR}/modules/glfw) set(pfd_DIR ${PROJECT_SOURCE_DIR}/modules/portable-file-dialogs) set(spdlog_DIR ${PROJECT_SOURCE_DIR}/modules/spdlog) find_package(OpenGL REQUIRED) -message(STATUS "IMGUI:\t" ${imgui_DIR}) message(STATUS "GLFW:\t" ${glfw_DIR}) message(STATUS "PFD:\t\t" ${pfd_DIR}) message(STATUS "SPDLOG:\t" ${spdlog_DIR}) @@ -38,17 +36,10 @@ add_subdirectory(src) add_subdirectory(lib) set(SRC - src/AppGLFW.cpp + src/MyApp.cpp src/views/PixelariumImageView.cpp src/viewmodels/ImageViewFactory.cpp - src/main.cpp - ${imgui_DIR}/imgui.cpp - ${imgui_DIR}/imgui_demo.cpp - ${imgui_DIR}/imgui_draw.cpp - ${imgui_DIR}/imgui_tables.cpp - ${imgui_DIR}/imgui_widgets.cpp - ${imgui_DIR}/backends/imgui_impl_opengl3.cpp - ${imgui_DIR}/backends/imgui_impl_glfw.cpp) + src/main.cpp) #==================== # needed for the spdlogger implemntation @@ -63,16 +54,15 @@ target_link_libraries(${PROJECT_NAME} PRIVATE pixelariumimagelib PRIVATE pixelariumrenderlib PRIVATE pixelariumutilslib - PRIVATE pixelariumresourcelib) + PRIVATE pixelariumresourcelib + PUBLIC pixelariumapplicationlib) target_include_directories(${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/src PUBLIC ${PROJECT_SOURCE_DIR}/lib PUBLIC ${PROJECT_SOURCE_DIR}/lib/imaging + PUBLIC ${PROJECT_SOURCE_DIR}/lib/app PUBLIC ${spdlog_DIR}/include - PUBLIC ${imgui_DIR} - PUBLIC ${imgui_DIR}/backends - PUBLIC ${glfw_INCLUDE_DIR} PUBLIC ${pfd_DIR} PUBLIC ${LIBCZI_INCLUDE_DIR} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index e131d02..071482d 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -2,3 +2,4 @@ add_subdirectory(utilities) add_subdirectory(imaging) add_subdirectory(rendering) add_subdirectory(resources) +add_subdirectory(app) diff --git a/src/AppGLFW.cpp b/lib/app/AppGLFW.cpp similarity index 77% rename from src/AppGLFW.cpp rename to lib/app/AppGLFW.cpp index e5f2da0..aca8c60 100644 --- a/src/AppGLFW.cpp +++ b/lib/app/AppGLFW.cpp @@ -1,21 +1,16 @@ #include "AppGLFW.hpp" -#include -#include - -#include "imaging/PixelariumImage.hpp" #include "imgui.h" #include "imgui_impl_glfw.h" #include "imgui_impl_opengl3.h" -#include "portable-file-dialogs.h" -#include "rendering/CvMatRender.hpp" -#include "uiresources.h" -#include "utilities/ILog.hpp" -#include "views/PixelariumImageView.hpp" +#include "uiresources_app.h" -using namespace pixelarium::imaging; +static void glfw_error_callback(int error, const char* description) +{ + fprintf(stderr, "GLFW Error %d: %s\n", error, description); +} -void pixelarium::ui::AppGLFW::InitMainWindow() +void pixelarium::application::AppGLFW::InitMainWindow() { glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) @@ -100,7 +95,7 @@ void pixelarium::ui::AppGLFW::InitMainWindow() ImGui_ImplOpenGL3_Init(glsl_version); } -int pixelarium::ui::AppGLFW::Run() +int pixelarium::application::AppGLFW::RunInternal() { ImGuiIO& io = ImGui::GetIO(); (void)io; @@ -115,20 +110,8 @@ int pixelarium::ui::AppGLFW::Run() ImGui::DockSpaceOverViewport(ImGui::GetID("Backspace")); this->MenuBar(); - if (demop_) ImGui::ShowDemoWindow(&this->demop_); - // if (this->image_view_) - // { - // this->image_view_->ShowImage(); - // } - - if (ImGui::BeginListBox("ListBox")) - { - pool_.EnumerateResources([](size_t id, const imaging::PixelariumImage&) -> void - { ImGui::Selectable(std::format("Image {}", id).c_str()); }); - - ImGui::EndListBox(); - } + this->Run(); // Rendering ImGui::Render(); @@ -146,6 +129,7 @@ int pixelarium::ui::AppGLFW::Run() glfwSwapBuffers(this->window); } + // Cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); @@ -157,7 +141,7 @@ int pixelarium::ui::AppGLFW::Run() return 0; } -void pixelarium::ui::AppGLFW::MenuBar() +void pixelarium::application::AppGLFW::MenuBar() { if (ImGui::BeginMainMenuBar()) { @@ -179,34 +163,36 @@ void pixelarium::ui::AppGLFW::MenuBar() ImGui::EndCombo(); } - ImGui::MenuItem(SHOWIMGUIDEMOS, NULL, &this->demop_); + // consumer main menu bar entries + this->MenuBarOptionsColumn1(); ImGui::EndMenu(); } - // file menu - if (ImGui::BeginMenu(FILEMENUNAME)) - { - if (ImGui::MenuItem("Load File")) - { - this->LoadImageProt(); - } - - ImGui::EndMenu(); - } + // consumer menu bar columns + this->MenuBarOptionsColumn2(); + this->MenuBarOptionsColumn3(); + this->MenuBarOptionsColumn4(); + this->MenuBarOptionsColumn5(); ImGui::EndMainMenuBar(); } } -void pixelarium::ui::AppGLFW::LoadImageProt() +void pixelarium::application::AppGLFW::LogLevelSelect() { - size_t last_id{}; - auto res{pfd::open_file("Load Inputs", pfd::path::home(), {"All Files", "*"}, pfd::opt::multiselect).result()}; - for (auto& p : res) + if (ImGui::BeginCombo(LOGLEVELSELECT, LOGLEVELS[log_level_].data())) { - this->logger_.Debug(std::format("{}: Creating image {}", __FUNCTION__, p)); - - last_id = image_view_model_->AddImage(std::make_unique(p)); + for (int n = 0; n < static_cast(LOGLEVELS.size()); n++) + { + bool is_selected = (LOGLEVELS[log_level_] == LOGLEVELS[n]); + if (ImGui::Selectable(LOGLEVELS[n].data(), is_selected)) + { + log_level_ = n; + this->logger_.ChangeLevel(static_cast(1 << log_level_)); + } + if (is_selected) ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); } } diff --git a/lib/app/AppGLFW.hpp b/lib/app/AppGLFW.hpp new file mode 100644 index 0000000..35bcde6 --- /dev/null +++ b/lib/app/AppGLFW.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include + +#include "imgui.h" +#include "utilities/ILog.hpp" + +namespace pixelarium::application +{ +class AppGLFW +{ + public: + explicit AppGLFW(std::unique_ptr& log) : logger_(*log) { this->InitMainWindow(); } + + void Start() { this->RunInternal(); } + + protected: + virtual void MenuBarOptionsColumn1() {} + virtual void MenuBarOptionsColumn2() {} + virtual void MenuBarOptionsColumn3() {} + virtual void MenuBarOptionsColumn4() {} + virtual void MenuBarOptionsColumn5() {} + virtual void Run() {} + + utils::log::ILog& logger_; + + private: + int RunInternal(); + void InitMainWindow(); + void MenuBar(); + void LogLevelSelect(); + int log_level_{0}; + GLFWwindow* window = nullptr; + ImGuiWindowFlags window_flags_ = 0; +}; +} // namespace pixelarium::application diff --git a/lib/app/CMakeLists.txt b/lib/app/CMakeLists.txt new file mode 100644 index 0000000..430b80d --- /dev/null +++ b/lib/app/CMakeLists.txt @@ -0,0 +1,36 @@ +set(imgui_DIR ${PROJECT_SOURCE_DIR}/modules/imgui) +# set(glfw_DIR ${PROJECT_SOURCE_DIR}/modules/glfw) + +message(STATUS "IMGUI:\t" ${imgui_DIR}) +# message(STATUS "GLFW:\t" ${glfw_DIR}) + +# add_directory(${glfw_DIR}) + +set(PIXELARIUM_TITLE ${CMAKE_PROJECT_NAME}) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/uiresources_app.h.in + ${CMAKE_BINARY_DIR}/uiresources_app.h @ONLY) + +set(APPLIBSRC + AppGLFW.cpp + ${imgui_DIR}/imgui.cpp + ${imgui_DIR}/imgui_demo.cpp + ${imgui_DIR}/imgui_draw.cpp + ${imgui_DIR}/imgui_tables.cpp + ${imgui_DIR}/imgui_widgets.cpp + ${imgui_DIR}/backends/imgui_impl_opengl3.cpp + ${imgui_DIR}/backends/imgui_impl_glfw.cpp) + +set(APPLIBNAME pixelariumapplicationlib) + +add_library(${APPLIBNAME} + STATIC ${APPLIBSRC}) + +target_link_libraries(${APPLIBNAME} + PRIVATE pixelariumutilslib) + +target_include_directories(${APPLIBNAME} + PUBLIC ${CMAKE_BINARY_DIR} + PUBLIC ${PROJECT_SOURCE_DIR}/lib + PUBLIC ${imgui_DIR} + PUBLIC ${imgui_DIR}/backends + PUBLIC ${glfw_INCLUDE_DIR}) diff --git a/src/uiresources.h.in b/lib/app/uiresources_app.h.in similarity index 75% rename from src/uiresources.h.in rename to lib/app/uiresources_app.h.in index 95f9614..e8b7159 100644 --- a/src/uiresources.h.in +++ b/lib/app/uiresources_app.h.in @@ -1,13 +1,13 @@ #pragma once -/*-- Gets filled in during the cmake configuration step --*/ #include #include + #cmakedefine PIXELARIUM_TITLE "@PIXELARIUM_TITLE@" #define MAINMENUNAME "Menu" #define FILEMENUNAME "File" #define LOGLEVELSELECT "Log Level" -#define SHOWIMGUIDEMOS "ImGui Demos" + inline constexpr std::array LOGLEVELS = {"Trace", "Debug", "Info", "Warning", "Error"}; diff --git a/src/AppGLFW.hpp b/src/AppGLFW.hpp deleted file mode 100644 index 54baf17..0000000 --- a/src/AppGLFW.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -#include "PixelariumImage.hpp" -#include "imgui.h" -#include "rendering/CvMatRender.hpp" -#include "resources/resource.hpp" -#include "utilities/ILog.hpp" -#include "viewmodels/ImageViewFactory.hpp" -#include "views/PixelariumImageView.hpp" - -namespace pixelarium::ui -{ -class AppGLFW -{ - public: - AppGLFW(std::unique_ptr& log, std::unique_ptr& pool) - : logger_(*log), pool_(*pool) - { - image_view_model_ = std::make_unique(pool_); - - this->InitMainWindow(); - } - int Run(); - - private: - void InitMainWindow(); - void MenuBar(); - void LoadImageProt(); - - private: - utils::log::ILog& logger_; - resources::ImageResourcePool& pool_; - GLFWwindow* window = nullptr; - ImGuiWindowFlags window_flags_ = 0; - // std::shared_ptr img_; - // std::shared_ptr image_view_; - std::unique_ptr image_view_model_; - // pixelarium::render::CvMatRender render_; - bool imagep_{false}; - bool demop_{false}; - int log_level_{0}; - ImVec2 curr_dim_; -}; - -static void glfw_error_callback(int error, const char* description) -{ - fprintf(stderr, "GLFW Error %d: %s\n", error, description); -} -} // namespace pixelarium::ui diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 76feb0c..6e49acd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,4 @@ -set(PIXELARIUM_TITLE ${CMAKE_PROJECT_NAME}) - message(STATUS "Configuring Resources") -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/uiresources.h.in - ${CMAKE_BINARY_DIR}/uiresources.h @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/uiresources_local.h.in + ${CMAKE_BINARY_DIR}/uiresources_local.h @ONLY) diff --git a/src/MyApp.cpp b/src/MyApp.cpp new file mode 100644 index 0000000..bee0ba1 --- /dev/null +++ b/src/MyApp.cpp @@ -0,0 +1,58 @@ +#include "MyApp.hpp" + +#include +#include + +#include "imaging/PixelariumImage.hpp" +#include "imgui.h" +#include "portable-file-dialogs.h" +#include "uiresources_app.h" +#include "uiresources_local.h" +#include "utilities/ILog.hpp" + +using namespace pixelarium::imaging; + +void pixelarium::ui::MyApp::MenuBarOptionsColumn1() { ImGui::MenuItem(SHOWIMGUIDEMOS, NULL, &this->demop_); } + +void pixelarium::ui::MyApp::MenuBarOptionsColumn2() +{ + if (ImGui::BeginMenu(FILEMENUNAME)) + { + if (ImGui::MenuItem("Load File")) + { + this->LoadImageProt(); + } + + ImGui::EndMenu(); + } +} + +void pixelarium::ui::MyApp::Run() +{ + if (demop_) ImGui::ShowDemoWindow(&this->demop_); + + // if (this->image_view_) + // { + // this->image_view_->ShowImage(); + // } + + if (ImGui::BeginListBox("ListBox")) + { + pool_.EnumerateResources([](size_t id, const imaging::PixelariumImage&) -> void + { ImGui::Selectable(std::format("Image {}", id).c_str()); }); + + ImGui::EndListBox(); + } +} + +void pixelarium::ui::MyApp::LoadImageProt() +{ + size_t last_id{}; + auto res{pfd::open_file("Load Inputs", pfd::path::home(), {"All Files", "*"}, pfd::opt::multiselect).result()}; + for (auto& p : res) + { + this->logger_.Debug(std::format("{}: Creating image {}", __FUNCTION__, p)); + + last_id = image_view_model_->AddImage(std::make_unique(p)); + } +} diff --git a/src/MyApp.hpp b/src/MyApp.hpp new file mode 100644 index 0000000..3ddefb2 --- /dev/null +++ b/src/MyApp.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include + +#include + +#include "AppGLFW.hpp" +#include "imgui.h" +#include "resources/resource.hpp" +#include "utilities/ILog.hpp" +#include "viewmodels/ImageViewFactory.hpp" + +namespace pixelarium::ui +{ +class MyApp : public application::AppGLFW +{ + public: + MyApp(std::unique_ptr& log, std::unique_ptr& pool) + : application::AppGLFW(log), pool_(*pool) + { + image_view_model_ = std::make_unique(pool_); + } + + protected: + void MenuBarOptionsColumn1() override; + void MenuBarOptionsColumn2() override; + void Run() override; + + private: + void LoadImageProt(); + + private: + resources::ImageResourcePool& pool_; + std::unique_ptr image_view_model_; + bool imagep_{false}; + bool demop_{false}; + int log_level_{0}; + ImVec2 curr_dim_; +}; +} // namespace pixelarium::ui diff --git a/src/main.cpp b/src/main.cpp index 7ec5dd0..82f1c4f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include #include -#include "AppGLFW.hpp" +#include "MyApp.hpp" #include "resources/resource.hpp" #include "uiresources.h" #include "utilities/ILog.hpp" @@ -23,7 +23,7 @@ int main(int argc, char** argv) logger->ChangeLevel(utils::log::LogLevel::Debug); auto image_pool{std::make_unique()}; - auto app = pixelarium::ui::AppGLFW(logger, image_pool); + pixelarium::ui::MyApp app = pixelarium::ui::MyApp(logger, image_pool); - return app.Run(); + app.Start(); } diff --git a/src/uiresources_local.h.in b/src/uiresources_local.h.in new file mode 100644 index 0000000..ef78617 --- /dev/null +++ b/src/uiresources_local.h.in @@ -0,0 +1,10 @@ +#pragma once + +/*-- Gets filled in during the cmake configuration step --*/ + +// #cmakedefine PIXELARIUM_TITLE "@PIXELARIUM_TITLE@" + +// #define MAINMENUNAME "Menu" +// #define FILEMENUNAME "File" +// #define LOGLEVELSELECT "Log Level" +#define SHOWIMGUIDEMOS "ImGui Demos"