Skip to content

Commit 972ca81

Browse files
committed
Tables: extracted code for TableGetMaxColumnWidth(), fixing "stuck" resize being lossy as it used an older calculation for it and didn't honor e.g. _NoKeepColumnsVisible
1 parent 1aa59f9 commit 972ca81

File tree

3 files changed

+45
-38
lines changed

3 files changed

+45
-38
lines changed

imgui.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,7 @@ enum ImGuiTableFlags_
10791079
ImGuiTableFlags_ColumnsWidthFixed = 1 << 14, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAutoResize policy (if Resizable is off). Read description above for more details.
10801080
ImGuiTableFlags_SameWidths = 1 << 15, // Make all columns the same widths which is useful with Fixed columns policy (but granted by default with Stretch policy + no resize). Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible and disable ImGuiTableFlags_Resizable.
10811081
ImGuiTableFlags_NoHostExtendY = 1 << 16, // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible)
1082-
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small.
1082+
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable.
10831083
ImGuiTableFlags_PreciseWidths = 1 << 18, // Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth.
10841084
// Clipping
10851085
ImGuiTableFlags_NoClip = 1 << 19, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze().

imgui_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2325,6 +2325,7 @@ namespace ImGui
23252325
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
23262326
IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0);
23272327
IMGUI_API float TableGetMinColumnWidth();
2328+
IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n);
23282329
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
23292330
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
23302331
IMGUI_API void TableRemove(ImGuiTable* table);

imgui_tables.cpp

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
703703

704704
// [Part 3] Fix column flags. Calculate ideal width for columns. Count how many fixed/stretch columns we have and sum of weights.
705705
const float min_column_width = TableGetMinColumnWidth();
706-
const float min_column_distance = min_column_width + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2;
707706
int count_fixed = 0; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!)
708707
int count_resizable = 0; // Number of columns the user can resize (this is NOT the opposite of count_fixed!)
709708
float sum_weights_stretched = 0.0f; // Sum of all weights for weighted columns.
@@ -895,42 +894,20 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
895894
if (is_hovering_table && g.IO.MousePos.x >= column->ClipRect.Min.x && g.IO.MousePos.x < column->ClipRect.Max.x)
896895
table->HoveredColumnBody = (ImGuiTableColumnIdx)column_n;
897896

898-
// Maximum width
899-
float max_width = FLT_MAX;
900-
if (table->Flags & ImGuiTableFlags_ScrollX)
901-
{
902-
// Frozen columns can't reach beyond visible width else scrolling will naturally break.
903-
if (order_n < table->FreezeColumnsRequest)
904-
{
905-
max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - order_n) * min_column_distance) - offset_x;
906-
max_width = max_width - table->OuterPaddingX - table->CellPaddingX - table->CellSpacingX2;
907-
}
908-
}
909-
else if ((table->Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0)
910-
{
911-
// If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make
912-
// sure they are all visible. Because of this we also know that all of the columns will always fit in
913-
// table->WorkRect and therefore in table->InnerRect (because ScrollX is off)
914-
// FIXME-TABLE: This is solved incorrectly but also quite a difficult problem to fix as we also want ClipRect width to match.
915-
// See "table_width_distrib" and "table_width_keep_visible" tests
916-
max_width = table->WorkRect.Max.x - (table->ColumnsEnabledCount - column->IndexWithinEnabledSet - 1) * min_column_distance - offset_x;
917-
//max_width -= table->CellSpacingX1;
918-
max_width -= table->CellSpacingX2;
919-
max_width -= table->CellPaddingX * 2.0f;
920-
max_width -= table->OuterPaddingX;
921-
}
922-
column->WidthGiven = ImMin(column->WidthGiven, max_width);
897+
// Lock start position
898+
column->MinX = offset_x;
923899

924-
// Minimum width
900+
// Lock width based on start position and minimum/maximum width for this position
901+
float max_width = TableGetMaxColumnWidth(table, column_n);
902+
column->WidthGiven = ImMin(column->WidthGiven, max_width);
925903
column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, min_column_width));
904+
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
926905

927-
// Lock all our positions
906+
// Lock other positions
928907
// - ClipRect.Min.x: Because merging draw commands doesn't compare min boundaries, we make ClipRect.Min.x match left bounds to be consistent regardless of merging.
929908
// - ClipRect.Max.x: using WorkMaxX instead of MaxX (aka including padding) makes things more consistent when resizing down, tho slightly detrimental to visibility in very-small column.
930909
// - ClipRect.Max.x: using MaxX makes it easier for header to receive hover highlight with no discontinuity and display sorting arrow.
931910
// - FIXME-TABLE: We want equal width columns to have equal (ClipRect.Max.x - WorkMinX) width, which means ClipRect.max.x cannot stray off host_clip_rect.Max.x else right-most column may appear shorter.
932-
column->MinX = offset_x;
933-
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
934911
column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
935912
column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
936913
column->ItemWidth = ImFloor(column->WidthGiven * 0.65f);
@@ -1835,6 +1812,7 @@ void ImGui::TableEndCell(ImGuiTable* table)
18351812
// [SECTION] Tables: Columns width management
18361813
//-------------------------------------------------------------------------
18371814
// - TableGetMinColumnWidth() [Internal]
1815+
// - TableGetMaxColumnWidth() [Internal]
18381816
// - TableSetColumnWidth()
18391817
// - TableSetColumnWidthAutoSingle() [Internal]
18401818
// - TableSetColumnWidthAutoAll() [Internal]
@@ -1849,6 +1827,37 @@ float ImGui::TableGetMinColumnWidth()
18491827
return g.Style.FramePadding.x * 1.0f;
18501828
}
18511829

1830+
// Maximum column content width given current layout. Use column->MinX so this value on a per-column basis.
1831+
float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n)
1832+
{
1833+
const ImGuiTableColumn* column = &table->Columns[column_n];
1834+
float max_width = FLT_MAX;
1835+
const float min_column_distance = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2;
1836+
if (table->Flags & ImGuiTableFlags_ScrollX)
1837+
{
1838+
// Frozen columns can't reach beyond visible width else scrolling will naturally break.
1839+
if (column->DisplayOrder < table->FreezeColumnsRequest)
1840+
{
1841+
max_width = (table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - column->DisplayOrder) * min_column_distance) - column->MinX;
1842+
max_width = max_width - table->OuterPaddingX - table->CellPaddingX - table->CellSpacingX2;
1843+
}
1844+
}
1845+
else if ((table->Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0)
1846+
{
1847+
// If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make
1848+
// sure they are all visible. Because of this we also know that all of the columns will always fit in
1849+
// table->WorkRect and therefore in table->InnerRect (because ScrollX is off)
1850+
// FIXME-TABLE: This is solved incorrectly but also quite a difficult problem to fix as we also want ClipRect width to match.
1851+
// See "table_width_distrib" and "table_width_keep_visible" tests
1852+
max_width = table->WorkRect.Max.x - (table->ColumnsEnabledCount - column->IndexWithinEnabledSet - 1) * min_column_distance - column->MinX;
1853+
//max_width -= table->CellSpacingX1;
1854+
max_width -= table->CellSpacingX2;
1855+
max_width -= table->CellPaddingX * 2.0f;
1856+
max_width -= table->OuterPaddingX;
1857+
}
1858+
return max_width;
1859+
}
1860+
18521861
// 'width' = inner column width, without padding
18531862
void ImGui::TableSetColumnWidth(int column_n, float width)
18541863
{
@@ -1859,14 +1868,11 @@ void ImGui::TableSetColumnWidth(int column_n, float width)
18591868
ImGuiTableColumn* column_0 = &table->Columns[column_n];
18601869
float column_0_width = width;
18611870

1862-
// Constraints
1863-
const float min_width = TableGetMinColumnWidth();
1864-
float max_width_0 = FLT_MAX;
1865-
if (!(table->Flags & ImGuiTableFlags_ScrollX))
1866-
max_width_0 = (table->WorkRect.Max.x - column_0->MinX) - (table->ColumnsEnabledCount - (column_0->IndexWithinEnabledSet + 1)) * min_width;
1867-
column_0_width = ImClamp(column_0_width, min_width, max_width_0);
1868-
1871+
// Apply constraints early
18691872
// Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded)
1873+
const float min_width = TableGetMinColumnWidth();
1874+
const float max_width = TableGetMaxColumnWidth(table, column_n);
1875+
column_0_width = ImClamp(column_0_width, min_width, max_width);
18701876
if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width)
18711877
return;
18721878

0 commit comments

Comments
 (0)