Tables: (Breaking) Added ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp. Removed ImGuiTableFlags_SameWidths.
Simplified some code and clariffied that currently non-resizable = always revert to default (while waiting to untangle Fixed vs Auto and programmatic override not going through TableSetupColumn)
Whereas ImGuiTableFlags_SameWidths has some unusual handling of mixed Fixed/Stretch columns, we know treat them separately.
diff --git a/imgui.h b/imgui.h
index 849bac5..db3d1fd 100644
--- a/imgui.h
+++ b/imgui.h
@@ -1081,9 +1081,10 @@
ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style
// Sizing Policy (read above for defaults)
ImGuiTableFlags_SizingFixedFit = 1 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching contents width.
+ ImGuiTableFlags_SizingFixedSame = 2 << 13, // Columns default to _WidthFixed or _WidthAuto (if resizable or not resizable), matching the maximum contents width of all columns. Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible.
+ ImGuiTableFlags_SizingStretchProp = 3 << 13, // Columns default to _WidthStretch with default weights proportional to each columns contents widths.
ImGuiTableFlags_SizingStretchSame = 4 << 13, // Columns default to _WidthStretch with default weights all equal, unless overriden by TableSetupColumn().
// Sizing Extra Options
- 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.
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)
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.
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.
@@ -1098,7 +1099,10 @@
ImGuiTableFlags_ScrollY = 1 << 24, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
// Sorting
ImGuiTableFlags_SortMulti = 1 << 25, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1).
- ImGuiTableFlags_SortTristate = 1 << 26 // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
+ ImGuiTableFlags_SortTristate = 1 << 26, // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0).
+
+ // [Internal] Combinations and masks
+ ImGuiTableFlags_SizingMask_ = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_SizingFixedSame | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_SizingStretchSame
// Obsolete names (will be removed soon)
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -1114,9 +1118,9 @@
ImGuiTableColumnFlags_None = 0,
ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column.
ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column.
- ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame).
+ ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingStretchSame or _SizingStretchProp).
ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit and table is resizable).
- ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _SizingFixedFit and table is not resizable). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN))
+ ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _SizingFixedFit and table is not resizable, or policy is _SizingFixedSame). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN))
ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing.
ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column.
ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column.
diff --git a/imgui_demo.cpp b/imgui_demo.cpp
index 912fa70..ff90501 100644
--- a/imgui_demo.cpp
+++ b/imgui_demo.cpp
@@ -3350,6 +3350,49 @@
ImGui::PopStyleVar(2);
}
+// Show a combo box with a choice of sizing policies
+static void EditTableSizingFlags(ImGuiTableFlags* p_flags)
+{
+ struct EnumDesc { ImGuiTableFlags Value; const char* Name; const char* Tooltip; };
+ static const EnumDesc policies[] =
+ {
+ { ImGuiTableFlags_None, "Default", "Use default sizing policy:\n- ImGuiTableFlags_SizingFixedFit if ScrollX is on or if host window has ImGuiWindowFlags_AlwaysAutoResize.\n- ImGuiTableFlags_SizingStretchSame otherwise." },
+ { ImGuiTableFlags_SizingFixedFit, "ImGuiTableFlags_SizingFixedFit", "Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width." },
+ { ImGuiTableFlags_SizingFixedSame, "ImGuiTableFlags_SizingFixedSame", "Columns are all the same width, matching the maximum contents width.\nImplicitly disable ImGuiTableFlags_Resizable and enable ImGuiTableFlags_NoKeepColumnsVisible." },
+ { ImGuiTableFlags_SizingStretchProp, "ImGuiTableFlags_SizingStretchProp", "Columns default to _WidthStretch with weights proportional to their widths." },
+ { ImGuiTableFlags_SizingStretchSame, "ImGuiTableFlags_SizingStretchSame", "Columns default to _WidthStretch with same weights." }
+ };
+ int idx;
+ for (idx = 0; idx < IM_ARRAYSIZE(policies); idx++)
+ if (policies[idx].Value == (*p_flags & ImGuiTableFlags_SizingMask_))
+ break;
+ const char* preview_text = (idx < IM_ARRAYSIZE(policies)) ? policies[idx].Name + (idx > 0 ? strlen("ImGuiTableFlags") : 0) : "";
+ if (ImGui::BeginCombo("Sizing Policy", preview_text))
+ {
+ for (int n = 0; n < IM_ARRAYSIZE(policies); n++)
+ if (ImGui::Selectable(policies[n].Name, idx == n))
+ *p_flags = (*p_flags & ~ImGuiTableFlags_SizingMask_) | policies[n].Value;
+ ImGui::EndCombo();
+ }
+ ImGui::SameLine();
+ ImGui::TextDisabled("(?)");
+ if (ImGui::IsItemHovered())
+ {
+ ImGui::BeginTooltip();
+ ImGui::PushTextWrapPos(ImGui::GetFontSize() * 50.0f);
+ for (int m = 0; m < IM_ARRAYSIZE(policies); m++)
+ {
+ ImGui::Separator();
+ ImGui::Text("%s:", policies[m].Name);
+ ImGui::Separator();
+ ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetStyle().IndentSpacing * 0.5f);
+ ImGui::TextUnformatted(policies[m].Tooltip);
+ }
+ ImGui::PopTextWrapPos();
+ ImGui::EndTooltip();
+ }
+}
+
static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags)
{
ImGui::CheckboxFlags("_DefaultHide", p_flags, ImGuiTableColumnFlags_DefaultHide);
@@ -3835,6 +3878,55 @@
ImGui::SetNextItemOpen(open_action != 0);
if (ImGui::TreeNode("Sizing policies"))
{
+ static bool fixed_fill = true;
+ static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_RowBg | ImGuiTableFlags_ContextMenuInBody;
+ PushStyleCompact();
+ ImGui::Checkbox("fill", &fixed_fill);
+ ImGui::SameLine(); HelpMarker(
+ "Value passed to outer_size only affects tables with _SizingFixedFit or _SizingFixedSame sizing policies.\n\n"
+ " - outer_size.x == 0: table fit to columns total contents.\n"
+ " - outer_size.x == -FLT_MIN: table fill until right-most edge.");
+ ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable);
+ PopStyleCompact();
+
+ ImVec2 outer_size = ImVec2(fixed_fill ? -FLT_MIN : 0.0f, 0.0f);
+ static ImGuiTableFlags sizing_policy_flags[4] = { ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingFixedSame, ImGuiTableFlags_SizingStretchProp, ImGuiTableFlags_SizingStretchSame };
+ for (int table_n = 0; table_n < 4; table_n++)
+ {
+ ImGui::PushID(table_n);
+ ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 30);
+ EditTableSizingFlags(&sizing_policy_flags[table_n]);
+
+ // To make it easier to understand the different sizing policy,
+ // For each policy: we display one table where the columns have equal contents width, and one where the columns have different contents width.
+ if (ImGui::BeginTable("##table1", 3, sizing_policy_flags[table_n] | flags1, outer_size))
+ {
+ for (int row = 0; row < 3; row++)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn(); ImGui::Text("Oh dear");
+ ImGui::TableNextColumn(); ImGui::Text("Oh dear");
+ ImGui::TableNextColumn(); ImGui::Text("Oh dear");
+ }
+ ImGui::EndTable();
+ }
+ if (ImGui::BeginTable("##table2", 3, sizing_policy_flags[table_n] | flags1, outer_size))
+ {
+ for (int row = 0; row < 3; row++)
+ {
+ ImGui::TableNextRow();
+ ImGui::TableNextColumn(); ImGui::Text("AAAA");
+ ImGui::TableNextColumn(); ImGui::Text("BBBBBBBB");
+ ImGui::TableNextColumn(); ImGui::Text("CCCCCCCCCCCC");
+ }
+ ImGui::EndTable();
+ }
+ ImGui::PopID();
+ }
+
+ ImGui::Spacing();
+ ImGui::TextUnformatted("Advanced");
+ ImGui::SameLine();
HelpMarker("This section allows you to interact and see the effect of various sizing policies depending on whether Scroll is enabled and the contents of your columns.");
enum ContentsType { CT_ShowWidth, CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
@@ -3843,7 +3935,9 @@
static int column_count = 3;
PushStyleCompact();
+ ImGui::PushID("Advanced");
ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30);
+ EditTableSizingFlags(&flags);
ImGui::Combo("Contents", &contents_type, "Show width\0Short Text\0Long Text\0Button\0Fill Button\0InputText\0");
if (contents_type == CT_FillButton)
{
@@ -3851,12 +3945,6 @@
HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width.");
}
ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp);
- if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingStretchSame", &flags, ImGuiTableFlags_SizingStretchSame))
- flags &= ~ImGuiTableFlags_SizingFixedFit; // Can't specify both sizing polices so we clear the other
- ImGui::SameLine(); HelpMarker("Default if _ScrollX if disabled. Makes columns use _WidthStretch policy by default.");
- if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit))
- flags &= ~ImGuiTableFlags_SizingStretchSame; // Can't specify both sizing polices so we clear the other
- ImGui::SameLine(); HelpMarker("Default if _ScrollX if enabled. Makes columns use _WidthFixed by default, or _WidthFixedResize if _Resizable is not set.");
ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable);
ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
ImGui::SameLine(); HelpMarker("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.");
@@ -3864,10 +3952,11 @@
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY);
ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
ImGui::PopItemWidth();
+ ImGui::PopID();
PopStyleCompact();
- ImVec2 outer_size(-FLT_MIN, TEXT_BASE_HEIGHT * 7);
- if (ImGui::BeginTable("##table1", column_count, flags, outer_size))
+ outer_size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 7);
+ if (ImGui::BeginTable("##table2", column_count, flags, outer_size))
{
for (int cell = 0; cell < 10 * column_count; cell++)
{
@@ -4757,19 +4846,13 @@
if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen))
{
- if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingStretchSame", &flags, ImGuiTableFlags_SizingStretchSame))
- flags &= ~ImGuiTableFlags_SizingFixedFit; // Can't specify both sizing polices so we clear the other
- ImGui::SameLine(); HelpMarker("[Default if ScrollX is off]\nFit all columns within available width (or specified inner_width). Fixed and Stretch columns allowed.");
- if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingFixedFit", &flags, ImGuiTableFlags_SizingFixedFit))
- flags &= ~ImGuiTableFlags_SizingStretchSame; // Can't specify both sizing polices so we clear the other
- ImGui::SameLine(); HelpMarker("[Default if ScrollX is on]\nEnlarge as needed: enable scrollbar if ScrollX is enabled, otherwise extend parent window's contents rectangle. Only Fixed columns allowed. Stretched columns will calculate their width assuming no scrolling.");
+ EditTableSizingFlags(&flags);
ImGui::SameLine(); HelpMarker("In the Advanced demo we override the policy of each column so those table-wide settings have less effect that typical.");
ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY);
ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible);
ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled.");
ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths);
ImGui::SameLine(); HelpMarker("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.");
- ImGui::CheckboxFlags("ImGuiTableFlags_SameWidths", &flags, ImGuiTableFlags_SameWidths);
ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip);
ImGui::SameLine(); HelpMarker("Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with ScrollFreeze options.");
ImGui::TreePop();
diff --git a/imgui_internal.h b/imgui_internal.h
index f800bb3..29559a6 100644
--- a/imgui_internal.h
+++ b/imgui_internal.h
@@ -2051,7 +2051,7 @@
ImGuiTableColumnIdx DeclColumnsCount; // Count calls to TableSetupColumn()
ImGuiTableColumnIdx HoveredColumnBody; // Index of column whose visible region is being hovered. Important: == ColumnsCount when hovering empty region after the right-most column!
ImGuiTableColumnIdx HoveredColumnBorder; // Index of column whose right-border is being hovered (for resizing).
- ImGuiTableColumnIdx AutoFitSingleStretchColumn; // Index of single stretch column requesting auto-fit.
+ ImGuiTableColumnIdx AutoFitSingleColumn; // Index of single column requesting auto-fit.
ImGuiTableColumnIdx ResizedColumn; // Index of column being resized. Reset when InstanceCurrent==0.
ImGuiTableColumnIdx LastResizedColumn; // Index of column being resized from previous frame.
ImGuiTableColumnIdx HeldHeaderColumn; // Index of column header being held.
diff --git a/imgui_tables.cpp b/imgui_tables.cpp
index 21bef43..a574e8c 100644
--- a/imgui_tables.cpp
+++ b/imgui_tables.cpp
@@ -116,15 +116,19 @@
// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f)
// and you can fit a 100.0f wide item in it without clipping and with full padding.
//-----------------------------------------------------------------------------
-// About default width policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag)
-// - When Table policy ImGuiTableFlags_SizingFixedFit && (Table is Resizable || init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed
-// - When Table policy ImGuiTableFlags_SizingFixedFit && (Table is !Resizable && init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto
-// - When Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch
+// About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag)
+// - with Table policy ImGuiTableFlags_SizingFixedFit && (Resizable == 1 || init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width
+// - with Table policy ImGuiTableFlags_SizingFixedFit && (Resizable == 0 && init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto, Width always equal to contents width
+// - with Table policy ImGuiTableFlags_SizingFixedSame --> default Column policy is ImGuiTableColumnFlags_WidthAuto, default Width is max of all contents width
+// - with Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is 1.0f
+// - with Table policy ImGuiTableFlags_SizingStretchWeight --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is proportional to contents
//-----------------------------------------------------------------------------
// About mixing Fixed/Auto and Stretch columns together:
// - the typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
// - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place!
// that is, unless 'inner_width' is passed to BeginTable() to explicitely provide a total width to layout columns in.
+// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the maximum contents width.
+// - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
@@ -225,12 +229,12 @@
inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window)
{
// Adjust flags: set default sizing policy
- if ((flags & (ImGuiTableFlags_SizingStretchSame | ImGuiTableFlags_SizingFixedFit)) == 0)
+ if ((flags & ImGuiTableFlags_SizingMask_) == 0)
flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_SizingFixedFit : ImGuiTableFlags_SizingStretchSame;
- // Adjust flags: disable Resizable when using SameWidths (done above enforcing BordersInnerV)
- if (flags & ImGuiTableFlags_SameWidths)
- flags = (flags & ~ImGuiTableFlags_Resizable) | ImGuiTableFlags_NoKeepColumnsVisible;
+ // Adjust flags: enable NoKeepColumnsVisible when using ImGuiTableFlags_SizingFixedSame
+ if ((flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
+ flags |= ImGuiTableFlags_NoKeepColumnsVisible;
// Adjust flags: enforce borders when resizable
if (flags & ImGuiTableFlags_Resizable)
@@ -449,7 +453,7 @@
table->InstanceInteracted = -1;
table->ContextPopupColumn = -1;
table->ReorderColumn = table->ResizedColumn = table->LastResizedColumn = -1;
- table->AutoFitSingleStretchColumn = -1;
+ table->AutoFitSingleColumn = -1;
table->HoveredColumnBody = table->HoveredColumnBorder = -1;
for (int n = 0; n < columns_count; n++)
{
@@ -535,12 +539,12 @@
table->ResizedColumnNextWidth = FLT_MAX;
table->ResizedColumn = -1;
- // Process auto-fit for single stretch column, which is a special case
+ // Process auto-fit for single column, which is a special case for stretch columns and fixed columns with FixedSame policy.
// FIXME-TABLE: Would be nice to redistribute available stretch space accordingly to other weights, instead of giving it all to siblings.
- if (table->AutoFitSingleStretchColumn != -1)
+ if (table->AutoFitSingleColumn != -1)
{
- TableSetColumnWidth(table->AutoFitSingleStretchColumn, table->Columns[table->AutoFitSingleStretchColumn].WidthAuto);
- table->AutoFitSingleStretchColumn = -1;
+ TableSetColumnWidth(table->AutoFitSingleColumn, table->Columns[table->AutoFitSingleColumn].WidthAuto);
+ table->AutoFitSingleColumn = -1;
}
}
@@ -598,7 +602,8 @@
if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
{
// FIXME-TABLE: clarify promotion to WidthAuto?
- if (table->Flags & ImGuiTableFlags_SizingFixedFit)
+ const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
+ if (table_sizing_policy == ImGuiTableFlags_SizingFixedFit || table_sizing_policy == ImGuiTableFlags_SizingFixedSame)
flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAuto;
else
flags |= ImGuiTableColumnFlags_WidthStretch;
@@ -654,17 +659,22 @@
ImGuiContext& g = *GImGui;
IM_ASSERT(table->IsLayoutLocked == false);
+ const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_);
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. Calculate auto/ideal width for columns.
+ // [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns. Count fixed/stretch columns.
// Process columns in their visible orders as we are building the Prev/Next indices.
+ int count_fixed = 0; // Number of columns that have fixed sizing policies
+ int count_stretch = 0; // Number of columns that have stretch sizing policies
int last_visible_column_idx = -1;
bool has_auto_fit_request = false;
bool has_resizable = false;
+ float stretch_sum_width_auto = 0.0f;
+ float fixed_max_width_auto = 0.0f;
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
{
const int column_n = table->DisplayOrderToIndex[order_n];
@@ -723,11 +733,25 @@
if (!column->IsPreserveWidthAuto)
column->WidthAuto = TableGetColumnWidthAuto(table, column);
+ // Non-resizable columns keep their requested width (apply user value regardless of IsPreserveWidthAuto)
const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0;
if (column_is_resizable)
has_resizable = true;
+ if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f && !column_is_resizable)
+ column->WidthAuto = column->InitStretchWeightOrWidth;
+
if (column->AutoFitQueue != 0x00)
has_auto_fit_request = true;
+ if (column->Flags & ImGuiTableColumnFlags_WidthStretch)
+ {
+ stretch_sum_width_auto += column->WidthAuto;
+ count_stretch++;
+ }
+ else
+ {
+ fixed_max_width_auto = ImMax(fixed_max_width_auto, column->WidthAuto);
+ count_fixed++;
+ }
}
if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate))
table->IsSortSpecsDirty = true;
@@ -742,10 +766,8 @@
if (has_auto_fit_request)
table->IsSettingsDirty = true;
- // [Part 3] Fix column flags. Count how many fixed/stretch columns we have and sum of weights.
- int count_fixed = 0; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!)
+ // [Part 3] Fix column flags and record a few extra information.
float sum_width_requests = 0.0f; // Sum of all width for fixed and auto-resize columns, excluding width contributed by Stretch columns but including spacing/padding.
- float max_width_auto = 0.0f; // Largest auto-width (used for SameWidths feature)
float stretch_sum_weights = 0.0f; // Sum of all weights for stretch columns.
table->LeftMostStretchedColumn = table->RightMostStretchedColumn = -1;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@@ -754,17 +776,18 @@
continue;
ImGuiTableColumn* column = &table->Columns[column_n];
+ const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0;
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); // Use user value regardless of IsPreserveWidthAuto
+ // Apply same widths policy
+ float width_auto = column->WidthAuto;
+ if (table_sizing_policy == ImGuiTableFlags_SizingFixedSame && (column->AutoFitQueue != 0x00 || !column_is_resizable))
+ width_auto = fixed_max_width_auto;
- // Process auto-fit for non-stretched columns
+ // Apply automatic width
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
- if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAuto) && column->IsVisibleX))
- column->WidthRequest = column->WidthAuto;
+ if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAuto) && column->IsVisibleX) || ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable))
+ column->WidthRequest = width_auto;
// 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
@@ -774,13 +797,20 @@
// 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_requests += column->WidthRequest;
}
else
{
- if (column->AutoFitQueue != 0x00 || column->StretchWeight < 0.0f)
- column->StretchWeight = (column->InitStretchWeightOrWidth > 0.0f) ? column->InitStretchWeightOrWidth : 1.0f;
+ // Initialize stretch weight
+ if (column->AutoFitQueue != 0x00 || column->StretchWeight < 0.0f || !column_is_resizable)
+ {
+ if (column->InitStretchWeightOrWidth > 0.0f)
+ column->StretchWeight = column->InitStretchWeightOrWidth;
+ else if (table_sizing_policy == ImGuiTableFlags_SizingStretchProp)
+ column->StretchWeight = (column->WidthAuto / stretch_sum_width_auto) * count_stretch;
+ else
+ column->StretchWeight = 1.0f;
+ }
stretch_sum_weights += column->StretchWeight;
if (table->LeftMostStretchedColumn == -1 || table->Columns[table->LeftMostStretchedColumn].DisplayOrder > column->DisplayOrder)
@@ -789,42 +819,15 @@
table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n;
}
column->IsPreserveWidthAuto = false;
- max_width_auto = ImMax(max_width_auto, column->WidthAuto);
sum_width_requests += table->CellPaddingX * 2.0f;
}
table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed;
- // [Part 4] Apply "all same widths" feature.
- // - When all columns are fixed or columns are of mixed type: use the maximum auto width.
- // - When all columns are stretch: use same weight.
- const bool mixed_same_widths = (table->Flags & ImGuiTableFlags_SameWidths) && count_fixed > 0;
- if (table->Flags & ImGuiTableFlags_SameWidths)
- {
- for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
- {
- if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n)))
- continue;
- ImGuiTableColumn* column = &table->Columns[column_n];
- if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto))
- {
- sum_width_requests += max_width_auto - column->WidthRequest; // Update old sum
- column->WidthRequest = max_width_auto;
- }
- else
- {
- stretch_sum_weights += 1.0f - column->StretchWeight; // Update old sum
- column->StretchWeight = 1.0f;
- if (mixed_same_widths)
- column->WidthRequest = max_width_auto;
- }
- }
- }
-
// [Part 5] Apply final widths based on requested widths
const ImRect work_rect = table->WorkRect;
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
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_requests;
+ const float width_avail_for_stretched_columns = width_avail - width_spacings - sum_width_requests;
float width_remaining_for_stretched_columns = width_avail_for_stretched_columns;
table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
@@ -834,7 +837,7 @@
ImGuiTableColumn* column = &table->Columns[column_n];
// Allocate width for stretched/weighted columns (StretchWeight gets converted into WidthRequest)
- if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && !mixed_same_widths)
+ if (column->Flags & ImGuiTableColumnFlags_WidthStretch)
{
float weight_ratio = column->StretchWeight / stretch_sum_weights;
column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, table->MinColumnWidth) + 0.01f);
@@ -1308,8 +1311,8 @@
// When passing a width automatically enforce WidthFixed policy
// (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable)
- if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0)
- if ((table->Flags & ImGuiTableFlags_SizingFixedFit) && (init_width_or_weight > 0.0f))
+ if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0 && init_width_or_weight > 0.0f)
+ if ((table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedFit || (table->Flags & ImGuiTableFlags_SizingMask_) == ImGuiTableFlags_SizingFixedSame)
flags |= ImGuiTableColumnFlags_WidthFixed;
TableSetupColumnFlags(table, column, flags);
@@ -1891,7 +1894,7 @@
// 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);
+ width_auto = column->InitStretchWeightOrWidth;
return ImMax(width_auto, table->MinColumnWidth);
}
@@ -1987,10 +1990,7 @@
if (!column->IsEnabled)
return;
column->CannotSkipItemsQueue = (1 << 0);
- if (column->Flags & ImGuiTableColumnFlags_WidthStretch)
- table->AutoFitSingleStretchColumn = (ImGuiTableColumnIdx)column_n;
- else
- column->AutoFitQueue = (1 << 1);
+ table->AutoFitSingleColumn = (ImGuiTableColumnIdx)column_n;
}
void ImGui::TableSetColumnWidthAutoAll(ImGuiTable* table)
@@ -2353,7 +2353,7 @@
if (column->MaxX > table->InnerClipRect.Max.x && !is_resized)
continue;
if (column->NextEnabledColumn == -1 && !is_resizable)
- if ((table->Flags & ImGuiTableFlags_SameWidths) == 0 || table->IsOuterRectAutoFitX)
+ if ((table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || table->IsOuterRectAutoFitX)
continue;
if (column->MaxX <= column->ClipRect.Min.x) // FIXME-TABLE FIXME-STYLE: Assume BorderSize==1, this is problematic if we want to increase the border size..
continue;
@@ -2868,12 +2868,10 @@
}
const char* size_all_desc;
- if (table->ColumnsEnabledFixedCount == table->ColumnsEnabledCount)
+ if (table->ColumnsEnabledFixedCount == table->ColumnsEnabledCount && (table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame)
size_all_desc = "Size all columns to fit###SizeAll"; // All fixed
- else if (table->ColumnsEnabledFixedCount == 0)
- size_all_desc = "Size all columns to default###SizeAll"; // All stretch
else
- size_all_desc = "Size all columns to fit/default###SizeAll";// Mixed
+ size_all_desc = "Size all columns to default###SizeAll"; // All stretch or mixed
if (MenuItem(size_all_desc, NULL))
TableSetColumnWidthAutoAll(table);
want_separator = true;
@@ -3322,6 +3320,16 @@
#ifndef IMGUI_DISABLE_METRICS_WINDOW
+static const char* DebugNodeTableGetSizingPolicyDesc(ImGuiTableFlags sizing_policy)
+{
+ sizing_policy &= ImGuiTableFlags_SizingMask_;
+ if (sizing_policy == ImGuiTableFlags_SizingFixedFit) { return "FixedFit"; }
+ if (sizing_policy == ImGuiTableFlags_SizingFixedSame) { return "FixedSame"; }
+ if (sizing_policy == ImGuiTableFlags_SizingStretchProp) { return "StretchProp"; }
+ if (sizing_policy == ImGuiTableFlags_SizingStretchSame) { return "StretchSame"; }
+ return "N/A";
+}
+
void ImGui::DebugNodeTable(ImGuiTable* table)
{
char buf[512];
@@ -3339,7 +3347,7 @@
if (!open)
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("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f) Sizing: '%s'", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight(), DebugNodeTableGetSizingPolicyDesc(table->Flags));
BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, 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);