@ -638,14 +638,16 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
ImGuiContext & g = * GImGui ;
IM_ASSERT ( table - > IsLayoutLocked = = false ) ;
// [Part 1] Apply/lock Enabled and Order states.
// Process columns in their visible orders as we are building the Prev/Next indices.
int last_visible_column_idx = - 1 ;
bool want_column_auto_fit = false ;
table - > IsDefaultDisplayOrder = true ;
table - > ColumnsEnabledCount = 0 ;
table - > EnabledMaskByIndex = 0x00 ;
table - > EnabledMaskByDisplayOrder = 0x00 ;
table - > MinColumnWidth = ImMax ( 1.0f , g . Style . FramePadding . x * 1.0f ) ; // g.Style.ColumnsMinSpacing; // FIXME-TABLE
// [Part 1] Apply/lock Enabled and Order states.
// Process columns in their visible orders as we are building the Prev/Next indices.
int last_visible_column_idx = - 1 ;
bool want_auto_fit = false ;
for ( int order_n = 0 ; order_n < table - > ColumnsCount ; order_n + + )
{
const int column_n = table - > DisplayOrderToIndex [ order_n ] ;
@ -686,7 +688,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column - > AutoFitQueue = column - > CannotSkipItemsQueue = ( 1 < < 3 ) - 1 ; // Fit for three frames
if ( column - > AutoFitQueue ! = 0x00 )
want_column_ auto_fit = true ;
want_auto_fit = true ;
ImU64 index_mask = ( ImU64 ) 1 < < column_n ;
ImU64 display_order_mask = ( ImU64 ) 1 < < column - > DisplayOrder ;
@ -717,13 +719,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible
// to avoid the column fitting to wait until the first visible frame of the child container (may or not be a good thing).
// FIXME-TABLE: for always auto-resizing columns may not want to do that all the time.
if ( want_column_ auto_fit & & table - > OuterWindow ! = table - > InnerWindow )
if ( want_auto_fit & & table - > OuterWindow ! = table - > InnerWindow )
table - > InnerWindow - > SkipItems = false ;
if ( want_column_ auto_fit )
if ( want_auto_fit )
table - > IsSettingsDirty = true ;
// [Part 3] Fix column flags. Calculate ideal width for columns. Count how many fixed/stretch columns we have and sum of weights.
const float min_column_width = TableGetMinColumnWidth ( ) ;
int count_fixed = 0 ; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!)
int count_resizable = 0 ; // Number of columns the user can resize (this is NOT the opposite of count_fixed!)
float sum_weights_stretched = 0.0f ; // Sum of all weights for weighted columns.
@ -743,22 +744,14 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping)
// Combine width from regular rows + width from headers unless requested not to.
if ( ! column - > IsPreserveWidthAuto )
{
const float content_width_body = ImMax ( column - > ContentMaxXFrozen , column - > ContentMaxXUnfrozen ) - column - > WorkMinX ;
const float content_width_headers = column - > ContentMaxXHeadersIdeal - column - > WorkMinX ;
float width_auto = content_width_body ;
if ( ! ( column - > Flags & ImGuiTableColumnFlags_NoHeaderWidth ) )
width_auto = ImMax ( width_auto , content_width_headers ) ;
column - > WidthAuto = ImMax ( width_auto , min_column_width ) ;
}
column - > IsPreserveWidthAuto = false ;
column - > WidthAuto = TableGetColumnWidthAuto ( table , column ) ;
if ( column - > Flags & ( ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto ) )
{
// Non-resizable columns keep their requested width
if ( ( column - > Flags & ImGuiTableColumnFlags_WidthFixed ) & & column - > InitStretchWeightOrWidth > 0.0f )
if ( ! ( table - > Flags & ImGuiTableFlags_Resizable ) | | ( column - > Flags & ImGuiTableColumnFlags_NoResize ) )
column - > WidthRequest = column - > WidthAuto = ImMax ( column - > WidthAuto , column - > InitStretchWeightOrWidth ) ;
column - > WidthRequest = column - > WidthAuto = ImMax ( column - > WidthAuto , column - > InitStretchWeightOrWidth ) ; // Use user value regardless of IsPreserveWidthAuto
// Process auto-fit for non-stretched columns
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
@ -770,8 +763,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// large height (= first frame scrollbar display very off + clipper would skip lots of items).
// This is merely making the side-effect less extreme, but doesn't properly fixes it.
// FIXME: Move this to ->WidthGiven to avoid temporary lossyless?
if ( column - > AutoFitQueue > 0x01 & & table - > IsInitializing )
column - > WidthRequest = ImMax ( column - > WidthRequest , min_column_width * 4.0f ) ; // FIXME-TABLE: Another constant/scale?
// FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller.
if ( column - > AutoFitQueue > 0x01 & & table - > IsInitializing & & ! column - > IsPreserveWidthAuto )
column - > WidthRequest = ImMax ( column - > WidthRequest , table - > MinColumnWidth * 4.0f ) ; // FIXME-TABLE: Another constant/scale?
count_fixed + = 1 ;
sum_width_fixed_requests + = column - > WidthRequest ;
}
@ -789,6 +783,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if ( table - > RightMostStretchedColumn = = - 1 | | table - > Columns [ table - > RightMostStretchedColumn ] . DisplayOrder < column - > DisplayOrder )
table - > RightMostStretchedColumn = ( ImGuiTableColumnIdx ) column_n ;
}
column - > IsPreserveWidthAuto = false ;
max_width_auto = ImMax ( max_width_auto , column - > WidthAuto ) ;
sum_width_fixed_requests + = table - > CellPaddingX * 2.0f ;
}
@ -826,8 +821,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
const float width_avail = ( ( table - > Flags & ImGuiTableFlags_ScrollX ) & & table - > InnerWidth = = 0.0f ) ? table - > InnerClipRect . GetWidth ( ) : work_rect . GetWidth ( ) ;
const float width_avail_for_stretched_columns = mixed_same_widths ? 0.0f : width_avail - width_spacings - sum_width_fixed_requests ;
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns ;
table - > ColumnsTotalWidth = width_spacings ;
table - > ColumnsAutoFitWidth = width_spacings ;
table - > ColumnsGivenWidth = width_spacings + ( table - > CellPaddingX * 2.0f ) * table - > ColumnsEnabledCount ;
for ( int column_n = 0 ; column_n < table - > ColumnsCount ; column_n + + )
{
if ( ! ( table - > EnabledMaskByIndex & ( ( ImU64 ) 1 < < column_n ) ) )
@ -838,7 +832,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if ( ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) & & ! mixed_same_widths )
{
float weight_ratio = column - > StretchWeight / sum_weights_stretched ;
column - > WidthRequest = IM_FLOOR ( ImMax ( width_avail_for_stretched_columns * weight_ratio , min_column_w idth) + 0.01f ) ;
column - > WidthRequest = IM_FLOOR ( ImMax ( width_avail_for_stretched_columns * weight_ratio , table - > MinColumnW idth) + 0.01f ) ;
width_remaining_for_stretched_columns - = column - > WidthRequest ;
}
@ -848,9 +842,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
column - > Flags | = ImGuiTableColumnFlags_NoDirectResize_ ;
// Assign final width, record width in case we will need to shrink
column - > WidthGiven = ImFloor ( ImMax ( column - > WidthRequest , min_column_width ) ) ;
table - > ColumnsTotalWidth + = column - > WidthGiven + table - > CellPaddingX * 2.0f ;
table - > ColumnsAutoFitWidth + = column - > WidthAuto + table - > CellPaddingX * 2.0f ;
column - > WidthGiven = ImFloor ( ImMax ( column - > WidthRequest , table - > MinColumnWidth ) ) ;
table - > ColumnsGivenWidth + = column - > WidthGiven ;
}
// [Part 6] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
@ -919,7 +912,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Lock width based on start position and minimum/maximum width for this position
float max_width = TableGetMaxColumnWidth ( table , column_n ) ;
column - > WidthGiven = ImMin ( column - > WidthGiven , max_width ) ;
column - > WidthGiven = ImMax ( column - > WidthGiven , ImMin ( column - > WidthRequest , min_column_w idth) ) ;
column - > WidthGiven = ImMax ( column - > WidthGiven , ImMin ( column - > WidthRequest , table - > MinColumnW idth) ) ;
column - > MaxX = offset_x + column - > WidthGiven + table - > CellSpacingX1 + table - > CellSpacingX2 + table - > CellPaddingX * 2.0f ;
// Lock other positions
@ -1175,16 +1168,6 @@ void ImGui::EndTable()
if ( ( flags & ImGuiTableFlags_Borders ) ! = 0 )
TableDrawBorders ( table ) ;
// Store content width reference for each column (before attempting to merge draw calls)
const float backup_outer_cursor_pos_x = outer_window - > DC . CursorPos . x ;
const float backup_outer_max_pos_x = outer_window - > DC . CursorMaxPos . x ;
const float backup_inner_max_pos_x = inner_window - > DC . CursorMaxPos . x ;
float max_pos_x = backup_inner_max_pos_x ;
if ( table - > RightMostEnabledColumn ! = - 1 )
max_pos_x = ImMax ( max_pos_x , table - > Columns [ table - > RightMostEnabledColumn ] . MaxX ) ;
if ( table - > ResizedColumn ! = - 1 )
max_pos_x = ImMax ( max_pos_x , table - > ResizeLockMinContentsX2 ) ;
#if 0
// Strip out dummy channel draw calls
// We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out)
@ -1204,14 +1187,22 @@ void ImGui::EndTable()
TableMergeDrawChannels ( table ) ;
table - > DrawSplitter . Merge ( inner_window - > DrawList ) ;
if ( ! ( table - > Flags & ImGuiTableFlags_ScrollX ) & & inner_window ! = outer_window )
// Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable()
const float width_spacings = ( table - > OuterPaddingX * 2.0f ) + ( table - > CellSpacingX1 + table - > CellSpacingX2 ) * ( table - > ColumnsEnabledCount - 1 ) ;
table - > ColumnsAutoFitWidth = width_spacings + ( table - > CellPaddingX * 2.0f ) * table - > ColumnsEnabledCount ;
for ( int column_n = 0 ; column_n < table - > ColumnsCount ; column_n + + )
if ( table - > EnabledMaskByIndex & ( ( ImU64 ) 1 < < column_n ) )
table - > ColumnsAutoFitWidth + = TableGetColumnWidthAuto ( table , & table - > Columns [ column_n ] ) ;
// Update scroll
if ( ( table - > Flags & ImGuiTableFlags_ScrollX ) = = 0 & & inner_window ! = outer_window )
{
inner_window - > Scroll . x = 0.0f ;
}
else if ( table - > LastResizedColumn ! = - 1 & & table - > ResizedColumn = = - 1 & & inner_window - > ScrollbarX & & table - > InstanceInteracted = = table - > InstanceCurrent )
{
// When releasing a column being resized, scroll to keep the resulting column in sight
const float neighbor_width_to_keep_visible = TableGetMinColumnWidth ( ) + table - > CellPaddingX * 2.0f ;
const float neighbor_width_to_keep_visible = table - > MinColumnWidth + table - > CellPaddingX * 2.0f ;
ImGuiTableColumn * column = & table - > Columns [ table - > LastResizedColumn ] ;
if ( column - > MaxX < table - > InnerClipRect . Min . x )
SetScrollFromPosX ( inner_window , column - > MaxX - inner_window - > Pos . x - neighbor_width_to_keep_visible , 1.0f ) ;
@ -1228,10 +1219,20 @@ void ImGui::EndTable()
table - > ResizedColumnNextWidth = new_width ;
}
// Layout in outer window
// Pop from id stack
IM_ASSERT_USER_ERROR ( inner_window - > IDStack . back ( ) = = table - > ID + table - > InstanceCurrent , " Mismatching PushID/PopID! " ) ;
IM_ASSERT_USER_ERROR ( outer_window - > DC . ItemWidthStack . Size > = table - > HostBackupItemWidthStackSize , " Too many PopItemWidth! " ) ;
PopID ( ) ;
// Layout in outer window
const float backup_outer_cursor_pos_x = outer_window - > DC . CursorPos . x ;
const float backup_outer_max_pos_x = outer_window - > DC . CursorMaxPos . x ;
const float backup_inner_max_pos_x = inner_window - > DC . CursorMaxPos . x ;
float max_pos_x = backup_inner_max_pos_x ;
if ( table - > RightMostEnabledColumn ! = - 1 )
max_pos_x = ImMax ( max_pos_x , table - > Columns [ table - > RightMostEnabledColumn ] . MaxX ) ;
if ( table - > ResizedColumn ! = - 1 )
max_pos_x = ImMax ( max_pos_x , table - > ResizeLockMinContentsX2 ) ;
inner_window - > WorkRect = table - > HostBackupWorkRect ;
inner_window - > ParentWorkRect = table - > HostBackupParentWorkRect ;
inner_window - > SkipItems = table - > HostSkipItems ;
@ -1255,7 +1256,7 @@ void ImGui::EndTable()
if ( table - > Flags & ImGuiTableFlags_ScrollX )
{
inner_window - > DC . CursorMaxPos . x = max_pos_x ; // Set contents width for scrolling
outer_window - > DC . CursorMaxPos . x = ImMax ( backup_outer_max_pos_x , backup_outer_cursor_pos_x + table - > ColumnsTotal Width + inner_window - > ScrollbarSizes . x ) ; // For auto-fit
outer_window - > DC . CursorMaxPos . x = ImMax ( backup_outer_max_pos_x , backup_outer_cursor_pos_x + table - > ColumnsGiven Width + inner_window - > ScrollbarSizes . x ) ; // For scrolling
}
else
{
@ -1825,28 +1826,20 @@ void ImGui::TableEndCell(ImGuiTable* table)
//-------------------------------------------------------------------------
// [SECTION] Tables: Columns width management
//-------------------------------------------------------------------------
// - TableGetMinColumnWidth() [Internal]
// - TableGetMaxColumnWidth() [Internal]
// - TableGetColumnWidthAuto() [Internal]
// - TableSetColumnWidth()
// - TableSetColumnWidthAutoSingle() [Internal]
// - TableSetColumnWidthAutoAll() [Internal]
// - TableUpdateColumnsWeightFromWidth() [Internal]
//-------------------------------------------------------------------------
// Minimum column content width (without padding)
float ImGui : : TableGetMinColumnWidth ( )
{
ImGuiContext & g = * GImGui ;
//return g.Style.ColumnsMinSpacing; // FIXME-TABLE
return g . Style . FramePadding . x * 1.0f ;
}
// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
float ImGui : : TableGetMaxColumnWidth ( const ImGuiTable * table , int column_n )
{
const ImGuiTableColumn * column = & table - > Columns [ column_n ] ;
float max_width = FLT_MAX ;
const float min_column_distance = TableGetMinColumnWidth ( ) + table - > CellPaddingX * 2.0f + table - > CellSpacingX1 + table - > CellSpacingX2 ;
const float min_column_distance = table - > MinColumnWidth + table - > CellPaddingX * 2.0f + table - > CellSpacingX1 + table - > CellSpacingX2 ;
if ( table - > Flags & ImGuiTableFlags_ScrollX )
{
// Frozen columns can't reach beyond visible width else scrolling will naturally break.
@ -1872,6 +1865,23 @@ float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
return max_width ;
}
// Note this is meant to be stored in column->WidthAuto, please generally use the WidthAuto field
float ImGui : : TableGetColumnWidthAuto ( ImGuiTable * table , ImGuiTableColumn * column )
{
const float content_width_body = ImMax ( column - > ContentMaxXFrozen , column - > ContentMaxXUnfrozen ) - column - > WorkMinX ;
const float content_width_headers = column - > ContentMaxXHeadersIdeal - column - > WorkMinX ;
float width_auto = content_width_body ;
if ( ! ( column - > Flags & ImGuiTableColumnFlags_NoHeaderWidth ) )
width_auto = ImMax ( width_auto , content_width_headers ) ;
// Non-resizable fixed columns preserve their requested width
if ( ( column - > Flags & ImGuiTableColumnFlags_WidthFixed ) & & column - > InitStretchWeightOrWidth > 0.0f )
if ( ! ( table - > Flags & ImGuiTableFlags_Resizable ) | | ( column - > Flags & ImGuiTableColumnFlags_NoResize ) )
width_auto = ImMax ( width_auto , column - > InitStretchWeightOrWidth ) ;
return ImMax ( width_auto , table - > MinColumnWidth ) ;
}
// 'width' = inner column width, without padding
void ImGui : : TableSetColumnWidth ( int column_n , float width )
{
@ -1884,7 +1894,8 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
// Apply constraints early
// Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
const float min_width = TableGetMinColumnWidth ( ) ;
IM_ASSERT ( table - > MinColumnWidth > 0.0f ) ;
const float min_width = table - > MinColumnWidth ;
const float max_width = ImMax ( min_width , TableGetMaxColumnWidth ( table , column_n ) ) ;
column_0_width = ImClamp ( column_0_width , min_width , max_width ) ;
if ( column_0 - > WidthGiven = = column_0_width | | column_0 - > WidthRequest = = column_0_width )
@ -3308,7 +3319,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
return ;
bool clear_settings = SmallButton ( " Clear settings " ) ;
BulletText ( " OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) " , table - > OuterRect . Min . x , table - > OuterRect . Min . y , table - > OuterRect . GetWidth ( ) , table - > OuterRect . GetHeight ( ) ) ;
BulletText ( " ColumnsWidth: %.1f, AutoFitWidth: %.1f, InnerWidth: %.1f%s " , table - > ColumnsTotal Width , table - > ColumnsAutoFitWidth , table - > InnerWidth , table - > InnerWidth = = 0.0f ? " (auto) " : " " ) ;
BulletText ( " ColumnsGiven Width: %.1f, Columns AutoFitWidth: %.1f, InnerWidth: %.1f%s " , table - > ColumnsGiven Width , table - > ColumnsAutoFitWidth , table - > InnerWidth , table - > InnerWidth = = 0.0f ? " (auto) " : " " ) ;
BulletText ( " CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f " , table - > CellPaddingX , table - > CellSpacingX1 , table - > CellSpacingX2 , table - > OuterPaddingX ) ;
BulletText ( " HoveredColumnBody: %d, HoveredColumnBorder: %d " , table - > HoveredColumnBody , table - > HoveredColumnBorder ) ;
BulletText ( " ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d " , table - > ResizedColumn , table - > ReorderColumn , table - > HeldHeaderColumn ) ;