From 532aa5a69bbec87560639702d78a2df97a4be2a0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 18 Dec 2020 17:27:41 +0100 Subject: [PATCH] Tables: (breaking) change outer_size.x default value to -FLT_MIN, make outer_size.x == 0.0f act as ImGuiTableFlags_NoHostExtendX (#3605, ad83976b) when no scrolling and no stretch column. Which is more consistent. Demo: moved "Compact table" to "Padding" section, makes more sense. Tweaked demo. --- imgui.h | 27 ++++--- imgui_demo.cpp | 190 ++++++++++++++++++++++++----------------------- imgui_internal.h | 2 +- imgui_tables.cpp | 46 +++++++----- 4 files changed, 138 insertions(+), 127 deletions(-) diff --git a/imgui.h b/imgui.h index c0d9dcf3b..f2f2f5350 100644 --- a/imgui.h +++ b/imgui.h @@ -462,7 +462,7 @@ namespace ImGui IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); IMGUI_API bool RadioButton(const char* label, bool active); // use with e.g. if (RadioButton("one", my_value==1)) { my_value = 1; } IMGUI_API bool RadioButton(const char* label, int* v, int v_button); // shortcut to handle the above pattern when value is an integer - IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1, 0), const char* overlay = NULL); + IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-FLT_MIN, 0), const char* overlay = NULL); IMGUI_API void Bullet(); // draw a small circle + keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses // Widgets: Combo Box @@ -679,7 +679,7 @@ namespace ImGui // TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! // ---------------------------------------------------------------------------------------------------------- // - 5. Call EndTable() - IMGUI_API bool BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f); + IMGUI_API bool BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(-FLT_MIN, 0), float inner_width = 0.0f); IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. @@ -1075,21 +1075,20 @@ enum ImGuiTableFlags_ ImGuiTableFlags_ColumnsWidthFixed = 1 << 14, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAutoResize policy (if Resizable is off). Read description above for more details. 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_NoHeadersWidth = 1 << 16, // Disable headers' contribution to automatic width calculation. - ImGuiTableFlags_NoHostExtendX = 1 << 17, // Disable extending table past the limit required by the right-most columns. Only meaningful with Fixed columns and when neither ScrollX nor ScrollY are set. - ImGuiTableFlags_NoHostExtendY = 1 << 18, // 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 << 19, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. - ImGuiTableFlags_PreciseWidths = 1 << 20, // 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. - ImGuiTableFlags_NoClip = 1 << 21, // 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_NoHostExtendY = 1 << 17, // 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 << 18, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. + ImGuiTableFlags_PreciseWidths = 1 << 19, // 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. + ImGuiTableFlags_NoClip = 1 << 20, // 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 - ImGuiTableFlags_PadOuterX = 1 << 22, // Default if BordersOuterV is on. Enable outer-most padding. - ImGuiTableFlags_NoPadOuterX = 1 << 23, // Default if BordersOuterV is off. Disable outer-most padding. - ImGuiTableFlags_NoPadInnerX = 1 << 24, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). + ImGuiTableFlags_PadOuterX = 1 << 21, // Default if BordersOuterV is on. Enable outer-most padding. + ImGuiTableFlags_NoPadOuterX = 1 << 22, // Default if BordersOuterV is off. Disable outer-most padding. + ImGuiTableFlags_NoPadInnerX = 1 << 23, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). // Scrolling - ImGuiTableFlags_ScrollX = 1 << 25, // 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 << 26, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. + ImGuiTableFlags_ScrollX = 1 << 24, // 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 << 25, // Enable vertical scrolling. Require 'outer_size' parameter of BeginTable() to specify the container size. // Sorting - ImGuiTableFlags_SortMulti = 1 << 27, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). - ImGuiTableFlags_SortTristate = 1 << 28 // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). + ImGuiTableFlags_SortMulti = 1 << 26, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). + ImGuiTableFlags_SortTristate = 1 << 27 // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). }; // Flags for ImGui::TableSetupColumn() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b4fd22d33..a4a2a4ed2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3692,7 +3692,8 @@ static void ShowDemoWindowTables() ImGui::EndTable(); } - if (ImGui::BeginTable("##table2", 3, flags | ImGuiTableFlags_ColumnsWidthFixed)) + // Use outer_size.x == 0.0f instead of default to make the table as tight as possible (only valid when no scrolling and no stretch column) + if (ImGui::BeginTable("##table2", 3, flags | ImGuiTableFlags_ColumnsWidthFixed, ImVec2(0.0f, 0.0f))) { ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("Two"); @@ -3716,8 +3717,8 @@ static void ShowDemoWindowTables() ImGui::SetNextItemOpen(open_action != 0); if (ImGui::TreeNode("Padding")) { - static ImGuiTableFlags flags = ImGuiTableFlags_BordersV; - + // First example: showcase use of padding flags and effect of BorderOuterV/BorderInnerV on X padding. + // We don't expose BorderOuterH/BorderInnerH here because they have no effect on X padding. HelpMarker( "We often want outer padding activated when any using features which makes the edges of a column visible:\n" "e.g.:\n" @@ -3726,20 +3727,21 @@ static void ShowDemoWindowTables() "Because of this, activating BorderOuterV sets the default to PadOuterX. Using PadOuterX or NoPadOuterX you can override the default.\n\n" "Actual padding values are using style.CellPadding."); + static ImGuiTableFlags flags1 = ImGuiTableFlags_BordersV; PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags, ImGuiTableFlags_PadOuterX); + ImGui::CheckboxFlags("ImGuiTableFlags_PadOuterX", &flags1, ImGuiTableFlags_PadOuterX); ImGui::SameLine(); HelpMarker("Enable outer-most padding (default if ImGuiTableFlags_BordersOuterV is set)"); - ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags, ImGuiTableFlags_NoPadOuterX); + ImGui::CheckboxFlags("ImGuiTableFlags_NoPadOuterX", &flags1, ImGuiTableFlags_NoPadOuterX); ImGui::SameLine(); HelpMarker("Disable outer-most padding (default if ImGuiTableFlags_BordersOuterV is not set)"); - ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags, ImGuiTableFlags_NoPadInnerX); + ImGui::CheckboxFlags("ImGuiTableFlags_NoPadInnerX", &flags1, ImGuiTableFlags_NoPadInnerX); ImGui::SameLine(); HelpMarker("Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off)"); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags1, ImGuiTableFlags_BordersOuterV); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags1, ImGuiTableFlags_BordersInnerV); static bool show_headers = false; ImGui::Checkbox("show_headers", &show_headers); PopStyleCompact(); - if (ImGui::BeginTable("##table1", 3, flags)) + if (ImGui::BeginTable("##table1", 3, flags1)) { if (show_headers) { @@ -3772,6 +3774,49 @@ static void ShowDemoWindowTables() ImGui::EndTable(); } + // Second example: set style.CellPadding to (0.0) or a custom value. + // FIXME-TABLE: Vertical border effectively not displayed the same way as horizontal one... + HelpMarker("Setting style.CellPadding to (0,0) or a custom value."); + static ImGuiTableFlags flags2 = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg; + static ImVec2 cell_padding(0.0f, 0.0f); + static bool show_widget_frame_bg = false; + + PushStyleCompact(); + ImGui::CheckboxFlags("ImGuiTableFlags_Borders", &flags2, ImGuiTableFlags_Borders); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags2, ImGuiTableFlags_BordersH); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags2, ImGuiTableFlags_BordersV); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersInner", &flags2, ImGuiTableFlags_BordersInner); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags2, ImGuiTableFlags_BordersOuter); + ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags2, ImGuiTableFlags_RowBg); + ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags2, ImGuiTableFlags_Resizable); + ImGui::Checkbox("show_widget_frame_bg", &show_widget_frame_bg); + ImGui::SliderFloat2("CellPadding", &cell_padding.x, 0.0f, 10.0f, "%.0f"); + PopStyleCompact(); + + ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, cell_padding); + if (ImGui::BeginTable("##table2", 3, flags2)) + { + static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells + static bool init = true; + if (!show_widget_frame_bg) + ImGui::PushStyleColor(ImGuiCol_FrameBg, 0); + for (int cell = 0; cell < 3 * 5; cell++) + { + ImGui::TableNextColumn(); + if (init) + strcpy(text_bufs[cell], "edit me"); + ImGui::SetNextItemWidth(-FLT_MIN); + ImGui::PushID(cell); + ImGui::InputText("##cell", text_bufs[cell], IM_ARRAYSIZE(text_bufs[cell])); + ImGui::PopID(); + } + if (!show_widget_frame_bg) + ImGui::PopStyleColor(); + init = false; + ImGui::EndTable(); + } + ImGui::PopStyleVar(); + ImGui::TreePop(); } @@ -3822,7 +3867,7 @@ static void ShowDemoWindowTables() // When using ScrollX or ScrollY we need to specify a size for our table container! // Otherwise by default the table will fit all available space, like a BeginChild() call. - ImVec2 size = ImVec2(0, TEXT_BASE_HEIGHT * 8); + ImVec2 size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 8); if (ImGui::BeginTable("##table1", 3, flags, size)) { ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible @@ -3875,7 +3920,7 @@ static void ShowDemoWindowTables() // When using ScrollX or ScrollY we need to specify a size for our table container! // Otherwise by default the table will fit all available space, like a BeginChild() call. - ImVec2 outer_size = ImVec2(0, TEXT_BASE_HEIGHT * 8); + ImVec2 outer_size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 8); if (ImGui::BeginTable("##table1", 7, flags, outer_size)) { ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); @@ -3949,7 +3994,7 @@ static void ShowDemoWindowTables() = ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable; - ImVec2 size = ImVec2(0, TEXT_BASE_HEIGHT * 9); + ImVec2 size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 9); if (ImGui::BeginTable("##table", column_count, flags, size)) { for (int column = 0; column < column_count; column++) @@ -4057,7 +4102,7 @@ static void ShowDemoWindowTables() ImGui::CheckboxFlags("ImGuiTableFlags_NoClip", &flags, ImGuiTableFlags_NoClip); PopStyleCompact(); - ImVec2 outer_size(0, TEXT_BASE_HEIGHT * 7); + ImVec2 outer_size(-FLT_MIN, TEXT_BASE_HEIGHT * 7); if (ImGui::BeginTable("##nways", column_count, flags, outer_size)) { for (int cell = 0; cell < 10 * column_count; cell++) @@ -4153,50 +4198,6 @@ static void ShowDemoWindowTables() ImGui::TreePop(); } - if (open_action != -1) - ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Compact table")) - { - // FIXME-TABLE: Vertical border not displayed the same way as horizontal one... - HelpMarker("Setting style.CellPadding to (0,0)."); - static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg; - static bool no_widget_frame = false; - - PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuter", &flags, ImGuiTableFlags_BordersOuter); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersH", &flags, ImGuiTableFlags_BordersH); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersV", &flags, ImGuiTableFlags_BordersV); - ImGui::CheckboxFlags("ImGuiTableFlags_RowBg", &flags, ImGuiTableFlags_RowBg); - ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); - ImGui::Checkbox("no_widget_frame", &no_widget_frame); - PopStyleCompact(); - - ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2(0, 0)); - if (ImGui::BeginTable("##3ways", 3, flags)) - { - for (int row = 0; row < 10; row++) - { - static char text_buf[32] = ""; - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableSetColumnIndex(column); - ImGui::SetNextItemWidth(-FLT_MIN); - ImGui::PushID(row * 3 + column); - if (no_widget_frame) - ImGui::PushStyleColor(ImGuiCol_FrameBg, 0); - ImGui::InputText("##cell", text_buf, IM_ARRAYSIZE(text_buf)); - if (no_widget_frame) - ImGui::PopStyleColor(); - ImGui::PopID(); - } - } - ImGui::EndTable(); - } - ImGui::PopStyleVar(); - ImGui::TreePop(); - } - if (open_action != -1) ImGui::SetNextItemOpen(open_action != 0); if (ImGui::TreeNode("Row height")) @@ -4216,12 +4217,37 @@ static void ShowDemoWindowTables() ImGui::TreePop(); } - if (open_action != -1) ImGui::SetNextItemOpen(open_action != 0); if (ImGui::TreeNode("Outer size")) { - ImGui::Text("Using manual/explicit size:"); + // Showcasing use of outer_size.x == 0.0f and ImGuiTableFlags_NoHostExtendY + // The default value of outer_size.x is -FLT_MIN which right-align tables. + // Using outer_size.x == 0.0f on a table with no scrolling and no stretch column we can make them tighter. + ImGui::Text("Using auto/all width, using NoHostExtendY:"); + static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_ColumnsWidthFixed; + static bool use_all_width = false; + ImGui::Checkbox("Use all width", &use_all_width); + ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); + if (ImGui::BeginTable("##table3", 3, flags, ImVec2(use_all_width ? -FLT_MIN : 0.0f, TEXT_BASE_HEIGHT * 5.5f))) + { + for (int row = 0; row < 10; row++) + { + ImGui::TableNextRow(); + for (int column = 0; column < 3; column++) + { + ImGui::TableNextColumn(); + ImGui::Text("Cell %d,%d", column, row); + } + } + ImGui::EndTable(); + } + ImGui::SameLine(); + ImGui::Text("Hello!"); + + ImGui::Spacing(); + + ImGui::Text("Using explicit size:"); if (ImGui::BeginTable("##table1", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg, ImVec2(TEXT_BASE_WIDTH * 30, 0.0f))) { for (int row = 0; row < 5; row++) @@ -4249,29 +4275,6 @@ static void ShowDemoWindowTables() } ImGui::EndTable(); } - ImGui::Spacing(); - - // Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY - // FIXME-TABLE: WIP API: Don't use yet, will probably rework/rename those flags. - ImGui::Text("Using NoHostExtend flags:"); - static ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_NoHostExtendX | ImGuiTableFlags_ColumnsWidthFixed; - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX); - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); - if (ImGui::BeginTable("##table3", 3, flags, ImVec2(0.0f, TEXT_BASE_HEIGHT * 5.5f))) - { - for (int row = 0; row < 10; row++) - { - ImGui::TableNextRow(); - for (int column = 0; column < 3; column++) - { - ImGui::TableNextColumn(); - ImGui::Text("Cell %d,%d", column, row); - } - } - ImGui::EndTable(); - } - ImGui::SameLine(); - ImGui::Text("Hello!"); ImGui::TreePop(); } @@ -4622,7 +4625,7 @@ static void ShowDemoWindowTables() ImGui::CheckboxFlags("ImGuiTableFlags_SortTristate", &flags, ImGuiTableFlags_SortTristate); ImGui::SameLine(); HelpMarker("When sorting is enabled: allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0)."); - if (ImGui::BeginTable("##table", 4, flags, ImVec2(0, TEXT_BASE_HEIGHT * 15), 0.0f)) + if (ImGui::BeginTable("##table", 4, flags, ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 15), 0.0f)) { // Declare columns // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications. @@ -4692,7 +4695,7 @@ static void ShowDemoWindowTables() static int freeze_cols = 1; static int freeze_rows = 1; static int items_count = IM_ARRAYSIZE(template_items_names) * 2; - static ImVec2 outer_size_value = ImVec2(0, TEXT_BASE_HEIGHT * 12); + static ImVec2 outer_size_value = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 12); static float row_min_height = 0.0f; // Auto static float inner_width_with_scroll = 0.0f; // Auto-extend static bool outer_size_enabled = true; @@ -4740,7 +4743,6 @@ static void ShowDemoWindowTables() flags &= ~ImGuiTableFlags_ColumnsWidthStretch; // 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."); ImGui::CheckboxFlags("ImGuiTableFlags_NoHeadersWidth", &flags, ImGuiTableFlags_NoHeadersWidth); - ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendX", &flags, ImGuiTableFlags_NoHostExtendX); ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible); ImGui::SameLine(); HelpMarker("Only available if ScrollX is disabled."); @@ -4790,7 +4792,11 @@ static void ShowDemoWindowTables() ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::Checkbox("outer_size", &outer_size_enabled); ImGui::SameLine(); - HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set), the table is output directly in the parent window. OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendV is set)."); + HelpMarker("If scrolling is disabled (ScrollX and ScrollY not set):\n" + "- The table is output directly in the parent window.\n" + "- OuterSize.x < 0.0f will right-align the table.\n" + "- OuterSize.x = 0.0f will narrow fit the table unless there are any Stretch column.\n" + "- OuterSize.y then becomes the minimum size for the table, which will extend vertically if there are more rows (unless NoHostExtendY is set)."); // From a user point of view we will tend to use 'inner_width' differently depending on whether our table is embedding scrolling. // To facilitate experimentation we expose two values and will select the right one depending on active flags. @@ -4837,12 +4843,12 @@ static void ShowDemoWindowTables() // Declare columns // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications. // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index! - ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, -1.0f, MyItemColumnID_ID); - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name); - ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); - ImGui::TableSetupColumn("Quantity (Long Label)", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 1.0f, MyItemColumnID_Quantity);// , ImGuiTableColumnFlags_WidthAutoResize); - ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch, 1.0f, MyItemColumnID_Description); - ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort); + ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, -1.0f, MyItemColumnID_ID); + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name); + ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); + ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, 1.0f, MyItemColumnID_Quantity); + ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch, 1.0f, MyItemColumnID_Description); + ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort); ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); // Sort our data if sort specs have been changed! diff --git a/imgui_internal.h b/imgui_internal.h index eb753fe52..0d5be7168 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2074,7 +2074,7 @@ struct ImGuiTable bool IsResetAllRequest; bool IsResetDisplayOrderRequest; bool IsUnfrozen; // Set when we got past the frozen row. - bool IsOuterRectFitX; // Set when outer_size value passed to BeginTable() is (>= -1.0f && <= 0.0f) + bool IsOuterRectAutoFitX; // Set when outer_size.x == 0.0f in BeginTable(), scrolling is disabled, and there are stretch columns. bool MemoryCompacted; bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 1c347b68c..be7512181 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -65,26 +65,31 @@ Index of this file: // TABLE SIZING //----------------------------------------------------------------------------- // (Read carefully because this is subtle but it does make sense!) -// About 'outer_size', its meaning needs to differ slightly depending of if we are using ScrollX/ScrollY flags: -// X: -// - outer_size.x < 0.0f -> right align from window/work-rect maximum x edge. -// - outer_size.x = 0.0f -> auto enlarge, use all available space. -// - outer_size.x > 0.0f -> fixed width -// Y with ScrollX/ScrollY: using a child window for scrolling: -// - outer_size.y < 0.0f -> bottom align -// - outer_size.y = 0.0f -> bottom align, consistent with BeginChild(). not recommended unless table is last item in parent window. -// - outer_size.y > 0.0f -> fixed child height. recommended when using Scrolling on any axis. -// Y without scrolling, we output table directly in parent window: -// - outer_size.y < 0.0f -> bottom align (will auto extend, unless NoHostExtendV is set) -// - outer_size.y = 0.0f -> zero minimum height (will auto extend, unless NoHostExtendV is set) -// - outer_size.y > 0.0f -> minimum height (will auto extend, unless NoHostExtendV is set) +//----------------------------------------------------------------------------- +// About 'outer_size': +// Its meaning needs to differ slightly depending of if we are using ScrollX/ScrollY flags. +// Default value is ImVec2(-FLT_MIN, 0.0f). When binding this in a scripting language please follow this default value. +// X +// - outer_size.x < 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN will right-align exactly on right-most edge. With -1.0f will right-align one pixel away from right-most edge. +// - outer_size.x = 0.0f -> Auto width. Generally use all available width. When NOT using scrolling and NOT using any Stretch column, use only necessary width, otherwise same as -FLT_MIN. +// - outer_size.x > 0.0f -> Fixed width. +// Y with ScrollX/ScrollY disabled: we output table directly in current window +// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless NoHostExtendV is set) +// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless NoHostExtendV is set) +// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless NoHostExtendV is set) +// Y with ScrollX/ScrollY enabled: using a child window for scrolling +// - outer_size.y < 0.0f -> Bottom-align +// - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window. +// - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis. +//----------------------------------------------------------------------------- // About 'inner_width': -// With ScrollX: +// With ScrollX disabled: +// - inner_width -> *ignored* +// With ScrollX enable: // - inner_width < 0.0f -> *illegal* fit in known width (right align from outer_size.x) <-- weird // - inner_width = 0.0f -> fit in outer_width: Fixed size columns will take space they need (if avail, otherwise shrink down), Stretch columns becomes Fixed columns. // - inner_width > 0.0f -> override scrolling width, generally to be larger than outer_size.x. Fixed column take space they need (if avail, otherwise shrink down), Stretch columns share remaining space! -// Without ScrollX: -// - inner_width -> *ignored* +//----------------------------------------------------------------------------- // Details: // - If you want to use Stretch columns with ScrollX, you generally need to specify 'inner_width' otherwise the concept // of "available space" doesn't make sense. @@ -278,7 +283,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->ColumnsCount = columns_count; table->IsLayoutLocked = false; table->InnerWidth = inner_width; - table->IsOuterRectFitX = (outer_size.x >= -1.0f && outer_size.x <= 0.0f); // Bit ambiguous + table->IsOuterRectAutoFitX = (outer_size.x == 0.0f) && (use_child_window == false); // When not using a child window, WorkRect.Max will grow as we append contents. if (use_child_window) @@ -1009,11 +1014,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // [Part 9] Lock actual OuterRect/WorkRect right-most position. // This is done late to handle the case of fixed-columns tables not claiming more widths that they need. // Because of this we are careful with uses of WorkRect and InnerClipRect before this point. - if ((table->Flags & ImGuiTableFlags_NoHostExtendX) && table->InnerWindow == table->OuterWindow && table->RightMostStretchedColumn == -1) + if (table->RightMostStretchedColumn != -1) + table->IsOuterRectAutoFitX = false; + if (table->IsOuterRectAutoFitX) { table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1; table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1); - table->IsOuterRectFitX = false; } table->InnerWindow->ParentWorkRect = table->WorkRect; table->BorderX1 = table->InnerClipRect.Min.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : -1.0f); @@ -1237,7 +1243,7 @@ void ImGui::EndTable() outer_window->DC.ItemWidth = table->HostBackupItemWidth; outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize; outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset; - const float outer_width = table->IsOuterRectFitX ? table->ColumnsAutoFitWidth : table->WorkRect.GetWidth(); + const float outer_width = table->IsOuterRectAutoFitX ? table->WorkRect.GetWidth() : table->ColumnsAutoFitWidth; if (inner_window != outer_window) { EndChild();