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".
This commit is contained in:
Maximilian Kueffner
2025-08-17 21:30:00 +02:00
parent e21ddb1246
commit 88cc7363c6
12 changed files with 225 additions and 123 deletions
+5 -15
View File
@@ -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})
+1
View File
@@ -2,3 +2,4 @@ add_subdirectory(utilities)
add_subdirectory(imaging)
add_subdirectory(rendering)
add_subdirectory(resources)
add_subdirectory(app)
+30 -44
View File
@@ -1,21 +1,16 @@
#include "AppGLFW.hpp"
#include <format>
#include <memory>
#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<PixelariumImage>(p));
for (int n = 0; n < static_cast<int>(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<utils::log::LogLevel>(1 << log_level_));
}
if (is_selected) ImGui::SetItemDefaultFocus();
}
ImGui::EndCombo();
}
}
+38
View File
@@ -0,0 +1,38 @@
#pragma once
#include <GLFW/glfw3.h>
#include <memory>
#include "imgui.h"
#include "utilities/ILog.hpp"
namespace pixelarium::application
{
class AppGLFW
{
public:
explicit AppGLFW(std::unique_ptr<utils::log::ILog>& 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
+36
View File
@@ -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})
@@ -1,13 +1,13 @@
#pragma once
/*-- Gets filled in during the cmake configuration step --*/
#include <array>
#include <string_view>
#cmakedefine PIXELARIUM_TITLE "@PIXELARIUM_TITLE@"
#define MAINMENUNAME "Menu"
#define FILEMENUNAME "File"
#define LOGLEVELSELECT "Log Level"
#define SHOWIMGUIDEMOS "ImGui Demos"
inline constexpr std::array<std::string_view, 5> LOGLEVELS = {"Trace", "Debug", "Info", "Warning", "Error"};
-55
View File
@@ -1,55 +0,0 @@
#pragma once
#include <GLFW/glfw3.h>
#include <cstdio>
#include <format>
#include <memory>
#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<utils::log::ILog>& log, std::unique_ptr<pixelarium::resources::ImageResourcePool>& pool)
: logger_(*log), pool_(*pool)
{
image_view_model_ = std::make_unique<ImageViewFactory>(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<pixelarium::imaging::PixelariumImage> img_;
// std::shared_ptr<pixelarium::ui::PixelariumImageView> image_view_;
std::unique_ptr<ImageViewFactory> 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
+2 -4
View File
@@ -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)
+58
View File
@@ -0,0 +1,58 @@
#include "MyApp.hpp"
#include <format>
#include <memory>
#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<PixelariumImage>(p));
}
}
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <GLFW/glfw3.h>
#include <memory>
#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<utils::log::ILog>& log, std::unique_ptr<pixelarium::resources::ImageResourcePool>& pool)
: application::AppGLFW(log), pool_(*pool)
{
image_view_model_ = std::make_unique<ImageViewFactory>(pool_);
}
protected:
void MenuBarOptionsColumn1() override;
void MenuBarOptionsColumn2() override;
void Run() override;
private:
void LoadImageProt();
private:
resources::ImageResourcePool& pool_;
std::unique_ptr<ImageViewFactory> image_view_model_;
bool imagep_{false};
bool demop_{false};
int log_level_{0};
ImVec2 curr_dim_;
};
} // namespace pixelarium::ui
+3 -3
View File
@@ -1,7 +1,7 @@
#include <iostream>
#include <memory>
#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<resources::ImageResourcePool>()};
auto app = pixelarium::ui::AppGLFW(logger, image_pool);
pixelarium::ui::MyApp app = pixelarium::ui::MyApp(logger, image_pool);
return app.Run();
app.Start();
}
+10
View File
@@ -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"