Skip to content

Commit 0c9ab0a

Browse files
committed
Tables: setup and maintain ItemWidth per column.
1 parent 8f126d5 commit 0c9ab0a

File tree

4 files changed

+79
-28
lines changed

4 files changed

+79
-28
lines changed

imgui.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,6 @@ enum ImGuiTableFlags_
10921092
};
10931093

10941094
// Flags for ImGui::TableSetupColumn()
1095-
// FIXME-TABLE: Rename to ImGuiColumns_*, stick old columns api flags in there under an obsolete api block
10961095
enum ImGuiTableColumnFlags_
10971096
{
10981097
ImGuiTableColumnFlags_None = 0,

imgui_demo.cpp

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4021,47 +4021,87 @@ static void ShowDemoWindowTables()
40214021
ImVec2 outer_size(0, TEXT_BASE_HEIGHT * 7);
40224022
if (ImGui::BeginTable("##nways", column_count, flags, outer_size))
40234023
{
4024-
for (int row = 0; row < 10; row++)
4024+
for (int cell = 0; cell < 10 * column_count; cell++)
4025+
{
4026+
ImGui::TableNextColumn();
4027+
int column = ImGui::TableGetColumnIndex();
4028+
int row = ImGui::TableGetRowIndex();
4029+
4030+
ImGui::PushID(cell);
4031+
char label[32];
4032+
static char text_buf[32] = "";
4033+
sprintf(label, "Hello %d,%d", column, row);
4034+
switch (contents_type)
4035+
{
4036+
case CT_ShortText: ImGui::TextUnformatted(label); break;
4037+
case CT_LongText: ImGui::Text("Some longer text %d,%d\nOver two lines..", column, row); break;
4038+
case CT_Button: ImGui::Button(label); break;
4039+
case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
4040+
case CT_InputText: ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
4041+
}
4042+
ImGui::PopID();
4043+
}
4044+
ImGui::EndTable();
4045+
}
4046+
4047+
ImGui::TextUnformatted("Item Widths");
4048+
ImGui::SameLine();
4049+
HelpMarker("Showcase using PushItemWidth() and how it is preserved on a per-column basis");
4050+
if (ImGui::BeginTable("##table2", 3, ImGuiTableFlags_Borders))
4051+
{
4052+
ImGui::TableSetupColumn("small");
4053+
ImGui::TableSetupColumn("half");
4054+
ImGui::TableSetupColumn("right-align");
4055+
ImGui::TableHeadersRow();
4056+
4057+
for (int row = 0; row < 3; row++)
40254058
{
40264059
ImGui::TableNextRow();
4027-
for (int column = 0; column < column_count; column++)
4060+
if (row == 0)
40284061
{
4029-
ImGui::TableSetColumnIndex(column);
4030-
char label[32];
4031-
static char text_buf[32] = "";
4032-
sprintf(label, "Hello %d,%d", column, row);
4033-
switch (contents_type)
4034-
{
4035-
case CT_ShortText: ImGui::TextUnformatted(label); break;
4036-
case CT_LongText: ImGui::Text("Some longer text %d,%d\nOver two lines..", column, row); break;
4037-
case CT_Button: ImGui::Button(label); break;
4038-
case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
4039-
case CT_InputText: ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
4040-
}
4062+
// Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
4063+
ImGui::TableSetColumnIndex(0);
4064+
ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
4065+
ImGui::TableSetColumnIndex(1);
4066+
ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
4067+
ImGui::TableSetColumnIndex(2);
4068+
ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
40414069
}
4070+
4071+
// Draw our contents
4072+
static float dummy_f = 0.0f;
4073+
ImGui::PushID(row);
4074+
ImGui::TableSetColumnIndex(0);
4075+
ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
4076+
ImGui::TableSetColumnIndex(1);
4077+
ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
4078+
ImGui::TableSetColumnIndex(2);
4079+
ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f);
4080+
ImGui::PopID();
40424081
}
40434082
ImGui::EndTable();
40444083
}
40454084

4085+
ImGui::TextUnformatted("Stretch + ScrollX");
4086+
ImGui::SameLine();
40464087
HelpMarker(
40474088
"Showcase using Stretch columns + ScrollX together: "
40484089
"this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
40494090
"Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
4050-
static ImGuiTableFlags flags2 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
4091+
static ImGuiTableFlags flags3 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
40514092
static float inner_width = 1000.0f;
40524093
PushStyleCompact();
4053-
ImGui::PushID("flags2");
4054-
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
4055-
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags2, ImGuiTableFlags_ColumnsWidthStretch))
4056-
flags2 &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other
4057-
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags2, ImGuiTableFlags_ColumnsWidthFixed))
4058-
flags2 &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other
4094+
ImGui::PushID("flags3");
4095+
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX);
4096+
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags3, ImGuiTableFlags_ColumnsWidthStretch))
4097+
flags3 &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other
4098+
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags3, ImGuiTableFlags_ColumnsWidthFixed))
4099+
flags3 &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other
40594100
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f);
40604101
ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
40614102
ImGui::PopID();
40624103
PopStyleCompact();
4063-
4064-
if (ImGui::BeginTable("##table2", 7, flags2 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
4104+
if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
40654105
{
40664106
for (int cell = 0; cell < 20 * 7; cell++)
40674107
{

imgui_internal.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,7 +1893,7 @@ struct ImGuiTabBar
18931893
#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
18941894
#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableUpdateDrawChannels()
18951895

1896-
// [Internal] sizeof() ~ 100
1896+
// [Internal] sizeof() ~ 104
18971897
// We use the terminology "Visible" to refer to a column that is not Hidden by user or settings. However it may still be out of view and clipped (see IsClipped).
18981898
struct ImGuiTableColumn
18991899
{
@@ -1910,6 +1910,7 @@ struct ImGuiTableColumn
19101910
float WidthGiven; // Final/actual width visible == (MaxX - MinX), locked in TableUpdateLayout(). May be > WidthRequest to honor minimum width, may be < WidthRequest to honor shrinking columns down in tight space.
19111911
float WorkMinX; // Start position for the frame, currently ~(MinX + CellPaddingX)
19121912
float WorkMaxX;
1913+
float ItemWidth;
19131914
float ContentMaxXFrozen; // Contents maximum position for frozen rows (apart from headers), from which we can infer content width.
19141915
float ContentMaxXUnfrozen;
19151916
float ContentMaxXHeadersUsed; // Contents maximum position for headers rows (regardless of freezing). TableHeader() automatically softclip itself + report ideal desired size, to avoid creating extraneous draw calls
@@ -2009,7 +2010,9 @@ struct ImGuiTable
20092010
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
20102011
ImRect HostBackupClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
20112012
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
2012-
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->ColumnsOffset at the end of BeginTable()
2013+
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
2014+
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
2015+
int HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
20132016
ImGuiWindow* OuterWindow; // Parent window for the table
20142017
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
20152018
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names

imgui_tables.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@
8282
// | TableEndRow() - finish existing row
8383
// | TableBeginRow() - add a new row
8484
// - TableSetColumnIndex() / TableNextColumn() user begin into a cell
85-
// | TableEndCell() - close existing cell
86-
// | TableBeginCell() - enter into current cell
85+
// | TableEndCell() - close existing column/cell
86+
// | TableBeginCell() - enter into current column/cell
8787
// - [...] user emit contents
8888
//-----------------------------------------------------------------------------
8989
// - EndTable() user ends the table
@@ -320,6 +320,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
320320
table->HostBackupParentWorkRect = inner_window->ParentWorkRect;
321321
table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
322322
table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
323+
table->HostBackupItemWidth = outer_window->DC.ItemWidth;
324+
table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
323325
inner_window->ParentWorkRect = table->WorkRect;
324326

325327
// Padding and Spacing
@@ -826,6 +828,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
826828
column->ClipRect.Max.y = FLT_MAX;
827829
column->ClipRect.ClipWithFull(host_clip_rect);
828830
column->IsClipped = column->IsSkipItems = true;
831+
column->ItemWidth = 1.0f;
829832
continue;
830833
}
831834

@@ -866,6 +869,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
866869
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
867870
column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
868871
column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
872+
column->ItemWidth = ImFloor(column->WidthGiven * 0.65f);
869873
column->ClipRect.Min.x = column->MinX;
870874
column->ClipRect.Min.y = work_rect.Min.y;
871875
column->ClipRect.Max.x = column->MaxX; // column->WorkMaxX;
@@ -1128,11 +1132,14 @@ void ImGui::EndTable()
11281132

11291133
// Layout in outer window
11301134
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
1135+
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
11311136
PopID();
11321137
inner_window->WorkRect = table->HostBackupWorkRect;
11331138
inner_window->ParentWorkRect = table->HostBackupParentWorkRect;
11341139
inner_window->SkipItems = table->HostSkipItems;
11351140
outer_window->DC.CursorPos = table->OuterRect.Min;
1141+
outer_window->DC.ItemWidth = table->HostBackupItemWidth;
1142+
outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize;
11361143
outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset;
11371144
if (inner_window != outer_window)
11381145
{
@@ -1927,6 +1934,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
19271934
window->WorkRect.Min.y = window->DC.CursorPos.y;
19281935
window->WorkRect.Min.x = column->WorkMinX;
19291936
window->WorkRect.Max.x = column->WorkMaxX;
1937+
window->DC.ItemWidth = column->ItemWidth;
19301938

19311939
// To allow ImGuiListClipper to function we propagate our row height
19321940
if (!column->IsVisible)
@@ -1961,6 +1969,7 @@ void ImGui::TableEndCell(ImGuiTable* table)
19611969
p_max_pos_x = table->IsUnfrozen ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
19621970
*p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
19631971
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
1972+
column->ItemWidth = window->DC.ItemWidth;
19641973

19651974
// Propagate text baseline for the entire row
19661975
// FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one.

0 commit comments

Comments
 (0)