Tables: Tidy up comments. Replaced some Columns by Tables in demo. Removed ImGuiTableFlags_Scroll (combining ScrollX/ScrollY) because each axis inccur different requirements/constraints.

This commit is contained in:
ocornut 2020-10-26 18:28:49 +01:00
parent 51abdd53e3
commit d9ca3939e1
4 changed files with 94 additions and 98 deletions

View File

@ -2201,7 +2201,7 @@ static void SetCursorPosYAndSetupForPrevLine(float pos_y, float line_height)
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage. window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
if (ImGuiOldColumns* columns = window->DC.CurrentColumns) if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly // FIXME-TABLE columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
if (ImGuiTable* table = g.CurrentTable) if (ImGuiTable* table = g.CurrentTable)
{ {
if (table->IsInsideRow) if (table->IsInsideRow)

11
imgui.h
View File

@ -687,7 +687,7 @@ namespace ImGui
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc. // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc.
// Important: this will not display anything! The name passed to TableSetupColumn() is used by TableHeadersRow() and context-menus. // Important: this will not display anything! The name passed to TableSetupColumn() is used by TableHeadersRow() and context-menus.
// - Use TableHeadersRow() to create a row and automatically submit a TableHeader() for each column. // - Use TableHeadersRow() to create a row and automatically submit a TableHeader() for each column.
// Headers are required to perform some interactions: reordering, sorting, context menu (FIXME-TABLE: context menu should work without!) // Headers are required to perform: reordering, sorting, and opening the context menu (but context menu can also be available in columns body using ImGuiTableFlags_ContextMenuInBody).
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in some advanced cases (e.g. adding custom widgets in header row). // - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in some advanced cases (e.g. adding custom widgets in header row).
// - Use TableSetupScrollFreeze() to lock columns (from the right) or rows (from the top) so they stay visible when scrolled. // - Use TableSetupScrollFreeze() to lock columns (from the right) or rows (from the top) so they stay visible when scrolled.
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = -1.0f, ImU32 user_id = 0); IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = -1.0f, ImU32 user_id = 0);
@ -1051,8 +1051,8 @@ enum ImGuiTableFlags_
// Features // Features
ImGuiTableFlags_None = 0, ImGuiTableFlags_None = 0,
ImGuiTableFlags_Resizable = 1 << 0, // Allow resizing columns. ImGuiTableFlags_Resizable = 1 << 0, // Allow resizing columns.
ImGuiTableFlags_Reorderable = 1 << 1, // Allow reordering columns (need calling TableSetupColumn() + TableHeadersRow() to display headers) ImGuiTableFlags_Reorderable = 1 << 1, // Allow reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers)
ImGuiTableFlags_Hideable = 1 << 2, // Allow hiding columns (with right-click on header) (FIXME-TABLE: allow without headers). ImGuiTableFlags_Hideable = 1 << 2, // Allow hiding columns in context menu.
ImGuiTableFlags_Sortable = 1 << 3, // Allow sorting on one column (sort_specs_count will always be == 1). Call TableGetSortSpecs() to obtain sort specs. ImGuiTableFlags_Sortable = 1 << 3, // Allow sorting on one column (sort_specs_count will always be == 1). Call TableGetSortSpecs() to obtain sort specs.
ImGuiTableFlags_MultiSortable = 1 << 4, // Allow sorting on multiple columns by holding Shift (sort_specs_count may be > 1). Call TableGetSortSpecs() to obtain sort specs. ImGuiTableFlags_MultiSortable = 1 << 4, // Allow sorting on multiple columns by holding Shift (sort_specs_count may be > 1). Call TableGetSortSpecs() to obtain sort specs.
ImGuiTableFlags_NoSavedSettings = 1 << 5, // Disable persisting columns order, width and sort settings in the .ini file. ImGuiTableFlags_NoSavedSettings = 1 << 5, // Disable persisting columns order, width and sort settings in the .ini file.
@ -1075,16 +1075,15 @@ enum ImGuiTableFlags_
ImGuiTableFlags_SizingPolicyStretchX = 1 << 15, // Default if ScrollX is off. Columns will default to use _WidthStretch policy. Read description above for more details. ImGuiTableFlags_SizingPolicyStretchX = 1 << 15, // Default if ScrollX is off. Columns will default to use _WidthStretch policy. Read description above for more details.
ImGuiTableFlags_NoHeadersWidth = 1 << 16, // Disable header width contribution to automatic width calculation. ImGuiTableFlags_NoHeadersWidth = 1 << 16, // Disable header width contribution to automatic width calculation.
ImGuiTableFlags_NoHostExtendY = 1 << 17, // (FIXME-TABLE: Reword as SizingPolicy?) Disable extending past the limit set by outer_size.y, only meaningful when neither of ScrollX|ScrollY are set (data below the limit will be clipped and not visible) ImGuiTableFlags_NoHostExtendY = 1 << 17, // (FIXME-TABLE: Reword as SizingPolicy?) Disable extending past the limit set by outer_size.y, only meaningful when neither of ScrollX|ScrollY are set (data below the limit will be clipped and not visible)
ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // (FIXME-TABLE) Disable code that keeps column always minimally visible when table width gets too small and horizontal scrolling is off. ImGuiTableFlags_NoKeepColumnsVisible = 1 << 18, // Disable keeping column always minimally visible when table width gets too small and horizontal scrolling is off.
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(). 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().
// Padding // Padding
ImGuiTableFlags_PadOuterX = 1 << 20, // Default if BordersOuterV is on. Enable outer-most padding. ImGuiTableFlags_PadOuterX = 1 << 20, // Default if BordersOuterV is on. Enable outer-most padding.
ImGuiTableFlags_NoPadOuterX = 1 << 21, // Default if BordersOuterV is off. Disable outer-most padding. ImGuiTableFlags_NoPadOuterX = 1 << 21, // Default if BordersOuterV is off. Disable outer-most padding.
ImGuiTableFlags_NoPadInnerX = 1 << 22, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). ImGuiTableFlags_NoPadInnerX = 1 << 22, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off).
// Scrolling // Scrolling
ImGuiTableFlags_ScrollX = 1 << 23, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Because this create a child window, ScrollY is currently generally recommended when using ScrollX. ImGuiTableFlags_ScrollX = 1 << 23, // Enable horizontal scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. Changes default sizing policy. Because this create a child window, ScrollY is currently generally recommended when using ScrollX.
ImGuiTableFlags_ScrollY = 1 << 24, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. ImGuiTableFlags_ScrollY = 1 << 24, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size.
ImGuiTableFlags_Scroll = ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY,
// [Internal] Combinations and masks // [Internal] Combinations and masks
ImGuiTableFlags_SizingPolicyMaskX_ = ImGuiTableFlags_SizingPolicyStretchX | ImGuiTableFlags_SizingPolicyFixedX ImGuiTableFlags_SizingPolicyMaskX_ = ImGuiTableFlags_SizingPolicyStretchX | ImGuiTableFlags_SizingPolicyFixedX

View File

@ -1087,15 +1087,36 @@ static void ShowDemoWindowWidgets()
} }
if (ImGui::TreeNode("In columns")) if (ImGui::TreeNode("In columns"))
{ {
ImGui::Columns(3, NULL, false); static bool selected[10] = {};
static bool selected[16] = {};
for (int i = 0; i < 16; i++) if (ImGui::BeginTable("split1", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
{ {
char label[32]; sprintf(label, "Item %d", i); for (int i = 0; i < 10; i++)
if (ImGui::Selectable(label, &selected[i])) {} {
ImGui::NextColumn(); char label[32];
sprintf(label, "Item %d", i);
ImGui::TableNextColumn();
ImGui::Selectable(label, &selected[i]); // FIXME-TABLE: Selection overlap
}
ImGui::EndTable();
}
ImGui::Separator();
if (ImGui::BeginTable("split2", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
{
for (int i = 0; i < 10; i++)
{
char label[32];
sprintf(label, "Item %d", i);
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Selectable(label, &selected[i], ImGuiSelectableFlags_SpanAllColumns);
ImGui::TableNextColumn();
ImGui::Text("Some other contents");
ImGui::TableNextColumn();
ImGui::Text("123456");
}
ImGui::EndTable();
} }
ImGui::Columns(1);
ImGui::TreePop(); ImGui::TreePop();
} }
if (ImGui::TreeNode("Grid")) if (ImGui::TreeNode("Grid"))
@ -2131,13 +2152,16 @@ static void ShowDemoWindowLayout()
} }
ImGui::EndMenuBar(); ImGui::EndMenuBar();
} }
ImGui::Columns(2); if (ImGui::BeginTable("split", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings))
for (int i = 0; i < 100; i++)
{ {
char buf[32]; for (int i = 0; i < 100; i++)
sprintf(buf, "%03d", i); {
ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f)); char buf[32];
ImGui::NextColumn(); sprintf(buf, "%03d", i);
ImGui::TableNextColumn();
ImGui::Button(buf, ImVec2(-FLT_MIN, 0.0f));
}
ImGui::EndTable();
} }
ImGui::EndChild(); ImGui::EndChild();
ImGui::PopStyleVar(); ImGui::PopStyleVar();
@ -2883,6 +2907,17 @@ static void ShowDemoWindowLayout()
} }
if (show_columns) if (show_columns)
{ {
ImGui::Text("Tables:");
if (ImGui::BeginTable("table", 4, ImGuiTableFlags_Borders))
{
for (int n = 0; n < 4; n++)
{
ImGui::TableNextColumn();
ImGui::Text("Width %.2f", ImGui::GetContentRegionAvail().x);
}
ImGui::EndTable();
}
ImGui::Text("Columns:");
ImGui::Columns(4); ImGui::Columns(4);
for (int n = 0; n < 4; n++) for (int n = 0; n < 4; n++)
{ {
@ -3509,7 +3544,10 @@ static void ShowDemoWindowTables()
// So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small) // So columns will adopt the "Fixed" policy and will maintain a fixed width regardless of the whole available width (unless table is small)
// If there is not enough available width to fit all columns, they will however be resized down. // If there is not enough available width to fit all columns, they will however be resized down.
// FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings
HelpMarker("Using _Resizable + _SizingPolicyFixedX flags.\nFixed-width columns generally makes more sense if you want to use horizontal scrolling."); HelpMarker(
"Using _Resizable + _SizingPolicyFixedX flags.\n"
"Fixed-width columns generally makes more sense if you want to use horizontal scrolling.\n\n"
"Double-click a column border to auto-fit the column to its contents.");
static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingPolicyFixedX | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV; static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingPolicyFixedX | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV;
//ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", (unsigned int*)&flags, ImGuiTableFlags_ScrollX); // FIXME-TABLE: Explain or fix the effect of enable Scroll on outer_size //ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", (unsigned int*)&flags, ImGuiTableFlags_ScrollX); // FIXME-TABLE: Explain or fix the effect of enable Scroll on outer_size
if (ImGui::BeginTable("##table1", 3, flags)) if (ImGui::BeginTable("##table1", 3, flags))
@ -3918,7 +3956,7 @@ static void ShowDemoWindowTables()
HelpMarker("This section allows you to interact and see the effect of StretchX vs FixedX sizing policies depending on whether Scroll is enabled and the contents of your columns."); HelpMarker("This section allows you to interact and see the effect of StretchX vs FixedX sizing policies depending on whether Scroll is enabled and the contents of your columns.");
enum ContentsType { CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText }; enum ContentsType { CT_ShortText, CT_LongText, CT_Button, CT_FillButton, CT_InputText };
static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg; static ImGuiTableFlags flags = ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg;
static int contents_type = CT_FillButton; static int contents_type = CT_Button;
PushStyleCompact(); PushStyleCompact();
ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 22); ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 22);
@ -3969,7 +4007,7 @@ static void ShowDemoWindowTables()
ImGui::SetNextItemOpen(open_action != 0); ImGui::SetNextItemOpen(open_action != 0);
if (ImGui::TreeNode("Compact table")) if (ImGui::TreeNode("Compact table"))
{ {
// FIXME-TABLE: Vertical border not overridden the same way as horizontal one // FIXME-TABLE: Vertical border not displayed the same way as horizontal one...
HelpMarker("Setting style.CellPadding to (0,0)."); HelpMarker("Setting style.CellPadding to (0,0).");
static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg; static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg;
static bool no_widget_frame = false; static bool no_widget_frame = false;
@ -4090,9 +4128,6 @@ static void ShowDemoWindowTables()
if (ImGui::TreeNode("Tree view")) if (ImGui::TreeNode("Tree view"))
{ {
static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody; static ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuterH | ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
//PushStyleCompact();
//ImGui::CheckboxFlags("ImGuiTableFlags_Scroll", (unsigned int*)&flags, ImGuiTableFlags_Scroll);
//PopStyleCompact();
if (ImGui::BeginTable("##3ways", 3, flags)) if (ImGui::BeginTable("##3ways", 3, flags))
{ {
@ -4407,7 +4442,7 @@ static void ShowDemoWindowTables()
; ;
enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable }; enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable };
static int contents_type = CT_FillButton; static int contents_type = CT_Button;
const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable" }; const char* contents_type_names[] = { "Text", "Button", "SmallButton", "FillButton", "Selectable" };
static int freeze_cols = 1; static int freeze_cols = 1;
static int freeze_rows = 1; static int freeze_rows = 1;
@ -4818,32 +4853,6 @@ static void ShowDemoWindowColumns()
ImGui::TreePop(); ImGui::TreePop();
} }
// Scrolling columns
/*
if (ImGui::TreeNode("Vertical Scrolling"))
{
ImGui::BeginChild("##header", ImVec2(0, ImGui::GetTextLineHeightWithSpacing()+ImGui::GetStyle().ItemSpacing.y));
ImGui::Columns(3);
ImGui::Text("ID"); ImGui::NextColumn();
ImGui::Text("Name"); ImGui::NextColumn();
ImGui::Text("Path"); ImGui::NextColumn();
ImGui::Columns(1);
ImGui::Separator();
ImGui::EndChild();
ImGui::BeginChild("##scrollingregion", ImVec2(0, 60));
ImGui::Columns(3);
for (int i = 0; i < 10; i++)
{
ImGui::Text("%04d", i); ImGui::NextColumn();
ImGui::Text("Foobar"); ImGui::NextColumn();
ImGui::Text("/path/foobar/%04d/", i); ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::EndChild();
ImGui::TreePop();
}
*/
if (ImGui::TreeNode("Horizontal Scrolling")) if (ImGui::TreeNode("Horizontal Scrolling"))
{ {
ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f)); ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f));
@ -6300,12 +6309,13 @@ static void ShowPlaceholderObject(const char* prefix, int uid)
ImGui::PushID(uid); ImGui::PushID(uid);
// Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high. // Text and Tree nodes are less high than framed widgets, using AlignTextToFramePadding() we add vertical spacing to make the tree lines equal high.
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid); bool node_open = ImGui::TreeNode("Object", "%s_%u", prefix, uid);
ImGui::NextColumn(); ImGui::TableSetColumnIndex(1);
ImGui::AlignTextToFramePadding();
ImGui::Text("my sailor is rich"); ImGui::Text("my sailor is rich");
ImGui::NextColumn();
if (node_open) if (node_open)
{ {
static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f }; static float placeholder_members[8] = { 0.0f, 0.0f, 1.0f, 3.1416f, 100.0f, 999.0f };
@ -6319,11 +6329,14 @@ static void ShowPlaceholderObject(const char* prefix, int uid)
else else
{ {
// Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well) // Here we use a TreeNode to highlight on hover (we could use e.g. Selectable as well)
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::AlignTextToFramePadding(); ImGui::AlignTextToFramePadding();
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet; ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen | ImGuiTreeNodeFlags_Bullet;
ImGui::TreeNodeEx("Field", flags, "Field_%d", i); ImGui::TreeNodeEx("Field", flags, "Field_%d", i);
ImGui::NextColumn();
ImGui::SetNextItemWidth(-1); ImGui::TableSetColumnIndex(1);
ImGui::SetNextItemWidth(-FLT_MIN);
if (i >= 5) if (i >= 5)
ImGui::InputFloat("##value", &placeholder_members[i], 1.0f); ImGui::InputFloat("##value", &placeholder_members[i], 1.0f);
else else
@ -6354,15 +6367,16 @@ static void ShowExampleAppPropertyEditor(bool* p_open)
"your cursor horizontally instead of using the Columns() API."); "your cursor horizontally instead of using the Columns() API.");
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2)); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2, 2));
ImGui::Columns(2); if (ImGui::BeginTable("split", 2, ImGuiTableFlags_BordersOuter | ImGuiTableFlags_Resizable))
ImGui::Separator(); {
// Iterate placeholder objects (all the same data)
// Iterate placeholder objects (all the same data) for (int obj_i = 0; obj_i < 4; obj_i++)
for (int obj_i = 0; obj_i < 3; obj_i++) {
ShowPlaceholderObject("Object", obj_i); ShowPlaceholderObject("Object", obj_i);
//ImGui::Separator();
ImGui::Columns(1); }
ImGui::Separator(); ImGui::EndTable();
}
ImGui::PopStyleVar(); ImGui::PopStyleVar();
ImGui::End(); ImGui::End();
} }

View File

@ -603,7 +603,7 @@ static void TableFixColumnSortDirection(ImGuiTableColumn* column)
static float TableGetMinColumnWidth() static float TableGetMinColumnWidth()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
// return g.Style.ColumnsMinSpacing; // FIXME-TABLE //return g.Style.ColumnsMinSpacing; // FIXME-TABLE
return g.Style.FramePadding.x * 1.0f; return g.Style.FramePadding.x * 1.0f;
} }
@ -667,7 +667,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (column->Flags & (ImGuiTableColumnFlags_WidthAlwaysAutoResize | ImGuiTableColumnFlags_WidthFixed)) if (column->Flags & (ImGuiTableColumnFlags_WidthAlwaysAutoResize | ImGuiTableColumnFlags_WidthFixed))
{ {
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
count_fixed += 1;
if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize) && !column->IsClipped)) if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAlwaysAutoResize) && !column->IsClipped))
column->WidthRequest = width_auto; column->WidthRequest = width_auto;
@ -679,6 +678,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (column->AutoFitQueue > 0x01 && table->IsInitializing) if (column->AutoFitQueue > 0x01 && table->IsInitializing)
column->WidthRequest = ImMax(column->WidthRequest, min_column_width * 4.0f); column->WidthRequest = ImMax(column->WidthRequest, min_column_width * 4.0f);
count_fixed += 1;
sum_width_fixed_requests += column->WidthRequest; sum_width_fixed_requests += column->WidthRequest;
} }
else else
@ -773,8 +773,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
// 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 // Using right-to-left distribution (more likely to match resizing cursor), could be adjusted depending
// on where 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: 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; sum_weights_stretched > 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--)
{ {
@ -829,15 +828,14 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
if (order_n < table->FreezeColumnsRequest) if (order_n < table->FreezeColumnsRequest)
max_x = table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - order_n) * min_column_width_padded - table->OuterPaddingX; max_x = table->InnerClipRect.Max.x - (table->FreezeColumnsRequest - order_n) * min_column_width_padded - table->OuterPaddingX;
} }
else else if ((table->Flags & ImGuiTableFlags_NoKeepColumnsVisible) == 0)
{ {
// If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make // If horizontal scrolling if disabled, we apply a final lossless shrinking of columns in order to make
// sure they are all visible. Because of this we also know that all of the columns will always fit in // sure they are all visible. Because of this we also know that all of the columns will always fit in
// table->WorkRect and therefore in table->InnerRect (because ScrollX is off) // table->WorkRect and therefore in table->InnerRect (because ScrollX is off)
if (!(table->Flags & ImGuiTableFlags_NoKeepColumnsVisible)) max_x = table->WorkRect.Max.x - (table->ColumnsVisibleCount - (column->IndexWithinVisibleSet + 1)) * min_column_width_padded - table->OuterPaddingX;
max_x = table->WorkRect.Max.x - (table->ColumnsVisibleCount - (column->IndexWithinVisibleSet + 1)) * min_column_width_padded - table->OuterPaddingX;
} }
if (offset_x + column->WidthGiven + table->CellPaddingX * 2.0f > max_x) // FIXME-TABLE: CHECK if (offset_x + column->WidthGiven + table->CellPaddingX * 2.0f > max_x)
column->WidthGiven = ImMax(max_x - offset_x - table->CellPaddingX * 2.0f, min_column_width); column->WidthGiven = ImMax(max_x - offset_x - table->CellPaddingX * 2.0f, min_column_width);
// Min, Max + starting positions // Min, Max + starting positions
@ -1080,13 +1078,8 @@ void ImGui::EndTable()
const float backup_outer_max_pos_x = outer_window->DC.CursorMaxPos.x; const float backup_outer_max_pos_x = outer_window->DC.CursorMaxPos.x;
const float backup_inner_max_pos_x = inner_window->DC.CursorMaxPos.x; const float backup_inner_max_pos_x = inner_window->DC.CursorMaxPos.x;
float max_pos_x = backup_inner_max_pos_x; float max_pos_x = backup_inner_max_pos_x;
for (int column_n = 0; column_n < table->ColumnsCount; column_n++) if (table->RightMostVisibleColumn != -1)
{ max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostVisibleColumn].MaxX);
// Add an extra 1 pixel so we can see the last column vertical line if it lies on the right-most edge.
ImGuiTableColumn* column = &table->Columns[column_n];
if (table->VisibleMaskByIndex & ((ImU64)1 << column_n))
max_pos_x = ImMax(max_pos_x, column->MaxX);
}
// Flatten channels and merge draw calls // Flatten channels and merge draw calls
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, 0); table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, 0);
@ -1094,13 +1087,13 @@ void ImGui::EndTable()
TableReorderDrawChannelsForMerge(table); TableReorderDrawChannelsForMerge(table);
table->DrawSplitter.Merge(inner_window->DrawList); table->DrawSplitter.Merge(inner_window->DrawList);
// When releasing a column being resized, scroll to keep the resulting column in sight
if (!(table->Flags & ImGuiTableFlags_ScrollX) && inner_window != outer_window) if (!(table->Flags & ImGuiTableFlags_ScrollX) && inner_window != outer_window)
{ {
inner_window->Scroll.x = 0.0f; inner_window->Scroll.x = 0.0f;
} }
else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent) else if (table->LastResizedColumn != -1 && table->ResizedColumn == -1 && inner_window->ScrollbarX && table->InstanceInteracted == table->InstanceCurrent)
{ {
// When releasing a column being resized, scroll to keep the resulting column in sight
const float min_column_width_padded = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f; const float min_column_width_padded = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f;
ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn]; ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn];
if (column->MaxX < table->InnerClipRect.Min.x) if (column->MaxX < table->InnerClipRect.Min.x)
@ -1154,8 +1147,7 @@ void ImGui::EndTable()
TableSaveSettings(table); TableSaveSettings(table);
// Clear or restore current table, if any // Clear or restore current table, if any
IM_ASSERT(g.CurrentWindow == outer_window); IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
IM_ASSERT(g.CurrentTable == table);
g.CurrentTableStack.pop_back(); g.CurrentTableStack.pop_back();
g.CurrentTable = g.CurrentTableStack.Size ? g.Tables.GetByIndex(g.CurrentTableStack.back().Index) : NULL; g.CurrentTable = g.CurrentTableStack.Size ? g.Tables.GetByIndex(g.CurrentTableStack.back().Index) : NULL;
outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
@ -1876,8 +1868,8 @@ void ImGui::TableEndCell(ImGuiTable* table)
table->RowTextBaseline = ImMax(table->RowTextBaseline, window->DC.PrevLineTextBaseOffset); table->RowTextBaseline = ImMax(table->RowTextBaseline, window->DC.PrevLineTextBaseOffset);
} }
// Append into the next cell // Append into the next column/cell
// FIXME-TABLE: Wrapping to next row should be optional? // FIXME-TABLE: Wrapping to next row could be optional?
bool ImGui::TableNextColumn() bool ImGui::TableNextColumn()
{ {
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
@ -1897,9 +1889,6 @@ bool ImGui::TableNextColumn()
TableBeginCell(table, 0); TableBeginCell(table, 0);
} }
// FIXME-TABLE: Need to clarify if we want to allow IsItemHovered() here
//g.CurrentWindow->DC.LastItemStatusFlags = (column_n == table->HoveredColumn) ? ImGuiItemStatusFlags_HoveredRect : ImGuiItemStatusFlags_None;
// FIXME-TABLE: it is likely to alter layout if user skips a columns contents based on clipping. // FIXME-TABLE: it is likely to alter layout if user skips a columns contents based on clipping.
int column_n = table->CurrentColumn; int column_n = table->CurrentColumn;
return (table->VisibleUnclippedMaskByIndex & ((ImU64)1 << column_n)) != 0; return (table->VisibleUnclippedMaskByIndex & ((ImU64)1 << column_n)) != 0;
@ -1920,9 +1909,6 @@ bool ImGui::TableSetColumnIndex(int column_n)
TableBeginCell(table, column_n); TableBeginCell(table, column_n);
} }
// FIXME-TABLE: Need to clarify if we want to allow IsItemHovered() here
//g.CurrentWindow->DC.LastItemStatusFlags = (column_n == table->HoveredColumn) ? ImGuiItemStatusFlags_HoveredRect : ImGuiItemStatusFlags_None;
// FIXME-TABLE: it is likely to alter layout if user skips a columns contents based on clipping. // FIXME-TABLE: it is likely to alter layout if user skips a columns contents based on clipping.
return (table->VisibleUnclippedMaskByIndex & ((ImU64)1 << column_n)) != 0; return (table->VisibleUnclippedMaskByIndex & ((ImU64)1 << column_n)) != 0;
} }
@ -2231,10 +2217,9 @@ void ImGui::TableHeader(const char* label)
// If we already got a row height, there's use that. // If we already got a row height, there's use that.
// FIXME-TABLE-PADDING: Problem if the correct outer-padding CellBgRect strays off our ClipRect // FIXME-TABLE-PADDING: Problem if the correct outer-padding CellBgRect strays off our ClipRect
ImRect cell_r = TableGetCellBgRect(table, column_n); ImRect cell_r = TableGetCellBgRect(table, column_n);
float label_height = ImMax(label_size.y, table->RowMinHeight - g.Style.CellPadding.y * 2.0f); float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f);
// Keep header highlighted when context menu is open. // Keep header highlighted when context menu is open.
// (FIXME-TABLE: however we cannot assume the ID of said popup if it has been created by the user...)
const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent); const bool selected = (table->IsContextPopupOpen && table->ContextPopupColumn == column_n && table->InstanceInteracted == table->InstanceCurrent);
ImGuiID id = window->GetID(label); ImGuiID id = window->GetID(label);
ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f)); ImRect bb(cell_r.Min.x, cell_r.Min.y, cell_r.Max.x, ImMax(cell_r.Max.y, cell_r.Min.y + label_height + g.Style.CellPadding.y * 2.0f));
@ -2333,9 +2318,7 @@ void ImGui::TableHeader(const char* label)
//window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE); //window->DrawList->AddCircleFilled(ImVec2(ellipsis_max, label_pos.y), 40, IM_COL32_WHITE);
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size); RenderTextEllipsis(window->DrawList, label_pos, ImVec2(ellipsis_max, label_pos.y + label_height + g.Style.FramePadding.y), ellipsis_max, ellipsis_max, label, label_end, &label_size);
// We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering // We feed our unclipped width to the column without writing on CursorMaxPos, so that column is still considering for merging.
// for merging.
// FIXME-TABLE: Clarify policies of how label width and potential decorations (arrows) fit into auto-resize of the column
float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow; float max_pos_x = label_pos.x + label_size.x + w_sort_text + w_arrow;
column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, cell_r.Max.x);// ImMin(max_pos_x, cell_r.Max.x)); column->ContentMaxXHeadersUsed = ImMax(column->ContentMaxXHeadersUsed, cell_r.Max.x);// ImMin(max_pos_x, cell_r.Max.x));
column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x); column->ContentMaxXHeadersIdeal = ImMax(column->ContentMaxXHeadersIdeal, max_pos_x);