From f2f326024c480e38de6404d11b5d85272bf8d9df Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Oct 2020 18:34:33 +0200 Subject: [PATCH 1/9] Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 6 ++++-- imgui_widgets.cpp | 26 ++++++++++++++++++-------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 164e3554..e91267d3 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -54,6 +54,7 @@ Breaking Changes: Other Changes: +- Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. - Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs. diff --git a/imgui_internal.h b/imgui_internal.h index e74d2a80..013c8139 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1754,7 +1754,8 @@ struct ImGuiTabBar int CurrFrameVisible; int PrevFrameVisible; ImRect BarRect; - float LastTabContentHeight; // Record the height of contents submitted below the tab bar + float CurrTabsContentsHeight; + float PrevTabsContentsHeight; // Record the height of contents submitted below the tab bar float WidthAllTabs; // Actual width of all tabs (locked during layout) float WidthAllTabsIdeal; // Ideal width if all tabs were visible and not clipped float ScrollingAnim; @@ -1770,8 +1771,9 @@ struct ImGuiTabBar bool WantLayout; bool VisibleTabWasSubmitted; bool TabsAddedNew; // Set to true when a new tab item or button has been added to the tab bar during last frame - short LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() + short LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar() + ImVec2 TabsContentsMin; ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. ImGuiTabBar(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 2ea773e2..5da42da5 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6805,7 +6805,7 @@ ImGuiTabBar::ImGuiTabBar() ID = 0; SelectedTabId = NextSelectedTabId = VisibleTabId = 0; CurrFrameVisible = PrevFrameVisible = -1; - LastTabContentHeight = 0.0f; + CurrTabsContentsHeight = PrevTabsContentsHeight = 0.0f; WidthAllTabs = WidthAllTabsIdeal = 0.0f; ScrollingAnim = ScrollingTarget = ScrollingTargetDistToVisibility = ScrollingSpeed = 0.0f; ScrollingRectMinX = ScrollingRectMaxX = 0.0f; @@ -6877,10 +6877,10 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG g.CurrentTabBarStack.push_back(GetTabBarRefFromTabBar(tab_bar)); g.CurrentTabBar = tab_bar; + // Append with multiple BeginTabBar()/EndTabBar() pairs. if (tab_bar->CurrFrameVisible == g.FrameCount) { - //IMGUI_DEBUG_LOG("BeginTabBarEx already called this frame\n", g.FrameCount); - IM_ASSERT(0); + window->DC.CursorPos = tab_bar->TabsContentsMin; return true; } @@ -6899,12 +6899,15 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG tab_bar->WantLayout = true; // Layout will be done on the first call to ItemTab() tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible; tab_bar->CurrFrameVisible = g.FrameCount; + tab_bar->PrevTabsContentsHeight = tab_bar->CurrTabsContentsHeight; + tab_bar->CurrTabsContentsHeight = 0.0f; tab_bar->FramePadding = g.Style.FramePadding; tab_bar->TabsActiveCount = 0; // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap - window->DC.CursorPos.x = tab_bar->BarRect.Min.x; - window->DC.CursorPos.y = tab_bar->BarRect.Max.y + g.Style.ItemSpacing.y; + tab_bar->TabsContentsMin.x = tab_bar->BarRect.Min.x; + tab_bar->TabsContentsMin.y = tab_bar->BarRect.Max.y + g.Style.ItemSpacing.y; + window->DC.CursorPos = tab_bar->TabsContentsMin; // Draw separator const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive); @@ -6930,15 +6933,22 @@ void ImGui::EndTabBar() IM_ASSERT_USER_ERROR(tab_bar != NULL, "Mismatched BeginTabBar()/EndTabBar()!"); return; } - if (tab_bar->WantLayout) // Fallback in case no TabItem have been submitted + + // Fallback in case no TabItem have been submitted + if (tab_bar->WantLayout) TabBarLayout(tab_bar); // Restore the last visible height if no tab is visible, this reduce vertical flicker/movement when a tabs gets removed without calling SetTabItemClosed(). const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); if (tab_bar->VisibleTabWasSubmitted || tab_bar->VisibleTabId == 0 || tab_bar_appearing) - tab_bar->LastTabContentHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, 0.0f); + { + tab_bar->CurrTabsContentsHeight = ImMax(window->DC.CursorPos.y - tab_bar->BarRect.Max.y, tab_bar->CurrTabsContentsHeight); + window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->CurrTabsContentsHeight; + } else - window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->LastTabContentHeight; + { + window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->PrevTabsContentsHeight; + } if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) PopID(); From 31a144b60ca41e5cc5a777b91c53610e068538f3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Oct 2020 19:37:18 +0200 Subject: [PATCH 2/9] Fix comments (#3534) --- misc/fonts/binary_to_compressed_c.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/misc/fonts/binary_to_compressed_c.cpp b/misc/fonts/binary_to_compressed_c.cpp index 1f621e16..441c8f67 100644 --- a/misc/fonts/binary_to_compressed_c.cpp +++ b/misc/fonts/binary_to_compressed_c.cpp @@ -10,7 +10,8 @@ // Build with, e.g: // # cl.exe binary_to_compressed_c.cpp -// # gcc binary_to_compressed_c.cpp +// # g++ binary_to_compressed_c.cpp +// # clang++ binary_to_compressed_c.cpp // You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui // Usage: From 127f13244730316582bcf230ad55cb20601d1776 Mon Sep 17 00:00:00 2001 From: xndcn Date: Thu, 15 Oct 2020 11:39:08 +0800 Subject: [PATCH 3/9] Backends: OpenGL3: Add compatibility of GL_VERSION for GL 2.x (#3530) GL_MAJOR_VERSION and GL_MINOR_VERSION are available on GL 3.0 and above. So we have to parse GL_VERSION under GL 2.x --- backends/imgui_impl_opengl3.cpp | 10 +++++++++- docs/CHANGELOG.txt | 2 ++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index ed151304..aa0e9e55 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) // 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. // 2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX. @@ -147,9 +148,16 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) { // Query for GL version (e.g. 320 for GL 3.2) #if !defined(IMGUI_IMPL_OPENGL_ES2) - GLint major, minor; + GLint major = 0; + GLint minor = 0; glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); + if (major == 0 && minor == 0) + { + // Query GL_VERSION in desktop GL 2.x, the string will start with "." + const char* gl_version = (const char*)glGetString(GL_VERSION); + sscanf(gl_version, "%d.%d", &major, &minor); + } g_GlVersion = (GLuint)(major * 100 + minor * 10); #else g_GlVersion = 200; // GLES 2 diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index e91267d3..b20c1a02 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Breaking Changes: Other Changes: - Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. +- Backends: OpenGL: use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) + when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. - Docs: Consistently renamed all occurences of "binding" and "back-end" to "backend" in comments and docs. From d015004f4541892526415dae2086401f110dc60b Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 15 Oct 2020 20:05:35 +0200 Subject: [PATCH 4/9] Rename colored>color in comments where possible (#3528) --- imgui.h | 14 +++++++------- imgui_demo.cpp | 12 ++++++------ imgui_widgets.cpp | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.h b/imgui.h index 01b01f2b..a54e3f9e 100644 --- a/imgui.h +++ b/imgui.h @@ -522,14 +522,14 @@ namespace ImGui IMGUI_API bool InputScalar(const char* label, ImGuiDataType data_type, void* p_data, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); IMGUI_API bool InputScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, const void* p_step = NULL, const void* p_step_fast = NULL, const char* format = NULL, ImGuiInputTextFlags flags = 0); - // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little colored preview square that can be left-clicked to open a picker, and right-clicked to open an option menu.) + // Widgets: Color Editor/Picker (tip: the ColorEdit* functions have a little color square that can be left-clicked to open a picker, and right-clicked to open an option menu.) // - Note that in C++ a 'float v[X]' function argument is the _same_ as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. // - You can pass the address of a first float element out of a contiguous structure, e.g. &myvector.x IMGUI_API bool ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); - IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a colored square/button, hover for details, return true when pressed. + IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed. IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. // Widgets: Trees @@ -865,7 +865,7 @@ enum ImGuiTreeNodeFlags_ { ImGuiTreeNodeFlags_None = 0, ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected - ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) + ImGuiTreeNodeFlags_Framed = 1 << 1, // Draw frame with background (e.g. for CollapsingHeader) ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) @@ -1249,13 +1249,13 @@ enum ImGuiColorEditFlags_ { ImGuiColorEditFlags_None = 0, ImGuiColorEditFlags_NoAlpha = 1 << 1, // // ColorEdit, ColorPicker, ColorButton: ignore Alpha component (will only read 3 components from the input pointer). - ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on colored square. + ImGuiColorEditFlags_NoPicker = 1 << 2, // // ColorEdit: disable picker when clicking on color square. ImGuiColorEditFlags_NoOptions = 1 << 3, // // ColorEdit: disable toggling options menu when right-clicking on inputs/small preview. - ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable colored square preview next to the inputs. (e.g. to show only the inputs) - ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview colored square). + ImGuiColorEditFlags_NoSmallPreview = 1 << 4, // // ColorEdit, ColorPicker: disable color square preview next to the inputs. (e.g. to show only the inputs) + ImGuiColorEditFlags_NoInputs = 1 << 5, // // ColorEdit, ColorPicker: disable inputs sliders/text widgets (e.g. to show only the small preview color square). ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker). - ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small colored square preview instead. + ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small color square preview instead. ImGuiColorEditFlags_NoDragDrop = 1 << 9, // // ColorEdit: disable drag and drop target. ColorButton: disable drag and drop source. ImGuiColorEditFlags_NoBorder = 1 << 10, // // ColorButton: disable border (which is enforced by default) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 13353bad..2ce3ddac 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -652,9 +652,9 @@ static void ShowDemoWindowWidgets() static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; ImGui::ColorEdit3("color 1", col1); ImGui::SameLine(); HelpMarker( - "Click on the colored square to open a color picker.\n" + "Click on the color square to open a color picker.\n" "Click and hold to use drag and drop.\n" - "Right-click on the colored square to show options.\n" + "Right-click on the color square to show options.\n" "CTRL+click on individual component to input value.\n"); ImGui::ColorEdit4("color 2", col2); @@ -823,7 +823,7 @@ static void ShowDemoWindowWidgets() if (ImGui::TreeNode("Text")) { - if (ImGui::TreeNode("Colored Text")) + if (ImGui::TreeNode("Colorful Text")) { // Using shortcut. You can use PushStyleColor()/PopStyleColor() for more flexibility. ImGui::TextColored(ImVec4(1.0f, 0.0f, 1.0f, 1.0f), "Pink"); @@ -1405,7 +1405,7 @@ static void ShowDemoWindowWidgets() ImGui::Text("Color widget:"); ImGui::SameLine(); HelpMarker( - "Click on the colored square to open a color picker.\n" + "Click on the color square to open a color picker.\n" "CTRL+click on individual component to input value.\n"); ImGui::ColorEdit3("MyColor##1", (float*)&color, misc_flags); @@ -1825,7 +1825,7 @@ static void ShowDemoWindowWidgets() // They are using standardized payload strings IMGUI_PAYLOAD_TYPE_COLOR_3F and IMGUI_PAYLOAD_TYPE_COLOR_4F // to allow your own widgets to use colors in their drag and drop interaction. // Also see 'Demo->Widgets->Color/Picker Widgets->Palette' demo. - HelpMarker("You can drag from the colored squares."); + HelpMarker("You can drag from the color squares."); static float col1[3] = { 1.0f, 0.0f, 0.2f }; static float col2[4] = { 0.4f, 0.7f, 0.0f, 0.5f }; ImGui::ColorEdit3("color 1", col1); @@ -3976,7 +3976,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) { alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf; } ImGui::SameLine(); HelpMarker( "In the color list:\n" - "Left-click on colored square to open color picker,\n" + "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); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 5da42da5..a908184f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -4573,7 +4573,7 @@ bool ImGui::ColorEdit3(const char* label, float col[3], ImGuiColorEditFlags flag // Edit colors components (each component in 0.0f..1.0f range). // See enum ImGuiColorEditFlags_ for available options. e.g. Only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set. -// With typical options: Left-click on colored square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. +// With typical options: Left-click on color square to open color picker. Right-click to open option menu. CTRL-Click over input fields to edit them and TAB to go to next item. bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags) { ImGuiWindow* window = GetCurrentWindow(); @@ -5209,7 +5209,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl return value_changed; } -// A little colored square. Return true when clicked. +// A little color square. Return true when clicked. // FIXME: May want to display/ignore the alpha component in the color display? Yet show it in the tooltip. // 'desc_id' is not called 'label' because we don't display it next to the button, but only in the tooltip. // Note that 'col' may be encoded in HSV if ImGuiColorEditFlags_InputHSV is set. From c9fafd5ea4e316996f20067882600676decc97e6 Mon Sep 17 00:00:00 2001 From: Black Cat! Date: Sat, 10 Oct 2020 17:39:06 +0400 Subject: [PATCH 5/9] Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b20c1a02..c4a8a8bd 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,8 @@ Breaking Changes: Other Changes: - Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. +- Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging + into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] - Backends: OpenGL: use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] - Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md improved them. diff --git a/imgui.cpp b/imgui.cpp index 81a39cd6..0bb82d23 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9584,7 +9584,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId); ImRect r = g.DragDropTargetRect; float r_surface = r.GetWidth() * r.GetHeight(); - if (r_surface < g.DragDropAcceptIdCurrRectSurface) + if (r_surface <= g.DragDropAcceptIdCurrRectSurface) { g.DragDropAcceptFlags = flags; g.DragDropAcceptIdCurr = g.DragDropTargetId; From 748bd1ba9ce2dd6bdbbf08ef5034f04c37b0a3ca Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Oct 2020 11:32:53 +0200 Subject: [PATCH 6/9] Tab Bar: Restore cursor position in EndTabBar() when amending (amend f2f32602) + made LastTabItemIdx consistent ImS8 as other tab storage relies on same type --- imgui_internal.h | 8 +++++--- imgui_widgets.cpp | 12 +++++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 013c8139..3cdc7792 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1743,10 +1743,11 @@ struct ImGuiTabItem ImGuiTabItem() { ID = 0; Flags = ImGuiTabItemFlags_None; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; BeginOrder = -1; IndexDuringLayout = -1; WantClose = false; } }; -// Storage for a tab bar (sizeof() 92~96 bytes) +// Storage for a tab bar (sizeof() 152 bytes) struct ImGuiTabBar { ImVector Tabs; + ImGuiTabBarFlags Flags; ImGuiID ID; // Zero for tab-bars used by docking ImGuiID SelectedTabId; // Selected tab/window ImGuiID NextSelectedTabId; @@ -1764,16 +1765,17 @@ struct ImGuiTabBar float ScrollingSpeed; float ScrollingRectMinX; float ScrollingRectMaxX; - ImGuiTabBarFlags Flags; ImGuiID ReorderRequestTabId; ImS8 ReorderRequestDir; ImS8 TabsActiveCount; // Number of tabs submitted this frame. + ImS8 LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() + ImS8 BeginCount; bool WantLayout; bool VisibleTabWasSubmitted; bool TabsAddedNew; // Set to true when a new tab item or button has been added to the tab bar during last frame - short LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar() ImVec2 TabsContentsMin; + ImVec2 BackupCursorPos; ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. ImGuiTabBar(); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index a908184f..b9346e3d 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6802,6 +6802,7 @@ namespace ImGui ImGuiTabBar::ImGuiTabBar() { + Flags = ImGuiTabBarFlags_None; ID = 0; SelectedTabId = NextSelectedTabId = VisibleTabId = 0; CurrFrameVisible = PrevFrameVisible = -1; @@ -6809,12 +6810,12 @@ ImGuiTabBar::ImGuiTabBar() WidthAllTabs = WidthAllTabsIdeal = 0.0f; ScrollingAnim = ScrollingTarget = ScrollingTargetDistToVisibility = ScrollingSpeed = 0.0f; ScrollingRectMinX = ScrollingRectMaxX = 0.0f; - Flags = ImGuiTabBarFlags_None; ReorderRequestTabId = 0; ReorderRequestDir = 0; TabsActiveCount = 0; - WantLayout = VisibleTabWasSubmitted = TabsAddedNew = false; LastTabItemIdx = -1; + BeginCount = 0; + WantLayout = VisibleTabWasSubmitted = TabsAddedNew = false; } static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs) @@ -6878,9 +6879,11 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG g.CurrentTabBar = tab_bar; // Append with multiple BeginTabBar()/EndTabBar() pairs. + tab_bar->BackupCursorPos = window->DC.CursorPos; if (tab_bar->CurrFrameVisible == g.FrameCount) { window->DC.CursorPos = tab_bar->TabsContentsMin; + tab_bar->BeginCount++; return true; } @@ -6903,6 +6906,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG tab_bar->CurrTabsContentsHeight = 0.0f; tab_bar->FramePadding = g.Style.FramePadding; tab_bar->TabsActiveCount = 0; + tab_bar->BeginCount = 1; // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap tab_bar->TabsContentsMin.x = tab_bar->BarRect.Min.x; @@ -6949,6 +6953,8 @@ void ImGui::EndTabBar() { window->DC.CursorPos.y = tab_bar->BarRect.Max.y + tab_bar->PrevTabsContentsHeight; } + if (tab_bar->BeginCount > 1) + window->DC.CursorPos = tab_bar->BackupCursorPos; if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0) PopID(); @@ -7543,7 +7549,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, tab_bar->TabsAddedNew = true; tab_is_new = true; } - tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab); + tab_bar->LastTabItemIdx = (ImS8)tab_bar->Tabs.index_from_ptr(tab); tab->ContentWidth = size.x; tab->BeginOrder = tab_bar->TabsActiveCount++; From 8c9b3c9013167606b7398188a81ac5d106b56b96 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Oct 2020 11:51:38 +0200 Subject: [PATCH 7/9] Tab Bar: Fixed using more than 128 tabs in a tab bar. Using ImS16 consistently + some better packing to avoid struct growing size. --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 10 +++++----- imgui_widgets.cpp | 11 +++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index c4a8a8bd..3ede8331 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -55,6 +55,7 @@ Breaking Changes: Other Changes: - Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. +- Tab Bar: Fixed using more than 128 tabs in a tab bar (scrolling policy recommended). - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] - Backends: OpenGL: use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) diff --git a/imgui_internal.h b/imgui_internal.h index 3cdc7792..5e408b62 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1736,8 +1736,8 @@ struct ImGuiTabItem float Width; // Width currently displayed float ContentWidth; // Width of label, stored during BeginTabItem() call ImS16 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames - ImS8 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable - ImS8 IndexDuringLayout; // Index only used during TabBarLayout() + ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable + ImS16 IndexDuringLayout; // Index only used during TabBarLayout() bool WantClose; // Marked as closed by SetTabItemClosed() ImGuiTabItem() { ID = 0; Flags = ImGuiTabItemFlags_None; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; BeginOrder = -1; IndexDuringLayout = -1; WantClose = false; } @@ -1767,14 +1767,14 @@ struct ImGuiTabBar float ScrollingRectMaxX; ImGuiID ReorderRequestTabId; ImS8 ReorderRequestDir; - ImS8 TabsActiveCount; // Number of tabs submitted this frame. - ImS8 LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() ImS8 BeginCount; bool WantLayout; bool VisibleTabWasSubmitted; bool TabsAddedNew; // Set to true when a new tab item or button has been added to the tab bar during last frame + ImS16 TabsActiveCount; // Number of tabs submitted this frame. + ImS16 LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem() + float ItemSpacingY; ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar() - ImVec2 TabsContentsMin; ImVec2 BackupCursorPos; ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index b9346e3d..022012fc 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6882,7 +6882,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG tab_bar->BackupCursorPos = window->DC.CursorPos; if (tab_bar->CurrFrameVisible == g.FrameCount) { - window->DC.CursorPos = tab_bar->TabsContentsMin; + window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); tab_bar->BeginCount++; return true; } @@ -6904,14 +6904,13 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG tab_bar->CurrFrameVisible = g.FrameCount; tab_bar->PrevTabsContentsHeight = tab_bar->CurrTabsContentsHeight; tab_bar->CurrTabsContentsHeight = 0.0f; + tab_bar->ItemSpacingY = g.Style.ItemSpacing.y; tab_bar->FramePadding = g.Style.FramePadding; tab_bar->TabsActiveCount = 0; tab_bar->BeginCount = 1; // Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap - tab_bar->TabsContentsMin.x = tab_bar->BarRect.Min.x; - tab_bar->TabsContentsMin.y = tab_bar->BarRect.Max.y + g.Style.ItemSpacing.y; - window->DC.CursorPos = tab_bar->TabsContentsMin; + window->DC.CursorPos = ImVec2(tab_bar->BarRect.Min.x, tab_bar->BarRect.Max.y + tab_bar->ItemSpacingY); // Draw separator const ImU32 col = GetColorU32((flags & ImGuiTabBarFlags_IsFocused) ? ImGuiCol_TabActive : ImGuiCol_TabUnfocusedActive); @@ -6990,7 +6989,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n]; tab = &tab_bar->Tabs[tab_dst_n]; - tab->IndexDuringLayout = (ImS8)tab_dst_n; + tab->IndexDuringLayout = (ImS16)tab_dst_n; // We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another) int curr_tab_section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1; @@ -7549,7 +7548,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, tab_bar->TabsAddedNew = true; tab_is_new = true; } - tab_bar->LastTabItemIdx = (ImS8)tab_bar->Tabs.index_from_ptr(tab); + tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab); tab->ContentWidth = size.x; tab->BeginOrder = tab_bar->TabsActiveCount++; From fbe74ed50c9aea079dbf4280f4689dffe7ef9d89 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Oct 2020 12:10:31 +0200 Subject: [PATCH 8/9] Tab Bar: zero clear more structures. --- imgui_internal.h | 2 +- imgui_widgets.cpp | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 5e408b62..72cabb28 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1740,7 +1740,7 @@ struct ImGuiTabItem ImS16 IndexDuringLayout; // Index only used during TabBarLayout() bool WantClose; // Marked as closed by SetTabItemClosed() - ImGuiTabItem() { ID = 0; Flags = ImGuiTabItemFlags_None; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; BeginOrder = -1; IndexDuringLayout = -1; WantClose = false; } + ImGuiTabItem() { memset(this, 0, sizeof(*this)); LastFrameVisible = LastFrameSelected = -1; NameOffset = BeginOrder = IndexDuringLayout = -1; } }; // Storage for a tab bar (sizeof() 152 bytes) diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 022012fc..bb84083e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6802,20 +6802,9 @@ namespace ImGui ImGuiTabBar::ImGuiTabBar() { - Flags = ImGuiTabBarFlags_None; - ID = 0; - SelectedTabId = NextSelectedTabId = VisibleTabId = 0; + memset(this, 0, sizeof(*this)); CurrFrameVisible = PrevFrameVisible = -1; - CurrTabsContentsHeight = PrevTabsContentsHeight = 0.0f; - WidthAllTabs = WidthAllTabsIdeal = 0.0f; - ScrollingAnim = ScrollingTarget = ScrollingTargetDistToVisibility = ScrollingSpeed = 0.0f; - ScrollingRectMinX = ScrollingRectMaxX = 0.0f; - ReorderRequestTabId = 0; - ReorderRequestDir = 0; - TabsActiveCount = 0; LastTabItemIdx = -1; - BeginCount = 0; - WantLayout = VisibleTabWasSubmitted = TabsAddedNew = false; } static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs) From e6b99a420b74a056da40f9a7af491446f26a29ea Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 19 Oct 2020 15:01:24 +0200 Subject: [PATCH 9/9] Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521) --- docs/CHANGELOG.txt | 1 + imgui_internal.h | 2 +- imgui_widgets.cpp | 26 +++++++++++++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3ede8331..68e30508 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -56,6 +56,7 @@ Other Changes: - Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again. - Tab Bar: Fixed using more than 128 tabs in a tab bar (scrolling policy recommended). +- Tab Bar: Do not display a tooltip if the name already fits over a given tab. (#3521) - Drag and Drop: Fix drag and drop to tie same-size drop targets by choosen the later one. Fixes dragging into a full-window-sized dockspace inside a zero-padded window. (#3519, #2717) [@Black-Cat] - Backends: OpenGL: use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) diff --git a/imgui_internal.h b/imgui_internal.h index 72cabb28..215f414e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1971,7 +1971,7 @@ namespace ImGui IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags); IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button); IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col); - IMGUI_API bool TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible); + IMGUI_API void TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped); // Render helpers // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index bb84083e..fe892451 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -7677,7 +7677,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // Render tab label, process close button const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0; - bool just_closed = TabItemLabelAndCloseButton(display_draw_list, bb, flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible); + bool just_closed; + bool text_clipped; + TabItemLabelAndCloseButton(display_draw_list, bb, flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped); if (just_closed && p_open != NULL) { *p_open = false; @@ -7691,7 +7693,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // Tooltip (FIXME: Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer) // We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar (which g.HoveredId ignores) - if (g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > 0.50f && IsItemHovered()) + if (text_clipped && g.HoveredId == id && !held && g.HoveredIdNotActiveTimer > 0.50f && IsItemHovered()) if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip)) SetTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label); @@ -7756,12 +7758,18 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI // Render text label (with custom clipping) + Unsaved Document marker + Close Button logic // We tend to lock style.FramePadding for a given tab-bar, hence the 'frame_padding' parameter. -bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible) +void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped) { ImGuiContext& g = *GImGui; ImVec2 label_size = CalcTextSize(label, NULL, true); + + if (out_just_closed) + *out_just_closed = false; + if (out_text_clipped) + *out_text_clipped = false; + if (bb.GetWidth() <= 1.0f) - return false; + return; // In Style V2 we'll have full override of all colors per state (e.g. focused, selected) // But right now if you want to alter text color of tabs this is what you need to do. @@ -7782,6 +7790,13 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, } ImRect text_ellipsis_clip_bb = text_pixel_clip_bb; + // Return clipped state ignoring the close button + if (out_text_clipped) + { + *out_text_clipped = (text_ellipsis_clip_bb.Min.x + label_size.x) > text_pixel_clip_bb.Max.x; + //draw_list->AddCircle(text_ellipsis_clip_bb.Min, 3.0f, *out_text_clipped ? IM_COL32(255, 0, 0, 255) : IM_COL32(0, 255, 0, 255)); + } + // Close Button // We are relying on a subtle and confusing distinction between 'hovered' and 'g.HoveredId' which happens because we are using ImGuiButtonFlags_AllowOverlapMode + SetItemAllowOverlap() // 'hovered' will be true when hovering the Tab but NOT when hovering the close button @@ -7819,7 +7834,8 @@ bool ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, g.Style.Alpha = backup_alpha; #endif - return close_button_pressed; + if (out_just_closed) + *out_just_closed = close_button_pressed; }