hello_imgui icon indicating copy to clipboard operation
hello_imgui copied to clipboard

Feature Request: Add ThemeChangedCallback for Theme Change

Open xuboying opened this issue 1 month ago • 2 comments

Version

v1.92.3-8-g812a05d

Description

I have several customized drawings in my application that need to update their colors when the theme changes, especially when switching between light and dark modes. Currently, there is no direct callback mechanism to handle theme changes in the Hello ImGui framework.

Proposed Changes

After reviewing the Hello ImGui codebase, I believe this modification is straightforward. The main changes would be:

  1. Add a new declaration in runner_callbacks.h:

    VoidFunction ThemeChangedCallback = EmptyVoidFunction();
    
  2. Modify the ApplyTheme(ImGuiTheme_ theme, HelloImGui::RunnerParams& params) function:

    • Accept RunnerParams as a parameter.
    • Call ThemeChangedCallback after the theme has been updated.
  3. Adapt the relevant callers to support the new callback.

Motivation

This feature would allow applications to react immediately to theme changes, ensuring that custom drawings and UI elements remain visually consistent with the selected theme.

Reference Diff

diff --git a/src/hello_imgui/imgui_theme.h b/src/hello_imgui/imgui_theme.h
index 8a2395c..0389a5e 100644
--- a/src/hello_imgui/imgui_theme.h
+++ b/src/hello_imgui/imgui_theme.h
@@ -7,7 +7,9 @@
 // provided the origin of those files is stated in the copied version
 // Some themes were adapted by themes posted by ImGui users at https://github.com/ocornut/imgui/issues/707
 //
-
+namespace HelloImGui{
+    struct RunnerParams;
+}
 namespace ImGuiTheme
 {
     enum ImGuiTheme_
@@ -34,7 +36,7 @@ namespace ImGuiTheme
     const char* ImGuiTheme_Name(ImGuiTheme_ theme);
     ImGuiTheme_ ImGuiTheme_FromName(const char* themeName);
     ImGuiStyle ThemeToStyle(ImGuiTheme_ theme);
-    void ApplyTheme(ImGuiTheme_ theme);
+    void ApplyTheme(ImGuiTheme_ theme, HelloImGui::RunnerParams& params);


     struct ImGuiThemeTweaks
diff --git a/src/hello_imgui/impl/imgui_theme.cpp b/src/hello_imgui/impl/imgui_theme.cpp
index fc71531..310c0dd 100644
--- a/src/hello_imgui/impl/imgui_theme.cpp
+++ b/src/hello_imgui/impl/imgui_theme.cpp
@@ -5,6 +5,7 @@
 // Some themes were adapted by themes posted by ImGui users at https://github.com/ocornut/imgui/issues/707
 //
 #include "hello_imgui/imgui_theme.h"
+#include "hello_imgui/runner_params.h"
 #include <string>
 #include <stack>

@@ -980,10 +981,12 @@ namespace ImGuiTheme
         return ImGuiStyle();
     }

-    void ApplyTheme(ImGuiTheme_ theme)
+    void ApplyTheme(ImGuiTheme_ theme, HelloImGui::RunnerParams& params)
     {
         ImGuiStyle style = ThemeToStyle(theme);
         ImGui::GetStyle() = style;
+        if ((params.callbacks.ThemeChangedCallback))
+            params.callbacks.ThemeChangedCallback();
     }

     ImGuiStyle TweakedThemeThemeToStyle(const ImGuiTweakedTheme& tweaked_theme)
diff --git a/src/hello_imgui/internal/docking_details.cpp b/src/hello_imgui/internal/docking_details.cpp
index 305ed5d..c007bc7 100644
--- a/src/hello_imgui/internal/docking_details.cpp
+++ b/src/hello_imgui/internal/docking_details.cpp
@@ -81,7 +81,7 @@ void ShowThemeTweakGuiWindow_Static()
     ShowThemeTweakGuiWindow(&gShowTweakWindow);
 }

-void MenuTheme()
+void MenuTheme(RunnerParams& params)
 {
     auto& tweakedTheme = HelloImGui::GetRunnerParams()->imGuiWindowParams.tweakedTheme;

@@ -97,7 +97,7 @@ void MenuTheme()
             if (ImGui::MenuItem(ImGuiTheme::ImGuiTheme_Name(theme), nullptr, selected))
             {
                 tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, params);
             }
         }
         ImGui::EndMenu();
@@ -272,7 +272,7 @@ void MenuView_Misc(RunnerParams& runnerParams)
        }

     if (runnerParams.imGuiWindowParams.showMenu_View_Themes)
-        MenuTheme();
+        MenuTheme(runnerParams);
 }

 void ShowViewMenu(RunnerParams & runnerParams)
diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
index e3ce2e6..fe98921 100644
--- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
+++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
@@ -453,7 +453,7 @@ namespace HelloImGui
             {
                 auto theme = ImGuiTheme::ImGuiTheme_FromName(themeName.c_str());
                 inOutRunnerParams->imGuiWindowParams.tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);
         }
         ImGui::EndMenu();
@@ -272,7 +272,7 @@ void MenuView_Misc(RunnerParams& runnerParams)
        }

     if (runnerParams.imGuiWindowParams.showMenu_View_Themes)
-        MenuTheme();
+        MenuTheme(runnerParams);
 }

 void ShowViewMenu(RunnerParams & runnerParams)
diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
index e3ce2e6..fe98921 100644
--- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
+++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
@@ -453,7 +453,7 @@ namespace HelloImGui
             {
                 auto theme = ImGuiTheme::ImGuiTheme_FromName(themeName.c_str());
                 inOutRunnerParams->imGuiWindowParams.tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);
         }
         ImGui::EndMenu();
@@ -272,7 +272,7 @@ void MenuView_Misc(RunnerParams& runnerParams)
        }

     if (runnerParams.imGuiWindowParams.showMenu_View_Themes)
-        MenuTheme();
+        MenuTheme(runnerParams);
 }

 void ShowViewMenu(RunnerParams & runnerParams)
diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
index e3ce2e6..fe98921 100644
--- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
+++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
@@ -453,7 +453,7 @@ namespace HelloImGui
             {
                 auto theme = ImGuiTheme::ImGuiTheme_FromName(themeName.c_str());
                 inOutRunnerParams->imGuiWindowParams.tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);

diff --git a/src/hello_imgui/runner_callbacks.h b/src/hello_imgui/runner_callbacks.h
        }

     if (runnerParams.imGuiWindowParams.showMenu_View_Themes)
-        MenuTheme();
+        MenuTheme(runnerParams);
 }

 void ShowViewMenu(RunnerParams & runnerParams)
diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
index e3ce2e6..fe98921 100644
--- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
+++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
@@ -453,7 +453,7 @@ namespace HelloImGui
             {
                 auto theme = ImGuiTheme::ImGuiTheme_FromName(themeName.c_str());
                 inOutRunnerParams->imGuiWindowParams.tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);
 }

 void ShowViewMenu(RunnerParams & runnerParams)
diff --git a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
index e3ce2e6..fe98921 100644
--- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
+++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
@@ -453,7 +453,7 @@ namespace HelloImGui
             {
                 auto theme = ImGuiTheme::ImGuiTheme_FromName(themeName.c_str());
                 inOutRunnerParams->imGuiWindowParams.tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);

diff --git a/src/hello_imgui/runner_callbacks.h b/src/hello_imgui/runner_callbacks.h
--- a/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
+++ b/src/hello_imgui/internal/hello_imgui_ini_settings.cpp
@@ -453,7 +453,7 @@ namespace HelloImGui
             {
                 auto theme = ImGuiTheme::ImGuiTheme_FromName(themeName.c_str());
                 inOutRunnerParams->imGuiWindowParams.tweakedTheme.Theme = theme;
-                ImGuiTheme::ApplyTheme(theme);
+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);

+                ImGuiTheme::ApplyTheme(theme, *inOutRunnerParams);
             }
             HelloImGui::SwitchLayout(layoutName);

diff --git a/src/hello_imgui/runner_callbacks.h b/src/hello_imgui/runner_callbacks.h
index ebe4fb7..c3322a3 100644
--- a/src/hello_imgui/runner_callbacks.h
+++ b/src/hello_imgui/runner_callbacks.h
@@ -264,6 +264,9 @@ struct RunnerCallbacks
     AnyEventCallback AnyBackendEventCallback = EmptyEventCallback();


+    VoidFunction ThemeChangedCallback = EmptyVoidFunction();
+
+
     // --------------- Mobile callbacks -------------------
 #ifdef HELLOIMGUI_MOBILEDEVICE
     // `mobileCallbacks`: Callbacks that are called by the application

xuboying avatar Dec 09 '25 16:12 xuboying

Hi,

Thank you. Please submit a PR, it will be easier to investigate

pthom avatar Dec 09 '25 17:12 pthom

Thanks, I’ve sent the PR.

Below is a minimal demo showing how I’m using the new callback:

    params.callbacks.ThemeChanged = []{
        puts("Theme changed");
        ImVec4 bg = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
        float luminance = 0.2126f * bg.x + 0.7152f * bg.y + 0.0722f * bg.z;
        puts(luminance < 0.5f ? "Dark" : "Light");
    };

This example prints a message whenever the theme changes and determines whether the current background is dark or light based on luminance.

xuboying avatar Dec 10 '25 14:12 xuboying