@ -7282,11 +7282,17 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
// - TabBarCalcTabID() [Internal]
// - TabBarCalcTabID() [Internal]
// - TabBarCalcMaxTabWidth() [Internal]
// - TabBarCalcMaxTabWidth() [Internal]
// - TabBarFindTabById() [Internal]
// - TabBarFindTabById() [Internal]
// - TabBarFindTabByOrder() [Internal]
// - TabBarGetCurrentTab() [Internal]
// - TabBarGetTabName() [Internal]
// - TabBarRemoveTab() [Internal]
// - TabBarRemoveTab() [Internal]
// - TabBarCloseTab() [Internal]
// - TabBarCloseTab() [Internal]
// - TabBarScrollClamp() [Internal]
// - TabBarScrollClamp() [Internal]
// - TabBarScrollToTab() [Internal]
// - TabBarScrollToTab() [Internal]
// - TabBarQueueChangeTabOrder() [Internal]
// - TabBarQueueFocus() [Internal]
// - TabBarQueueReorder() [Internal]
// - TabBarProcessReorderFromMousePos() [Internal]
// - TabBarProcessReorder() [Internal]
// - TabBarScrollingButtons() [Internal]
// - TabBarScrollingButtons() [Internal]
// - TabBarTabListPopupButton() [Internal]
// - TabBarTabListPopupButton() [Internal]
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
@ -7411,6 +7417,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
tab_bar - > ItemSpacingY = g . Style . ItemSpacing . y ;
tab_bar - > ItemSpacingY = g . Style . ItemSpacing . y ;
tab_bar - > FramePadding = g . Style . FramePadding ;
tab_bar - > FramePadding = g . Style . FramePadding ;
tab_bar - > TabsActiveCount = 0 ;
tab_bar - > TabsActiveCount = 0 ;
tab_bar - > LastTabItemIdx = - 1 ;
tab_bar - > BeginCount = 1 ;
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
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
@ -7459,6 +7466,7 @@ void ImGui::EndTabBar()
if ( tab_bar - > BeginCount > 1 )
if ( tab_bar - > BeginCount > 1 )
window - > DC . CursorPos = tab_bar - > BackupCursorPos ;
window - > DC . CursorPos = tab_bar - > BackupCursorPos ;
tab_bar - > LastTabItemIdx = - 1 ;
if ( ( tab_bar - > Flags & ImGuiTabBarFlags_DockNode ) = = 0 )
if ( ( tab_bar - > Flags & ImGuiTabBarFlags_DockNode ) = = 0 )
PopID ( ) ;
PopID ( ) ;
@ -7568,7 +7576,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
// 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 = TabBarGetTabName ( tab_bar , tab ) ;
const bool has_close_button_or_unsaved_marker = ( tab - > Flags & ImGuiTabItemFlags_NoCloseButton ) = = 0 | | ( tab - > Flags & ImGuiTabItemFlags_UnsavedDocument ) ;
const bool has_close_button_or_unsaved_marker = ( tab - > Flags & ImGuiTabItemFlags_NoCloseButton ) = = 0 | | ( tab - > Flags & ImGuiTabItemFlags_UnsavedDocument ) ;
tab - > ContentWidth = ( tab - > RequestedWidth > = 0.0f ) ? tab - > RequestedWidth : TabItemCalcSize ( tab_name , has_close_button_or_unsaved_marker ) . x ;
tab - > ContentWidth = ( tab - > RequestedWidth > = 0.0f ) ? tab - > RequestedWidth : TabItemCalcSize ( tab_name , has_close_button_or_unsaved_marker ) . x ;
@ -7729,7 +7737,28 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
return NULL ;
return NULL ;
}
}
// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
// Order = visible order, not submission order! (which is tab->BeginOrder)
ImGuiTabItem * ImGui : : TabBarFindTabByOrder ( ImGuiTabBar * tab_bar , int order )
{
if ( order < 0 | | order > = tab_bar - > Tabs . Size )
return NULL ;
return & tab_bar - > Tabs [ order ] ;
}
ImGuiTabItem * ImGui : : TabBarGetCurrentTab ( ImGuiTabBar * tab_bar )
{
if ( tab_bar - > LastTabItemIdx < = 0 | | tab_bar - > LastTabItemIdx > = tab_bar - > Tabs . Size )
return NULL ;
return & tab_bar - > Tabs [ tab_bar - > LastTabItemIdx ] ;
}
const char * ImGui : : TabBarGetTabName ( ImGuiTabBar * tab_bar , ImGuiTabItem * tab )
{
IM_ASSERT ( tab - > NameOffset ! = - 1 & & tab - > NameOffset < tab_bar - > TabsNames . Buf . Size ) ;
return tab_bar - > TabsNames . Buf . Data + tab - > NameOffset ;
}
// The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
void ImGui : : TabBarRemoveTab ( ImGuiTabBar * tab_bar , ImGuiID tab_id )
void ImGui : : TabBarRemoveTab ( ImGuiTabBar * tab_bar , ImGuiID tab_id )
{
{
if ( ImGuiTabItem * tab = TabBarFindTabByID ( tab_bar , tab_id ) )
if ( ImGuiTabItem * tab = TabBarFindTabByID ( tab_bar , tab_id ) )
@ -7760,7 +7789,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
{
{
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
if ( tab_bar - > VisibleTabId ! = tab - > ID )
if ( tab_bar - > VisibleTabId ! = tab - > ID )
tab_bar - > NextSelectedTabId = tab - > ID ;
TabBarQueueFocus ( tab_bar , tab ) ;
}
}
}
}
@ -7781,7 +7810,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
float margin = g . FontSize * 1.0f ; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
float margin = g . FontSize * 1.0f ; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
int order = tab_bar - > GetTabOrder ( tab ) ;
int order = TabBarGetTabOrder ( tab_bar , tab ) ;
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
// FIXME: This is all confusing.
// FIXME: This is all confusing.
@ -7805,7 +7834,12 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
}
}
}
}
void ImGui : : TabBarQueueReorder ( ImGuiTabBar * tab_bar , const ImGuiTabItem * tab , int offset )
void ImGui : : TabBarQueueFocus ( ImGuiTabBar * tab_bar , ImGuiTabItem * tab )
{
tab_bar - > NextSelectedTabId = tab - > ID ;
}
void ImGui : : TabBarQueueReorder ( ImGuiTabBar * tab_bar , ImGuiTabItem * tab , int offset )
{
{
IM_ASSERT ( offset ! = 0 ) ;
IM_ASSERT ( offset ! = 0 ) ;
IM_ASSERT ( tab_bar - > ReorderRequestTabId = = 0 ) ;
IM_ASSERT ( tab_bar - > ReorderRequestTabId = = 0 ) ;
@ -7813,7 +7847,7 @@ void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, in
tab_bar - > ReorderRequestOffset = ( ImS16 ) offset ;
tab_bar - > ReorderRequestOffset = ( ImS16 ) offset ;
}
}
void ImGui : : TabBarQueueReorderFromMousePos ( ImGuiTabBar * tab_bar , const ImGuiTabItem * src_tab , ImVec2 mouse_pos )
void ImGui : : TabBarQueueReorderFromMousePos ( ImGuiTabBar * tab_bar , ImGuiTabItem * src_tab , ImVec2 mouse_pos )
{
{
ImGuiContext & g = * GImGui ;
ImGuiContext & g = * GImGui ;
IM_ASSERT ( tab_bar - > ReorderRequestTabId = = 0 ) ;
IM_ASSERT ( tab_bar - > ReorderRequestTabId = = 0 ) ;
@ -7856,7 +7890,7 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
return false ;
return false ;
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
int tab2_order = tab_bar - > GetTabOrder ( tab1 ) + tab_bar - > ReorderRequestOffset ;
int tab2_order = TabBarGetTabOrder ( tab_bar , tab1 ) + tab_bar - > ReorderRequestOffset ;
if ( tab2_order < 0 | | tab2_order > = tab_bar - > Tabs . Size )
if ( tab2_order < 0 | | tab2_order > = tab_bar - > Tabs . Size )
return false ;
return false ;
@ -7916,7 +7950,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
if ( select_dir ! = 0 )
if ( select_dir ! = 0 )
if ( ImGuiTabItem * tab_item = TabBarFindTabByID ( tab_bar , tab_bar - > SelectedTabId ) )
if ( ImGuiTabItem * tab_item = TabBarFindTabByID ( tab_bar , tab_bar - > SelectedTabId ) )
{
{
int selected_order = tab_bar - > GetTabOrder ( tab_item ) ;
int selected_order = TabBarGetTabOrder ( tab_bar , tab_item ) ;
int target_order = selected_order + select_dir ;
int target_order = selected_order + select_dir ;
// Skip tab item buttons until another tab item is found or end is reached
// Skip tab item buttons until another tab item is found or end is reached
@ -7968,7 +8002,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
if ( tab - > Flags & ImGuiTabItemFlags_Button )
if ( tab - > Flags & ImGuiTabItemFlags_Button )
continue ;
continue ;
const char * tab_name = tab_bar - > GetTabName ( tab ) ;
const char * tab_name = TabBarGetTabName ( tab_bar , tab ) ;
if ( Selectable ( tab_name , tab_bar - > SelectedTabId = = tab - > ID ) )
if ( Selectable ( tab_name , tab_bar - > SelectedTabId = = tab - > ID ) )
tab_to_select = tab ;
tab_to_select = tab ;
}
}
@ -8132,9 +8166,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
{
{
if ( tab_appearing & & ( tab_bar - > Flags & ImGuiTabBarFlags_AutoSelectNewTabs ) & & tab_bar - > NextSelectedTabId = = 0 )
if ( tab_appearing & & ( tab_bar - > Flags & ImGuiTabBarFlags_AutoSelectNewTabs ) & & tab_bar - > NextSelectedTabId = = 0 )
if ( ! tab_bar_appearing | | tab_bar - > SelectedTabId = = 0 )
if ( ! tab_bar_appearing | | tab_bar - > SelectedTabId = = 0 )
tab_bar - > NextSelectedTabId = id ; // New tabs gets activated
TabBarQueueFocus ( tab_bar , tab ) ; // 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
tab_bar - > NextSelectedTabId = id ;
TabBarQueueFocus ( tab_bar , tab ) ;
}
}
// Lock visibility
// Lock visibility
@ -8198,7 +8232,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
bool hovered , held ;
bool hovered , held ;
bool pressed = ButtonBehavior ( bb , id , & hovered , & held , button_flags ) ;
bool pressed = ButtonBehavior ( bb , id , & hovered , & held , button_flags ) ;
if ( pressed & & ! is_tab_button )
if ( pressed & & ! is_tab_button )
tab_bar - > NextSelectedTabId = id ;
TabBarQueueFocus ( tab_bar , tab ) ;
// Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
// Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
if ( g . ActiveId ! = id )
if ( g . ActiveId ! = id )
@ -8239,9 +8273,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
const bool hovered_unblocked = IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByPopup ) ;
const bool hovered_unblocked = IsItemHovered ( ImGuiHoveredFlags_AllowWhenBlockedByPopup ) ;
if ( hovered_unblocked & & ( IsMouseClicked ( 1 ) | | IsMouseReleased ( 1 ) ) )
if ( hovered_unblocked & & ( IsMouseClicked ( 1 ) | | IsMouseReleased ( 1 ) ) & & ! is_tab_button )
if ( ! is_tab_button )
TabBarQueueFocus ( tab_bar , tab ) ;
tab_bar - > NextSelectedTabId = id ;
if ( tab_bar - > Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton )
if ( tab_bar - > Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton )
flags | = ImGuiTabItemFlags_NoCloseWithMiddleMouseButton ;
flags | = ImGuiTabItemFlags_NoCloseWithMiddleMouseButton ;