@ -64,26 +64,26 @@
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Typical call flow: (root level is public API):
// Typical call flow: (root level is public API):
// - BeginTable() user begin into a table
// - BeginTable() user begin into a table
// - BeginChild() - (if ScrollX/ScrollY is set)
// | BeginChild() - (if ScrollX/ScrollY is set)
// - TableBeginUpdateColumns() - apply resize/order requests, lock columns active state, order
// | TableBeginUpdateColumns() - apply resize/order requests, lock columns active state, order
// | - TableSetColumnWidth() - apply resizing width (for mouse resize, often requested by previous frame)
// | - TableUpdateColumnsWeightFromWidth()- recompute columns weights (of weighted columns) from their respective width
// - TableSetupColumn() user submit columns details (optional)
// - TableSetupColumn() user submit columns details (optional)
// - TableAutoHeaders() or TableHeader() user submit a headers row (optional)
// - TableAutoHeaders() or TableHeader() user submit a headers row (optional)
// - TableSortSpecsClickColumn() - when clicked: alter sort order and sort direction
// | TableSortSpecsClickColumn() - when clicked: alter sort order and sort direction
// - TableGetSortSpecs() user queries updated sort specs (optional )
// - TableGetSortSpecs() user queries updated sort specs (optional , generally after submitting headers )
// - TableNextRow() / TableNextCell() user begin into the first row, also automatically called by TableAutoHeaders()
// - TableNextRow() / TableNextCell() user begin into the first row, also automatically called by TableAutoHeaders()
// - TableUpdateLayout() - called by the FIRST call to TableNextRow()!
// | TableUpdateLayout() - called by the FIRST call to TableNextRow()! lock all widths and columns positions.
// - TableUpdateDrawChannels() - setup ImDrawList channels
// | - TableUpdateDrawChannels() - setup ImDrawList channels
// - TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission
// | - TableUpdateBorders() - detect hovering columns for resize, ahead of contents submission
// - TableDrawContextMenu() - draw right-click context menu
// | - TableDrawContextMenu() - draw right-click context menu
// - TableEndCell() - close existing cell if not the first time
// | TableEndCell() - close existing cell if not the first time
// - TableBeginCell() - enter into current cell
// | TableBeginCell() - enter into current cell
// - [...] user emit contents
// - [...] user emit contents
// - EndTable() user ends the table
// - EndTable() user ends the table
// - TableDrawBorders() - draw outer borders, inner vertical borders
// | TableDrawBorders() - draw outer borders, inner vertical borders
// - TableDrawMergeChannels() - merge draw channels if clipping isn't required
// | TableDrawMergeChannels() - merge draw channels if clipping isn't required
// - TableSetColumnWidth() - apply resizing width
// | EndChild() - (if ScrollX/ScrollY is set)
// - TableUpdateColumnsWeightFromWidth() - recompute columns weights (of weighted columns) from their respective width
// - EndChild() - (if ScrollX/ScrollY is set)
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Configuration
// Configuration
@ -562,8 +562,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
const float min_column_width = TableGetMinColumnWidth ( ) ;
const float min_column_width = TableGetMinColumnWidth ( ) ;
int count_fixed = 0 ;
int count_fixed = 0 ;
float width_fixed = 0.0f ;
float sum_weights_stretched = 0.0f ; // Sum of all weights for weighted columns.
float total_weights = 0.0f ;
float sum_width_fixed_requests = 0.0f ; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns.
table - > LeftMostStretchedColumnDisplayOrder = - 1 ;
table - > LeftMostStretchedColumnDisplayOrder = - 1 ;
table - > ColumnsAutoFitWidth = 0.0f ;
table - > ColumnsAutoFitWidth = 0.0f ;
for ( int order_n = 0 ; order_n < table - > ColumnsCount ; order_n + + )
for ( int order_n = 0 ; order_n < table - > ColumnsCount ; order_n + + )
@ -598,27 +598,27 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
{
{
// Latch initial size for fixed columns
// Latch initial size for fixed columns
count_fixed + = 1 ;
count_fixed + = 1 ;
const bool init_size = ( column - > AutoFitQueue ! = 0x00 ) | | ( column - > Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize ) ;
const bool auto_fit = ( column - > AutoFitQueue ! = 0x00 ) | | ( column - > Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize ) ;
if ( init_size )
if ( auto_fit )
{
{
column - > WidthRequest ed = column_width_ideal ;
column - > WidthRequest = column_width_ideal ;
// FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
// FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets
// (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
// (e.g. TextWrapped) too much. Otherwise what tends to happen is that TextWrapped would output a very
// large height (= first frame scrollbar display very off + clipper would skip lots of items).
// 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.
// This is merely making the side-effect less extreme, but doesn't properly fixes it.
if ( column - > AutoFitQueue > 0x01 & & table - > IsInitializing )
if ( column - > AutoFitQueue > 0x01 & & table - > IsInitializing )
column - > WidthRequest ed = ImMax ( column - > WidthRequest ed , min_column_width * 4.0f ) ;
column - > WidthRequest = ImMax ( column - > WidthRequest , min_column_width * 4.0f ) ;
}
}
width_fixed + = column - > WidthRequest ed ;
sum_ width_fixed_requests + = column - > WidthRequest ;
}
}
else
else
{
{
IM_ASSERT ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) ;
IM_ASSERT ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) ;
const int init_size = ( column - > Resize Weight < 0.0f ) ;
const int init_size = ( column - > WidthStretch Weight < 0.0f ) ;
if ( init_size )
if ( init_size )
column - > Resize Weight = 1.0f ;
column - > WidthStretch Weight = 1.0f ;
total_weights + = column - > Resize Weight;
sum_weights_stretched + = column - > WidthStretch Weight;
if ( table - > LeftMostStretchedColumnDisplayOrder = = - 1 )
if ( table - > LeftMostStretchedColumnDisplayOrder = = - 1 )
table - > LeftMostStretchedColumnDisplayOrder = ( ImS8 ) column - > DisplayOrder ;
table - > LeftMostStretchedColumnDisplayOrder = ( ImS8 ) column - > DisplayOrder ;
}
}
@ -636,7 +636,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
width_avail = table - > InnerClipRect . GetWidth ( ) - width_spacings - 1.0f ;
width_avail = table - > InnerClipRect . GetWidth ( ) - width_spacings - 1.0f ;
else
else
width_avail = work_rect . GetWidth ( ) - width_spacings - 1.0f ;
width_avail = work_rect . GetWidth ( ) - width_spacings - 1.0f ;
const float width_avail_for_stretched_columns = width_avail - width_fixed;
const float width_avail_for_stretched_columns = width_avail - sum_ width_fixed_requests ;
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns ;
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns ;
// Apply final width based on requested widths
// Apply final width based on requested widths
@ -652,12 +652,13 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// Allocate width for stretched/weighted columns
// Allocate width for stretched/weighted columns
if ( column - > Flags & ImGuiTableColumnFlags_WidthStretch )
if ( column - > Flags & ImGuiTableColumnFlags_WidthStretch )
{
{
float weight_ratio = column - > ResizeWeight / total_weights ;
// WidthStretchWeight gets converted into WidthRequest
column - > WidthRequested = IM_FLOOR ( ImMax ( width_avail_for_stretched_columns * weight_ratio , min_column_width ) + 0.01f ) ;
float weight_ratio = column - > WidthStretchWeight / sum_weights_stretched ;
width_remaining_for_stretched_columns - = column - > WidthRequested ;
column - > WidthRequest = IM_FLOOR ( ImMax ( width_avail_for_stretched_columns * weight_ratio , min_column_width ) + 0.01f ) ;
width_remaining_for_stretched_columns - = column - > WidthRequest ;
// [Resize Rule 2] Resizing from right-side of a weighted column before a fixed column froward sizing
// [Resize Rule 2] Resizing from right-side of a weighted column preceding a fixed column
// to left-side of fixed column. We also need to copy the NoResize flag..
// needs to forward resizing to left-side of fixed column. We also need to copy the NoResize flag..
if ( column - > NextVisibleColumn ! = - 1 )
if ( column - > NextVisibleColumn ! = - 1 )
if ( ImGuiTableColumn * next_column = & table - > Columns [ column - > NextVisibleColumn ] )
if ( ImGuiTableColumn * next_column = & table - > Columns [ column - > NextVisibleColumn ] )
if ( next_column - > Flags & ImGuiTableColumnFlags_WidthFixed )
if ( next_column - > Flags & ImGuiTableColumnFlags_WidthFixed )
@ -673,7 +674,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
count_resizable + + ;
count_resizable + + ;
// Assign final width, record width in case we will need to shrink
// Assign final width, record width in case we will need to shrink
column - > WidthGiven = ImFloor ( ImMax ( column - > WidthRequest ed , min_column_width ) ) ;
column - > WidthGiven = ImFloor ( ImMax ( column - > WidthRequest , min_column_width ) ) ;
table - > ColumnsTotalWidth + = column - > WidthGiven ;
table - > ColumnsTotalWidth + = column - > WidthGiven ;
}
}
@ -703,19 +704,19 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
# endif
# endif
// Redistribute remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
// Redistribute remainder width due to rounding (remainder width is < 1.0f * number of Stretch column).
// Using right-to-left distribution (more likely to match resizing cursor), could be adjusted depending where
// Using right-to-left distribution (more likely to match resizing cursor), could be adjusted depending
// the mouse cursor is and/or relative weights.
// on where the mouse cursor is and/or relative weights.
// FIXME-TABLE: May be simpler to store floating width and floor final positions only
// FIXME-TABLE: May be simpler to store floating width and floor final positions only
// FIXME-TABLE: Make it optional? User might prefer to preserve pixel perfect same size?
// FIXME-TABLE: Make it optional? User might prefer to preserve pixel perfect same size?
if ( width_remaining_for_stretched_columns > = 1.0f )
if ( width_remaining_for_stretched_columns > = 1.0f )
for ( int order_n = table - > ColumnsCount - 1 ; total_weights > 0.0f & & width_remaining_for_stretched_columns > = 1.0f & & order_n > = 0 ; order_n - - )
for ( int order_n = table - > ColumnsCount - 1 ; sum_weights_stretched > 0.0f & & width_remaining_for_stretched_columns > = 1.0f & & order_n > = 0 ; order_n - - )
{
{
if ( ! ( table - > VisibleMaskByDisplayOrder & ( ( ImU64 ) 1 < < order_n ) ) )
if ( ! ( table - > VisibleMaskByDisplayOrder & ( ( ImU64 ) 1 < < order_n ) ) )
continue ;
continue ;
ImGuiTableColumn * column = & table - > Columns [ table - > DisplayOrderToIndex [ order_n ] ] ;
ImGuiTableColumn * column = & table - > Columns [ table - > DisplayOrderToIndex [ order_n ] ] ;
if ( ! ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) )
if ( ! ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) )
continue ;
continue ;
column - > WidthRequest ed + = 1.0f ;
column - > WidthRequest + = 1.0f ;
column - > WidthGiven + = 1.0f ;
column - > WidthGiven + = 1.0f ;
width_remaining_for_stretched_columns - = 1.0f ;
width_remaining_for_stretched_columns - = 1.0f ;
}
}
@ -1168,8 +1169,8 @@ static void TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
ImGuiTableColumn * column = & table - > Columns [ column_n ] ;
ImGuiTableColumn * column = & table - > Columns [ column_n ] ;
if ( ! column - > IsVisible | | ! ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) )
if ( ! column - > IsVisible | | ! ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) )
continue ;
continue ;
visible_weight + = column - > Resize Weight;
visible_weight + = column - > WidthStretch Weight;
visible_width + = column - > WidthRequest ed ;
visible_width + = column - > WidthRequest ;
}
}
IM_ASSERT ( visible_weight > 0.0f & & visible_width > 0.0f ) ;
IM_ASSERT ( visible_weight > 0.0f & & visible_width > 0.0f ) ;
@ -1179,7 +1180,7 @@ static void TableUpdateColumnsWeightFromWidth(ImGuiTable* table)
ImGuiTableColumn * column = & table - > Columns [ column_n ] ;
ImGuiTableColumn * column = & table - > Columns [ column_n ] ;
if ( ! column - > IsVisible | | ! ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) )
if ( ! column - > IsVisible | | ! ( column - > Flags & ImGuiTableColumnFlags_WidthStretch ) )
continue ;
continue ;
column - > Resize Weight = ( column - > WidthRequest ed + 0.0f ) / visible_width ;
column - > WidthStretch Weight = ( column - > WidthRequest + 0.0f ) / visible_width ;
}
}
}
}
@ -1205,7 +1206,7 @@ void ImGui::TableSetColumnWidth(ImGuiTable* table, ImGuiTableColumn* column_0, f
column_0_width = ImClamp ( column_0_width , min_width , max_width_0 ) ;
column_0_width = ImClamp ( column_0_width , min_width , max_width_0 ) ;
// Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
// Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
if ( column_0 - > WidthGiven = = column_0_width | | column_0 - > WidthRequest ed = = column_0_width )
if ( column_0 - > WidthGiven = = column_0_width | | column_0 - > WidthRequest = = column_0_width )
return ;
return ;
ImGuiTableColumn * column_1 = ( column_0 - > NextVisibleColumn ! = - 1 ) ? & table - > Columns [ column_0 - > NextVisibleColumn ] : NULL ;
ImGuiTableColumn * column_1 = ( column_0 - > NextVisibleColumn ! = - 1 ) ? & table - > Columns [ column_0 - > NextVisibleColumn ] : NULL ;
@ -1241,14 +1242,14 @@ void ImGui::TableSetColumnWidth(ImGuiTable* table, ImGuiTableColumn* column_0, f
if ( table - > LeftMostStretchedColumnDisplayOrder ! = - 1 & & table - > LeftMostStretchedColumnDisplayOrder < column_0 - > DisplayOrder )
if ( table - > LeftMostStretchedColumnDisplayOrder ! = - 1 & & table - > LeftMostStretchedColumnDisplayOrder < column_0 - > DisplayOrder )
{
{
// (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b)
// (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b)
float column_1_width = ImMax ( column_1 - > WidthRequest ed - ( column_0_width - column_0 - > WidthRequest ed ) , min_width ) ;
float column_1_width = ImMax ( column_1 - > WidthRequest - ( column_0_width - column_0 - > WidthRequest ) , min_width ) ;
column_0_width = column_0 - > WidthRequest ed + column_1 - > WidthRequest ed - column_1_width ;
column_0_width = column_0 - > WidthRequest + column_1 - > WidthRequest - column_1_width ;
column_1 - > WidthRequest ed = column_1_width ;
column_1 - > WidthRequest = column_1_width ;
}
}
// Apply
// Apply
//IMGUI_DEBUG_LOG("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthRequested, column_0_width);
//IMGUI_DEBUG_LOG("TableSetColumnWidth(%d, %.1f->%.1f)\n", column_0_idx, column_0->WidthRequested, column_0_width);
column_0 - > WidthRequest ed = column_0_width ;
column_0 - > WidthRequest = column_0_width ;
}
}
else if ( column_0 - > Flags & ImGuiTableColumnFlags_WidthStretch )
else if ( column_0 - > Flags & ImGuiTableColumnFlags_WidthStretch )
{
{
@ -1257,15 +1258,15 @@ void ImGui::TableSetColumnWidth(ImGuiTable* table, ImGuiTableColumn* column_0, f
{
{
float off = ( column_0 - > WidthGiven - column_0_width ) ;
float off = ( column_0 - > WidthGiven - column_0_width ) ;
float column_1_width = column_1 - > WidthGiven + off ;
float column_1_width = column_1 - > WidthGiven + off ;
column_1 - > WidthRequest ed = ImMax ( min_width , column_1_width ) ;
column_1 - > WidthRequest = ImMax ( min_width , column_1_width ) ;
return ;
return ;
}
}
// (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b)
// (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b)
float column_1_width = ImMax ( column_1 - > WidthRequest ed - ( column_0_width - column_0 - > WidthRequest ed ) , min_width ) ;
float column_1_width = ImMax ( column_1 - > WidthRequest - ( column_0_width - column_0 - > WidthRequest ) , min_width ) ;
column_0_width = column_0 - > WidthRequest ed + column_1 - > WidthRequest ed - column_1_width ;
column_0_width = column_0 - > WidthRequest + column_1 - > WidthRequest - column_1_width ;
column_1 - > WidthRequest ed = column_1_width ;
column_1 - > WidthRequest = column_1_width ;
column_0 - > WidthRequest ed = column_0_width ;
column_0 - > WidthRequest = column_0_width ;
TableUpdateColumnsWeightFromWidth ( table ) ;
TableUpdateColumnsWeightFromWidth ( table ) ;
}
}
table - > IsSettingsDirty = true ;
table - > IsSettingsDirty = true ;
@ -1462,23 +1463,23 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags,
// Initialize defaults
// Initialize defaults
// FIXME-TABLE: We don't restore widths/weight so let's avoid using IsSettingsLoaded for now
// FIXME-TABLE: We don't restore widths/weight so let's avoid using IsSettingsLoaded for now
if ( table - > IsInitializing & & column - > WidthRequest ed < 0.0f & & column - > Resize Weight < 0.0f ) // && !table->IsSettingsLoaded)
if ( table - > IsInitializing & & column - > WidthRequest < 0.0f & & column - > WidthStretch Weight < 0.0f ) // && !table->IsSettingsLoaded)
{
{
// Init width or weight
// Init width or weight
// Disable auto-fit if a default fixed width has been specified
// Disable auto-fit if a default fixed width has been specified
if ( ( flags & ImGuiTableColumnFlags_WidthFixed ) & & init_width_or_weight > 0.0f )
if ( ( flags & ImGuiTableColumnFlags_WidthFixed ) & & init_width_or_weight > 0.0f )
{
{
column - > WidthRequest ed = init_width_or_weight ;
column - > WidthRequest = init_width_or_weight ;
column - > AutoFitQueue = 0x00 ;
column - > AutoFitQueue = 0x00 ;
}
}
if ( flags & ImGuiTableColumnFlags_WidthStretch )
if ( flags & ImGuiTableColumnFlags_WidthStretch )
{
{
IM_ASSERT ( init_width_or_weight < 0.0f | | init_width_or_weight > 0.0f ) ;
IM_ASSERT ( init_width_or_weight < 0.0f | | init_width_or_weight > 0.0f ) ;
column - > Resize Weight = ( init_width_or_weight < 0.0f ? 1.0f : init_width_or_weight ) ;
column - > WidthStretch Weight = ( init_width_or_weight < 0.0f ? 1.0f : init_width_or_weight ) ;
}
}
else
else
{
{
column - > Resize Weight = 1.0f ;
column - > WidthStretch Weight = 1.0f ;
}
}
}
}
if ( table - > IsInitializing )
if ( table - > IsInitializing )
@ -2594,13 +2595,13 @@ void ImGui::DebugNodeTable(ImGuiTable* table)
const char * name = TableGetColumnName ( table , n ) ;
const char * name = TableGetColumnName ( table , n ) ;
BulletText ( " Column %d order %d name '%s': +%.1f to +%.1f \n "
BulletText ( " Column %d order %d name '%s': +%.1f to +%.1f \n "
" Visible: %d, Clipped: %d, DrawChannels: %d,%d \n "
" Visible: %d, Clipped: %d, DrawChannels: %d,%d \n "
" WidthGiven/Request ed: %.1f/%.1f, Weight: %.2 f\n "
" WidthGiven/Request : %.1f/%.1f, WidthWeight: %.3 f\n "
" ContentWidth: RowsFrozen %d, RowsUnfrozen %d, HeadersUsed/Ideal %d/%d \n "
" ContentWidth: RowsFrozen %d, RowsUnfrozen %d, HeadersUsed/Ideal %d/%d \n "
" SortOrder: %d, SortDir: %s \n "
" SortOrder: %d, SortDir: %s \n "
" UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s.. " ,
" UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s.. " ,
n , column - > DisplayOrder , name ? name : " NULL " , column - > MinX - table - > WorkRect . Min . x , column - > MaxX - table - > WorkRect . Min . x ,
n , column - > DisplayOrder , name ? name : " NULL " , column - > MinX - table - > WorkRect . Min . x , column - > MaxX - table - > WorkRect . Min . x ,
column - > IsVisible , column - > IsClipped , column - > DrawChannelRowsBeforeFreeze , column - > DrawChannelRowsAfterFreeze ,
column - > IsVisible , column - > IsClipped , column - > DrawChannelRowsBeforeFreeze , column - > DrawChannelRowsAfterFreeze ,
column - > WidthGiven , column - > WidthRequest ed , column - > Resize Weight,
column - > WidthGiven , column - > WidthRequest , column - > WidthStretch Weight,
column - > ContentWidthRowsFrozen , column - > ContentWidthRowsUnfrozen , column - > ContentWidthHeadersUsed , column - > ContentWidthHeadersIdeal ,
column - > ContentWidthRowsFrozen , column - > ContentWidthRowsUnfrozen , column - > ContentWidthHeadersUsed , column - > ContentWidthHeadersIdeal ,
column - > SortOrder , ( column - > SortDirection = = ImGuiSortDirection_Ascending ) ? " Ascending " : ( column - > SortDirection = = ImGuiSortDirection_Descending ) ? " Descending " : " None " ,
column - > SortOrder , ( column - > SortDirection = = ImGuiSortDirection_Ascending ) ? " Ascending " : ( column - > SortDirection = = ImGuiSortDirection_Descending ) ? " Descending " : " None " ,
column - > UserID , column - > Flags ,
column - > UserID , column - > Flags ,