Tab Bar: Fixed a small bug where toggling a tab bar from Reorderable to not Reorderable would leave tabs reordered in the tab list popup.

This commit is contained in:
Louis Schnellbach 2020-08-26 12:18:02 +02:00 committed by ocornut
parent b30d33378d
commit 8c80d533d9
3 changed files with 14 additions and 8 deletions

View File

@ -53,6 +53,8 @@ Other Changes:
and amends the change done in 1.76 which only affected cases were _OpenOnArrow flag was set. and amends the change done in 1.76 which only affected cases were _OpenOnArrow flag was set.
(This is also necessary to support full multi/range-select/drag and drop operations.) (This is also necessary to support full multi/range-select/drag and drop operations.)
- Tab Bar: Keep tab item close button visible while dragging a tab (independent of hovering state). - Tab Bar: Keep tab item close button visible while dragging a tab (independent of hovering state).
- Tab Bar: Fixed a small bug where toggling a tab bar from Reorderable to not Reorderable would leave
tabs reordered in the tab list popup. [@Xipiryon]
- Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible. - Metrics: Various tweaks, listing windows front-to-back, greying inactive items when possible.
- Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console'). - Demo: Add simple InputText() callbacks demo (aside from the more elaborate ones in 'Examples->Console').
- Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO] - Examples: Vulkan: Reworked buffer resize handling, fix for Linux/X11. (#3390, #2626) [@RoryO]

View File

@ -1710,9 +1710,10 @@ struct ImGuiTabItem
float Width; // Width currently displayed float Width; // Width currently displayed
float ContentWidth; // Width of actual contents, stored during BeginTabItem() call float ContentWidth; // Width of actual contents, stored during BeginTabItem() call
ImS16 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames 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
bool WantClose; // Marked as closed by SetTabItemClosed() bool WantClose; // Marked as closed by SetTabItemClosed()
ImGuiTabItem() { ID = 0; Flags = ImGuiTabItemFlags_None; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; WantClose = false; } ImGuiTabItem() { ID = 0; Flags = ImGuiTabItemFlags_None; LastFrameVisible = LastFrameSelected = -1; NameOffset = -1; Offset = Width = ContentWidth = 0.0f; BeginOrder = -1; WantClose = false; }
}; };
// Storage for a tab bar (sizeof() 92~96 bytes) // Storage for a tab bar (sizeof() 92~96 bytes)
@ -1737,9 +1738,10 @@ struct ImGuiTabBar
ImGuiTabBarFlags Flags; ImGuiTabBarFlags Flags;
ImGuiID ReorderRequestTabId; ImGuiID ReorderRequestTabId;
ImS8 ReorderRequestDir; ImS8 ReorderRequestDir;
ImS8 TabsActiveCount; // Number of tabs submitted this frame.
bool WantLayout; bool WantLayout;
bool VisibleTabWasSubmitted; bool VisibleTabWasSubmitted;
short LastTabItemIdx; // For BeginTabItem()/EndTabItem() short LastTabItemIdx; // Index of last BeginTabItem() tab for use by EndTabItem()
ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar() ImVec2 FramePadding; // style.FramePadding locked at the time of BeginTabBar()
ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer. ImGuiTextBuffer TabsNames; // For non-docking tab bar we re-append names in a contiguous buffer.

View File

@ -6782,15 +6782,16 @@ ImGuiTabBar::ImGuiTabBar()
Flags = ImGuiTabBarFlags_None; Flags = ImGuiTabBarFlags_None;
ReorderRequestTabId = 0; ReorderRequestTabId = 0;
ReorderRequestDir = 0; ReorderRequestDir = 0;
TabsActiveCount = 0;
WantLayout = VisibleTabWasSubmitted = false; WantLayout = VisibleTabWasSubmitted = false;
LastTabItemIdx = -1; LastTabItemIdx = -1;
} }
static int IMGUI_CDECL TabItemComparerByVisibleOffset(const void* lhs, const void* rhs) static int IMGUI_CDECL TabItemComparerByBeginOrder(const void* lhs, const void* rhs)
{ {
const ImGuiTabItem* a = (const ImGuiTabItem*)lhs; const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
const ImGuiTabItem* b = (const ImGuiTabItem*)rhs; const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
return (int)(a->Offset - b->Offset); return (int)(a->BeginOrder - b->BeginOrder);
} }
static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref) static ImGuiTabBar* GetTabBarFromTabBarRef(const ImGuiPtrOrIndex& ref)
@ -6842,10 +6843,9 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
return true; return true;
} }
// When toggling back from ordered to manually-reorderable, shuffle tabs to enforce the last visible order. // When toggling ImGuiTabBarFlags_Reorderable flag, ensure tabs are ordered based on their submission order.
// Otherwise, the most recently inserted tabs would move at the end of visible list which can be a little too confusing or magic for the user. if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1)
if ((flags & ImGuiTabBarFlags_Reorderable) && !(tab_bar->Flags & ImGuiTabBarFlags_Reorderable) && tab_bar->Tabs.Size > 1 && tab_bar->PrevFrameVisible != -1) ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByVisibleOffset);
// Flags // Flags
if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) if ((flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0)
@ -6857,6 +6857,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible; tab_bar->PrevFrameVisible = tab_bar->CurrFrameVisible;
tab_bar->CurrFrameVisible = g.FrameCount; tab_bar->CurrFrameVisible = g.FrameCount;
tab_bar->FramePadding = g.Style.FramePadding; 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 // 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.x = tab_bar->BarRect.Min.x;
@ -7362,6 +7363,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
} }
tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab); tab_bar->LastTabItemIdx = (short)tab_bar->Tabs.index_from_ptr(tab);
tab->ContentWidth = size.x; tab->ContentWidth = size.x;
tab->BeginOrder = tab_bar->TabsActiveCount++;
const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount); const bool tab_bar_appearing = (tab_bar->PrevFrameVisible + 1 < g.FrameCount);
const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0; const bool tab_bar_focused = (tab_bar->Flags & ImGuiTabBarFlags_IsFocused) != 0;