diff --git a/src/hello_imgui/imgui_theme.h b/src/hello_imgui/imgui_theme.h index 7cd79a08..8a2395c4 100644 --- a/src/hello_imgui/imgui_theme.h +++ b/src/hello_imgui/imgui_theme.h @@ -70,11 +70,34 @@ namespace ImGuiTheme { ImGuiTheme_ Theme = ImGuiTheme_DarculaDarker; ImGuiThemeTweaks Tweaks = ImGuiThemeTweaks(); + + ImGuiTweakedTheme(ImGuiTheme_ theme = ImGuiTheme_DarculaDarker, const ImGuiThemeTweaks& tweaks = ImGuiThemeTweaks()) + : Theme(theme), Tweaks(tweaks) {} }; ImGuiStyle TweakedThemeThemeToStyle(const ImGuiTweakedTheme& tweaked_theme); void ApplyTweakedTheme(const ImGuiTweakedTheme& tweaked_theme); + // PushTweakedTheme() / PopTweakedTheme() + // Push and pop a tweaked theme + // + // Note: If you want the theme to apply globally to a window, you need to apply it + // *before* calling ImGui::Begin + // + // For example, within Hello ImGui, given a dockable window, you should set this option: + // myDockableWindow.callBeginEnd = false; + // And then: + // - call ImGuiTheme::PushTweakedTheme + // - call ImGui::Begin + // - display your content + // - call ImGui::End + // - call ImGuiTheme::PopTweakedTheme + // + // See demo inside src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp: + // look at `GuiWindowAlternativeTheme()` + void PushTweakedTheme(const ImGuiTweakedTheme& tweaked_theme); + void PopTweakedTheme(); + // Show the theme selection listbox, the theme tweak widgets, as well as ImGui::ShowStyleEditor. Returns true if modified (Warning, when using ShowStyleEditor, no info about modification is transmitted) bool ShowThemeTweakGui(ImGuiTweakedTheme *tweaked_theme); diff --git a/src/hello_imgui/impl/imgui_theme.cpp b/src/hello_imgui/impl/imgui_theme.cpp index ceb0c73e..2a8dd055 100644 --- a/src/hello_imgui/impl/imgui_theme.cpp +++ b/src/hello_imgui/impl/imgui_theme.cpp @@ -6,6 +6,7 @@ // #include "hello_imgui/imgui_theme.h" #include +#include namespace ImGuiTheme { @@ -970,6 +971,26 @@ namespace ImGuiTheme ImGui::GetStyle() = TweakedThemeThemeToStyle(tweaked_theme); } + std::stack gPreviousStyles_PushTweakedTheme; + + void PushTweakedTheme(const ImGuiTweakedTheme& tweaked_theme) + { + gPreviousStyles_PushTweakedTheme.push(ImGui::GetStyle()); + ApplyTweakedTheme(tweaked_theme); + + bool tooManyThemes = gPreviousStyles_PushTweakedTheme.size() > 10; + if (tooManyThemes) + IM_ASSERT(false && "Too many PushTweakedTheme() calls without matching PopTweakedTheme()"); + } + + void PopTweakedTheme() + { + IM_ASSERT(!gPreviousStyles_PushTweakedTheme.empty()); + ImGui::GetStyle() = gPreviousStyles_PushTweakedTheme.top(); + gPreviousStyles_PushTweakedTheme.pop(); + } + + bool _ShowThemeSelector(ImGuiTheme_* theme) { bool changed = false; diff --git a/src/hello_imgui_demos/hello_imgui_demodocking/assets/images/haiku.png b/src/hello_imgui_demos/hello_imgui_demodocking/assets/images/haiku.png new file mode 100644 index 00000000..778cc9d4 Binary files /dev/null and b/src/hello_imgui_demos/hello_imgui_demodocking/assets/images/haiku.png differ diff --git a/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp b/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp index 30da0336..009b8dfe 100644 --- a/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp +++ b/src/hello_imgui_demos/hello_imgui_demodocking/hello_imgui_demodocking.main.cpp @@ -68,10 +68,10 @@ struct AppState MyAppSettings myAppSettings; // This values will be stored in the application settings - HelloImGui::FontDpiResponsive *TitleFont; - HelloImGui::FontDpiResponsive *ColorFont; - HelloImGui::FontDpiResponsive *EmojiFont; - HelloImGui::FontDpiResponsive *LargeIconFont; + HelloImGui::FontDpiResponsive *TitleFont; + HelloImGui::FontDpiResponsive *ColorFont; + HelloImGui::FontDpiResponsive *EmojiFont; + HelloImGui::FontDpiResponsive *LargeIconFont; }; @@ -332,6 +332,113 @@ void GuiWindowLayoutCustomization(AppState& appState) } +void GuiWindowAlternativeTheme(AppState& appState) +{ + // Since this window applies a theme, We need to call "ImGui::Begin" ourselves so + // that we can apply the theme before opening the window. + // + // In order to obtain this, we applied the following option to the window + // that displays this Gui: + // alternativeThemeWindow.callBeginEnd = false; + + // Apply the theme before opening the window + ImGuiTheme::ImGuiTweakedTheme tweakedTheme; + tweakedTheme.Theme = ImGuiTheme::ImGuiTheme_WhiteIsWhite; + tweakedTheme.Tweaks.Rounding = 0.0f; + ImGuiTheme::PushTweakedTheme(tweakedTheme); + + // Open the window + bool windowOpened = ImGui::Begin("Alternative Theme"); + if (windowOpened) + { + // Display some widgets + ImGui::PushFont(appState.TitleFont->font); ImGui::Text("Alternative Theme"); ImGui::PopFont(); + ImGui::Text("This window uses a different theme"); + ImGui::SetItemTooltip(" ImGuiTheme::ImGuiTweakedTheme tweakedTheme;\n" + " tweakedTheme.Theme = ImGuiTheme::ImGuiTheme_WhiteIsWhite;\n" + " tweakedTheme.Tweaks.Rounding = 0.0f;\n" + " ImGuiTheme::PushTweakedTheme(tweakedTheme);"); + + if (ImGui::CollapsingHeader("Basic Widgets", ImGuiTreeNodeFlags_DefaultOpen)) + { + static bool checked = true; + ImGui::Checkbox("Checkbox", &checked); + + if (ImGui::Button("Button")) + HelloImGui::Log(HelloImGui::LogLevel::Info, "Button was pressed"); + ImGui::SetItemTooltip("This is a button"); + + static int radio = 0; + ImGui::RadioButton("Radio 1", &radio, 0); ImGui::SameLine(); + ImGui::RadioButton("Radio 2", &radio, 1); ImGui::SameLine(); + ImGui::RadioButton("Radio 3", &radio, 2); + + // Haiku + { + // Display a image of the haiku below with Japanese characters + // with an informative tooltip + float haikuImageHeight = HelloImGui::EmSize(5.f); + HelloImGui::ImageFromAsset("images/haiku.png", ImVec2(0.f, haikuImageHeight)); + ImGui::SetItemTooltip(R"( +Extract from Wikipedia +------------------------------------------------------------------------------- + +In early 1686, Bashō composed one of his best-remembered haiku: + + furu ike ya / kawazu tobikomu / mizu no oto + + an ancient pond / a frog jumps in / the splash of water + +This poem became instantly famous. + +------------------------------------------------------------------------------- + +This haiku is here rendered as an image, mainly to preserve space, +because adding a Japanese font to the project would enlarge its size. +Handling Japanese font is of course possible within ImGui / Hello ImGui! + )"); + + // Display the haiku text as an InputTextMultiline + static std::string poem = + " Old Pond\n" + " Frog Leaps In\n" + " Water's Sound\n" + "\n" + " Matsuo Bashō - 1686"; + ImGui::InputTextMultiline("##Poem", &poem, HelloImGui::EmToVec2(15.f, 5.5f)); + } + + // A popup with a modal window + if (ImGui::Button("Open Modal")) + ImGui::OpenPopup("MyModal"); + if (ImGui::BeginPopupModal("MyModal", NULL, ImGuiWindowFlags_AlwaysAutoResize)) + { + ImGui::Text("This is a modal window"); + if (ImGui::Button("Close")) + ImGui::CloseCurrentPopup(); + ImGui::EndPopup(); + } + + static std::string text = "Hello, world!"; + ImGui::InputText("Input text", &text); + + if (ImGui::TreeNode("Text Display")) + { + ImGui::Text("Hello, world!"); + ImGui::TextColored(ImVec4(1.f, 0.5f, 0.5f, 1.f), "Some text"); + ImGui::TextDisabled("Disabled text"); + ImGui::TextWrapped("This is a long text that will be wrapped in the window"); + ImGui::TreePop(); + } + } + } + // Close the window + ImGui::End(); + + // Restore the theme + ImGuiTheme::PopTweakedTheme(); +} + void DemoAssets(AppState& appState) { ImGui::PushFont(appState.TitleFont->font); ImGui::Text("Image From Asset"); ImGui::PopFont(); @@ -448,6 +555,7 @@ void StatusBarGui(AppState& app_state) } } + // The menu gui void ShowMenuGui(HelloImGui::RunnerParams& runnerParams) { @@ -520,9 +628,9 @@ std::vector CreateDefaultDockingSplits() // | | | // | Command| | // | Space | MainDockSpace | - // | | | - // | | | - // | | | + // |------- | | + // | Command| | + // | Space2 | | // ------------------------------------------- // | MiscSpace | // ------------------------------------------- @@ -543,7 +651,14 @@ std::vector CreateDefaultDockingSplits() splitMainCommand.direction = ImGuiDir_Left; splitMainCommand.ratio = 0.25f; - std::vector splits {splitMainMisc, splitMainCommand}; + // Then, add CommandSpace2 below CommandSpace + HelloImGui::DockingSplit splitMainCommand2; + splitMainCommand2.initialDock = "CommandSpace"; + splitMainCommand2.newDock = "CommandSpace2"; + splitMainCommand2.direction = ImGuiDir_Down; + splitMainCommand2.ratio = 0.4f; + + std::vector splits {splitMainMisc, splitMainCommand, splitMainCommand2}; return splits; } @@ -556,10 +671,10 @@ std::vector CreateAlternativeDockingSplits() // | Space | MainDockSpace | // | | | // ------------------------------------------- - // | | - // | | - // | CommandSpace | - // | | + // | | | + // | | Command | + // | CommandSpace | Space2 | + // | | | // ------------------------------------------- HelloImGui::DockingSplit splitMainCommand; @@ -568,13 +683,19 @@ std::vector CreateAlternativeDockingSplits() splitMainCommand.direction = ImGuiDir_Down; splitMainCommand.ratio = 0.5f; + HelloImGui::DockingSplit splitMainCommand2; + splitMainCommand2.initialDock = "CommandSpace"; + splitMainCommand2.newDock = "CommandSpace2"; + splitMainCommand2.direction = ImGuiDir_Right; + splitMainCommand2.ratio = 0.4f; + HelloImGui::DockingSplit splitMainMisc; splitMainMisc.initialDock = "MainDockSpace"; splitMainMisc.newDock = "MiscSpace"; splitMainMisc.direction = ImGuiDir_Left; splitMainMisc.ratio = 0.5f; - std::vector splits {splitMainCommand, splitMainMisc}; + std::vector splits {splitMainCommand, splitMainCommand2, splitMainMisc}; return splits; } @@ -618,12 +739,22 @@ std::vector CreateDockableWindows(AppState& appState additionalWindow.dockSpaceName = "MiscSpace"; // when shown, it will appear in BottomSpace. additionalWindow.GuiFunction = [] { ImGui::Text("This is the additional window"); }; + // alternativeThemeWindow + HelloImGui::DockableWindow alternativeThemeWindow; + // Since this window applies a theme, We need to call "ImGui::Begin" ourselves so + // that we can apply the theme before opening the window. + alternativeThemeWindow.callBeginEnd = false; + alternativeThemeWindow.label = "Alternative Theme"; + alternativeThemeWindow.dockSpaceName = "CommandSpace2"; + alternativeThemeWindow.GuiFunction = [&appState]() { GuiWindowAlternativeTheme(appState); }; + std::vector dockableWindows { featuresDemoWindow, layoutCustomizationWindow, logsWindow, dearImGuiDemoWindow, additionalWindow, + alternativeThemeWindow }; return dockableWindows; }