Tab Bar: Made it possible to append to an existing tab bar by calling BeginTabBar()/EndTabBar() again.
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 164e355..e91267d 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -54,6 +54,7 @@
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 e74d2a8..013c813 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -1754,7 +1754,8 @@
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 @@
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 2ea773e..5da42da 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -6805,7 +6805,7 @@
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 @@
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 @@
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 @@
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();