Begin: WIP consistent Begin/End behavior.
diff --git a/docs/FAQ.md b/docs/FAQ.md
index f47015d..8c247f3 100644
--- a/docs/FAQ.md
+++ b/docs/FAQ.md
@@ -429,8 +429,10 @@
### Q: How can I display custom shapes? (using low-level ImDrawList API)
- You can use the low-level `ImDrawList` api to render shapes within a window.
+
```cpp
-ImGui::Begin("My shapes");
+if (!ImGui::Begin("My shapes"))
+ return;
ImDrawList* draw_list = ImGui::GetWindowDrawList();
diff --git a/docs/README.md b/docs/README.md
index a555588..c3bccc3 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -52,7 +52,8 @@
Code:
```cpp
// Create a window called "My First Tool", with a menu bar.
-ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar);
+if (!ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar))
+ return;
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("File"))
diff --git a/examples/example_win32_directx11/main.cpp b/examples/example_win32_directx11/main.cpp
index e6a098d..6bae5fc 100644
--- a/examples/example_win32_directx11/main.cpp
+++ b/examples/example_win32_directx11/main.cpp
@@ -122,17 +122,21 @@
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
+#if 1
+ // Enable Debugging
+ io.ConfigDebugBeginReturnValue = io.KeyShift;
+#endif
+
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
if (show_demo_window)
ImGui::ShowDemoWindow(&show_demo_window);
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
+ if (ImGui::Begin("Hello, world!")) // Create a window called "Hello, world!" and append into it.
{
static float f = 0.0f;
static int counter = 0;
- ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
-
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
ImGui::Checkbox("Another Window", &show_another_window);
@@ -150,9 +154,9 @@
}
// 3. Show another simple window.
- if (show_another_window)
+ // Passing a pointer to our bool variable in the Begin() call: the window will have a closing button that will clear the bool when clicked.
+ if (show_another_window && ImGui::Begin("Another Window", &show_another_window))
{
- ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
ImGui::Text("Hello from another window!");
if (ImGui::Button("Close Me"))
show_another_window = false;
diff --git a/imgui.cpp b/imgui.cpp
index 8531fbb..a818748 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -1083,6 +1083,9 @@
ConfigWindowsMoveFromTitleBarOnly = false;
ConfigMemoryCompactTimer = 60.0f;
+ // Debug options
+ ConfigDebugBeginReturnValue = false;
+
// Platform Functions
BackendPlatformName = BackendRendererName = NULL;
BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
@@ -4107,13 +4110,27 @@
UpdateDebugToolItemPicker();
// Create implicit/fallback window - which we will only render it if the user has added something to it.
- // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
- // This fallback is particularly important as it avoid ImGui:: calls from crashing.
+ // - We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
+ // - This fallback is particularly important as it avoid ImGui:: calls from crashing.
+ // - The fallback window exceptionally doesn't call End() automatically if Begin() returns false (this is intended).
g.WithinFrameScopeWithImplicitWindow = true;
SetNextWindowSize(ImVec2(400, 400), ImGuiCond_FirstUseEver);
Begin("Debug##Default");
IM_ASSERT(g.CurrentWindow->IsFallbackWindow == true);
+ // [DEBUG] When io.ConfigDebugBeginReturnValue is set, we make Begin() return false at different level of the window stack to validate Begin()/End() behavior in user code.
+ if (g.IO.ConfigDebugBeginReturnValue)
+ {
+ g.DebugBeginReturnValueCullDepth = (g.DebugBeginReturnValueCullDepth == -1) ? 0 : ((g.DebugBeginReturnValueCullDepth + ((g.FrameCount % 4) == 0 ? 1 : 0)) % 10);
+ char buf[64];
+ ImFormatString(buf, IM_ARRAYSIZE(buf), "Cull depth %d", g.DebugBeginReturnValueCullDepth);
+ GetForegroundDrawList()->AddText(ImVec2(0, 0), IM_COL32(255, 255, 0, 255), buf);
+ }
+ else
+ {
+ g.DebugBeginReturnValueCullDepth = -1;
+ }
+
CallContextHooks(&g, ImGuiContextHookType_NewFramePost);
}
@@ -5120,7 +5137,7 @@
bool ret = Begin(title, NULL, flags);
g.Style.ChildBorderSize = backup_border_size;
- ImGuiWindow* child_window = g.CurrentWindow;
+ ImGuiWindow* child_window = g.LastBeginWindow; // FIXME-NEWBEGIN
child_window->ChildId = id;
child_window->AutoFitChildAxises = (ImS8)auto_fit_axises;
@@ -5198,6 +5215,7 @@
// Helper to create a child window / scrolling region that looks like a normal widget frame.
bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags)
{
+ // FIXME-NEWBEGIN
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
@@ -5981,6 +5999,7 @@
// We intentionally set g.CurrentWindow to NULL to prevent usage until when the viewport is set, then will call SetCurrentWindow()
g.CurrentWindowStack.push_back(window);
g.CurrentWindow = window;
+ g.LastBeginWindow = window;
window->DC.StackSizesOnBegin.SetToCurrentState();
g.CurrentWindow = NULL;
@@ -6740,7 +6759,24 @@
window->SkipItems = skip_items;
}
- return !window->SkipItems;
+ // FIXME-OPT
+ if (window->SkipItems || g.DebugBeginReturnValueCullDepth == g.CurrentWindowStack.Size)
+ {
+ // The implicit fallback is NOT automatically ended as an exception to the rule,
+ // allowing it to always be able to receive commands without crashing.
+ if (!window->IsFallbackWindow)
+ {
+ if (window->Flags & ImGuiWindowFlags_Popup)
+ EndPopup();
+ else if (window->Flags & ImGuiWindowFlags_ChildWindow)
+ EndChild();
+ else
+ End();
+ }
+ return false;
+ }
+
+ return true;
}
void ImGui::End()
@@ -6751,6 +6787,34 @@
// Error checking: verify that user hasn't called End() too many times!
if (g.CurrentWindowStack.Size <= 1 && g.WithinFrameScopeWithImplicitWindow)
{
+ // - IMPORTANT: SINCE 1.XX (XXXX 2020): Only call a matching End() if Begin() returned true!.
+ // - IMPORTANT: BEFORE 1.XX (XXXX 2020): The return value of Begin() was inconsistent with most other BeginXXX()
+ // functions, and would require the user to always call End() even if Begin() returned false.
+
+ // - When transitioning a codebase from < 1.XX to >= 1.XX, code needs to be refactored the following way:
+ // Before ------------------------------------> After
+ // ImGui::Begin("Hello"); if (ImGui::Begin("Hello"))
+ // ImGui::Button("OK"); {
+ // ImGui::End(); ImGui::Button("OK");
+ // ImGui::End();
+ // }
+ //
+ // Before ------------------------------------> After
+ // if (ImGui::Begin("Hello")) if (ImGui::Begin("Hello"))
+ // { {
+ // ImGui::Button("OK"); ImGui::Button("OK");
+ // } ImGui::End();
+ // ImGui::End(); }
+ //
+ // Before ------------------------------------> After
+ // if (!ImGui::Begin("Hello")) if (!ImGui::Begin("Hello"))
+ // { return;
+ // ImGui::End(); ImGui::Button("OK");
+ // return; ImGui::End();
+ // }
+ // ImGui::Button("OK");
+ // ImGui::End();
+
IM_ASSERT_USER_ERROR(g.CurrentWindowStack.Size > 1, "Calling End() too many times!");
return;
}
@@ -8509,7 +8573,9 @@
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount);
}
ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDocking;
- Begin(window_name, NULL, flags | extra_flags);
+ bool ret = Begin(window_name, NULL, flags | extra_flags);
+ // FIXME-NEWBEGIN
+ IM_ASSERT(ret);
}
void ImGui::EndTooltip()
@@ -8765,11 +8831,9 @@
else
ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame
+ // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
flags |= ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoDocking;
bool is_open = Begin(name, NULL, flags);
- if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display)
- EndPopup();
-
return is_open;
}
@@ -8811,9 +8875,11 @@
const bool is_open = Begin(name, p_open, flags);
if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
{
- EndPopup();
if (is_open)
+ {
+ EndPopup();
ClosePopupToLevel(g.BeginPopupStack.Size, true);
+ }
return false;
}
return is_open;
@@ -10188,7 +10254,10 @@
SetNextWindowSizeConstraints(ImVec2(viewport->Size.x * 0.20f, viewport->Size.y * 0.20f), ImVec2(FLT_MAX, FLT_MAX));
SetNextWindowPos(viewport->Pos + viewport->Size * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
PushStyleVar(ImGuiStyleVar_WindowPadding, g.Style.WindowPadding * 2.0f);
- Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
+ bool ret = Begin("###NavWindowingList", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoSavedSettings);
+ PopStyleVar();
+ if (!ret)
+ return;
for (int n = g.WindowsFocusOrder.Size - 1; n >= 0; n--)
{
ImGuiWindow* window = g.WindowsFocusOrder[n];
@@ -10200,7 +10269,6 @@
Selectable(label, g.NavWindowingTarget == window);
}
End();
- PopStyleVar();
}
@@ -15680,10 +15748,7 @@
void ImGui::ShowMetricsWindow(bool* p_open)
{
if (!Begin("Dear ImGui Metrics/Debugger", p_open))
- {
- End();
return;
- }
ImGuiContext& g = *GImGui;
ImGuiIO& io = g.IO;
diff --git a/imgui.h b/imgui.h
index 52110b8..af4e787 100644
--- a/imgui.h
+++ b/imgui.h
@@ -68,6 +68,9 @@
#define IMGUI_HAS_VIEWPORT 1 // Viewport WIP branch
#define IMGUI_HAS_DOCK 1 // Docking WIP branch
+// Features
+#define IMGUI_HAS_NEWBEGIN 1
+
// Define attributes of all API symbols declarations (e.g. for DLL under Windows)
// IMGUI_API is used for core imgui functions, IMGUI_IMPL_API is used for the default backends files (imgui_impl_xxx.h)
// Using dear imgui via a shared library is not recommended, because we don't guarantee backward nor forward ABI compatibility (also function call overhead, as dear imgui is a call-heavy API)
@@ -297,10 +300,10 @@
// - You may append multiple times to the same window during the same frame by calling Begin()/End() pairs multiple times.
// Some information such as 'flags' or 'p_open' will only be considered by the first call to Begin().
// - Begin() return false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting
- // anything to the window. Always call a matching End() for each Begin() call, regardless of its return value!
- // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
- // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function
- // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
+ // anything to the window.
+ // - IMPORTANT: SINCE 1.XX (XXXX 2020): Only call a matching End() if Begin() returned true!.
+ // - IMPORTANT: BEFORE 1.XX (XXXX 2020): The return value of Begin() was inconsistent with most other BeginXXX()
+ // functions, and would require the user to always call End() even if Begin() returned false.
// - Note that the bottom of window stack always contains a window called "Debug".
IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0);
IMGUI_API void End();
@@ -309,10 +312,9 @@
// - Use child windows to begin into a self-contained independent scrolling/clipping regions within a host window. Child windows can embed their own child.
// - For each independent axis of 'size': ==0.0f: use remaining host window size / >0.0f: fixed size / <0.0f: use remaining window size minus abs(size) / Each axis can use a different mode, e.g. ImVec2(0,400).
// - BeginChild() returns false to indicate the window is collapsed or fully clipped, so you may early out and omit submitting anything to the window.
- // Always call a matching EndChild() for each BeginChild() call, regardless of its return value.
- // [Important: due to legacy reason, this is inconsistent with most other functions such as BeginMenu/EndMenu,
- // BeginPopup/EndPopup, etc. where the EndXXX call should only be called if the corresponding BeginXXX function
- // returned true. Begin and BeginChild are the only odd ones out. Will be fixed in a future update.]
+ // - IMPORTANT: SINCE 1.XX (XXXX 2020): Only call a matching EndChild() if BeginChild() returned true!.
+ // - IMPORTANT: BEFORE 1.XX (XXXX 2020): The return value of BeginChild() was inconsistent with most other BeginXXX()
+ // functions, and would require the user to always call EndChild() even if BeginChild() returned false. This has been changed.
IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0, 0), bool border = false, ImGuiWindowFlags flags = 0);
IMGUI_API void EndChild();
@@ -1821,6 +1823,9 @@
bool ConfigWindowsMoveFromTitleBarOnly; // = false // [BETA] Set to true to only allow moving windows when clicked+dragged from the title bar. Windows without a title bar are not affected.
float ConfigMemoryCompactTimer; // = 60.0f // [BETA] Free transient windows/tables memory buffers when unused for given amount of time. Set to -1.0f to disable.
+ // Debug options
+ bool ConfigDebugBeginReturnValue; // = false // When set, some calls to Begin() will return false to facilitate testing and transitioning to 1.78 Begin()/End() pairing behavior. Will cycle through each unique window depth then repeat. Suggested use: add "io.ConfigDebugBeginReturnValue = io.KeyShift" in your main loop then occasionally press SHIFT. Windows should be flickering. Your code will assert in End() if calling End() incorrectly.
+
//------------------------------------------------------------------
// Platform Functions
// (the imgui_impl_xxxx backend files are setting those up for you)
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 4df021c..76b8c95 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -300,9 +300,11 @@
if (show_app_about) { ImGui::ShowAboutWindow(&show_app_about); }
if (show_app_style_editor)
{
- ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor);
- ImGui::ShowStyleEditor();
- ImGui::End();
+ if (ImGui::Begin("Dear ImGui Style Editor", &show_app_style_editor))
+ {
+ ImGui::ShowStyleEditor();
+ ImGui::End();
+ }
}
// Demonstrate the various window flags. Typically you would just use the default!
@@ -339,11 +341,7 @@
// Main body of the Demo window starts here.
if (!ImGui::Begin("Dear ImGui Demo", p_open, window_flags))
- {
- // Early out if the window is collapsed, as an optimization.
- ImGui::End();
return;
- }
// Most "big" widgets share a common width settings by default. See 'Demo->Layout->Widgets Width' for details.
@@ -2109,48 +2107,54 @@
static bool embed_all_inside_a_child_window = false;
ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window);
+ bool visible = true;
if (embed_all_inside_a_child_window)
- ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true);
+ visible = ImGui::BeginChild("outer_child", ImVec2(0, ImGui::GetFontSize() * 20.0f), true);
- // Testing IsWindowFocused() function with its various flags.
- // Note that the ImGuiFocusedFlags_XXX flags can be combined.
- ImGui::BulletText(
- "IsWindowFocused() = %d\n"
- "IsWindowFocused(_ChildWindows) = %d\n"
- "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
- "IsWindowFocused(_RootWindow) = %d\n"
- "IsWindowFocused(_AnyWindow) = %d\n",
- ImGui::IsWindowFocused(),
- ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
- ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
- ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
- ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
+ if (visible)
+ {
+ // Testing IsWindowFocused() function with its various flags.
+ // Note that the ImGuiFocusedFlags_XXX flags can be combined.
+ ImGui::BulletText(
+ "IsWindowFocused() = %d\n"
+ "IsWindowFocused(_ChildWindows) = %d\n"
+ "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n"
+ "IsWindowFocused(_RootWindow) = %d\n"
+ "IsWindowFocused(_AnyWindow) = %d\n",
+ ImGui::IsWindowFocused(),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow),
+ ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow));
- // Testing IsWindowHovered() function with its various flags.
- // Note that the ImGuiHoveredFlags_XXX flags can be combined.
- ImGui::BulletText(
- "IsWindowHovered() = %d\n"
- "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
- "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
- "IsWindowHovered(_ChildWindows) = %d\n"
- "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
- "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
- "IsWindowHovered(_RootWindow) = %d\n"
- "IsWindowHovered(_AnyWindow) = %d\n",
- ImGui::IsWindowHovered(),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
- ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
+ // Testing IsWindowHovered() function with its various flags.
+ // Note that the ImGuiHoveredFlags_XXX flags can be combined.
+ ImGui::BulletText(
+ "IsWindowHovered() = %d\n"
+ "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n"
+ "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n"
+ "IsWindowHovered(_ChildWindows) = %d\n"
+ "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n"
+ "IsWindowHovered(_ChildWindows|_AllowWhenBlockedByPopup) = %d\n"
+ "IsWindowHovered(_RootWindow) = %d\n"
+ "IsWindowHovered(_AnyWindow) = %d\n",
+ ImGui::IsWindowHovered(),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_AllowWhenBlockedByPopup),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow),
+ ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow));
- ImGui::BeginChild("child", ImVec2(0, 50), true);
- ImGui::Text("This is another child window for testing the _ChildWindows flag.");
- ImGui::EndChild();
- if (embed_all_inside_a_child_window)
- ImGui::EndChild();
+ if (ImGui::BeginChild("child", ImVec2(0, 50), true))
+ {
+ ImGui::Text("This is another child window for testing the _ChildWindows flag.");
+ ImGui::EndChild();
+ }
+ if (embed_all_inside_a_child_window)
+ ImGui::EndChild();
+ }
static char unused_str[] = "This widget is only here to be able to tab-out of the widgets above.";
ImGui::InputText("unused", unused_str, IM_ARRAYSIZE(unused_str), ImGuiInputTextFlags_ReadOnly);
@@ -2159,12 +2163,11 @@
// This is useful in particular if you want to create a context menu associated to the title bar of a window.
// This will also work when docked into a Tab (the Tab replace the Title Bar and guarantee the same properties).
static bool test_window = false;
+ // FIXME-DOCK: This window cannot be docked within the ImGui Demo window, this will cause a feedback loop and get them stuck.
+ // Could we fix this through an ImGuiWindowClass feature? Or an API call to tag our parent as "don't skip items"?
ImGui::Checkbox("Hovered/Active tests after Begin() for title bar testing", &test_window);
- if (test_window)
+ if (test_window && ImGui::Begin("Title bar Hovered/Active tests", &test_window))
{
- // FIXME-DOCK: This window cannot be docked within the ImGui Demo window, this will cause a feedback loop and get them stuck.
- // Could we fix this through an ImGuiWindowClass feature? Or an API call to tag our parent as "don't skip items"?
- ImGui::Begin("Title bar Hovered/Active tests", &test_window);
if (ImGui::BeginPopupContextItem()) // <-- This is using IsItemHovered()
{
if (ImGui::MenuItem("Close")) { test_window = false; }
@@ -2199,10 +2202,12 @@
ImGuiWindowFlags window_flags = ImGuiWindowFlags_HorizontalScrollbar;
if (disable_mouse_wheel)
window_flags |= ImGuiWindowFlags_NoScrollWithMouse;
- ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags);
- for (int i = 0; i < 100; i++)
- ImGui::Text("%04d: scrollable region", i);
- ImGui::EndChild();
+ if (ImGui::BeginChild("ChildL", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 260), false, window_flags))
+ {
+ for (int i = 0; i < 100; i++)
+ ImGui::Text("%04d: scrollable region", i);
+ ImGui::EndChild();
+ }
}
ImGui::SameLine();
@@ -2215,29 +2220,32 @@
if (!disable_menu)
window_flags |= ImGuiWindowFlags_MenuBar;
ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f);
- ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
- if (!disable_menu && ImGui::BeginMenuBar())
- {
- if (ImGui::BeginMenu("Menu"))
- {
- ShowExampleMenuFile();
- ImGui::EndMenu();
- }
- ImGui::EndMenuBar();
- }
- if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
- {
- for (int i = 0; i < 100; i++)
- {
- char buf[32];
- sprintf(buf, "%03d", i);
- ImGui::TableNextColumn();
- ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
- }
- ImGui::EndTable();
- }
- ImGui::EndChild();
+ bool visible = ImGui::BeginChild("ChildR", ImVec2(0, 260), true, window_flags);
ImGui::PopStyleVar();
+ if (visible)
+ {
+ if (!disable_menu && ImGui::BeginMenuBar())
+ {
+ if (ImGui::BeginMenu("Menu"))
+ {
+ ShowExampleMenuFile();
+ ImGui::EndMenu();
+ }
+ ImGui::EndMenuBar();
+ }
+ if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ char buf[32];
+ sprintf(buf, "%03d", i);
+ ImGui::TableNextColumn();
+ ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
+ }
+ ImGui::EndTable();
+ }
+ ImGui::EndChild();
+ }
}
ImGui::Separator();
@@ -2256,14 +2264,17 @@
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
ImGui::PushStyleColor(ImGuiCol_ChildBg, IM_COL32(255, 0, 0, 100));
- ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
- for (int n = 0; n < 50; n++)
- ImGui::Text("Some test %d", n);
- ImGui::EndChild();
+ bool visible = ImGui::BeginChild("Red", ImVec2(200, 100), true, ImGuiWindowFlags_None);
+ ImGui::PopStyleColor();
+ if (visible)
+ {
+ for (int n = 0; n < 50; n++)
+ ImGui::Text("Some test %d", n);
+ ImGui::EndChild();
+ }
bool child_is_hovered = ImGui::IsItemHovered();
ImVec2 child_rect_min = ImGui::GetItemRectMin();
ImVec2 child_rect_max = ImGui::GetItemRectMax();
- ImGui::PopStyleColor();
ImGui::Text("Hovered: %d", child_is_hovered);
ImGui::Text("Rect of child window is: (%.0f,%.0f) (%.0f,%.0f)", child_rect_min.x, child_rect_min.y, child_rect_max.x, child_rect_max.y);
}
@@ -2780,18 +2791,17 @@
const ImGuiWindowFlags child_flags = enable_extra_decorations ? ImGuiWindowFlags_MenuBar : 0;
const ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
- const bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags);
- if (ImGui::BeginMenuBar())
+ if (ImGui::BeginChild(child_id, ImVec2(child_w, 200.0f), true, child_flags))
{
- ImGui::TextUnformatted("abc");
- ImGui::EndMenuBar();
- }
- if (scroll_to_off)
- ImGui::SetScrollY(scroll_to_off_px);
- if (scroll_to_pos)
- ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
- if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
- {
+ if (ImGui::BeginMenuBar())
+ {
+ ImGui::TextUnformatted("abc");
+ ImGui::EndMenuBar();
+ }
+ if (scroll_to_off)
+ ImGui::SetScrollY(scroll_to_off_px);
+ if (scroll_to_pos)
+ ImGui::SetScrollFromPosY(ImGui::GetCursorStartPos().y + scroll_to_pos_px, i * 0.25f);
for (int item = 0; item < 100; item++)
{
if (enable_track && item == track_item)
@@ -2804,11 +2814,15 @@
ImGui::Text("Item %d", item);
}
}
+ float scroll_y = ImGui::GetScrollY();
+ float scroll_max_y = ImGui::GetScrollMaxY();
+ ImGui::EndChild();
+ ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
}
- float scroll_y = ImGui::GetScrollY();
- float scroll_max_y = ImGui::GetScrollMaxY();
- ImGui::EndChild();
- ImGui::Text("%.0f/%.0f", scroll_y, scroll_max_y);
+ else
+ {
+ ImGui::Text("N/A");
+ }
ImGui::EndGroup();
}
ImGui::PopID();
@@ -2826,13 +2840,14 @@
float child_height = ImGui::GetTextLineHeight() + style.ScrollbarSize + style.WindowPadding.y * 2.0f;
ImGuiWindowFlags child_flags = ImGuiWindowFlags_HorizontalScrollbar | (enable_extra_decorations ? ImGuiWindowFlags_AlwaysVerticalScrollbar : 0);
ImGuiID child_id = ImGui::GetID((void*)(intptr_t)i);
- bool child_is_visible = ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags);
- if (scroll_to_off)
- ImGui::SetScrollX(scroll_to_off_px);
- if (scroll_to_pos)
- ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
- if (child_is_visible) // Avoid calling SetScrollHereY when running with culled items
+ float scroll_x = 0.0f;
+ float scroll_max_x = 0.0f;
+ if (ImGui::BeginChild(child_id, ImVec2(-100, child_height), true, child_flags))
{
+ if (scroll_to_off)
+ ImGui::SetScrollX(scroll_to_off_px);
+ if (scroll_to_pos)
+ ImGui::SetScrollFromPosX(ImGui::GetCursorStartPos().x + scroll_to_pos_px, i * 0.25f);
for (int item = 0; item < 100; item++)
{
if (enable_track && item == track_item)
@@ -2846,10 +2861,10 @@
}
ImGui::SameLine();
}
+ scroll_x = ImGui::GetScrollX();
+ scroll_max_x = ImGui::GetScrollMaxX();
+ ImGui::EndChild();
}
- float scroll_x = ImGui::GetScrollX();
- float scroll_max_x = ImGui::GetScrollMaxX();
- ImGui::EndChild();
ImGui::SameLine();
const char* names[] = { "Left", "25%", "Center", "75%", "Right" };
ImGui::Text("%s\n%.0f/%.0f", names[i], scroll_x, scroll_max_x);
@@ -2866,33 +2881,37 @@
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f);
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f));
ImVec2 scrolling_child_size = ImVec2(0, ImGui::GetFrameHeightWithSpacing() * 7 + 30);
- ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar);
- for (int line = 0; line < lines; line++)
+ float scroll_x = 0.0f;
+ float scroll_max_x = 0.0f;
+ if (ImGui::BeginChild("scrolling", scrolling_child_size, true, ImGuiWindowFlags_HorizontalScrollbar))
{
- // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
- // If you want to create your own time line for a real application you may be better off manipulating
- // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
- // yourself. You may also want to use the lower-level ImDrawList API.
- int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
- for (int n = 0; n < num_buttons; n++)
+ for (int line = 0; line < lines; line++)
{
- if (n > 0) ImGui::SameLine();
- ImGui::PushID(n + line * 1000);
- char num_buf[16];
- sprintf(num_buf, "%d", n);
- const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
- float hue = n * 0.05f;
- ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
- ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
- ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
- ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
- ImGui::PopStyleColor(3);
- ImGui::PopID();
+ // Display random stuff. For the sake of this trivial demo we are using basic Button() + SameLine()
+ // If you want to create your own time line for a real application you may be better off manipulating
+ // the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
+ // yourself. You may also want to use the lower-level ImDrawList API.
+ int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
+ for (int n = 0; n < num_buttons; n++)
+ {
+ if (n > 0) ImGui::SameLine();
+ ImGui::PushID(n + line * 1000);
+ char num_buf[16];
+ sprintf(num_buf, "%d", n);
+ const char* label = (!(n % 15)) ? "FizzBuzz" : (!(n % 3)) ? "Fizz" : (!(n % 5)) ? "Buzz" : num_buf;
+ float hue = n * 0.05f;
+ ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
+ ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
+ ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
+ ImGui::PopStyleColor(3);
+ ImGui::PopID();
+ }
}
+ scroll_x = ImGui::GetScrollX();
+ scroll_max_x = ImGui::GetScrollMaxX();
+ ImGui::EndChild();
}
- float scroll_x = ImGui::GetScrollX();
- float scroll_max_x = ImGui::GetScrollMaxX();
- ImGui::EndChild();
ImGui::PopStyleVar(2);
float scroll_x_delta = 0.0f;
ImGui::SmallButton("<<");
@@ -2909,9 +2928,12 @@
{
// Demonstrate a trick: you can use Begin to set yourself in the context of another window
// (here we are already out of your child window)
- ImGui::BeginChild("scrolling");
- ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
- ImGui::EndChild();
+ // FIXME-NEWBEGIN: Becomes more awkward
+ if (ImGui::BeginChild("scrolling"))
+ {
+ ImGui::SetScrollX(ImGui::GetScrollX() + scroll_x_delta);
+ ImGui::EndChild();
+ }
}
ImGui::Spacing();
@@ -2931,88 +2953,90 @@
static float contents_size_x = 300.0f;
if (explicit_content_size)
ImGui::SetNextWindowContentSize(ImVec2(contents_size_x, 0.0f));
- ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0);
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
- ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
- HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
- ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
- ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten)
- ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width
- ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
- ImGui::Checkbox("Columns", &show_columns); // Will use contents size
- ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size
- ImGui::Checkbox("Child", &show_child); // Will grow and use contents size
- ImGui::Checkbox("Explicit content size", &explicit_content_size);
- ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
- if (explicit_content_size)
+ if (ImGui::Begin("Horizontal contents size demo window", &show_horizontal_contents_size_demo_window, show_h_scrollbar ? ImGuiWindowFlags_HorizontalScrollbar : 0))
{
- ImGui::SameLine();
- ImGui::SetNextItemWidth(100);
- ImGui::DragFloat("##csx", &contents_size_x);
- ImVec2 p = ImGui::GetCursorScreenPos();
- ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
- ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
- ImGui::Dummy(ImVec2(0, 10));
- }
- ImGui::PopStyleVar(2);
- ImGui::Separator();
- if (show_button)
- {
- ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
- }
- if (show_tree_nodes)
- {
- bool open = true;
- if (ImGui::TreeNode("this is a tree node"))
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(2, 0));
+ ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 0));
+ HelpMarker("Test of different widgets react and impact the work rectangle growing when horizontal scrolling is enabled.\n\nUse 'Metrics->Tools->Show windows rectangles' to visualize rectangles.");
+ ImGui::Checkbox("H-scrollbar", &show_h_scrollbar);
+ ImGui::Checkbox("Button", &show_button); // Will grow contents size (unless explicitly overwritten)
+ ImGui::Checkbox("Tree nodes", &show_tree_nodes); // Will grow contents size and display highlight over full width
+ ImGui::Checkbox("Text wrapped", &show_text_wrapped);// Will grow and use contents size
+ ImGui::Checkbox("Columns", &show_columns); // Will use contents size
+ ImGui::Checkbox("Tab bar", &show_tab_bar); // Will use contents size
+ ImGui::Checkbox("Child", &show_child); // Will grow and use contents size
+ ImGui::Checkbox("Explicit content size", &explicit_content_size);
+ ImGui::Text("Scroll %.1f/%.1f %.1f/%.1f", ImGui::GetScrollX(), ImGui::GetScrollMaxX(), ImGui::GetScrollY(), ImGui::GetScrollMaxY());
+ if (explicit_content_size)
{
- if (ImGui::TreeNode("another one of those tree node..."))
+ ImGui::SameLine();
+ ImGui::SetNextItemWidth(100);
+ ImGui::DragFloat("##csx", &contents_size_x);
+ ImVec2 p = ImGui::GetCursorScreenPos();
+ ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x + 10, p.y + 10), IM_COL32_WHITE);
+ ImGui::GetWindowDrawList()->AddRectFilled(ImVec2(p.x + contents_size_x - 10, p.y), ImVec2(p.x + contents_size_x, p.y + 10), IM_COL32_WHITE);
+ ImGui::Dummy(ImVec2(0, 10));
+ }
+ ImGui::PopStyleVar(2);
+ ImGui::Separator();
+ if (show_button)
+ {
+ ImGui::Button("this is a 300-wide button", ImVec2(300, 0));
+ }
+ if (show_tree_nodes)
+ {
+ bool open = true;
+ if (ImGui::TreeNode("this is a tree node"))
{
- ImGui::Text("Some tree contents");
+ if (ImGui::TreeNode("another one of those tree node..."))
+ {
+ ImGui::Text("Some tree contents");
+ ImGui::TreePop();
+ }
ImGui::TreePop();
}
- ImGui::TreePop();
+ ImGui::CollapsingHeader("CollapsingHeader", &open);
}
- ImGui::CollapsingHeader("CollapsingHeader", &open);
- }
- if (show_text_wrapped)
- {
- ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
- }
- if (show_columns)
- {
- ImGui::Text("Tables:");
- if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
+ if (show_text_wrapped)
{
+ ImGui::TextWrapped("This text should automatically wrap on the edge of the work rectangle.");
+ }
+ if (show_columns)
+ {
+ ImGui::Text("Tables:");
+ if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
+ {
+ for (int n = 0; n < 4; n++)
+ {
+ ImGui::TableNextColumn();
+ ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
+ }
+ ImGui::EndTable();
+ }
+ ImGui::Text("Columns:");
+ ImGui::Columns(4);
for (int n = 0; n < 4; n++)
{
- ImGui::TableNextColumn();
- ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
+ ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
+ ImGui::NextColumn();
}
- ImGui::EndTable();
+ ImGui::Columns(1);
}
- ImGui::Text("Columns:");
- ImGui::Columns(4);
- for (int n = 0; n < 4; n++)
+ if (show_tab_bar && ImGui::BeginTabBar("Hello"))
{
- ImGui::Text("Width %.2f", ImGui::GetColumnWidth());
- ImGui::NextColumn();
+ if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
+ if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
+ if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
+ if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
+ ImGui::EndTabBar();
}
- ImGui::Columns(1);
+ if (show_child)
+ {
+ if (ImGui::BeginChild("child", ImVec2(0, 0), true))
+ ImGui::EndChild();
+ }
+ ImGui::End();
}
- if (show_tab_bar && ImGui::BeginTabBar("Hello"))
- {
- if (ImGui::BeginTabItem("OneOneOne")) { ImGui::EndTabItem(); }
- if (ImGui::BeginTabItem("TwoTwoTwo")) { ImGui::EndTabItem(); }
- if (ImGui::BeginTabItem("ThreeThreeThree")) { ImGui::EndTabItem(); }
- if (ImGui::BeginTabItem("FourFourFour")) { ImGui::EndTabItem(); }
- ImGui::EndTabBar();
- }
- if (show_child)
- {
- ImGui::BeginChild("child", ImVec2(0, 0), true);
- ImGui::EndChild();
- }
- ImGui::End();
}
ImGui::TreePop();
@@ -5147,24 +5171,25 @@
{
ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
ImVec2 child_size = ImVec2(0, ImGui::GetFontSize() * 20.0f);
- ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar);
- ImGui::Columns(10);
-
- // Also demonstrate using clipper for large vertical lists
- int ITEMS_COUNT = 2000;
- ImGuiListClipper clipper;
- clipper.Begin(ITEMS_COUNT);
- while (clipper.Step())
+ if (ImGui::BeginChild("##ScrollingRegion", child_size, false, ImGuiWindowFlags_HorizontalScrollbar))
{
- for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
- for (int j = 0; j < 10; j++)
- {
- ImGui::Text("Line %d Column %d...", i, j);
- ImGui::NextColumn();
- }
+ // Also demonstrate using clipper for large vertical lists
+ ImGui::Columns(10);
+ int ITEMS_COUNT = 2000;
+ ImGuiListClipper clipper;
+ clipper.Begin(ITEMS_COUNT);
+ while (clipper.Step())
+ {
+ for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ for (int j = 0; j < 10; j++)
+ {
+ ImGui::Text("Line %d Column %d...", i, j);
+ ImGui::NextColumn();
+ }
+ }
+ ImGui::Columns(1);
+ ImGui::EndChild();
}
- ImGui::Columns(1);
- ImGui::EndChild();
ImGui::TreePop();
}
@@ -5388,10 +5413,8 @@
void ImGui::ShowAboutWindow(bool* p_open)
{
if (!ImGui::Begin("About Dear ImGui", p_open, ImGuiWindowFlags_AlwaysAutoResize))
- {
- ImGui::End();
return;
- }
+
ImGui::Text("Dear ImGui %s", ImGui::GetVersion());
ImGui::Separator();
ImGui::Text("By Omar Cornut and all Dear ImGui contributors.");
@@ -5407,6 +5430,7 @@
bool copy_to_clipboard = ImGui::Button("Copy to clipboard");
ImVec2 child_size = ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 18);
ImGui::BeginChildFrame(ImGui::GetID("cfg_infos"), child_size, ImGuiWindowFlags_NoMove);
+
if (copy_to_clipboard)
{
ImGui::LogToClipboard();
@@ -5534,7 +5558,6 @@
ImGui::LogText("\n```\n");
ImGui::LogFinish();
}
- ImGui::EndChildFrame();
}
ImGui::End();
}
@@ -5804,29 +5827,31 @@
"Left-click on color square to open color picker,\n"
"Right-click to open edit options menu.");
- ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened);
- ImGui::PushItemWidth(-160);
- for (int i = 0; i < ImGuiCol_COUNT; i++)
+ if (ImGui::BeginChild("##colors", ImVec2(0, 0), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened))
{
- const char* name = ImGui::GetStyleColorName(i);
- if (!filter.PassFilter(name))
- continue;
- ImGui::PushID(i);
- ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
- if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
+ ImGui::PushItemWidth(-160);
+ for (int i = 0; i < ImGuiCol_COUNT; i++)
{
- // Tips: in a real user application, you may want to merge and use an icon font into the main font,
- // so instead of "Save"/"Revert" you'd use icons!
- // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
- ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
- ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
+ const char* name = ImGui::GetStyleColorName(i);
+ if (!filter.PassFilter(name))
+ continue;
+ ImGui::PushID(i);
+ ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags);
+ if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
+ {
+ // Tips: in a real user application, you may want to merge and use an icon font into the main font,
+ // so instead of "Save"/"Revert" you'd use icons!
+ // Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
+ }
+ ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
+ ImGui::TextUnformatted(name);
+ ImGui::PopID();
}
- ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
- ImGui::TextUnformatted(name);
- ImGui::PopID();
+ ImGui::PopItemWidth();
+ ImGui::EndChild();
}
- ImGui::PopItemWidth();
- ImGui::EndChild();
ImGui::EndTabItem();
}
@@ -5986,10 +6011,12 @@
{
static bool enabled = true;
ImGui::MenuItem("Enabled", "", &enabled);
- ImGui::BeginChild("child", ImVec2(0, 60), true);
- for (int i = 0; i < 10; i++)
- ImGui::Text("Scrolling Text %d", i);
- ImGui::EndChild();
+ if (ImGui::BeginChild("child", ImVec2(0, 60), true))
+ {
+ for (int i = 0; i < 10; i++)
+ ImGui::Text("Scrolling Text %d", i);
+ ImGui::EndChild();
+ }
static float f = 0.5f;
static int n = 0;
ImGui::SliderFloat("Value", &f, 0.0f, 1.0f);
@@ -6099,10 +6126,7 @@
{
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, p_open))
- {
- ImGui::End();
return;
- }
// As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar.
// So e.g. IsItemHovered() will return true when hovering the title bar.
@@ -6148,67 +6172,69 @@
// Reserve enough left-over height for 1 separator + 1 input text
const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
- ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar);
- if (ImGui::BeginPopupContextWindow())
+ if (ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar))
{
- if (ImGui::Selectable("Clear")) ClearLog();
- ImGui::EndPopup();
+ if (ImGui::BeginPopupContextWindow())
+ {
+ if (ImGui::Selectable("Clear")) ClearLog();
+ ImGui::EndPopup();
+ }
+
+ // Display every line as a separate entry so we can change their color or add custom widgets.
+ // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
+ // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
+ // to only process visible items. The clipper will automatically measure the height of your first item and then
+ // "seek" to display only items in the visible area.
+ // To use the clipper we can replace your standard loop:
+ // for (int i = 0; i < Items.Size; i++)
+ // With:
+ // ImGuiListClipper clipper;
+ // clipper.Begin(Items.Size);
+ // while (clipper.Step())
+ // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
+ // - That your items are evenly spaced (same height)
+ // - That you have cheap random access to your elements (you can access them given their index,
+ // without processing all the ones before)
+ // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
+ // We would need random-access on the post-filtered list.
+ // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
+ // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
+ // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
+ // to improve this example code!
+ // If your items are of variable height:
+ // - Split them into same height items would be simpler and facilitate random-seeking into your list.
+ // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
+ if (copy_to_clipboard)
+ ImGui::LogToClipboard();
+ for (int i = 0; i < Items.Size; i++)
+ {
+ const char* item = Items[i];
+ if (!Filter.PassFilter(item))
+ continue;
+
+ // Normally you would store more information in your item than just a string.
+ // (e.g. make Items[] an array of structure, store color/type etc.)
+ ImVec4 color;
+ bool has_color = false;
+ if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
+ else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
+ if (has_color)
+ ImGui::PushStyleColor(ImGuiCol_Text, color);
+ ImGui::TextUnformatted(item);
+ if (has_color)
+ ImGui::PopStyleColor();
+ }
+ if (copy_to_clipboard)
+ ImGui::LogFinish();
+
+ if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
+ ImGui::SetScrollHereY(1.0f);
+ ScrollToBottom = false;
+
+ ImGui::PopStyleVar();
+ ImGui::EndChild();
}
-
- // Display every line as a separate entry so we can change their color or add custom widgets.
- // If you only want raw text you can use ImGui::TextUnformatted(log.begin(), log.end());
- // NB- if you have thousands of entries this approach may be too inefficient and may require user-side clipping
- // to only process visible items. The clipper will automatically measure the height of your first item and then
- // "seek" to display only items in the visible area.
- // To use the clipper we can replace your standard loop:
- // for (int i = 0; i < Items.Size; i++)
- // With:
- // ImGuiListClipper clipper;
- // clipper.Begin(Items.Size);
- // while (clipper.Step())
- // for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
- // - That your items are evenly spaced (same height)
- // - That you have cheap random access to your elements (you can access them given their index,
- // without processing all the ones before)
- // You cannot this code as-is if a filter is active because it breaks the 'cheap random-access' property.
- // We would need random-access on the post-filtered list.
- // A typical application wanting coarse clipping and filtering may want to pre-compute an array of indices
- // or offsets of items that passed the filtering test, recomputing this array when user changes the filter,
- // and appending newly elements as they are inserted. This is left as a task to the user until we can manage
- // to improve this example code!
- // If your items are of variable height:
- // - Split them into same height items would be simpler and facilitate random-seeking into your list.
- // - Consider using manual call to IsRectVisible() and skipping extraneous decoration from your items.
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
- if (copy_to_clipboard)
- ImGui::LogToClipboard();
- for (int i = 0; i < Items.Size; i++)
- {
- const char* item = Items[i];
- if (!Filter.PassFilter(item))
- continue;
-
- // Normally you would store more information in your item than just a string.
- // (e.g. make Items[] an array of structure, store color/type etc.)
- ImVec4 color;
- bool has_color = false;
- if (strstr(item, "[error]")) { color = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); has_color = true; }
- else if (strncmp(item, "# ", 2) == 0) { color = ImVec4(1.0f, 0.8f, 0.6f, 1.0f); has_color = true; }
- if (has_color)
- ImGui::PushStyleColor(ImGuiCol_Text, color);
- ImGui::TextUnformatted(item);
- if (has_color)
- ImGui::PopStyleColor();
- }
- if (copy_to_clipboard)
- ImGui::LogFinish();
-
- if (ScrollToBottom || (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
- ImGui::SetScrollHereY(1.0f);
- ScrollToBottom = false;
-
- ImGui::PopStyleVar();
- ImGui::EndChild();
ImGui::Separator();
// Command-line
@@ -6432,10 +6458,7 @@
void Draw(const char* title, bool* p_open = NULL)
{
if (!ImGui::Begin(title, p_open))
- {
- ImGui::End();
return;
- }
// Options menu
if (ImGui::BeginPopup("Options"))
@@ -6455,64 +6478,65 @@
Filter.Draw("Filter", -100.0f);
ImGui::Separator();
- ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
-
- if (clear)
- Clear();
- if (copy)
- ImGui::LogToClipboard();
-
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
- const char* buf = Buf.begin();
- const char* buf_end = Buf.end();
- if (Filter.IsActive())
+ if (ImGui::BeginChild("scrolling", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar))
{
- // In this example we don't use the clipper when Filter is enabled.
- // This is because we don't have a random access on the result on our filter.
- // A real application processing logs with ten of thousands of entries may want to store the result of
- // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
- for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
+ if (clear)
+ Clear();
+ if (copy)
+ ImGui::LogToClipboard();
+
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ const char* buf = Buf.begin();
+ const char* buf_end = Buf.end();
+ if (Filter.IsActive())
{
- const char* line_start = buf + LineOffsets[line_no];
- const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
- if (Filter.PassFilter(line_start, line_end))
- ImGui::TextUnformatted(line_start, line_end);
- }
- }
- else
- {
- // The simplest and easy way to display the entire buffer:
- // ImGui::TextUnformatted(buf_begin, buf_end);
- // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
- // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
- // within the visible area.
- // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
- // on your side is recommended. Using ImGuiListClipper requires
- // - A) random access into your data
- // - B) items all being the same height,
- // both of which we can handle since we an array pointing to the beginning of each line of text.
- // When using the filter (in the block of code above) we don't have random access into the data to display
- // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
- // it possible (and would be recommended if you want to search through tens of thousands of entries).
- ImGuiListClipper clipper;
- clipper.Begin(LineOffsets.Size);
- while (clipper.Step())
- {
- for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
+ // In this example we don't use the clipper when Filter is enabled.
+ // This is because we don't have a random access on the result on our filter.
+ // A real application processing logs with ten of thousands of entries may want to store the result of
+ // search/filter.. especially if the filtering function is not trivial (e.g. reg-exp).
+ for (int line_no = 0; line_no < LineOffsets.Size; line_no++)
{
const char* line_start = buf + LineOffsets[line_no];
const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
- ImGui::TextUnformatted(line_start, line_end);
+ if (Filter.PassFilter(line_start, line_end))
+ ImGui::TextUnformatted(line_start, line_end);
}
}
- clipper.End();
+ else
+ {
+ // The simplest and easy way to display the entire buffer:
+ // ImGui::TextUnformatted(buf_begin, buf_end);
+ // And it'll just work. TextUnformatted() has specialization for large blob of text and will fast-forward
+ // to skip non-visible lines. Here we instead demonstrate using the clipper to only process lines that are
+ // within the visible area.
+ // If you have tens of thousands of items and their processing cost is non-negligible, coarse clipping them
+ // on your side is recommended. Using ImGuiListClipper requires
+ // - A) random access into your data
+ // - B) items all being the same height,
+ // both of which we can handle since we an array pointing to the beginning of each line of text.
+ // When using the filter (in the block of code above) we don't have random access into the data to display
+ // anymore, which is why we don't use the clipper. Storing or skimming through the search result would make
+ // it possible (and would be recommended if you want to search through tens of thousands of entries).
+ ImGuiListClipper clipper;
+ clipper.Begin(LineOffsets.Size);
+ while (clipper.Step())
+ {
+ for (int line_no = clipper.DisplayStart; line_no < clipper.DisplayEnd; line_no++)
+ {
+ const char* line_start = buf + LineOffsets[line_no];
+ const char* line_end = (line_no + 1 < LineOffsets.Size) ? (buf + LineOffsets[line_no + 1] - 1) : buf_end;
+ ImGui::TextUnformatted(line_start, line_end);
+ }
+ }
+ clipper.End();
+ }
+ ImGui::PopStyleVar();
+
+ if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
+ ImGui::SetScrollHereY(1.0f);
+
+ ImGui::EndChild();
}
- ImGui::PopStyleVar();
-
- if (AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
- ImGui::SetScrollHereY(1.0f);
-
- ImGui::EndChild();
ImGui::End();
}
};
@@ -6526,22 +6550,24 @@
// We take advantage of a rarely used feature: multiple calls to Begin()/End() are appending to the _same_ window.
// Most of the contents of the window will be added by the log.Draw() call.
ImGui::SetNextWindowSize(ImVec2(500, 400), ImGuiCond_FirstUseEver);
- ImGui::Begin("Example: Log", p_open);
- if (ImGui::SmallButton("[Debug] Add 5 entries"))
+ if (ImGui::Begin("Example: Log", p_open))
{
- static int counter = 0;
- const char* categories[3] = { "info", "warn", "error" };
- const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
- for (int n = 0; n < 5; n++)
+ if (ImGui::SmallButton("[Debug] Add 5 entries"))
{
- const char* category = categories[counter % IM_ARRAYSIZE(categories)];
- const char* word = words[counter % IM_ARRAYSIZE(words)];
- log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
- ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
- counter++;
+ static int counter = 0;
+ const char* categories[3] = { "info", "warn", "error" };
+ const char* words[] = { "Bumfuzzled", "Cattywampus", "Snickersnee", "Abibliophobia", "Absquatulate", "Nincompoop", "Pauciloquent" };
+ for (int n = 0; n < 5; n++)
+ {
+ const char* category = categories[counter % IM_ARRAYSIZE(categories)];
+ const char* word = words[counter % IM_ARRAYSIZE(words)];
+ log.AddLog("[%05d] [%s] Hello, current time is %.1f, here's a word: '%s'\n",
+ ImGui::GetFrameCount(), category, ImGui::GetTime(), word);
+ counter++;
+ }
}
+ ImGui::End();
}
- ImGui::End();
// Actually call in the regular Log helper (which will Begin() into the same window as we just did)
log.Draw("Example: Log", p_open);
@@ -6555,22 +6581,23 @@
static void ShowExampleAppLayout(bool* p_open)
{
ImGui::SetNextWindowSize(ImVec2(500, 440), ImGuiCond_FirstUseEver);
- if (ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
+ if (!ImGui::Begin("Example: Simple layout", p_open, ImGuiWindowFlags_MenuBar))
+ return;
+ if (ImGui::BeginMenuBar())
{
- if (ImGui::BeginMenuBar())
+ if (ImGui::BeginMenu("File"))
{
- if (ImGui::BeginMenu("File"))
- {
- if (ImGui::MenuItem("Close")) *p_open = false;
- ImGui::EndMenu();
- }
- ImGui::EndMenuBar();
+ if (ImGui::MenuItem("Close")) *p_open = false;
+ ImGui::EndMenu();
}
+ ImGui::EndMenuBar();
+ }
- // Left
- static int selected = 0;
+ // Left
+ static int selected = 0;
+ {
+ if (ImGui::BeginChild("left pane", ImVec2(150, 0), true))
{
- ImGui::BeginChild("left pane", ImVec2(150, 0), true);
for (int i = 0; i < 100; i++)
{
char label[128];
@@ -6580,12 +6607,14 @@
}
ImGui::EndChild();
}
- ImGui::SameLine();
+ }
+ ImGui::SameLine();
- // Right
+ // Right
+ {
+ ImGui::BeginGroup();
+ if (ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()))) // Leave room for 1 line below us
{
- ImGui::BeginGroup();
- ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us
ImGui::Text("MyObject: %d", selected);
ImGui::Separator();
if (ImGui::BeginTabBar("##Tabs", ImGuiTabBarFlags_None))
@@ -6603,11 +6632,11 @@
ImGui::EndTabBar();
}
ImGui::EndChild();
- if (ImGui::Button("Revert")) {}
- ImGui::SameLine();
- if (ImGui::Button("Save")) {}
- ImGui::EndGroup();
}
+ if (ImGui::Button("Revert")) {}
+ ImGui::SameLine();
+ if (ImGui::Button("Save")) {}
+ ImGui::EndGroup();
}
ImGui::End();
}
@@ -6668,10 +6697,7 @@
{
ImGui::SetNextWindowSize(ImVec2(430, 450), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Property editor", p_open))
- {
- ImGui::End();
return;
- }
HelpMarker(
"This example shows how you may implement a property editor using two columns.\n"
@@ -6703,10 +6729,7 @@
{
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Example: Long text display", p_open))
- {
- ImGui::End();
return;
- }
static int test_type = 0;
static ImGuiTextBuffer log;
@@ -6725,14 +6748,16 @@
log.appendf("%i The quick brown fox jumps over the lazy dog\n", lines + i);
lines += 1000;
}
- ImGui::BeginChild("Log");
- switch (test_type)
+
+ if (ImGui::BeginChild("Log"))
{
- case 0:
- // Single call to TextUnformatted() with a big buffer
- ImGui::TextUnformatted(log.begin(), log.end());
- break;
- case 1:
+ switch (test_type)
+ {
+ case 0:
+ // Single call to TextUnformatted() with a big buffer
+ ImGui::TextUnformatted(log.begin(), log.end());
+ break;
+ case 1:
{
// Multiple calls to Text(), manually coarsely clipped - demonstrate how to use the ImGuiListClipper helper.
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
@@ -6744,15 +6769,16 @@
ImGui::PopStyleVar();
break;
}
- case 2:
- // Multiple calls to Text(), not clipped (slow)
- ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
- for (int i = 0; i < lines; i++)
- ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
- ImGui::PopStyleVar();
- break;
+ case 2:
+ // Multiple calls to Text(), not clipped (slow)
+ ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
+ for (int i = 0; i < lines; i++)
+ ImGui::Text("%i The quick brown fox jumps over the lazy dog", i);
+ ImGui::PopStyleVar();
+ break;
+ }
+ ImGui::EndChild();
}
- ImGui::EndChild();
ImGui::End();
}
@@ -6764,10 +6790,7 @@
static void ShowExampleAppAutoResize(bool* p_open)
{
if (!ImGui::Begin("Example: Auto-resizing window", p_open, ImGuiWindowFlags_AlwaysAutoResize))
- {
- ImGui::End();
return;
- }
static int lines = 10;
ImGui::TextUnformatted(
@@ -6817,21 +6840,22 @@
if (type == 6) ImGui::SetNextWindowSizeConstraints(ImVec2(0, 0), ImVec2(FLT_MAX, FLT_MAX), CustomConstraints::Step, (void*)(intptr_t)100); // Fixed Step
ImGuiWindowFlags flags = auto_resize ? ImGuiWindowFlags_AlwaysAutoResize : 0;
- if (ImGui::Begin("Example: Constrained Resize", p_open, flags))
- {
- if (ImGui::IsWindowDocked())
- ImGui::Text("Warning: Sizing Constraints won't work if the window is docked!");
- if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
- if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
- if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
- ImGui::SetNextItemWidth(200);
- ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
- ImGui::SetNextItemWidth(200);
- ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
- ImGui::Checkbox("Auto-resize", &auto_resize);
- for (int i = 0; i < display_lines; i++)
- ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
- }
+ if (!ImGui::Begin("Example: Constrained Resize", p_open, flags))
+ return;
+
+ if (ImGui::IsWindowDocked())
+ ImGui::Text("Warning: Sizing Constraints won't work if the window is docked!");
+
+ if (ImGui::Button("200x200")) { ImGui::SetWindowSize(ImVec2(200, 200)); } ImGui::SameLine();
+ if (ImGui::Button("500x500")) { ImGui::SetWindowSize(ImVec2(500, 500)); } ImGui::SameLine();
+ if (ImGui::Button("800x200")) { ImGui::SetWindowSize(ImVec2(800, 200)); }
+ ImGui::SetNextItemWidth(200);
+ ImGui::Combo("Constraint", &type, test_desc, IM_ARRAYSIZE(test_desc));
+ ImGui::SetNextItemWidth(200);
+ ImGui::DragInt("Lines", &display_lines, 0.2f, 1, 100);
+ ImGui::Checkbox("Auto-resize", &auto_resize);
+ for (int i = 0; i < display_lines; i++)
+ ImGui::Text("%*sHello, sailor! Making this line long enough for the example.", i * 4, "");
ImGui::End();
}
@@ -6860,24 +6884,24 @@
ImGui::SetNextWindowViewport(viewport->ID);
}
ImGui::SetNextWindowBgAlpha(0.35f); // Transparent background
- if (ImGui::Begin("Example: Simple overlay", p_open, window_flags))
+ if (!ImGui::Begin("Example: Simple overlay", p_open, window_flags))
+ return;
+
+ ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
+ ImGui::Separator();
+ if (ImGui::IsMousePosValid())
+ ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
+ else
+ ImGui::Text("Mouse Position: <invalid>");
+ if (ImGui::BeginPopupContextWindow())
{
- ImGui::Text("Simple overlay\n" "in the corner of the screen.\n" "(right-click to change position)");
- ImGui::Separator();
- if (ImGui::IsMousePosValid())
- ImGui::Text("Mouse Position: (%.1f,%.1f)", io.MousePos.x, io.MousePos.y);
- else
- ImGui::Text("Mouse Position: <invalid>");
- if (ImGui::BeginPopupContextWindow())
- {
- if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
- if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
- if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
- if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
- if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
- if (p_open && ImGui::MenuItem("Close")) *p_open = false;
- ImGui::EndPopup();
- }
+ if (ImGui::MenuItem("Custom", NULL, corner == -1)) corner = -1;
+ if (ImGui::MenuItem("Top-left", NULL, corner == 0)) corner = 0;
+ if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1;
+ if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2;
+ if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3;
+ if (p_open && ImGui::MenuItem("Close")) *p_open = false;
+ ImGui::EndPopup();
}
ImGui::End();
}
@@ -6896,22 +6920,28 @@
// Using "##" to display same title but have unique identifier.
ImGui::SetNextWindowPos(ImVec2(100, 100), ImGuiCond_FirstUseEver);
- ImGui::Begin("Same title as another window##1");
- ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
- ImGui::End();
+ if (ImGui::Begin("Same title as another window##1"))
+ {
+ ImGui::Text("This is window 1.\nMy title is the same as window 2, but my identifier is unique.");
+ ImGui::End();
+ }
ImGui::SetNextWindowPos(ImVec2(100, 200), ImGuiCond_FirstUseEver);
- ImGui::Begin("Same title as another window##2");
- ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
- ImGui::End();
+ if (ImGui::Begin("Same title as another window##2"))
+ {
+ ImGui::Text("This is window 2.\nMy title is the same as window 1, but my identifier is unique.");
+ ImGui::End();
+ }
// Using "###" to display a changing title but keep a static identifier "AnimatedTitle"
char buf[128];
sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime() / 0.25f) & 3], ImGui::GetFrameCount());
ImGui::SetNextWindowPos(ImVec2(100, 300), ImGuiCond_FirstUseEver);
- ImGui::Begin(buf);
- ImGui::Text("This window has a changing title.");
- ImGui::End();
+ if (ImGui::Begin(buf))
+ {
+ ImGui::Text("This window has a changing title.");
+ ImGui::End();
+ }
}
//-----------------------------------------------------------------------------
@@ -6922,10 +6952,7 @@
static void ShowExampleAppCustomRendering(bool* p_open)
{
if (!ImGui::Begin("Example: Custom rendering", p_open))
- {
- ImGui::End();
return;
- }
// Tip: If you do a lot of custom rendering, you probably want to use your own geometrical types and benefit of
// overloaded operators, etc. Define IM_VEC2_CLASS_EXTRA in imconfig.h to create implicit conversions between your
@@ -7376,11 +7403,8 @@
// Another solution may be to make the "Example: Documents" window use the ImGuiWindowFlags_NoDocking.
bool window_contents_visible = ImGui::Begin("Example: Documents", p_open, ImGuiWindowFlags_MenuBar);
- if (!window_contents_visible && opt_target != Target_DockSpaceAndWindow)
- {
- ImGui::End();
+ if (!window_contents_visible && opt_target != Target_DockSpaceAndWindow) // FIXME-NEWBEGIN
return;
- }
// Menu
if (ImGui::BeginMenuBar())
diff --git a/imgui_internal.h b/imgui_internal.h
index bb8ea5c..3ff9cde 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1438,6 +1438,7 @@
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
ImGuiDockNode* HoveredDockNode; // Hovered dock node.
ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actual window that is moved is generally MovingWindow->RootWindow.
+ ImGuiWindow* LastBeginWindow; // Track the last window we called Begin() on, this is used to easily access it even if Begin() returned false.
ImGuiWindow* WheelingWindow; // Track the window we started mouse-wheeling on. Until a timer elapse or mouse has moved, generally keep scrolling the same window even if during the course of scrolling the mouse ends up hovering a child window.
ImVec2 WheelingWindowRefMousePos;
float WheelingWindowTimer;
@@ -1640,6 +1641,7 @@
// Debug Tools
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
ImGuiID DebugItemPickerBreakId; // Will call IM_DEBUG_BREAK() when encountering this id
+ int DebugBeginReturnValueCullDepth; // Cycle between 0..9 then wrap around.
ImGuiMetricsConfig DebugMetricsConfig;
// Misc
@@ -1675,6 +1677,7 @@
HoveredWindowUnderMovingWindow = NULL;
HoveredDockNode = NULL;
MovingWindow = NULL;
+ LastBeginWindow = NULL;
WheelingWindow = NULL;
WheelingWindowTimer = 0.0f;
@@ -1793,6 +1796,7 @@
DebugItemPickerActive = false;
DebugItemPickerBreakId = 0;
+ DebugBeginReturnValueCullDepth = -1;
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
FramerateSecPerFrameIdx = 0;
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 4d232fb..2e99e6e 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -1627,7 +1627,6 @@
PopStyleVar();
if (!ret)
{
- EndPopup();
IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
return false;
}
@@ -3838,7 +3837,6 @@
PopStyleColor();
if (!child_visible)
{
- EndChild();
EndGroup();
return false;
}
@@ -6133,8 +6131,8 @@
if (label_size.x > 0)
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
- BeginChildFrame(id, frame_bb.GetSize());
- return true;
+ // FIXME-NEWBEGIN
+ return BeginChildFrame(id, frame_bb.GetSize());
}
// FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature.
@@ -6568,10 +6566,7 @@
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
if (!is_open)
- {
- End();
return false;
- }
return true; //-V1020
}
diff --git a/misc/freetype/README.md b/misc/freetype/README.md
index e565097..0a83602 100644
--- a/misc/freetype/README.md
+++ b/misc/freetype/README.md
@@ -104,7 +104,8 @@
// Call to draw interface
void ShowFreetypeOptionsWindow()
{
- ImGui::Begin("FreeType Options");
+ if (!ImGui::Begin("FreeType Options"))
+ return;
ImGui::ShowFontSelector("Fonts");
WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType);
ImGui::SameLine();