mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-29 14:56:36 +00:00
Tables: setup and maintain ItemWidth per column.
This commit is contained in:
parent
8f126d5d95
commit
0c9ab0acdd
1
imgui.h
1
imgui.h
@ -1092,7 +1092,6 @@ enum ImGuiTableFlags_
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Flags for ImGui::TableSetupColumn()
|
// Flags for ImGui::TableSetupColumn()
|
||||||
// FIXME-TABLE: Rename to ImGuiColumns_*, stick old columns api flags in there under an obsolete api block
|
|
||||||
enum ImGuiTableColumnFlags_
|
enum ImGuiTableColumnFlags_
|
||||||
{
|
{
|
||||||
ImGuiTableColumnFlags_None = 0,
|
ImGuiTableColumnFlags_None = 0,
|
||||||
|
@ -4021,47 +4021,87 @@ static void ShowDemoWindowTables()
|
|||||||
ImVec2 outer_size(0, TEXT_BASE_HEIGHT * 7);
|
ImVec2 outer_size(0, TEXT_BASE_HEIGHT * 7);
|
||||||
if (ImGui::BeginTable("##nways", column_count, flags, outer_size))
|
if (ImGui::BeginTable("##nways", column_count, flags, outer_size))
|
||||||
{
|
{
|
||||||
for (int row = 0; row < 10; row++)
|
for (int cell = 0; cell < 10 * column_count; cell++)
|
||||||
{
|
{
|
||||||
ImGui::TableNextRow();
|
ImGui::TableNextColumn();
|
||||||
for (int column = 0; column < column_count; column++)
|
int column = ImGui::TableGetColumnIndex();
|
||||||
|
int row = ImGui::TableGetRowIndex();
|
||||||
|
|
||||||
|
ImGui::PushID(cell);
|
||||||
|
char label[32];
|
||||||
|
static char text_buf[32] = "";
|
||||||
|
sprintf(label, "Hello %d,%d", column, row);
|
||||||
|
switch (contents_type)
|
||||||
{
|
{
|
||||||
ImGui::TableSetColumnIndex(column);
|
case CT_ShortText: ImGui::TextUnformatted(label); break;
|
||||||
char label[32];
|
case CT_LongText: ImGui::Text("Some longer text %d,%d\nOver two lines..", column, row); break;
|
||||||
static char text_buf[32] = "";
|
case CT_Button: ImGui::Button(label); break;
|
||||||
sprintf(label, "Hello %d,%d", column, row);
|
case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
|
||||||
switch (contents_type)
|
case CT_InputText: ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
|
||||||
{
|
|
||||||
case CT_ShortText: ImGui::TextUnformatted(label); break;
|
|
||||||
case CT_LongText: ImGui::Text("Some longer text %d,%d\nOver two lines..", column, row); break;
|
|
||||||
case CT_Button: ImGui::Button(label); break;
|
|
||||||
case CT_FillButton: ImGui::Button(label, ImVec2(-FLT_MIN, 0.0f)); break;
|
|
||||||
case CT_InputText: ImGui::SetNextItemWidth(-FLT_MIN); ImGui::InputText("##", text_buf, IM_ARRAYSIZE(text_buf)); break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("Item Widths");
|
||||||
|
ImGui::SameLine();
|
||||||
|
HelpMarker("Showcase using PushItemWidth() and how it is preserved on a per-column basis");
|
||||||
|
if (ImGui::BeginTable("##table2", 3, ImGuiTableFlags_Borders))
|
||||||
|
{
|
||||||
|
ImGui::TableSetupColumn("small");
|
||||||
|
ImGui::TableSetupColumn("half");
|
||||||
|
ImGui::TableSetupColumn("right-align");
|
||||||
|
ImGui::TableHeadersRow();
|
||||||
|
|
||||||
|
for (int row = 0; row < 3; row++)
|
||||||
|
{
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
if (row == 0)
|
||||||
|
{
|
||||||
|
// Setup ItemWidth once (instead of setting up every time, which is also possible but less efficient)
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::PushItemWidth(TEXT_BASE_WIDTH * 3.0f); // Small
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::PushItemWidth(-ImGui::GetContentRegionAvail().x * 0.5f);
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
ImGui::PushItemWidth(-FLT_MIN); // Right-aligned
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw our contents
|
||||||
|
static float dummy_f = 0.0f;
|
||||||
|
ImGui::PushID(row);
|
||||||
|
ImGui::TableSetColumnIndex(0);
|
||||||
|
ImGui::SliderFloat("float0", &dummy_f, 0.0f, 1.0f);
|
||||||
|
ImGui::TableSetColumnIndex(1);
|
||||||
|
ImGui::SliderFloat("float1", &dummy_f, 0.0f, 1.0f);
|
||||||
|
ImGui::TableSetColumnIndex(2);
|
||||||
|
ImGui::SliderFloat("float2", &dummy_f, 0.0f, 1.0f);
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::TextUnformatted("Stretch + ScrollX");
|
||||||
|
ImGui::SameLine();
|
||||||
HelpMarker(
|
HelpMarker(
|
||||||
"Showcase using Stretch columns + ScrollX together: "
|
"Showcase using Stretch columns + ScrollX together: "
|
||||||
"this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
|
"this is rather unusual and only makes sense when specifying an 'inner_width' for the table!\n"
|
||||||
"Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
|
"Without an explicit value, inner_width is == outer_size.x and therefore using Stretch columns + ScrollX together doesn't make sense.");
|
||||||
static ImGuiTableFlags flags2 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
|
static ImGuiTableFlags flags3 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
|
||||||
static float inner_width = 1000.0f;
|
static float inner_width = 1000.0f;
|
||||||
PushStyleCompact();
|
PushStyleCompact();
|
||||||
ImGui::PushID("flags2");
|
ImGui::PushID("flags3");
|
||||||
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags2, ImGuiTableFlags_ScrollX);
|
ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX);
|
||||||
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags2, ImGuiTableFlags_ColumnsWidthStretch))
|
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags3, ImGuiTableFlags_ColumnsWidthStretch))
|
||||||
flags2 &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other
|
flags3 &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other
|
||||||
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags2, ImGuiTableFlags_ColumnsWidthFixed))
|
if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags3, ImGuiTableFlags_ColumnsWidthFixed))
|
||||||
flags2 &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other
|
flags3 &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other
|
||||||
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f);
|
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f);
|
||||||
ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
|
ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f");
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
PopStyleCompact();
|
PopStyleCompact();
|
||||||
|
if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
|
||||||
if (ImGui::BeginTable("##table2", 7, flags2 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width))
|
|
||||||
{
|
{
|
||||||
for (int cell = 0; cell < 20 * 7; cell++)
|
for (int cell = 0; cell < 20 * 7; cell++)
|
||||||
{
|
{
|
||||||
|
@ -1893,7 +1893,7 @@ struct ImGuiTabBar
|
|||||||
#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
|
#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
|
||||||
#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableUpdateDrawChannels()
|
#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableUpdateDrawChannels()
|
||||||
|
|
||||||
// [Internal] sizeof() ~ 100
|
// [Internal] sizeof() ~ 104
|
||||||
// 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).
|
// 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).
|
||||||
struct ImGuiTableColumn
|
struct ImGuiTableColumn
|
||||||
{
|
{
|
||||||
@ -1910,6 +1910,7 @@ struct ImGuiTableColumn
|
|||||||
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.
|
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.
|
||||||
float WorkMinX; // Start position for the frame, currently ~(MinX + CellPaddingX)
|
float WorkMinX; // Start position for the frame, currently ~(MinX + CellPaddingX)
|
||||||
float WorkMaxX;
|
float WorkMaxX;
|
||||||
|
float ItemWidth;
|
||||||
float ContentMaxXFrozen; // Contents maximum position for frozen rows (apart from headers), from which we can infer content width.
|
float ContentMaxXFrozen; // Contents maximum position for frozen rows (apart from headers), from which we can infer content width.
|
||||||
float ContentMaxXUnfrozen;
|
float ContentMaxXUnfrozen;
|
||||||
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
|
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
|
|||||||
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
|
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
|
||||||
ImRect HostBackupClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
|
ImRect HostBackupClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
|
||||||
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
|
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
|
||||||
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->ColumnsOffset at the end of BeginTable()
|
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
|
||||||
|
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
|
||||||
|
int HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
|
||||||
ImGuiWindow* OuterWindow; // Parent window for the table
|
ImGuiWindow* OuterWindow; // Parent window for the table
|
||||||
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
|
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
|
||||||
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
|
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
|
||||||
|
@ -82,8 +82,8 @@
|
|||||||
// | TableEndRow() - finish existing row
|
// | TableEndRow() - finish existing row
|
||||||
// | TableBeginRow() - add a new row
|
// | TableBeginRow() - add a new row
|
||||||
// - TableSetColumnIndex() / TableNextColumn() user begin into a cell
|
// - TableSetColumnIndex() / TableNextColumn() user begin into a cell
|
||||||
// | TableEndCell() - close existing cell
|
// | TableEndCell() - close existing column/cell
|
||||||
// | TableBeginCell() - enter into current cell
|
// | TableBeginCell() - enter into current column/cell
|
||||||
// - [...] user emit contents
|
// - [...] user emit contents
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// - EndTable() user ends the table
|
// - EndTable() user ends the table
|
||||||
@ -320,6 +320,8 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
|||||||
table->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
table->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
||||||
table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
||||||
table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
|
table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
|
||||||
|
table->HostBackupItemWidth = outer_window->DC.ItemWidth;
|
||||||
|
table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
|
||||||
inner_window->ParentWorkRect = table->WorkRect;
|
inner_window->ParentWorkRect = table->WorkRect;
|
||||||
|
|
||||||
// Padding and Spacing
|
// Padding and Spacing
|
||||||
@ -826,6 +828,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
column->ClipRect.Max.y = FLT_MAX;
|
column->ClipRect.Max.y = FLT_MAX;
|
||||||
column->ClipRect.ClipWithFull(host_clip_rect);
|
column->ClipRect.ClipWithFull(host_clip_rect);
|
||||||
column->IsClipped = column->IsSkipItems = true;
|
column->IsClipped = column->IsSkipItems = true;
|
||||||
|
column->ItemWidth = 1.0f;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -866,6 +869,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
|||||||
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
|
column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
|
||||||
column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
|
column->WorkMinX = column->MinX + table->CellPaddingX + table->CellSpacingX1;
|
||||||
column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
|
column->WorkMaxX = column->MaxX - table->CellPaddingX - table->CellSpacingX2; // Expected max
|
||||||
|
column->ItemWidth = ImFloor(column->WidthGiven * 0.65f);
|
||||||
column->ClipRect.Min.x = column->MinX;
|
column->ClipRect.Min.x = column->MinX;
|
||||||
column->ClipRect.Min.y = work_rect.Min.y;
|
column->ClipRect.Min.y = work_rect.Min.y;
|
||||||
column->ClipRect.Max.x = column->MaxX; // column->WorkMaxX;
|
column->ClipRect.Max.x = column->MaxX; // column->WorkMaxX;
|
||||||
@ -1128,11 +1132,14 @@ void ImGui::EndTable()
|
|||||||
|
|
||||||
// Layout in outer window
|
// Layout in outer window
|
||||||
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
|
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();
|
PopID();
|
||||||
inner_window->WorkRect = table->HostBackupWorkRect;
|
inner_window->WorkRect = table->HostBackupWorkRect;
|
||||||
inner_window->ParentWorkRect = table->HostBackupParentWorkRect;
|
inner_window->ParentWorkRect = table->HostBackupParentWorkRect;
|
||||||
inner_window->SkipItems = table->HostSkipItems;
|
inner_window->SkipItems = table->HostSkipItems;
|
||||||
outer_window->DC.CursorPos = table->OuterRect.Min;
|
outer_window->DC.CursorPos = table->OuterRect.Min;
|
||||||
|
outer_window->DC.ItemWidth = table->HostBackupItemWidth;
|
||||||
|
outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize;
|
||||||
outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset;
|
outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset;
|
||||||
if (inner_window != outer_window)
|
if (inner_window != outer_window)
|
||||||
{
|
{
|
||||||
@ -1927,6 +1934,7 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
|
|||||||
window->WorkRect.Min.y = window->DC.CursorPos.y;
|
window->WorkRect.Min.y = window->DC.CursorPos.y;
|
||||||
window->WorkRect.Min.x = column->WorkMinX;
|
window->WorkRect.Min.x = column->WorkMinX;
|
||||||
window->WorkRect.Max.x = column->WorkMaxX;
|
window->WorkRect.Max.x = column->WorkMaxX;
|
||||||
|
window->DC.ItemWidth = column->ItemWidth;
|
||||||
|
|
||||||
// To allow ImGuiListClipper to function we propagate our row height
|
// To allow ImGuiListClipper to function we propagate our row height
|
||||||
if (!column->IsVisible)
|
if (!column->IsVisible)
|
||||||
@ -1961,6 +1969,7 @@ void ImGui::TableEndCell(ImGuiTable* table)
|
|||||||
p_max_pos_x = table->IsUnfrozen ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
|
p_max_pos_x = table->IsUnfrozen ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen;
|
||||||
*p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
|
*p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x);
|
||||||
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
|
table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY);
|
||||||
|
column->ItemWidth = window->DC.ItemWidth;
|
||||||
|
|
||||||
// Propagate text baseline for the entire row
|
// Propagate text baseline for the entire row
|
||||||
// FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one.
|
// FIXME-TABLE: Here we propagate text baseline from the last line of the cell.. instead of the first one.
|
||||||
|
Loading…
Reference in New Issue
Block a user