@ -6975,12 +6975,17 @@ ImGuiTabBar::ImGuiTabBar()
LastTabItemIdx = - 1 ;
}
static inline int TabItemGetSectionIdx ( const ImGuiTabItem * tab )
{
return ( tab - > Flags & ImGuiTabItemFlags_Leading ) ? 0 : ( tab - > Flags & ImGuiTabItemFlags_Trailing ) ? 2 : 1 ;
}
static int IMGUI_CDECL TabItemComparerBySection ( const void * lhs , const void * rhs )
{
const ImGuiTabItem * a = ( const ImGuiTabItem * ) lhs ;
const ImGuiTabItem * b = ( const ImGuiTabItem * ) rhs ;
const int a_section = ( a - > Flags & ImGuiTabItemFlags_Leading ) ? 0 : ( a - > Flags & ImGuiTabItemFlags_Trailing ) ? 2 : 1 ;
const int b_section = ( b - > Flags & ImGuiTabItemFlags_Leading ) ? 0 : ( b - > Flags & ImGuiTabItemFlags_Trailing ) ? 2 : 1 ;
const int a_section = TabItemGetSectionIdx ( a ) ;
const int b_section = TabItemGetSectionIdx ( b ) ;
if ( a_section ! = b_section )
return a_section - b_section ;
return ( int ) ( a - > IndexDuringLayout - b - > IndexDuringLayout ) ;
@ -7156,11 +7161,11 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
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 ;
int curr_tab_section_n = TabItemGetSectionIdx ( tab ) ;
if ( tab_dst_n > 0 )
{
ImGuiTabItem * prev_tab = & tab_bar - > Tabs [ tab_dst_n - 1 ] ;
int prev_tab_section_n = ( prev_tab - > Flags & ImGuiTabItemFlags_Leading ) ? 0 : ( prev_tab - > Flags & ImGuiTabItemFlags_Trailing ) ? 2 : 1 ;
int prev_tab_section_n = TabItemGetSectionIdx ( prev_tab ) ;
if ( curr_tab_section_n = = 0 & & prev_tab_section_n ! = 0 )
need_sort_by_section = true ;
if ( prev_tab_section_n = = 2 & & curr_tab_section_n ! = 2 )
@ -7232,7 +7237,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
const bool has_close_button = ( tab - > Flags & ImGuiTabItemFlags_NoCloseButton ) = = 0 ;
tab - > ContentWidth = TabItemCalcSize ( tab_name , has_close_button ) . x ;
int section_n = ( tab - > Flags & ImGuiTabItemFlags_Leading ) ? 0 : ( tab - > Flags & ImGuiTabItemFlags_Trailing ) ? 2 : 1 ;
int section_n = TabItemGetSectionIdx ( tab ) ;
ImGuiTabBarSection * section = & sections [ section_n ] ;
section - > Width + = tab - > ContentWidth + ( section_n = = curr_section_n ? g . Style . ItemInnerSpacing . x : 0.0f ) ;
curr_section_n = section_n ;
@ -7287,7 +7292,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
if ( shrinked_width < 0.0f )
continue ;
int section_n = ( tab - > Flags & ImGuiTabItemFlags_Leading ) ? 0 : ( tab - > Flags & ImGuiTabItemFlags_Trailing ) ? 2 : 1 ;
int section_n = TabItemGetSectionIdx ( tab ) ;
sections [ section_n ] . Width - = ( tab - > Width - shrinked_width ) ;
tab - > Width = shrinked_width ;
}
@ -7470,7 +7475,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
ImGuiTabItem * tab = TabBarFindTabByID ( tab_bar , tab_id ) ;
if ( tab = = NULL )
return ;
if ( tab - > Flags & ( ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing ) )
if ( tab - > Flags & ImGuiTabItemFlags_SectionMask_ )
return ;
ImGuiContext & g = * GImGui ;
@ -7499,56 +7504,48 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
}
}
void ImGui : : TabBarQueueReorder ( ImGuiTabBar * tab_bar , const ImGuiTabItem * tab , int dir )
void ImGui : : TabBarQueueReorder ( ImGuiTabBar * tab_bar , const ImGuiTabItem * tab , int offset )
{
IM_ASSERT ( dir = = - 1 | | dir = = + 1 ) ;
IM_ASSERT ( offset ! = 0 ) ;
IM_ASSERT ( tab_bar - > ReorderRequestTabId = = 0 ) ;
tab_bar - > ReorderRequestTabId = tab - > ID ;
tab_bar - > ReorderRequest Dir = ( ImS8 ) dir ;
tab_bar - > ReorderRequest Offset = ( ImS16 ) offset ;
}
void ImGui : : TabBarQueueReorderFromMousePos ( ImGuiTabBar * tab_bar , const ImGuiTabItem * tab, ImVec2 mouse_pos )
void ImGui : : TabBarQueueReorderFromMousePos ( ImGuiTabBar * tab_bar , const ImGuiTabItem * src_ tab, ImVec2 mouse_pos )
{
ImGuiContext & g = * GImGui ;
IM_ASSERT ( tab_bar - > ReorderRequestTabId = = 0 ) ;
if ( ( tab_bar - > Flags & ImGuiTabBarFlags_Reorderable ) = = 0 )
return ;
int source_idx = tab_bar - > Tabs . index_from_ptr ( tab ) ;
float bar_x = tab_bar - > BarRect . Min . x ;
int dir = bar_x + tab - > Offset > mouse_pos . x ? - 1 : + 1 ;
int target_idx = source_idx ;
const bool is_central_section = ( src_tab - > Flags & ImGuiTabItemFlags_SectionMask_ ) = = 0 ;
const float bar_offset = tab_bar - > BarRect . Min . x - ( is_central_section ? tab_bar - > ScrollingTarget : 0 ) ;
for ( int i = source_idx ; 0 < = i & & i < tab_bar - > Tabs . Size ; i + = dir )
// Count number of contiguous tabs we are crossing over
const int dir = ( bar_offset + src_tab - > Offset ) > mouse_pos . x ? - 1 : + 1 ;
const int src_idx = tab_bar - > Tabs . index_from_ptr ( src_tab ) ;
int dst_idx = src_idx ;
for ( int i = src_idx ; i > = 0 & & i < tab_bar - > Tabs . Size ; i + = dir )
{
const ImGuiTabItem * target_tab = & tab_bar - > Tabs [ i ] ;
// Reorder only within tab groups with _Leading, _Trailing flag or without either of them.
if ( ( target_tab - > Flags & ImGuiTabItemFlags_Leading ) ! = ( tab - > Flags & ImGuiTabItemFlags_Leading ) )
break ;
if ( ( target_tab - > Flags & ImGuiTabItemFlags_Trailing ) ! = ( tab - > Flags & ImGuiTabItemFlags_Trailing ) )
// Reordered tabs must share the same section
const ImGuiTabItem * dst_tab = & tab_bar - > Tabs [ i ] ;
if ( dst_tab - > Flags & ImGuiTabItemFlags_NoReorder )
break ;
// Do not reorder past tabs with _NoReorder flag.
if ( target_tab - > Flags & ImGuiTabItemFlags_NoReorder )
if ( ( dst_tab - > Flags & ImGuiTabItemFlags_SectionMask_ ) ! = ( src_tab - > Flags & ImGuiTabItemFlags_SectionMask_ ) )
break ;
dst_idx = i ;
target_idx = i ; // target_tab can be swapped with dragged tab.
// Current tab is destination tab under mouse position. Also include space after tab, so when mouse cursor is
// between tabs we would not continue checking further tabs that are not hovered.
if ( dir > 0 & & mouse_pos . x < bar_x + target_tab - > Offset + target_tab - > Width + g . Style . ItemInnerSpacing . x ) // End of tab is past mouse_pos.
break ;
if ( dir < 0 & & mouse_pos . x > bar_x + target_tab - > Offset - g . Style . ItemInnerSpacing . x ) // Mouse pos is past start of tab.
// Include spacing after tab, so when mouse cursor is between tabs we would not continue checking further tabs that are not hovered.
const float x1 = bar_offset + dst_tab - > Offset - g . Style . ItemInnerSpacing . x ;
const float x2 = bar_offset + dst_tab - > Offset + dst_tab - > Width + g . Style . ItemInnerSpacing . x ;
//GetForegroundDrawList()->AddRect(ImVec2(x1, tab_bar->BarRect.Min.y), ImVec2(x2, tab_bar->BarRect.Max.y), IM_COL32(255, 0, 0, 255));
if ( ( dir < 0 & & mouse_pos . x > x1 ) | | ( dir > 0 & & mouse_pos . x < x2 ) )
break ;
}
if ( target_idx ! = source_idx )
{
tab_bar - > ReorderRequestTabId = tab - > ID ;
tab_bar - > ReorderRequestDir = ( ImS8 ) ( target_idx - source_idx ) ;
}
if ( dst_idx ! = src_idx )
TabBarQueueReorder ( tab_bar , src_tab , dst_idx - src_idx ) ;
}
bool ImGui : : TabBarProcessReorder ( ImGuiTabBar * tab_bar )
@ -7558,30 +7555,23 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
return false ;
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
int tab2_order = tab_bar - > GetTabOrder ( tab1 ) + tab_bar - > ReorderRequest Dir ;
int tab2_order = tab_bar - > GetTabOrder ( tab1 ) + tab_bar - > ReorderRequest Offset ;
if ( tab2_order < 0 | | tab2_order > = tab_bar - > Tabs . Size )
return false ;
// Reordered TabItem must share the same position flags than target
// Reordered tabs must share the same section
// (Note: TabBarQueueReorderFromMousePos() also has a similar test but since we allow direct calls to TabBarQueueReorder() we do it here too)
ImGuiTabItem * tab2 = & tab_bar - > Tabs [ tab2_order ] ;
if ( tab2 - > Flags & ImGuiTabItemFlags_NoReorder )
return false ;
if ( ( tab1 - > Flags & ( ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing ) ) ! = ( tab2 - > Flags & ( ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing ) ) )
if ( ( tab1 - > Flags & ImGuiTabItemFlags_SectionMask_ ) ! = ( tab2 - > Flags & ImGuiTabItemFlags_SectionMask_ ) )
return false ;
ImGuiTabItem item_tmp = * tab1 ;
ImGuiTabItem * src , * dst ;
if ( tab_bar - > ReorderRequestDir > 0 )
{
dst = tab1 ;
src = tab1 + 1 ;
}
else
{
dst = tab2 + 1 ;
src = tab2 ;
}
memmove ( dst , src , abs ( tab_bar - > ReorderRequestDir ) * sizeof ( ImGuiTabItem ) ) ;
ImGuiTabItem * src_tab = ( tab_bar - > ReorderRequestOffset > 0 ) ? tab1 + 1 : tab2 ;
ImGuiTabItem * dst_tab = ( tab_bar - > ReorderRequestOffset > 0 ) ? tab1 : tab2 + 1 ;
const int move_count = ( tab_bar - > ReorderRequestOffset > 0 ) ? tab_bar - > ReorderRequestOffset : - tab_bar - > ReorderRequestOffset ;
memmove ( dst_tab , src_tab , move_count * sizeof ( ImGuiTabItem ) ) ;
* tab2 = item_tmp ;
if ( tab_bar - > Flags & ImGuiTabBarFlags_SaveSettings )
@ -7874,7 +7864,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
const ImVec2 backup_main_cursor_pos = window - > DC . CursorPos ;
// Layout
const bool is_central_section = ( tab - > Flags & ( ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing ) ) = = 0 ;
const bool is_central_section = ( tab - > Flags & ImGuiTabItemFlags_SectionMask_ ) = = 0 ;
size . x = tab - > Width ;
if ( is_central_section )
window - > DC . CursorPos = tab_bar - > BarRect . Min + ImVec2 ( IM_FLOOR ( tab - > Offset - tab_bar - > ScrollingAnim ) , 0.0f ) ;
@ -7964,7 +7954,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
if ( distance_from_edge_y > = threshold_y )
undocking_tab = true ;
else if ( drag_distance_from_edge_x > threshold_x )
if ( ( tab_bar - > ReorderRequest Dir < 0 & & tab_bar - > GetTabOrder ( tab ) = = 0 ) | | ( tab_bar - > ReorderRequest Dir > 0 & & tab_bar - > GetTabOrder ( tab ) = = tab_bar - > Tabs . Size - 1 ) )
if ( ( tab_bar - > ReorderRequest Offset < 0 & & tab_bar - > GetTabOrder ( tab ) = = 0 ) | | ( tab_bar - > ReorderRequest Offset > 0 & & tab_bar - > GetTabOrder ( tab ) = = tab_bar - > Tabs . Size - 1 ) )
undocking_tab = true ;
}