TabBar: TabItem() now reacts to SetNextItemWidth() and SetNextItemOpen(true). (#5262)

This commit is contained in:
ocornut 2022-06-21 16:20:01 +02:00
parent d3fd2630b7
commit 4b97296148
3 changed files with 29 additions and 15 deletions

View File

@ -105,6 +105,7 @@ Other Changes:
merging drawcall of the last column didn't always work (regression since 1.87). (#4843, #4844) [@rokups] merging drawcall of the last column didn't always work (regression since 1.87). (#4843, #4844) [@rokups]
- Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate. - Inputs: Fixed IsMouseClicked() repeat mode rate being half of keyboard repeat rate.
- ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label. - ColorEdit: Fixed text baseline alignment after a SameLine() after a ColorEdit() with visible label.
- TabBar: TabItem() now reacts to SetNextItemWidth() and SetNextItemOpen(true). (#5262)
- Menus: Adjusted BeginMenu() closing logic so hovering void or non-MenuItem() in parent window - Menus: Adjusted BeginMenu() closing logic so hovering void or non-MenuItem() in parent window
always lead to menu closure. Fixes using items that are not MenuItem() or BeginItem() at the root always lead to menu closure. Fixes using items that are not MenuItem() or BeginItem() at the root
level of a popup with a child menu opened. level of a popup with a child menu opened.

View File

@ -2184,6 +2184,7 @@ struct ImGuiTabItem
float Offset; // Position relative to beginning of tab float Offset; // Position relative to beginning of tab
float Width; // Width currently displayed float Width; // Width currently displayed
float ContentWidth; // Width of label, stored during BeginTabItem() call float ContentWidth; // Width of label, stored during BeginTabItem() call
float RequestedWidth; // Width optionally requested by caller, -1.0f is unused
ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames ImS32 NameOffset; // When Window==NULL, offset to name within parent ImGuiTabBar::TabsNames
ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable ImS16 BeginOrder; // BeginTabItem() order, used to re-order tabs after toggling ImGuiTabBarFlags_Reorderable
ImS16 IndexDuringLayout; // Index only used during TabBarLayout() ImS16 IndexDuringLayout; // Index only used during TabBarLayout()

View File

@ -7548,7 +7548,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window. // and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
const char* tab_name = tab_bar->GetTabName(tab); const char* tab_name = tab_bar->GetTabName(tab);
const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true; const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true;
tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x; tab->ContentWidth = (tab->RequestedWidth > 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button).x;
int section_n = TabItemGetSectionIdx(tab); int section_n = TabItemGetSectionIdx(tab);
ImGuiTabBarSection* section = &sections[section_n]; ImGuiTabBarSection* section = &sections[section_n];
@ -8029,10 +8029,13 @@ bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags)
bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags) bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags)
{ {
// Layout whole tab bar if not already done // Layout whole tab bar if not already done
if (tab_bar->WantLayout)
TabBarLayout(tab_bar);
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
if (tab_bar->WantLayout)
{
ImGuiNextItemData backup_next_item_data = g.NextItemData;
TabBarLayout(tab_bar);
g.NextItemData = backup_next_item_data;
}
ImGuiWindow* window = g.CurrentWindow; ImGuiWindow* window = g.CurrentWindow;
if (window->SkipItems) if (window->SkipItems)
return false; return false;
@ -8058,9 +8061,6 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
else if (p_open == NULL) else if (p_open == NULL)
flags |= ImGuiTabItemFlags_NoCloseButton; flags |= ImGuiTabItemFlags_NoCloseButton;
// Calculate tab contents size
ImVec2 size = TabItemCalcSize(label, p_open != NULL);
// Acquire tab data // Acquire tab data
ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id); ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, id);
bool tab_is_new = false; bool tab_is_new = false;
@ -8069,11 +8069,17 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
tab_bar->Tabs.push_back(ImGuiTabItem()); tab_bar->Tabs.push_back(ImGuiTabItem());
tab = &tab_bar->Tabs.back(); tab = &tab_bar->Tabs.back();
tab->ID = id; tab->ID = id;
tab->Width = size.x; tab_bar->TabsAddedNew = tab_is_new = true;
tab_bar->TabsAddedNew = true;
tab_is_new = true;
} }
tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab); tab_bar->LastTabItemIdx = (ImS16)tab_bar->Tabs.index_from_ptr(tab);
// Calculate tab contents size
ImVec2 size = TabItemCalcSize(label, p_open != NULL);
tab->RequestedWidth = -1.0f;
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasWidth)
size.x = tab->RequestedWidth = g.NextItemData.Width;
if (tab_is_new)
tab->Width = size.x;
tab->ContentWidth = size.x; tab->ContentWidth = size.x;
tab->BeginOrder = tab_bar->TabsActiveCount++; tab->BeginOrder = tab_bar->TabsActiveCount++;
@ -8089,13 +8095,19 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
tab_bar->TabsNames.append(label, label + strlen(label) + 1); tab_bar->TabsNames.append(label, label + strlen(label) + 1);
// Update selected tab // Update selected tab
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0) if (!is_tab_button)
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0) {
if (!is_tab_button) if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
tab_bar->NextSelectedTabId = id; // New tabs gets activated tab_bar->NextSelectedTabId = id; // New tabs gets activated
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // SetSelected can only be passed on explicit tab bar if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
if (!is_tab_button)
tab_bar->NextSelectedTabId = id; tab_bar->NextSelectedTabId = id;
if (g.NextItemData.Flags & ImGuiNextItemDataFlags_HasOpen)
{
IM_ASSERT(g.NextItemData.OpenVal == true && g.NextItemData.OpenCond == ImGuiCond_Always); // SetNextItemOpen(true, ImGuiCond_Always) is supported but other combinations are not.
tab_bar->NextSelectedTabId = id;
}
}
// Lock visibility // Lock visibility
// (Note: tab_contents_visible != tab_selected... because CTRL+TAB operations may preview some tabs without selecting them!) // (Note: tab_contents_visible != tab_selected... because CTRL+TAB operations may preview some tabs without selecting them!)