From 956435768f2de89297bfb713465af1eb9fc92b85 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 22 Dec 2020 22:32:30 +0100 Subject: [PATCH 01/13] Tables: (breaking) renamed ImGuiTableColumnFlags_WidthAutoResize to _WidthAuto., default to WidthFixed policy when host window has auto-resize. Fix edge case with TableSetColumnWidth on small windows (amend 972ca816) --- imgui.h | 31 +++++++++++++++++-------------- imgui_demo.cpp | 4 ++-- imgui_tables.cpp | 35 +++++++++++++++++++---------------- 3 files changed, 38 insertions(+), 32 deletions(-) diff --git a/imgui.h b/imgui.h index 94422644d..f3d05e62a 100644 --- a/imgui.h +++ b/imgui.h @@ -1035,22 +1035,25 @@ enum ImGuiTabItemFlags_ }; // Flags for ImGui::BeginTable() -// - Important! Sizing policies have particularly complex and subtle side effects, more so than you would expect. +// - Important! Sizing policies have complex and subtle side effects, more so than you would expect. // Read comments/demos carefully + experiment with live demos to get acquainted with them. -// - The default sizing policy for columns depends on whether the ScrollX flag is set on the table: -// When ScrollX is off: +// - The DEFAULT policy depends on whether the _ScrollX flag is set on the table, and whether _AlwaysAutoResize flag is set on window. +// - ImGuiTableFlags_ColumnsWidthStretch is the default if ScrollX if off. +// - ImGuiTableFlags_ColumnsWidthFixed is the default if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. +// - When ScrollX is off: // - Table defaults to ImGuiTableFlags_ColumnsWidthStretch -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch. -// - Columns sizing policy allowed: Stretch (default) or Fixed/Auto. -// - Fixed Columns will generally obtain their requested width (unless the Table cannot fit them all). +// - Columns sizing policy allowed: Stretch (default), Fixed/Auto. +// - Fixed Columns will generally obtain their requested width (unless the table cannot fit them all). // - Stretch Columns will share the remaining width. -// When ScrollX is on: -// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed. -// - Columns sizing policy allowed: Fixed/Auto mostly! +// - Mixed Fixed/Stretch columns is possible but has various side-effects on resizing behaviors. +// The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. +// (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). +// - When ScrollX is on: +// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto +// - Columns sizing policy allowed: Fixed/Auto mostly. // - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. // - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). -// - Mixing up columns with different sizing policy is possible BUT can be tricky and has some side-effects and restrictions. -// (their visible order and the scrolling state have subtle but necessary effects on how they can be manually resized). -// The typical use of mixing sizing policies is to have ScrollX disabled, first Fixed columns and then one or two TRAILING Stretch columns. +// If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. enum ImGuiTableFlags_ { // Features @@ -1076,7 +1079,7 @@ enum ImGuiTableFlags_ ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). // Sizing ImGuiTableFlags_ColumnsWidthStretch = 1 << 13, // Default if ScrollX is off. Columns will default to use _WidthStretch. Read description above for more details. - 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_ColumnsWidthFixed = 1 << 14, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAuto 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_NoHostExtendY = 1 << 16, // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible) ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. @@ -1104,7 +1107,7 @@ enum ImGuiTableColumnFlags_ ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column. ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _ColumnsWidthStretch). ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _ColumnsWidthFixed and table is resizable). - ImGuiTableColumnFlags_WidthAutoResize = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _ColumnsWidthFixed and table is not resizable). + ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _ColumnsWidthFixed and table is not resizable). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN)) ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing. ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column. @@ -1125,7 +1128,7 @@ enum ImGuiTableColumnFlags_ ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse // [Internal] Combinations and masks - ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize, + ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto, ImGuiTableColumnFlags_IndentMask_ = ImGuiTableColumnFlags_IndentEnable | ImGuiTableColumnFlags_IndentDisable, ImGuiTableColumnFlags_StatusMask_ = ImGuiTableColumnFlags_IsEnabled | ImGuiTableColumnFlags_IsVisible | ImGuiTableColumnFlags_IsSorted | ImGuiTableColumnFlags_IsHovered, ImGuiTableColumnFlags_NoDirectResize_ = 1 << 30 // [Internal] Disable user resizing this column directly (it may however we resized indirectly from its left edge) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6ef335919..804fa0848 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3357,8 +3357,8 @@ static void EditTableColumnsFlags(ImGuiTableColumnFlags* p_flags) *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthStretch); if (ImGui::CheckboxFlags("_WidthFixed", p_flags, ImGuiTableColumnFlags_WidthFixed)) *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthFixed); - if (ImGui::CheckboxFlags("_WidthAutoResize", p_flags, ImGuiTableColumnFlags_WidthAutoResize)) - *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthAutoResize); + if (ImGui::CheckboxFlags("_WidthAuto", p_flags, ImGuiTableColumnFlags_WidthAuto)) + *p_flags &= ~(ImGuiTableColumnFlags_WidthMask_ ^ ImGuiTableColumnFlags_WidthAuto); ImGui::CheckboxFlags("_NoResize", p_flags, ImGuiTableColumnFlags_NoResize); ImGui::CheckboxFlags("_NoReorder", p_flags, ImGuiTableColumnFlags_NoReorder); ImGui::CheckboxFlags("_NoHide", p_flags, ImGuiTableColumnFlags_NoHide); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 731063ba7..f03c99e6a 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -98,12 +98,15 @@ Index of this file: //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -// TABLES CULLING +// TABLES CLIPPING/CULLING //----------------------------------------------------------------------------- // About clipping/culling of Rows in Tables: // - For large numbers of rows, it is recommended you use ImGuiListClipper to only submit visible rows. // ImGuiListClipper is reliant on the fact that rows are of equal height. // See 'Demo->Tables->Vertical Scrolling' or 'Demo->Tables->Advanced' for a demo of using the clipper. +// - Note that columns with the ImGuiTableColumnFlags_WidthAuto policy generally don't play well with using the clipper, +// and by default a table with _ScrollX but without _Resizable will have columns default to _WidthAuto. +// So, if you want to use the clipper, make sure to either enable _Resizable, either setup columns explicitly with _WidthFixed. //----------------------------------------------------------------------------- // About clipping/culling of Columns in Tables: // - Case A: column is not hidden by user, and at least partially in sight (most common case). @@ -193,7 +196,7 @@ inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_w { // Adjust flags: set default sizing policy if ((flags & (ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ColumnsWidthFixed)) == 0) - flags |= (flags & ImGuiTableFlags_ScrollX) ? ImGuiTableFlags_ColumnsWidthFixed : ImGuiTableFlags_ColumnsWidthStretch; + flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_ColumnsWidthFixed : ImGuiTableFlags_ColumnsWidthStretch; // Adjust flags: disable Resizable when using SameWidths (done above enforcing BordersInnerV) if (flags & ImGuiTableFlags_SameWidths) @@ -564,14 +567,14 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I // Sizing Policy if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) { - // FIXME-TABLE: Inconsistent to promote columns to WidthAutoResize + // FIXME-TABLE: Inconsistent to promote columns to WidthAuto if (table->Flags & ImGuiTableFlags_ColumnsWidthFixed) - flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAutoResize; + flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAuto; else flags |= ImGuiTableColumnFlags_WidthStretch; } IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used. - if (flags & ImGuiTableColumnFlags_WidthAutoResize) + if (flags & ImGuiTableColumnFlags_WidthAuto) flags |= ImGuiTableColumnFlags_NoResize; // Sorting @@ -609,9 +612,8 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I // Layout columns for the frame. This is in essence the followup to BeginTable(). // Runs on the first call to TableNextRow(), to give a chance for TableSetupColumn() to be called first. -// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for WidthAutoResize -// columns, increase feedback side-effect with widgets relying on WorkRect.Max.x. Maybe provide a default distribution -// for WidthAutoResize columns? +// FIXME-TABLE: Our width (and therefore our WorkRect) will be minimal in the first frame for _WidthAuto columns. +// Increase feedback side-effect with widgets relying on WorkRect.Max.x... Maybe provide a default distribution for _WidthAuto columns? void ImGui::TableUpdateLayout(ImGuiTable* table) { ImGuiContext& g = *GImGui; @@ -657,7 +659,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) table->IsSortSpecsDirty = true; bool start_auto_fit = false; - if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize)) + if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) start_auto_fit = column->WidthRequest < 0.0f; else start_auto_fit = column->StretchWeight < 0.0f; @@ -739,11 +741,11 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) } column->IsPreserveWidthAuto = false; - if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize)) + if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) { // Process auto-fit for non-stretched columns // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) - if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAutoResize) && column->IsVisibleX)) + if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAuto) && column->IsVisibleX)) column->WidthRequest = column->WidthAuto; // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets @@ -786,7 +788,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n))) continue; ImGuiTableColumn* column = &table->Columns[column_n]; - if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAutoResize)) + if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) { sum_width_fixed_requests += max_width_auto - column->WidthRequest; // Update old sum column->WidthRequest = max_width_auto; @@ -978,7 +980,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // [Part 8] Detect/store when we are hovering the unused space after the right-most column (so e.g. context menus can react on it) // Clear Resizable flag if none of our column are actually resizable (either via an explicit _NoResize flag, either - // because of using _WidthAutoResize/_WidthStretch). This will hide the resizing option from the context menu. + // because of using _WidthAuto/_WidthStretch). This will hide the resizing option from the context menu. const float unused_x1 = ImMax(table->WorkRect.Min.x, table->Columns[table->RightMostEnabledColumn].ClipRect.Max.x); if (is_hovering_table && table->HoveredColumnBody == -1) { @@ -1279,7 +1281,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo table->DeclColumnsCount++; // When passing a width automatically enforce WidthFixed policy - // (whereas TableSetupColumnFlags would default to WidthAutoResize) + // (whereas TableSetupColumnFlags would default to WidthAuto) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) if ((table->Flags & ImGuiTableFlags_ColumnsWidthFixed) && (init_width_or_weight > 0.0f)) flags |= ImGuiTableColumnFlags_WidthFixed; @@ -1871,7 +1873,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width) // Apply constraints early // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) const float min_width = TableGetMinColumnWidth(); - const float max_width = TableGetMaxColumnWidth(table, column_n); + const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n)); column_0_width = ImClamp(column_0_width, min_width, max_width); if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) return; @@ -1931,6 +1933,7 @@ void ImGui::TableSetColumnWidth(int column_n, float width) // (old_a + old_b == new_a + new_b) --> (new_a == old_a + old_b - new_b) float column_1_width = ImMax(column_1->WidthRequest - (column_0_width - column_0->WidthRequest), min_width); column_0_width = column_0->WidthRequest + column_1->WidthRequest - column_1_width; + IM_ASSERT(column_0_width > 0.0f && column_1_width > 0.0f); column_0->WidthRequest = column_0_width; column_1->WidthRequest = column_1_width; if ((column_0->Flags | column_1->Flags) & ImGuiTableColumnFlags_WidthStretch) @@ -3321,7 +3324,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table) column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags, (column->Flags & ImGuiTableColumnFlags_WidthStretch) ? "WidthStretch " : "", (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? "WidthFixed " : "", - (column->Flags & ImGuiTableColumnFlags_WidthAutoResize) ? "WidthAutoResize " : "", + (column->Flags & ImGuiTableColumnFlags_WidthAuto) ? "WidthAuto " : "", (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : ""); Bullet(); Selectable(buf); From 3fbb928c9f91c80b4ae7de679bf80f078d4fdf6e Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 23 Dec 2020 12:11:39 +0100 Subject: [PATCH 02/13] Tables: explicit/custom width in TableSetupColumn() is reapplied when table or column becomes not resizable. Comments. --- imgui.h | 3 ++- imgui_demo.cpp | 1 + imgui_tables.cpp | 42 +++++++++++++++++++++++++++--------------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/imgui.h b/imgui.h index f3d05e62a..43a05ed37 100644 --- a/imgui.h +++ b/imgui.h @@ -1049,11 +1049,12 @@ enum ImGuiTabItemFlags_ // The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. // (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). // - When ScrollX is on: -// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto +// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto. // - Columns sizing policy allowed: Fixed/Auto mostly. // - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. // - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). // If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. +// - Read on documentation at the top of imgui_tables.cpp for details. enum ImGuiTableFlags_ { // Features diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 804fa0848..2e2ee67c2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3912,6 +3912,7 @@ static void ShowDemoWindowTables() static int freeze_rows = 1; PushStyleCompact(); + ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags, ImGuiTableFlags_Resizable); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); ImGui::SetNextItemWidth(ImGui::GetFrameHeight()); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f03c99e6a..a508dde50 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -97,6 +97,25 @@ Index of this file: // of what the value does. //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// COLUMNS SIZING POLICIES +//----------------------------------------------------------------------------- +// About overriding column width/weight with TableSetupColumn(): +// We use a default parameter of 'init_width_or_weight == -1'. +// - With ImGuiTableColumnFlags_WidthAuto, init_width (ignored) --> width is automatic +// - With ImGuiTableColumnFlags_WidthFixed, init_width <= 0 (default) --> width is automatic +// - With ImGuiTableColumnFlags_WidthFixed, init_width > 0 (explicit) --> width is custom +// - With ImGuiTableColumnFlags_WidthStretch, init_weight <= 0 (default) --> weight is 1.0f +// - With ImGuiTableColumnFlags_WidthStretch, init_weight > 0 (explicit) --> weight is custom +// Widths are specified _without_ CellPadding. If you specify a width of 100.0f, the column will be cover (100.0f + Padding * 2.0f) +// and you can fit a 100.0f wide item in it without clipping and with full padding. +//----------------------------------------------------------------------------- +// About default width policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) +// - When Table policy ImGuiTableFlags_ColumnsWidthStretch --> default Column policy is ImGuiTableColumnFlags_WidthStretch +// - When Table policy ImGuiTableFlags_ColumnsWidthFixed and (Table is Resizable or init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed +// - When Table policy ImGuiTableFlags_ColumnsWidthFixed and (Table is not Resizable and init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto +//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // TABLES CLIPPING/CULLING //----------------------------------------------------------------------------- @@ -730,19 +749,17 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) float width_auto = content_width_body; if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth)) width_auto = ImMax(width_auto, content_width_headers); - width_auto = ImMax(width_auto, min_column_width); - - // Non-resizable columns also submit their requested width - if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) - if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) - width_auto = ImMax(width_auto, column->InitStretchWeightOrWidth); - - column->WidthAuto = width_auto; + column->WidthAuto = ImMax(width_auto, min_column_width); } column->IsPreserveWidthAuto = false; if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) { + // Non-resizable columns keep their requested width + if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) + if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) + column->WidthRequest = column->WidthAuto = ImMax(column->WidthAuto, column->InitStretchWeightOrWidth); + // Process auto-fit for non-stretched columns // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) if ((column->AutoFitQueue != 0x00) || ((column->Flags & ImGuiTableColumnFlags_WidthAuto) && column->IsVisibleX)) @@ -1258,12 +1275,7 @@ void ImGui::EndTable() outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; } -// We use a default parameter of 'init_width_or_weight == -1', -// - with ImGuiTableColumnFlags_WidthFixed, width <= 0 --> init width == auto -// - with ImGuiTableColumnFlags_WidthFixed, width > 0 --> init width == manual -// - with ImGuiTableColumnFlags_WidthStretch, weight < 0 --> init weight == 1.0f -// - with ImGuiTableColumnFlags_WidthStretch, weight >= 0 --> init weight == custom -// Widths are specified _without_ CellPadding. So if you specify a width of 100.0f the column will be 100.0f+Padding*2.0f and you can fit a 100.0-wide item in it. +// See "COLUMN SIZING POLICIES" comments at the top of this file void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) { ImGuiContext& g = *GImGui; @@ -1281,7 +1293,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo table->DeclColumnsCount++; // When passing a width automatically enforce WidthFixed policy - // (whereas TableSetupColumnFlags would default to WidthAuto) + // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) if ((table->Flags & ImGuiTableFlags_ColumnsWidthFixed) && (init_width_or_weight > 0.0f)) flags |= ImGuiTableColumnFlags_WidthFixed; From b015ea93fd79c3aa634b0acf87244f8618618ae5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 24 Dec 2020 11:42:28 +0100 Subject: [PATCH 03/13] Style tweaks, disabled default window rounding by default, reduced size of resize grip, made less prominent, increased WindowBg alpha in classic style. TestEngine: Fixed Checkbox() not reporting its checkable state when clipped. --- docs/CHANGELOG.txt | 4 +++- docs/README.md | 2 +- imgui.cpp | 4 ++-- imgui.h | 12 ++++++------ imgui_demo.cpp | 10 ++++++---- imgui_draw.cpp | 8 ++++---- imgui_widgets.cpp | 3 +++ 7 files changed, 25 insertions(+), 18 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index d0bf6534b..6fba2f098 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -63,7 +63,6 @@ Breaking Changes: - Renamed io.ConfigWindowsMemoryCompactTimer to io.ConfigMemoryCompactTimer as the feature will apply to other data structures. (#2636) - Other Changes: - Tables: added new Tables Beta API as a replacement for old Columns. (#2957, #125) @@ -112,6 +111,9 @@ Other Changes: - Misc: Made EndFrame() assertion for key modifiers being unchanged during the frame (added in 1.76) more lenient, allowing full mid-frame releases. This is to accommodate the use of mid-frame modal native windows calls, which leads backends such as GLFW to send key clearing events on focus loss. (#3575) +- Style: Changed default style.WindowRounding value to 0.0f (matches default for multi-viewports). +- Style: Reduced the size of the resizing grip, made alpha less prominent. +- Style: Classic: Increase the default alpha value of WindowBg to be closer to other styles. - Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width. - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] diff --git a/docs/README.md b/docs/README.md index b21ddaeb2..c9f9e2cb5 100644 --- a/docs/README.md +++ b/docs/README.md @@ -120,7 +120,7 @@ Officially maintained backends/bindings (in repository): - Frameworks: Emscripten, Allegro5, Marmalade. [Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page: -- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... +- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift... - Frameworks: AGS/Adventure Game Studio, Amethyst, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, NanoRT, nCine, Nim Game Lib, Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SFML, Sokol, Unity, Unreal Engine 4, vtk, Win32 GDI, WxWidgets. - Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages. diff --git a/imgui.cpp b/imgui.cpp index c0809faaa..fabdcce86 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -941,7 +941,7 @@ ImGuiStyle::ImGuiStyle() { Alpha = 1.0f; // Global alpha applies to everything in ImGui WindowPadding = ImVec2(8,8); // Padding within a window - WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. + WindowRounding = 0.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. Large values tend to lead to variety of artifacts and are not recommended. WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. WindowMinSize = ImVec2(32,32); // Minimum window size WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text @@ -5855,7 +5855,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) int border_held = -1; ImU32 resize_grip_col[4] = {}; const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. - const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); + const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.10f, window->WindowRounding + 1.0f + g.FontSize * 0.2f)); if (!window->Collapsed) if (UpdateWindowManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0], visibility_rect)) use_current_size_for_scrollbar_x = use_current_size_for_scrollbar_y = true; diff --git a/imgui.h b/imgui.h index 43a05ed37..1064db1ea 100644 --- a/imgui.h +++ b/imgui.h @@ -1059,10 +1059,10 @@ enum ImGuiTableFlags_ { // Features ImGuiTableFlags_None = 0, - ImGuiTableFlags_Resizable = 1 << 0, // Allow resizing columns. - ImGuiTableFlags_Reorderable = 1 << 1, // Allow reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) - ImGuiTableFlags_Hideable = 1 << 2, // Allow hiding/disabling 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_Resizable = 1 << 0, // Enable resizing columns. + ImGuiTableFlags_Reorderable = 1 << 1, // Enable reordering columns in header row (need calling TableSetupColumn() + TableHeadersRow() to display headers) + ImGuiTableFlags_Hideable = 1 << 2, // Enable hiding/disabling columns in context menu. + ImGuiTableFlags_Sortable = 1 << 3, // Enable sorting. Call TableGetSortSpecs() to obtain sort specs. Also see ImGuiTableFlags_SortMulti and ImGuiTableFlags_SortTristate. ImGuiTableFlags_NoSavedSettings = 1 << 4, // Disable persisting columns order, width and sort settings in the .ini file. ImGuiTableFlags_ContextMenuInBody = 1 << 5, // Right-click on columns body/contents will display table context menu. By default it is available in TableHeadersRow(). // Decorations @@ -1076,8 +1076,8 @@ enum ImGuiTableFlags_ ImGuiTableFlags_BordersInner = ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerH, // Draw inner borders. ImGuiTableFlags_BordersOuter = ImGuiTableFlags_BordersOuterV | ImGuiTableFlags_BordersOuterH, // Draw outer borders. ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. - ImGuiTableFlags_NoBordersInBody = 1 << 11, // Disable vertical borders in columns Body (borders will always appears in Headers). - ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). + ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appears in Headers). -> May move to style + ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style // Sizing ImGuiTableFlags_ColumnsWidthStretch = 1 << 13, // Default if ScrollX is off. Columns will default to use _WidthStretch. Read description above for more details. ImGuiTableFlags_ColumnsWidthFixed = 1 << 14, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAuto policy (if Resizable is off). Read description above for more details. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2e2ee67c2..6ef6b125e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3595,7 +3595,9 @@ static void ShowDemoWindowTables() "Double-click a column border to auto-fit the column to its contents."); static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody; static bool use_all_width = true; - ImGui::Checkbox("Use all width", &use_all_width); + if (ImGui::RadioButton("fit", use_all_width == false)) { use_all_width = false; } + ImGui::SameLine(); + if (ImGui::RadioButton("right-most edge", use_all_width == true)) { use_all_width = true; } if (ImGui::BeginTable("##table1", 3, flags, ImVec2(use_all_width ? -FLT_MIN : 0.0f, 0.0f))) { @@ -4025,11 +4027,11 @@ static void ShowDemoWindowTables() if (open_action != -1) ImGui::SetNextItemOpen(open_action != 0); - if (ImGui::TreeNode("Recursive")) + if (ImGui::TreeNode("Nested")) { HelpMarker("This demonstrate embedding a table into another table cell."); - if (ImGui::BeginTable("recurse1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) + if (ImGui::BeginTable("nested1", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) { ImGui::TableSetupColumn("A0"); ImGui::TableSetupColumn("A1"); @@ -4039,7 +4041,7 @@ static void ShowDemoWindowTables() ImGui::Text("A0 Cell 0"); { float rows_height = TEXT_BASE_HEIGHT * 2; - if (ImGui::BeginTable("recurse2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) + if (ImGui::BeginTable("nested2", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable)) { ImGui::TableSetupColumn("B0"); ImGui::TableSetupColumn("B1"); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index fc6d48163..71b53837a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -210,7 +210,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_Separator] = colors[ImGuiCol_Border]; colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.20f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); @@ -242,7 +242,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f); colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f); + colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f); colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f); colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f); @@ -270,7 +270,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f); + colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.80f); @@ -331,7 +331,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 0.62f); colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f); colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.35f, 0.35f, 0.35f, 0.17f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_Tab] = ImLerp(colors[ImGuiCol_Header], colors[ImGuiCol_TitleBgActive], 0.90f); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index da08b6ee5..99e4fc896 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1063,7 +1063,10 @@ bool ImGui::Checkbox(const char* label, bool* v) const ImRect total_bb(pos, pos + ImVec2(square_sz + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), label_size.y + style.FramePadding.y * 2.0f)); ItemSize(total_bb, style.FramePadding.y); if (!ItemAdd(total_bb, id)) + { + IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0)); return false; + } bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); From 3573195112d5e416856abe0ddea4938c393e28b5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 24 Dec 2020 18:32:27 +0100 Subject: [PATCH 04/13] Tables: (breaking) rename ImGuiTableFlags_ColumnsWidthStretch > ImGuiTableFlags_SizingPolicyStretch, ImGuiTableFlags_ColumnsWidthFixed > ImGuiTableFlags_SizingPolicyFixed in prevision for other policies. --- imgui.h | 28 ++++++++++++++--------- imgui_demo.cpp | 59 +++++++++++++++++++++++++----------------------- imgui_tables.cpp | 14 ++++++------ 3 files changed, 55 insertions(+), 46 deletions(-) diff --git a/imgui.h b/imgui.h index 1064db1ea..f18178ab6 100644 --- a/imgui.h +++ b/imgui.h @@ -59,7 +59,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.80 WIP" -#define IMGUI_VERSION_NUM 17907 +#define IMGUI_VERSION_NUM 17908 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -1038,10 +1038,10 @@ enum ImGuiTabItemFlags_ // - Important! Sizing policies have complex and subtle side effects, more so than you would expect. // Read comments/demos carefully + experiment with live demos to get acquainted with them. // - The DEFAULT policy depends on whether the _ScrollX flag is set on the table, and whether _AlwaysAutoResize flag is set on window. -// - ImGuiTableFlags_ColumnsWidthStretch is the default if ScrollX if off. -// - ImGuiTableFlags_ColumnsWidthFixed is the default if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. +// - ImGuiTableFlags_SizingPolicyStretch is the default if ScrollX if off. +// - ImGuiTableFlags_SizingPolicyFixed is the default if ScrollX is on, or if host window has ImGuiWindowFlags_AlwaysAutoResize. // - When ScrollX is off: -// - Table defaults to ImGuiTableFlags_ColumnsWidthStretch -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch. +// - Table defaults to ImGuiTableFlags_SizingPolicyStretch -> all Columns defaults to ImGuiTableColumnFlags_WidthStretch. // - Columns sizing policy allowed: Stretch (default), Fixed/Auto. // - Fixed Columns will generally obtain their requested width (unless the table cannot fit them all). // - Stretch Columns will share the remaining width. @@ -1049,7 +1049,7 @@ enum ImGuiTabItemFlags_ // The typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. // (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). // - When ScrollX is on: -// - Table defaults to ImGuiTableFlags_ColumnsWidthFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto. +// - Table defaults to ImGuiTableFlags_SizingPolicyFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto. // - Columns sizing policy allowed: Fixed/Auto mostly. // - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. // - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). @@ -1078,9 +1078,10 @@ enum ImGuiTableFlags_ ImGuiTableFlags_Borders = ImGuiTableFlags_BordersInner | ImGuiTableFlags_BordersOuter, // Draw all borders. ImGuiTableFlags_NoBordersInBody = 1 << 11, // [ALPHA] Disable vertical borders in columns Body (borders will always appears in Headers). -> May move to style ImGuiTableFlags_NoBordersInBodyUntilResize = 1 << 12, // [ALPHA] Disable vertical borders in columns Body until hovered for resize (borders will always appears in Headers). -> May move to style - // Sizing - ImGuiTableFlags_ColumnsWidthStretch = 1 << 13, // Default if ScrollX is off. Columns will default to use _WidthStretch. Read description above for more details. - ImGuiTableFlags_ColumnsWidthFixed = 1 << 14, // Default if ScrollX is on. Columns will default to use _WidthFixed or _WidthAuto policy (if Resizable is off). Read description above for more details. + // Sizing Policy + ImGuiTableFlags_SizingPolicyFixed = 1 << 13, // [Default if ScrollX is on] Columns default to _WidthFixed (if resizable) or _WidthAuto (if not resizable), matching contents width. + ImGuiTableFlags_SizingPolicyStretch = 1 << 14, // [Default if ScrollX is off] Columns default to _WidthStretch with same weights. + // Sizing Extra Options ImGuiTableFlags_SameWidths = 1 << 15, // Make all columns the same widths which is useful with Fixed columns policy (but granted by default with Stretch policy + no resize). Implicitly enable ImGuiTableFlags_NoKeepColumnsVisible and disable ImGuiTableFlags_Resizable. ImGuiTableFlags_NoHostExtendY = 1 << 16, // Disable extending table past the limit set by outer_size.y. Only meaningful when neither ScrollX nor ScrollY are set (data below the limit will be clipped and not visible) ImGuiTableFlags_NoKeepColumnsVisible = 1 << 17, // Disable keeping column always minimally visible when ScrollX is off and table gets too small. Not recommended if columns are resizable. @@ -1097,6 +1098,11 @@ enum ImGuiTableFlags_ // Sorting ImGuiTableFlags_SortMulti = 1 << 25, // Hold shift when clicking headers to sort on multiple column. TableGetSortSpecs() may return specs where (SpecsCount > 1). ImGuiTableFlags_SortTristate = 1 << 26 // Allow no sorting, disable default sorting. TableGetSortSpecs() may return specs where (SpecsCount == 0). + + // Obsolete names (will be removed soon) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiTableFlags_ColumnsWidthFixed = ImGuiTableFlags_SizingPolicyFixed, ImGuiTableFlags_ColumnsWidthStretch = ImGuiTableFlags_SizingPolicyStretch +#endif }; // Flags for ImGui::TableSetupColumn() @@ -1106,9 +1112,9 @@ enum ImGuiTableColumnFlags_ ImGuiTableColumnFlags_None = 0, ImGuiTableColumnFlags_DefaultHide = 1 << 0, // Default as a hidden/disabled column. ImGuiTableColumnFlags_DefaultSort = 1 << 1, // Default as a sorting column. - ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _ColumnsWidthStretch). - ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _ColumnsWidthFixed and table is resizable). - ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _ColumnsWidthFixed and table is not resizable). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN)) + ImGuiTableColumnFlags_WidthStretch = 1 << 2, // Column will stretch. Preferable with horizontal scrolling disabled (default if table sizing policy is _SizingPolicyStretch). + ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingPolicyFixed and table is resizable). + ImGuiTableColumnFlags_WidthAuto = 1 << 4, // Column will not stretch and keep resizing based on submitted contents (default if table sizing policy is _SizingPolicyFixed and table is not resizable). Generally compatible with using right-most fitting widgets (e.g. SetNextItemWidth(-FLT_MIN)) ImGuiTableColumnFlags_NoResize = 1 << 5, // Disable manual resizing. ImGuiTableColumnFlags_NoReorder = 1 << 6, // Disable manual reordering this column, this will also prevent other columns from crossing over this column. ImGuiTableColumnFlags_NoHide = 1 << 7, // Disable ability to hide/disable this column. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6ef6b125e..456e0b4e5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3585,15 +3585,15 @@ static void ShowDemoWindowTables() ImGui::SetNextItemOpen(open_action != 0); if (ImGui::TreeNode("Resizable, fixed")) { - // Here we use ImGuiTableFlags_ColumnsWidthFixed (even though _ScrollX is not set) + // Here we use ImGuiTableFlags_SizingPolicyFixed (even though _ScrollX is not set) // 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. // FIXME-TABLE: Providing a stretch-on-init would make sense especially for tables which don't have saved settings HelpMarker( - "Using _Resizable + _ColumnsWidthFixed flags.\n" + "Using _Resizable + _SizingPolicyFixed 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_ColumnsWidthFixed | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody; + static ImGuiTableFlags flags = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_ContextMenuInBody; static bool use_all_width = true; if (ImGui::RadioButton("fit", use_all_width == false)) { use_all_width = false; } ImGui::SameLine(); @@ -3620,7 +3620,7 @@ static void ShowDemoWindowTables() if (ImGui::TreeNode("Resizable, mixed")) { HelpMarker("Using columns flag to alter resizing policy on a per-column basis."); - static ImGuiTableFlags flags = ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; + static ImGuiTableFlags flags = ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable; if (ImGui::BeginTable("##table1", 3, flags)) { @@ -3697,7 +3697,7 @@ static void ShowDemoWindowTables() } // 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))) + if (ImGui::BeginTable("##table2", 3, flags | ImGuiTableFlags_SizingPolicyFixed, ImVec2(0.0f, 0.0f))) { ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("Two"); @@ -3837,7 +3837,7 @@ static void ShowDemoWindowTables() if (ImGui::BeginTable("##table1", 4, flags)) { - // We could also set ImGuiTableFlags_ColumnsWidthFixed on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. + // We could also set ImGuiTableFlags_SizingPolicyFixed on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 15.0f); ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 30.0f); @@ -3905,7 +3905,7 @@ static void ShowDemoWindowTables() if (ImGui::TreeNode("Horizontal scrolling")) { HelpMarker( - "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_ColumnsWidthFixed," + "When ScrollX is enabled, the default sizing policy becomes ImGuiTableFlags_SizingPolicyFixed," "as automatically stretching columns doesn't make much sense with horizontal scrolling.\n\n" "Also note that as of the current version, you will almost always want to enable ScrollY along with ScrollX," "because the container window won't automatically extend vertically to fix contents (this may be improved in future versions)."); @@ -3996,7 +3996,7 @@ static void ShowDemoWindowTables() // We use a scrolling table to be able to showcase the difference between the _IsEnabled and _IsVisible flags above, otherwise in // a non-scrolling table columns are always visible (unless using ImGuiTableFlags_NoKeepColumnsVisible + resizing the parent window down) const ImGuiTableFlags flags - = ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY + = ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Sortable; ImVec2 size = ImVec2(-FLT_MIN, TEXT_BASE_HEIGHT * 9); @@ -4095,11 +4095,11 @@ static void ShowDemoWindowTables() ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags, ImGuiTableFlags_ScrollX); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollY", &flags, ImGuiTableFlags_ScrollY); - if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags, ImGuiTableFlags_ColumnsWidthStretch)) - flags &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other + if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags, ImGuiTableFlags_SizingPolicyStretch)) + flags &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other ImGui::SameLine(); HelpMarker("Default if _ScrollX if disabled. Makes columns use _WidthStretch policy by default."); - if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags, ImGuiTableFlags_ColumnsWidthFixed)) - flags &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other + if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags, ImGuiTableFlags_SizingPolicyFixed)) + flags &= ~ImGuiTableFlags_SizingPolicyStretch; // Can't specify both sizing polices so we clear the other ImGui::SameLine(); HelpMarker("Default if _ScrollX if enabled. Makes columns use _WidthFixed by default, or _WidthFixedResize if _Resizable is not set."); ImGui::CheckboxFlags("ImGuiTableFlags_PreciseWidths", &flags, ImGuiTableFlags_PreciseWidths); ImGui::SameLine(); HelpMarker("Disable distributing remainder width to stretched columns (width allocation on a 100-wide table with 3 columns: Without this flag: 33,33,34. With this flag: 33,33,33). With larger number of columns, resizing will appear to be less smooth."); @@ -4177,20 +4177,20 @@ static void ShowDemoWindowTables() "Showcase using Stretch columns + ScrollX together: " "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."); - static ImGuiTableFlags flags3 = ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg; + static ImGuiTableFlags flags3 = ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_RowBg; static float inner_width = 1000.0f; PushStyleCompact(); ImGui::PushID("flags3"); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX); - if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags3, ImGuiTableFlags_ColumnsWidthStretch)) - flags3 &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other - if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags3, ImGuiTableFlags_ColumnsWidthFixed)) - flags3 &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other + if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags3, ImGuiTableFlags_SizingPolicyStretch)) + flags3 &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other + if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags3, ImGuiTableFlags_SizingPolicyFixed)) + flags3 &= ~ImGuiTableFlags_SizingPolicyStretch; // Can't specify both sizing polices so we clear the other ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f); ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f"); ImGui::PopID(); PopStyleCompact(); - if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width)) + if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width)) { for (int cell = 0; cell < 20 * 7; cell++) { @@ -4230,7 +4230,7 @@ static void ShowDemoWindowTables() // 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 ImGuiTableFlags flags = ImGuiTableFlags_Borders | ImGuiTableFlags_Resizable | ImGuiTableFlags_ContextMenuInBody | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingPolicyFixed; static bool use_all_width = false; ImGui::Checkbox("Use all width", &use_all_width); ImGui::CheckboxFlags("ImGuiTableFlags_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); @@ -4502,7 +4502,7 @@ static void ShowDemoWindowTables() // [2.2] Right-click on the ".." to open a custom popup // [2.3] Right-click in columns to open another custom popup HelpMarker("Demonstrate mixing table context menu (over header), item context button (over button) and custom per-colum context menu (over column body)."); - ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders; + ImGuiTableFlags flags2 = ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders; if (ImGui::BeginTable("##table2", COLUMNS_COUNT, flags2)) { ImGui::TableSetupColumn("One"); @@ -4576,7 +4576,7 @@ static void ShowDemoWindowTables() char buf[32]; sprintf(buf, "Synced Table %d", n); bool open = ImGui::CollapsingHeader(buf, ImGuiTreeNodeFlags_DefaultOpen); - if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ColumnsWidthFixed | ImGuiTableFlags_NoSavedSettings)) + if (open && ImGui::BeginTable("Table", 3, ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_SizingPolicyFixed | ImGuiTableFlags_NoSavedSettings)) { ImGui::TableSetupColumn("One"); ImGui::TableSetupColumn("Two"); @@ -4692,7 +4692,7 @@ static void ShowDemoWindowTables() | ImGuiTableFlags_Sortable | ImGuiTableFlags_SortMulti | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_ScrollX | ImGuiTableFlags_ScrollY - | ImGuiTableFlags_ColumnsWidthFixed; + | ImGuiTableFlags_SizingPolicyFixed; enum ContentsType { CT_Text, CT_Button, CT_SmallButton, CT_FillButton, CT_Selectable, CT_SelectableSpanRow }; static int contents_type = CT_SelectableSpanRow; @@ -4741,11 +4741,11 @@ static void ShowDemoWindowTables() if (ImGui::TreeNodeEx("Sizing:", ImGuiTreeNodeFlags_DefaultOpen)) { - if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthStretch", &flags, ImGuiTableFlags_ColumnsWidthStretch)) - flags &= ~ImGuiTableFlags_ColumnsWidthFixed; // Can't specify both sizing polices so we clear the other + if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags, ImGuiTableFlags_SizingPolicyStretch)) + flags &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other ImGui::SameLine(); HelpMarker("[Default if ScrollX is off]\nFit all columns within available width (or specified inner_width). Fixed and Stretch columns allowed."); - if (ImGui::CheckboxFlags("ImGuiTableFlags_ColumnsWidthFixed", &flags, ImGuiTableFlags_ColumnsWidthFixed)) - flags &= ~ImGuiTableFlags_ColumnsWidthStretch; // Can't specify both sizing polices so we clear the other + if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags, ImGuiTableFlags_SizingPolicyFixed)) + flags &= ~ImGuiTableFlags_SizingPolicyStretch; // 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_NoHostExtendY", &flags, ImGuiTableFlags_NoHostExtendY); ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible); @@ -4792,6 +4792,7 @@ static void ShowDemoWindowTables() { ImGui::Checkbox("show_headers", &show_headers); ImGui::Checkbox("show_wrapped_text", &show_wrapped_text); + ImGui::DragFloat2("##OuterSize", &outer_size_value.x); ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x); ImGui::Checkbox("outer_size", &outer_size_enabled); @@ -4803,12 +4804,14 @@ static void ShowDemoWindowTables() "- 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. + // To facilitate toying with this demo we will actually pass 0.0f to the BeginTable() when ScrollX is disabled. ImGui::DragFloat("inner_width (when ScrollX active)", &inner_width_with_scroll, 1.0f, 0.0f, FLT_MAX); + ImGui::DragFloat("row_min_height", &row_min_height, 1.0f, 0.0f, FLT_MAX); ImGui::SameLine(); HelpMarker("Specify height of the Selectable item."); + ImGui::DragInt("items_count", &items_count, 0.1f, 0, 9999); - ImGui::Combo("contents_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names)); + ImGui::Combo("items_type (first column)", &contents_type, contents_type_names, IM_ARRAYSIZE(contents_type_names)); //filter.Draw("filter"); ImGui::TreePop(); } diff --git a/imgui_tables.cpp b/imgui_tables.cpp index a508dde50..c29a6a9b3 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -111,9 +111,9 @@ Index of this file: // and you can fit a 100.0f wide item in it without clipping and with full padding. //----------------------------------------------------------------------------- // About default width policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) -// - When Table policy ImGuiTableFlags_ColumnsWidthStretch --> default Column policy is ImGuiTableColumnFlags_WidthStretch -// - When Table policy ImGuiTableFlags_ColumnsWidthFixed and (Table is Resizable or init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed -// - When Table policy ImGuiTableFlags_ColumnsWidthFixed and (Table is not Resizable and init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto +// - When Table policy ImGuiTableFlags_SizingPolicyStretch --> default Column policy is ImGuiTableColumnFlags_WidthStretch +// - When Table policy ImGuiTableFlags_SizingPolicyFixed and (Table is Resizable or init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed +// - When Table policy ImGuiTableFlags_SizingPolicyFixed and (Table is not Resizable and init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- @@ -214,8 +214,8 @@ static const float TABLE_RESIZE_SEPARATOR_FEEDBACK_TIMER = 0.06f; // Delay/tim inline ImGuiTableFlags TableFixFlags(ImGuiTableFlags flags, ImGuiWindow* outer_window) { // Adjust flags: set default sizing policy - if ((flags & (ImGuiTableFlags_ColumnsWidthStretch | ImGuiTableFlags_ColumnsWidthFixed)) == 0) - flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_ColumnsWidthFixed : ImGuiTableFlags_ColumnsWidthStretch; + if ((flags & (ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_SizingPolicyFixed)) == 0) + flags |= ((flags & ImGuiTableFlags_ScrollX) || (outer_window->Flags & ImGuiWindowFlags_AlwaysAutoResize)) ? ImGuiTableFlags_SizingPolicyFixed : ImGuiTableFlags_SizingPolicyStretch; // Adjust flags: disable Resizable when using SameWidths (done above enforcing BordersInnerV) if (flags & ImGuiTableFlags_SameWidths) @@ -587,7 +587,7 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) { // FIXME-TABLE: Inconsistent to promote columns to WidthAuto - if (table->Flags & ImGuiTableFlags_ColumnsWidthFixed) + if (table->Flags & ImGuiTableFlags_SizingPolicyFixed) flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAuto; else flags |= ImGuiTableColumnFlags_WidthStretch; @@ -1295,7 +1295,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo // When passing a width automatically enforce WidthFixed policy // (whereas TableSetupColumnFlags would default to WidthAuto if table is not Resizable) if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) - if ((table->Flags & ImGuiTableFlags_ColumnsWidthFixed) && (init_width_or_weight > 0.0f)) + if ((table->Flags & ImGuiTableFlags_SizingPolicyFixed) && (init_width_or_weight > 0.0f)) flags |= ImGuiTableColumnFlags_WidthFixed; TableSetupColumnFlags(table, column, flags); From 68faa16e1ddea35494e2c6202af14176e55cb757 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 25 Dec 2020 14:35:57 +0100 Subject: [PATCH 05/13] Tables: report auto-fit width in EndTable(), extracted TableGetColumnWidthAuto(). fix minor flickering with IsPreserveWidthAuto (which is a debug feature still), moved some code. --- imgui_internal.h | 5 +- imgui_tables.cpp | 117 ++++++++++++++++++++++++++--------------------- 2 files changed, 67 insertions(+), 55 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 51556f291..7c9c9a1ff 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2002,6 +2002,7 @@ struct ImGuiTable float BorderX1; float BorderX2; float HostIndentX; + float MinColumnWidth; float OuterPaddingX; float CellPaddingX; // Padding from each borders float CellPaddingY; @@ -2010,7 +2011,7 @@ struct ImGuiTable float LastOuterHeight; // Outer height from last frame float LastFirstRowHeight; // Height of first row from last frame float InnerWidth; // User value passed to BeginTable(), see comments at the top of BeginTable() for details. - float ColumnsTotalWidth; // Sum of current column width + float ColumnsGivenWidth; // Sum of current column width float ColumnsAutoFitWidth; // Sum of ideal column width in order nothing to be clipped, used for auto-fitting and content width submission in outer window float ResizedColumnNextWidth; float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. @@ -2317,6 +2318,7 @@ namespace ImGui IMGUI_API void TableSortSpecsBuild(ImGuiTable* table); IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column); IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column); + IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column); IMGUI_API void TableBeginRow(ImGuiTable* table); IMGUI_API void TableEndRow(ImGuiTable* table); IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n); @@ -2324,7 +2326,6 @@ namespace ImGui IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n); IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n); IMGUI_API ImGuiID TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no = 0); - IMGUI_API float TableGetMinColumnWidth(); IMGUI_API float TableGetMaxColumnWidth(const ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n); IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index c29a6a9b3..07ea39c1b 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -638,14 +638,16 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) ImGuiContext& g = *GImGui; IM_ASSERT(table->IsLayoutLocked == false); - // [Part 1] Apply/lock Enabled and Order states. - // Process columns in their visible orders as we are building the Prev/Next indices. - int last_visible_column_idx = -1; - bool want_column_auto_fit = false; table->IsDefaultDisplayOrder = true; table->ColumnsEnabledCount = 0; table->EnabledMaskByIndex = 0x00; table->EnabledMaskByDisplayOrder = 0x00; + table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE + + // [Part 1] Apply/lock Enabled and Order states. + // Process columns in their visible orders as we are building the Prev/Next indices. + int last_visible_column_idx = -1; + bool want_auto_fit = false; for (int order_n = 0; order_n < table->ColumnsCount; order_n++) { const int column_n = table->DisplayOrderToIndex[order_n]; @@ -686,7 +688,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames if (column->AutoFitQueue != 0x00) - want_column_auto_fit = true; + want_auto_fit = true; ImU64 index_mask = (ImU64)1 << column_n; ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder; @@ -717,13 +719,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // [Part 2] Disable child window clipping while fitting columns. This is not strictly necessary but makes it possible // to avoid the column fitting to wait until the first visible frame of the child container (may or not be a good thing). // FIXME-TABLE: for always auto-resizing columns may not want to do that all the time. - if (want_column_auto_fit && table->OuterWindow != table->InnerWindow) + if (want_auto_fit && table->OuterWindow != table->InnerWindow) table->InnerWindow->SkipItems = false; - if (want_column_auto_fit) + if (want_auto_fit) table->IsSettingsDirty = true; // [Part 3] Fix column flags. Calculate ideal width for columns. Count how many fixed/stretch columns we have and sum of weights. - const float min_column_width = TableGetMinColumnWidth(); int count_fixed = 0; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!) int count_resizable = 0; // Number of columns the user can resize (this is NOT the opposite of count_fixed!) float sum_weights_stretched = 0.0f; // Sum of all weights for weighted columns. @@ -743,22 +744,14 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) // Combine width from regular rows + width from headers unless requested not to. if (!column->IsPreserveWidthAuto) - { - const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX; - const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX; - float width_auto = content_width_body; - if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth)) - width_auto = ImMax(width_auto, content_width_headers); - column->WidthAuto = ImMax(width_auto, min_column_width); - } - column->IsPreserveWidthAuto = false; + column->WidthAuto = TableGetColumnWidthAuto(table, column); if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) { // Non-resizable columns keep their requested width if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) - column->WidthRequest = column->WidthAuto = ImMax(column->WidthAuto, column->InitStretchWeightOrWidth); + column->WidthRequest = column->WidthAuto = ImMax(column->WidthAuto, column->InitStretchWeightOrWidth); // Use user value regardless of IsPreserveWidthAuto // Process auto-fit for non-stretched columns // Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!) @@ -770,8 +763,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // large height (= first frame scrollbar display very off + clipper would skip lots of items). // This is merely making the side-effect less extreme, but doesn't properly fixes it. // FIXME: Move this to ->WidthGiven to avoid temporary lossyless? - if (column->AutoFitQueue > 0x01 && table->IsInitializing) - column->WidthRequest = ImMax(column->WidthRequest, min_column_width * 4.0f); // FIXME-TABLE: Another constant/scale? + // FIXME: This break IsPreserveWidthAuto from not flickering if the stored WidthAuto was smaller. + if (column->AutoFitQueue > 0x01 && table->IsInitializing && !column->IsPreserveWidthAuto) + column->WidthRequest = ImMax(column->WidthRequest, table->MinColumnWidth * 4.0f); // FIXME-TABLE: Another constant/scale? count_fixed += 1; sum_width_fixed_requests += column->WidthRequest; } @@ -789,6 +783,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (table->RightMostStretchedColumn == -1 || table->Columns[table->RightMostStretchedColumn].DisplayOrder < column->DisplayOrder) table->RightMostStretchedColumn = (ImGuiTableColumnIdx)column_n; } + column->IsPreserveWidthAuto = false; max_width_auto = ImMax(max_width_auto, column->WidthAuto); sum_width_fixed_requests += table->CellPaddingX * 2.0f; } @@ -826,8 +821,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) const float width_avail = ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth(); const float width_avail_for_stretched_columns = mixed_same_widths ? 0.0f : width_avail - width_spacings - sum_width_fixed_requests; float width_remaining_for_stretched_columns = width_avail_for_stretched_columns; - table->ColumnsTotalWidth = width_spacings; - table->ColumnsAutoFitWidth = width_spacings; + table->ColumnsGivenWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; for (int column_n = 0; column_n < table->ColumnsCount; column_n++) { if (!(table->EnabledMaskByIndex & ((ImU64)1 << column_n))) @@ -838,7 +832,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if ((column->Flags & ImGuiTableColumnFlags_WidthStretch) && !mixed_same_widths) { float weight_ratio = column->StretchWeight / sum_weights_stretched; - column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, min_column_width) + 0.01f); + column->WidthRequest = IM_FLOOR(ImMax(width_avail_for_stretched_columns * weight_ratio, table->MinColumnWidth) + 0.01f); width_remaining_for_stretched_columns -= column->WidthRequest; } @@ -848,9 +842,8 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->Flags |= ImGuiTableColumnFlags_NoDirectResize_; // Assign final width, record width in case we will need to shrink - column->WidthGiven = ImFloor(ImMax(column->WidthRequest, min_column_width)); - table->ColumnsTotalWidth += column->WidthGiven + table->CellPaddingX * 2.0f; - table->ColumnsAutoFitWidth += column->WidthAuto + table->CellPaddingX * 2.0f; + column->WidthGiven = ImFloor(ImMax(column->WidthRequest, table->MinColumnWidth)); + table->ColumnsGivenWidth += column->WidthGiven; } // [Part 6] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column). @@ -919,7 +912,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // Lock width based on start position and minimum/maximum width for this position float max_width = TableGetMaxColumnWidth(table, column_n); column->WidthGiven = ImMin(column->WidthGiven, max_width); - column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, min_column_width)); + column->WidthGiven = ImMax(column->WidthGiven, ImMin(column->WidthRequest, table->MinColumnWidth)); column->MaxX = offset_x + column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; // Lock other positions @@ -1175,16 +1168,6 @@ void ImGui::EndTable() if ((flags & ImGuiTableFlags_Borders) != 0) TableDrawBorders(table); - // Store content width reference for each column (before attempting to merge draw calls) - const float backup_outer_cursor_pos_x = outer_window->DC.CursorPos.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; - float max_pos_x = backup_inner_max_pos_x; - if (table->RightMostEnabledColumn != -1) - max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].MaxX); - if (table->ResizedColumn != -1) - max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); - #if 0 // Strip out dummy channel draw calls // We have no way to prevent user submitting direct ImDrawList calls into a hidden column (but ImGui:: calls will be clipped out) @@ -1204,14 +1187,22 @@ void ImGui::EndTable() TableMergeDrawChannels(table); table->DrawSplitter.Merge(inner_window->DrawList); - if (!(table->Flags & ImGuiTableFlags_ScrollX) && inner_window != outer_window) + // Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable() + const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); + table->ColumnsAutoFitWidth = width_spacings + (table->CellPaddingX * 2.0f) * table->ColumnsEnabledCount; + for (int column_n = 0; column_n < table->ColumnsCount; column_n++) + if (table->EnabledMaskByIndex & ((ImU64)1 << column_n)) + table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, &table->Columns[column_n]); + + // Update scroll + if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window) { inner_window->Scroll.x = 0.0f; } 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 neighbor_width_to_keep_visible = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f; + const float neighbor_width_to_keep_visible = table->MinColumnWidth + table->CellPaddingX * 2.0f; ImGuiTableColumn* column = &table->Columns[table->LastResizedColumn]; if (column->MaxX < table->InnerClipRect.Min.x) SetScrollFromPosX(inner_window, column->MaxX - inner_window->Pos.x - neighbor_width_to_keep_visible, 1.0f); @@ -1228,10 +1219,20 @@ void ImGui::EndTable() table->ResizedColumnNextWidth = new_width; } - // Layout in outer window + // Pop from id stack 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(); + + // Layout in outer window + const float backup_outer_cursor_pos_x = outer_window->DC.CursorPos.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; + float max_pos_x = backup_inner_max_pos_x; + if (table->RightMostEnabledColumn != -1) + max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].MaxX); + if (table->ResizedColumn != -1) + max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); inner_window->WorkRect = table->HostBackupWorkRect; inner_window->ParentWorkRect = table->HostBackupParentWorkRect; inner_window->SkipItems = table->HostSkipItems; @@ -1255,7 +1256,7 @@ void ImGui::EndTable() if (table->Flags & ImGuiTableFlags_ScrollX) { inner_window->DC.CursorMaxPos.x = max_pos_x; // Set contents width for scrolling - outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, backup_outer_cursor_pos_x + table->ColumnsTotalWidth + inner_window->ScrollbarSizes.x); // For auto-fit + outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, backup_outer_cursor_pos_x + table->ColumnsGivenWidth + inner_window->ScrollbarSizes.x); // For scrolling } else { @@ -1825,28 +1826,20 @@ void ImGui::TableEndCell(ImGuiTable* table) //------------------------------------------------------------------------- // [SECTION] Tables: Columns width management //------------------------------------------------------------------------- -// - TableGetMinColumnWidth() [Internal] // - TableGetMaxColumnWidth() [Internal] +// - TableGetColumnWidthAuto() [Internal] // - TableSetColumnWidth() // - TableSetColumnWidthAutoSingle() [Internal] // - TableSetColumnWidthAutoAll() [Internal] // - TableUpdateColumnsWeightFromWidth() [Internal] //------------------------------------------------------------------------- -// Minimum column content width (without padding) -float ImGui::TableGetMinColumnWidth() -{ - ImGuiContext& g = *GImGui; - //return g.Style.ColumnsMinSpacing; // FIXME-TABLE - return g.Style.FramePadding.x * 1.0f; -} - // Maximum column content width given current layout. Use column->MinX so this value on a per-column basis. float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) { const ImGuiTableColumn* column = &table->Columns[column_n]; float max_width = FLT_MAX; - const float min_column_distance = TableGetMinColumnWidth() + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2; + const float min_column_distance = table->MinColumnWidth + table->CellPaddingX * 2.0f + table->CellSpacingX1 + table->CellSpacingX2; if (table->Flags & ImGuiTableFlags_ScrollX) { // Frozen columns can't reach beyond visible width else scrolling will naturally break. @@ -1872,6 +1865,23 @@ float ImGui::TableGetMaxColumnWidth(const ImGuiTable* table, int column_n) return max_width; } +// Note this is meant to be stored in column->WidthAuto, please generally use the WidthAuto field +float ImGui::TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column) +{ + const float content_width_body = ImMax(column->ContentMaxXFrozen, column->ContentMaxXUnfrozen) - column->WorkMinX; + const float content_width_headers = column->ContentMaxXHeadersIdeal - column->WorkMinX; + float width_auto = content_width_body; + if (!(column->Flags & ImGuiTableColumnFlags_NoHeaderWidth)) + width_auto = ImMax(width_auto, content_width_headers); + + // Non-resizable fixed columns preserve their requested width + if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && column->InitStretchWeightOrWidth > 0.0f) + if (!(table->Flags & ImGuiTableFlags_Resizable) || (column->Flags & ImGuiTableColumnFlags_NoResize)) + width_auto = ImMax(width_auto, column->InitStretchWeightOrWidth); + + return ImMax(width_auto, table->MinColumnWidth); +} + // 'width' = inner column width, without padding void ImGui::TableSetColumnWidth(int column_n, float width) { @@ -1884,7 +1894,8 @@ void ImGui::TableSetColumnWidth(int column_n, float width) // Apply constraints early // Compare both requested and actual given width to avoid overwriting requested width when column is stuck (minimum size, bounded) - const float min_width = TableGetMinColumnWidth(); + IM_ASSERT(table->MinColumnWidth > 0.0f); + const float min_width = table->MinColumnWidth; const float max_width = ImMax(min_width, TableGetMaxColumnWidth(table, column_n)); column_0_width = ImClamp(column_0_width, min_width, max_width); if (column_0->WidthGiven == column_0_width || column_0->WidthRequest == column_0_width) @@ -3308,7 +3319,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table) return; bool clear_settings = SmallButton("Clear settings"); BulletText("OuterRect: Pos: (%.1f,%.1f) Size: (%.1f,%.1f)", table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.GetWidth(), table->OuterRect.GetHeight()); - BulletText("ColumnsWidth: %.1f, AutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsTotalWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); + BulletText("ColumnsGivenWidth: %.1f, ColumnsAutoFitWidth: %.1f, InnerWidth: %.1f%s", table->ColumnsGivenWidth, table->ColumnsAutoFitWidth, table->InnerWidth, table->InnerWidth == 0.0f ? " (auto)" : ""); BulletText("CellPaddingX: %.1f, CellSpacingX: %.1f/%.1f, OuterPaddingX: %.1f", table->CellPaddingX, table->CellSpacingX1, table->CellSpacingX2, table->OuterPaddingX); BulletText("HoveredColumnBody: %d, HoveredColumnBorder: %d", table->HoveredColumnBody, table->HoveredColumnBorder); BulletText("ResizedColumn: %d, ReorderColumn: %d, HeldHeaderColumn: %d", table->ResizedColumn, table->ReorderColumn, table->HeldHeaderColumn); From eb88fee052ce368ca8305a88494341e2e8dd422f Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 25 Dec 2020 16:10:12 +0100 Subject: [PATCH 06/13] Tables: internal tidying up, calculate WidthAuto in first loop of layout + TableSetupColumn() with unspecified stretch weight leaves it at -1.0f (unset) rather than overrding default. Amend 3b3503e. Both changes are intended to have no side-effects. Committed separately from upcoming commit for easier future bissecting. Small demo fix. --- imgui.h | 2 +- imgui_demo.cpp | 11 ++++++----- imgui_tables.cpp | 49 ++++++++++++++++++++++++------------------------ 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/imgui.h b/imgui.h index f18178ab6..e6e2e0c3a 100644 --- a/imgui.h +++ b/imgui.h @@ -664,7 +664,7 @@ namespace ImGui // - 1. Call BeginTable() // - 2. Optionally call TableSetupColumn() to submit column name/flags/defaults // - 3. Optionally call TableSetupScrollFreeze() to request scroll freezing of columns/rows - // - 4. Optionally call TableHeadersRow() to submit a header row (names will be pulled from data submitted to TableSetupColumns) + // - 4. Optionally call TableHeadersRow() to submit a header row. Names will be pulled from data provided TableSetupColumn() calls) // - 5. Populate contents // - In most situations you can use TableNextRow() + TableSetColumnIndex(N) to start appending into a column. // - If you are using tables as a sort of grid, where every columns is holding the same type of contents, diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 456e0b4e5..5427dfb8c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -4080,15 +4080,15 @@ static void ShowDemoWindowTables() static int column_count = 3; PushStyleCompact(); - ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 22); + ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30); ImGui::Combo("Contents", &contents_type, "Short Text\0Long Text\0Button\0Fill Button\0InputText\0"); if (contents_type == CT_FillButton) { ImGui::SameLine(); HelpMarker("Be mindful that using right-alignment (e.g. size.x = -FLT_MIN) creates a feedback loop where contents width can feed into auto-column width can feed into contents width."); } - ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 22); ImGui::DragInt("Columns", &column_count, 0.1f, 1, 64, "%d", ImGuiSliderFlags_AlwaysClamp); + ImGui::PopItemWidth(); ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerH", &flags, ImGuiTableFlags_BordersInnerH); ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterH", &flags, ImGuiTableFlags_BordersOuterH); ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV); @@ -4181,13 +4181,14 @@ static void ShowDemoWindowTables() static float inner_width = 1000.0f; PushStyleCompact(); ImGui::PushID("flags3"); + ImGui::PushItemWidth(TEXT_BASE_WIDTH * 30); ImGui::CheckboxFlags("ImGuiTableFlags_ScrollX", &flags3, ImGuiTableFlags_ScrollX); if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyStretch", &flags3, ImGuiTableFlags_SizingPolicyStretch)) flags3 &= ~ImGuiTableFlags_SizingPolicyFixed; // Can't specify both sizing polices so we clear the other if (ImGui::CheckboxFlags("ImGuiTableFlags_SizingPolicyFixed", &flags3, ImGuiTableFlags_SizingPolicyFixed)) flags3 &= ~ImGuiTableFlags_SizingPolicyStretch; // Can't specify both sizing polices so we clear the other - ImGui::SetNextItemWidth(TEXT_BASE_WIDTH * 10.0f); ImGui::DragFloat("inner_width", &inner_width, 1.0f, 0.0f, FLT_MAX, "%.1f"); + ImGui::PopItemWidth(); ImGui::PopID(); PopStyleCompact(); if (ImGui::BeginTable("##table3", 7, flags3 | ImGuiTableFlags_SizingPolicyStretch | ImGuiTableFlags_ContextMenuInBody, outer_size, inner_width)) @@ -4853,8 +4854,8 @@ static void ShowDemoWindowTables() 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("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); diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 07ea39c1b..a942af2eb 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -644,7 +644,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) table->EnabledMaskByDisplayOrder = 0x00; table->MinColumnWidth = ImMax(1.0f, g.Style.FramePadding.x * 1.0f); // g.Style.ColumnsMinSpacing; // FIXME-TABLE - // [Part 1] Apply/lock Enabled and Order states. + // [Part 1] Apply/lock Enabled and Order states. Calculate auto/ideal width for columns. // Process columns in their visible orders as we are building the Prev/Next indices. int last_visible_column_idx = -1; bool want_auto_fit = false; @@ -687,29 +687,33 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (start_auto_fit) column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames - if (column->AutoFitQueue != 0x00) - want_auto_fit = true; - ImU64 index_mask = (ImU64)1 << column_n; ImU64 display_order_mask = (ImU64)1 << column->DisplayOrder; - if (column->IsEnabled) - { - // Mark as enabled and link to previous/next enabled column - column->PrevEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx; - column->NextEnabledColumn = -1; - if (last_visible_column_idx != -1) - table->Columns[last_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n; - column->IndexWithinEnabledSet = table->ColumnsEnabledCount; - table->ColumnsEnabledCount++; - table->EnabledMaskByIndex |= index_mask; - table->EnabledMaskByDisplayOrder |= display_order_mask; - last_visible_column_idx = column_n; - } - else + if (!column->IsEnabled) { column->IndexWithinEnabledSet = -1; + continue; } + + // Mark as enabled and link to previous/next enabled column + column->PrevEnabledColumn = (ImGuiTableColumnIdx)last_visible_column_idx; + column->NextEnabledColumn = -1; + if (last_visible_column_idx != -1) + table->Columns[last_visible_column_idx].NextEnabledColumn = (ImGuiTableColumnIdx)column_n; + column->IndexWithinEnabledSet = table->ColumnsEnabledCount; + table->ColumnsEnabledCount++; + table->EnabledMaskByIndex |= index_mask; + table->EnabledMaskByDisplayOrder |= display_order_mask; + last_visible_column_idx = column_n; IM_ASSERT(column->IndexWithinEnabledSet <= column->DisplayOrder); + + // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) + // Combine width from regular rows + width from headers unless requested not to. + if (!column->IsPreserveWidthAuto) + column->WidthAuto = TableGetColumnWidthAuto(table, column); + + if (column->AutoFitQueue != 0x00) + want_auto_fit = true; } if ((table->Flags & ImGuiTableFlags_Sortable) && table->SortSpecsCount == 0 && !(table->Flags & ImGuiTableFlags_SortTristate)) table->IsSortSpecsDirty = true; @@ -724,7 +728,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (want_auto_fit) table->IsSettingsDirty = true; - // [Part 3] Fix column flags. Calculate ideal width for columns. Count how many fixed/stretch columns we have and sum of weights. + // [Part 3] Fix column flags. Count how many fixed/stretch columns we have and sum of weights. int count_fixed = 0; // Number of columns that have fixed sizing policy (not stretched sizing policy) (this is NOT the opposite of count_resizable!) int count_resizable = 0; // Number of columns the user can resize (this is NOT the opposite of count_fixed!) float sum_weights_stretched = 0.0f; // Sum of all weights for weighted columns. @@ -741,11 +745,6 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if ((column->Flags & ImGuiTableColumnFlags_NoResize) == 0) count_resizable++; - // Calculate ideal/auto column width (that's the width required for all contents to be visible without clipping) - // Combine width from regular rows + width from headers unless requested not to. - if (!column->IsPreserveWidthAuto) - column->WidthAuto = TableGetColumnWidthAuto(table, column); - if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) { // Non-resizable columns keep their requested width @@ -1313,7 +1312,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo if ((flags & ImGuiTableColumnFlags_WidthFixed) && init_width_or_weight > 0.0f) column->WidthRequest = init_width_or_weight; if (flags & ImGuiTableColumnFlags_WidthStretch) - column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : 1.0f; + column->StretchWeight = (init_width_or_weight > 0.0f) ? init_width_or_weight : -1.0f; // Disable auto-fit if an explicit width/weight has been specified if (init_width_or_weight > 0.0f) From fa963b9aafde7f05b1d32d42e3d2b084c9685e31 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 25 Dec 2020 17:52:01 +0100 Subject: [PATCH 07/13] Inputs: Internal: added SetItemUsingMouseWheel() and mechanism to request mouse wheel for both HoveredId and ActiveId. (#2891) Based on @kudaba PR. --- imgui.cpp | 22 ++++++++++++++++++++-- imgui.h | 2 +- imgui_internal.h | 8 +++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fabdcce86..35657374d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3026,6 +3026,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) // Clear declaration of inputs claimed by the widget // (Please note that this is WIP and not all keys/inputs are thoroughly declared by all widgets yet) + g.ActiveIdUsingMouseWheel = false; g.ActiveIdUsingNavDirMask = 0x00; g.ActiveIdUsingNavInputMask = 0x00; g.ActiveIdUsingKeyInputMask = 0x00; @@ -3041,6 +3042,7 @@ void ImGui::SetHoveredID(ImGuiID id) ImGuiContext& g = *GImGui; g.HoveredId = id; g.HoveredIdAllowOverlap = false; + g.HoveredIdUsingMouseWheel = false; if (id != 0 && g.HoveredIdPreviousFrame != id) g.HoveredIdTimer = g.HoveredIdNotActiveTimer = 0.0f; } @@ -3606,6 +3608,9 @@ void ImGui::UpdateMouseWheel() if (g.IO.MouseWheel == 0.0f && g.IO.MouseWheelH == 0.0f) return; + if ((g.ActiveId != 0 && g.ActiveIdUsingMouseWheel) || (g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrameUsingMouseWheel)) + return; + ImGuiWindow* window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow; if (!window || window->Collapsed) return; @@ -3839,8 +3844,10 @@ void ImGui::NewFrame() if (g.HoveredId && g.ActiveId != g.HoveredId) g.HoveredIdNotActiveTimer += g.IO.DeltaTime; g.HoveredIdPreviousFrame = g.HoveredId; + g.HoveredIdPreviousFrameUsingMouseWheel = g.HoveredIdUsingMouseWheel; g.HoveredId = 0; g.HoveredIdAllowOverlap = false; + g.HoveredIdUsingMouseWheel = false; g.HoveredIdDisabled = false; // Update ActiveId data (clear reference to active widget if the widget isn't alive anymore) @@ -4768,12 +4775,23 @@ bool ImGui::IsItemEdited() void ImGui::SetItemAllowOverlap() { ImGuiContext& g = *GImGui; - if (g.HoveredId == g.CurrentWindow->DC.LastItemId) + ImGuiID id = g.CurrentWindow->DC.LastItemId; + if (g.HoveredId == id) g.HoveredIdAllowOverlap = true; - if (g.ActiveId == g.CurrentWindow->DC.LastItemId) + if (g.ActiveId == id) g.ActiveIdAllowOverlap = true; } +void ImGui::SetItemUsingMouseWheel() +{ + ImGuiContext& g = *GImGui; + ImGuiID id = g.CurrentWindow->DC.LastItemId; + if (g.HoveredId == id) + g.HoveredIdUsingMouseWheel = true; + if (g.ActiveId == id) + g.ActiveIdUsingMouseWheel = true; +} + ImVec2 ImGui::GetItemRectMin() { ImGuiWindow* window = GetCurrentWindowRead(); diff --git a/imgui.h b/imgui.h index e6e2e0c3a..7bfa5ff48 100644 --- a/imgui.h +++ b/imgui.h @@ -59,7 +59,7 @@ Index of this file: // Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens) #define IMGUI_VERSION "1.80 WIP" -#define IMGUI_VERSION_NUM 17908 +#define IMGUI_VERSION_NUM 17909 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE diff --git a/imgui_internal.h b/imgui_internal.h index 7c9c9a1ff..de1eeb061 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1275,9 +1275,11 @@ struct ImGuiContext float WheelingWindowTimer; // Item/widgets state and tracking information - ImGuiID HoveredId; // Hovered widget + ImGuiID HoveredId; // Hovered widget, filled during the frame ImGuiID HoveredIdPreviousFrame; bool HoveredIdAllowOverlap; + bool HoveredIdUsingMouseWheel; // Hovered widget will use mouse wheel. Blocks scrolling the underlying window. + bool HoveredIdPreviousFrameUsingMouseWheel; bool HoveredIdDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0. float HoveredIdTimer; // Measure contiguous hovering time float HoveredIdNotActiveTimer; // Measure contiguous hovering time where the item has not been active @@ -1290,6 +1292,7 @@ struct ImGuiContext bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch. bool ActiveIdHasBeenEditedBefore; // Was the value associated to the widget Edited over the course of the Active state. bool ActiveIdHasBeenEditedThisFrame; + bool ActiveIdUsingMouseWheel; // Active widget will want to read mouse wheel. Blocks scrolling the underlying window. ImU32 ActiveIdUsingNavDirMask; // Active widget will want to read those nav move requests (e.g. can activate a button and move away from it) ImU32 ActiveIdUsingNavInputMask; // Active widget will want to read those nav inputs. ImU64 ActiveIdUsingKeyInputMask; // Active widget will want to read those key inputs. When we grow the ImGuiKey enum we'll need to either to order the enum to make useful keys come first, either redesign this into e.g. a small array. @@ -1501,6 +1504,7 @@ struct ImGuiContext HoveredId = HoveredIdPreviousFrame = 0; HoveredIdAllowOverlap = false; + HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false; HoveredIdDisabled = false; HoveredIdTimer = HoveredIdNotActiveTimer = 0.0f; ActiveId = 0; @@ -1512,6 +1516,7 @@ struct ImGuiContext ActiveIdHasBeenPressedBefore = false; ActiveIdHasBeenEditedBefore = false; ActiveIdHasBeenEditedThisFrame = false; + ActiveIdUsingMouseWheel = false; ActiveIdUsingNavDirMask = 0x00; ActiveIdUsingNavInputMask = 0x00; ActiveIdUsingKeyInputMask = 0x00; @@ -2267,6 +2272,7 @@ namespace ImGui // Inputs // FIXME: Eventually we should aim to move e.g. IsActiveIdUsingKey() into IsKeyXXX functions. + IMGUI_API void SetItemUsingMouseWheel(); inline bool IsActiveIdUsingNavDir(ImGuiDir dir) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavDirMask & (1 << dir)) != 0; } inline bool IsActiveIdUsingNavInput(ImGuiNavInput input) { ImGuiContext& g = *GImGui; return (g.ActiveIdUsingNavInputMask & (1 << input)) != 0; } inline bool IsActiveIdUsingKey(ImGuiKey key) { ImGuiContext& g = *GImGui; IM_ASSERT(key < 64); return (g.ActiveIdUsingKeyInputMask & ((ImU64)1 << key)) != 0; } From 8ec5daf35df3a5e973175075875e66ed48ec5230 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 Jan 2021 14:59:32 +0100 Subject: [PATCH 08/13] Happy new year! --- LICENSE.txt | 2 +- backends/imgui_impl_glut.cpp | 4 ++-- backends/imgui_impl_glut.h | 4 ++-- docs/BACKENDS.md | 2 +- docs/EXAMPLES.md | 4 ++-- examples/example_glut_opengl2/main.cpp | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index d87639959..780533dcb 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2020 Omar Cornut +Copyright (c) 2014-2021 Omar Cornut Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/backends/imgui_impl_glut.cpp b/backends/imgui_impl_glut.cpp index 90ad33307..6be4682c8 100644 --- a/backends/imgui_impl_glut.cpp +++ b/backends/imgui_impl_glut.cpp @@ -1,8 +1,8 @@ // dear imgui: Platform Backend for GLUT/FreeGLUT // This needs to be used along with a Renderer (e.g. OpenGL2) -// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! +// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! +// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! // Issues: diff --git a/backends/imgui_impl_glut.h b/backends/imgui_impl_glut.h index 9d8282e70..2f18ab763 100644 --- a/backends/imgui_impl_glut.h +++ b/backends/imgui_impl_glut.h @@ -1,8 +1,8 @@ // dear imgui: Platform Backend for GLUT/FreeGLUT // This needs to be used along with a Renderer (e.g. OpenGL2) -// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! +// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! +// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! // Issues: diff --git a/docs/BACKENDS.md b/docs/BACKENDS.md index 835bf94ef..2463ce795 100644 --- a/docs/BACKENDS.md +++ b/docs/BACKENDS.md @@ -56,7 +56,7 @@ List of Platforms Backends: imgui_impl_osx.mm ; macOS native API (not as feature complete as glfw/sdl backends) imgui_impl_sdl.cpp ; SDL2 (Windows, macOS, Linux, iOS, Android) https://www.libsdl.org imgui_impl_win32.cpp ; Win32 native API (Windows) - imgui_impl_glut.cpp ; GLUT/FreeGLUT (absolutely not recommended in 2020!) + imgui_impl_glut.cpp ; GLUT/FreeGLUT (this is prehistoric software and absolutely not recommended today!) List of Renderer Backends: diff --git a/docs/EXAMPLES.md b/docs/EXAMPLES.md index d6fac021b..932f46044 100644 --- a/docs/EXAMPLES.md +++ b/docs/EXAMPLES.md @@ -198,9 +198,9 @@ This is quite long and tedious, because: DirectX12. **Building** -Unfortunately in 2020 it is still tedious to create and maintain portable build files using external +Unfortunately nowadays it is still tedious to create and maintain portable build files using external libraries (the kind we're using here to create a window and render 3D triangles) without relying on -third party software. For most examples here we choose to provide: +third party software and build systems. For most examples here we choose to provide: - Makefiles for Linux/OSX - Batch files for Visual Studio 2008+ - A .sln project file for Visual Studio 2012+ diff --git a/examples/example_glut_opengl2/main.cpp b/examples/example_glut_opengl2/main.cpp index b8efae9b4..ecb1ece26 100644 --- a/examples/example_glut_opengl2/main.cpp +++ b/examples/example_glut_opengl2/main.cpp @@ -2,8 +2,8 @@ // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp. // Read online: https://github.com/ocornut/imgui/tree/master/docs -// !!! GLUT/FreeGLUT IS OBSOLETE SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! -// !!! If someone or something is teaching you GLUT in 2020, you are being abused. Please show some resistance. !!! +// !!! GLUT/FreeGLUT IS OBSOLETE PREHISTORIC SOFTWARE. Using GLUT is not recommended unless you really miss the 90's. !!! +// !!! If someone or something is teaching you GLUT today, you are being abused. Please show some resistance. !!! // !!! Nowadays, prefer using GLFW or SDL instead! #include "imgui.h" From 1c1d3b7ab5372a2c3a6c5b836d7af3f8ff3d6032 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 Jan 2021 11:31:30 +0100 Subject: [PATCH 09/13] Added 64-bit variants of CheckboxFlags() in imgui_internal.h. Improve assert on mismatched ListBoxFooter() call. Fix FAQ index. (#3687) --- docs/FAQ.md | 2 +- imgui_internal.h | 2 ++ imgui_widgets.cpp | 14 +++++++++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/FAQ.md b/docs/FAQ.md index 7ed9b06d2..2d5e80606 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -23,7 +23,7 @@ or view this file with any Markdown viewer. | [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) | | [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) | | **Q&A: Usage** | -| **[Why is my widget not reacting when I click on it?
How can I have multiple widgets with the same label?
Why are multiple widgets reacting when I interact with one?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** | +| **[Why is my widget not reacting when I click on it?
How can I have widgets with an empty label?
How can I have multiple widgets with the same label?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** | | [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)| | [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) | | [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) | diff --git a/imgui_internal.h b/imgui_internal.h index de1eeb061..bd2112425 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2403,6 +2403,8 @@ namespace ImGui IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis); IMGUI_API ImGuiID GetWindowResizeID(ImGuiWindow* window, int n); // 0..3: corners, 4..7: borders IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags); + IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value); + IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value); // Widgets low-level behaviors IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 99e4fc896..c40b7a69e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1142,6 +1142,16 @@ bool ImGui::CheckboxFlags(const char* label, unsigned int* flags, unsigned int f return CheckboxFlagsT(label, flags, flags_value); } +bool ImGui::CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value) +{ + return CheckboxFlagsT(label, flags, flags_value); +} + +bool ImGui::CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value) +{ + return CheckboxFlagsT(label, flags, flags_value); +} + bool ImGui::RadioButton(const char* label, bool active) { ImGuiWindow* window = GetCurrentWindow(); @@ -6152,7 +6162,9 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item // FIXME: In principle this function should be called EndListBox(). We should rename it after re-evaluating if we want to keep the same signature. void ImGui::ListBoxFooter() { - ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow; + ImGuiWindow * window = GetCurrentWindow(); + IM_ASSERT((window->Flags & ImGuiWindowFlags_ChildWindow) && "Mismatched ListBoxHeader/ListBoxFooter calls. Did you test the return value of ListBoxHeader()?"); + ImGuiWindow* parent_window = window->ParentWindow; const ImRect bb = parent_window->DC.LastItemRect; const ImGuiStyle& style = GetStyle(); From 0a5f399805b95472046630385b204ca159d88ad5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 Jan 2021 15:10:35 +0100 Subject: [PATCH 10/13] Tables: Fix hiding column right after the frozen line. Fix hovering/resising column delimiter scrolled under frozen columns. (#3678) --- imgui.cpp | 2 +- imgui_internal.h | 2 +- imgui_tables.cpp | 26 +++++++++++++++++--------- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 35657374d..6c6747c97 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2286,7 +2286,7 @@ bool ImGuiListClipper::Step() { // While we are in frozen row state, keep displaying items one by one, unclipped // FIXME: Could be stored as a table-agnostic state. - if (table != NULL && !table->IsUnfrozen) + if (table != NULL && !table->IsUnfrozenRows) { DisplayStart = ItemsFrozen; DisplayEnd = ItemsFrozen + 1; diff --git a/imgui_internal.h b/imgui_internal.h index bd2112425..a27c82218 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2080,7 +2080,7 @@ struct ImGuiTable bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1) bool IsResetAllRequest; bool IsResetDisplayOrderRequest; - bool IsUnfrozen; // Set when we got past the frozen row. + bool IsUnfrozenRows; // Set when we got past the frozen row. 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 a942af2eb..e8bb00f73 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -392,7 +392,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow() table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any table->FreezeColumnsRequest = table->FreezeColumnsCount = 0; - table->IsUnfrozen = true; + table->IsUnfrozenRows = true; table->DeclColumnsCount = 0; // Using opaque colors facilitate overlapping elements of the grid @@ -868,6 +868,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // [Part 7] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column // Process columns in their visible orders as we are comparing the visible order and adjusting host_clip_rect while looping. int visible_n = 0; + bool offset_x_frozen = (table->FreezeColumnsCount > 0); float offset_x = ((table->FreezeColumnsCount > 0) ? table->OuterRect.Min.x : work_rect.Min.x) + table->OuterPaddingX - table->CellSpacingX1; ImRect host_clip_rect = table->InnerClipRect; //host_clip_rect.Max.x += table->CellPaddingX + table->CellSpacingX2; @@ -880,8 +881,11 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) column->NavLayerCurrent = (ImS8)((table->FreezeRowsCount > 0 || column_n < table->FreezeColumnsCount) ? ImGuiNavLayer_Menu : ImGuiNavLayer_Main); - if (table->FreezeColumnsCount > 0 && table->FreezeColumnsCount == visible_n) + if (offset_x_frozen && table->FreezeColumnsCount == visible_n) + { offset_x += work_rect.Min.x - table->OuterRect.Min.x; + offset_x_frozen = false; + } // Clear status flags column->Flags &= ~ImGuiTableColumnFlags_StatusMask_; @@ -1084,6 +1088,10 @@ void ImGui::TableUpdateBorders(ImGuiTable* table) if ((table->Flags & ImGuiTableFlags_NoBordersInBody) && table->IsUsingHeaders == false) continue; + if (table->FreezeColumnsCount > 0) + if (column->MaxX < table->Columns[table->DisplayOrderToIndex[table->FreezeColumnsCount - 1]].MaxX) + continue; + ImGuiID column_id = TableGetColumnResizeID(table, column_n, table->InstanceCurrent); ImRect hit_rect(column->MaxX - hit_half_width, hit_y1, column->MaxX + hit_half_width, border_y2_hit); //GetForegroundDrawList()->AddRect(hit_rect.Min, hit_rect.Max, IM_COL32(255, 0, 0, 100)); @@ -1353,7 +1361,7 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows) table->FreezeColumnsCount = (table->InnerWindow->Scroll.x != 0.0f) ? table->FreezeColumnsRequest : 0; table->FreezeRowsRequest = (table->Flags & ImGuiTableFlags_ScrollY) ? (ImGuiTableColumnIdx)rows : 0; table->FreezeRowsCount = (table->InnerWindow->Scroll.y != 0.0f) ? table->FreezeRowsRequest : 0; - table->IsUnfrozen = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b + table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b } int ImGui::TableGetColumnCount() @@ -1653,8 +1661,8 @@ void ImGui::TableEndRow(ImGuiTable* table) } if (unfreeze_rows_actual) { - IM_ASSERT(table->IsUnfrozen == false); - table->IsUnfrozen = true; + IM_ASSERT(table->IsUnfrozenRows == false); + table->IsUnfrozenRows = true; // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y); @@ -1812,7 +1820,7 @@ void ImGui::TableEndCell(ImGuiTable* table) if (table->RowFlags & ImGuiTableRowFlags_Headers) p_max_pos_x = &column->ContentMaxXHeadersUsed; // Useful in case user submit contents in header row that is not a TableHeader() call else - p_max_pos_x = table->IsUnfrozen ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; + p_max_pos_x = table->IsUnfrozenRows ? &column->ContentMaxXUnfrozen : &column->ContentMaxXFrozen; *p_max_pos_x = ImMax(*p_max_pos_x, window->DC.CursorMaxPos.x); table->RowPosY2 = ImMax(table->RowPosY2, window->DC.CursorMaxPos.y + table->CellPaddingY); column->ItemWidth = window->DC.ItemWidth; @@ -3332,15 +3340,15 @@ void ImGui::DebugNodeTable(ImGuiTable* table) ImGuiTableColumn* column = &table->Columns[n]; const char* name = TableGetColumnName(table, n); ImFormatString(buf, IM_ARRAYSIZE(buf), - "Column %d order %d name '%s': offset %+.2f to %+.2f\n" + "Column %d order %d '%s': offset %+.2f to %+.2f%s\n" "Enabled: %d, VisibleX/Y: %d/%d, RequestOutput: %d, SkipItems: %d, DrawChannels: %d,%d\n" "WidthGiven: %.1f, Request/Auto: %.1f/%.1f, StretchWeight: %.3f (%.1f%%)\n" "MinX: %.1f, MaxX: %.1f (%+.1f), ClipRect: %.1f to %.1f (+%.1f)\n" "ContentWidth: %.1f,%.1f, HeadersUsed/Ideal %.1f/%.1f\n" "Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s%s..", - n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, + n, column->DisplayOrder, name, column->MinX - table->WorkRect.Min.x, column->MaxX - table->WorkRect.Min.x, (n < table->FreezeColumnsRequest) ? " (Frozen)" : "", column->IsEnabled, column->IsVisibleX, column->IsVisibleY, column->IsRequestOutput, column->IsSkipItems, column->DrawChannelFrozen, column->DrawChannelUnfrozen, - column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, (column->StretchWeight / sum_weights) * 100.0f, + column->WidthGiven, column->WidthRequest, column->WidthAuto, column->StretchWeight, column->StretchWeight > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f, column->MinX, column->MaxX, column->MaxX - column->MinX, column->ClipRect.Min.x, column->ClipRect.Max.x, column->ClipRect.Max.x - column->ClipRect.Min.x, column->ContentMaxXFrozen - column->WorkMinX, column->ContentMaxXUnfrozen - column->WorkMinX, column->ContentMaxXHeadersUsed - column->WorkMinX, column->ContentMaxXHeadersIdeal - column->WorkMinX, column->SortOrder, (column->SortDirection == ImGuiSortDirection_Ascending) ? " (Asc)" : (column->SortDirection == ImGuiSortDirection_Descending) ? " (Des)" : "", column->UserID, column->Flags, From 7d5d5711c20d2448fb379de245ddc3b950289873 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 3 Jan 2021 15:55:12 +0100 Subject: [PATCH 11/13] Backends: OpenGL2, OpenGL3: Backup and restore GL_SHADE_MODAL, GL_STENCIL_TEST, clear GL_NORMAL_ARRAY. Comments., (#3671, #3668) --- backends/imgui_impl_opengl2.cpp | 23 ++++++++++++++++------- backends/imgui_impl_opengl3.cpp | 6 +++++- docs/CHANGELOG.txt | 13 ++++++++----- examples/example_glfw_opengl2/main.cpp | 2 +- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index e56e87d6b..3603a0650 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -18,7 +18,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2020-01-23: OpenGL: Explicitly backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. +// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODAL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. +// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. @@ -82,23 +83,29 @@ static void ImGui_ImplOpenGL2_SetupRenderState(ImDrawData* draw_data, int fb_wid glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glEnable(GL_SCISSOR_TEST); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glShadeModel(GL_SMOOTH); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), - // you may need to backup/reset/restore current shader using the lines below. DO NOT MODIFY THIS FILE! Add the code in your calling function: - // GLint last_program; - // glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); - // glUseProgram(0); - // ImGui_ImplOpenGL2_RenderDrawData(...); - // glUseProgram(last_program) + // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below. + // (DO NOT MODIFY THIS FILE! Add the code in your calling function) + // GLint last_program; + // glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); + // glUseProgram(0); + // ImGui_ImplOpenGL2_RenderDrawData(...); + // glUseProgram(last_program) + // There are potentially many more states you could need to clear/setup that we can't access from default headers. + // e.g. glBindBuffer(GL_ARRAY_BUFFER, 0), glDisable(GL_TEXTURE_CUBE_MAP). // Setup viewport, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. @@ -128,6 +135,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode); GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport); GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box); + GLint last_shade_model; glGetIntegerv(GL_SHADE_MODEL, &last_shade_model); GLint last_tex_env_mode; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &last_tex_env_mode); glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT); @@ -196,6 +204,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data) glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); + glShadeModel(last_shade_model); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, last_tex_env_mode); } diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index c70cfd6cc..b1339afad 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -13,7 +13,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2020-10-23: OpenGL: Save and restore current GL_PRIMITIVE_RESTART state. +// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state. +// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state. // 2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x) // 2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader. // 2020-07-10: OpenGL: Added support for glad2 OpenGL loader. @@ -249,6 +250,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); glEnable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART if (g_GlVersion >= 310) @@ -343,6 +345,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) GLboolean last_enable_blend = glIsEnabled(GL_BLEND); GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE); GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST); + GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST); GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART GLboolean last_enable_primitive_restart = (g_GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE; @@ -431,6 +434,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND); if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); + if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART if (g_GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); } diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6fba2f098..6536eb9f9 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -39,8 +39,8 @@ Breaking Changes: - Added imgui_tables.cpp file! Manually constructed project files will need the new file added! - Backends: moved all backends files (imgui_impl_XXXX.cpp, imgui_impl_XXXX.h) from examples/ to backends/. (#3513) -- Renamed ImDrawList::AddBezierCurve() to ImDrawList::AddBezierCubic(). Kept inline redirection function (will obsolete). -- Renamed ImDrawList::PathBezierCurveTo() to ImDrawList::PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete). +- Renamed ImDrawList::AddBezierCurve() to ImDrawList::AddBezierCubic(). Kept inline redirection function (will obsolete). +- Renamed ImDrawList::PathBezierCurveTo() to ImDrawList::PathBezierCubicCurveTo(). Kept inline redirection function (will obsolete). - Removed redirecting functions/enums names that were marked obsolete in 1.60 (April 2018): - io.RenderDrawListsFn pointer -> use ImGui::GetDrawData() value and call the render function of your backend - ImGui::IsAnyWindowFocused() -> use ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow) @@ -67,8 +67,8 @@ Other Changes: - Tables: added new Tables Beta API as a replacement for old Columns. (#2957, #125) Check out 'Demo->Tables' for many demos + API comments in imgui.h for details. - - Added 16 functions: BeginTable(), EndTable(), - TableNextRow(), TableNextColumn(), TableSetColumnIndex(), TableGetColumnIndex(), TableGetRowIndex(), + - Added 16 functions: BeginTable(), EndTable(), + TableNextRow(), TableNextColumn(), TableSetColumnIndex(), TableGetColumnIndex(), TableGetRowIndex(), TableSetupColumn(), TableSetupScrollFreeze(), TableHeadersRow(), TableHeader(), TableSetBgColor(), TableGetSortSpecs(), TableGetColumnCount(), TableGetColumnName(), TableGetColumnFlags(). @@ -95,7 +95,7 @@ Other Changes: feedback and control of keyboard/gamepad navigation highlight and mouse hover disable flag. (#787, #2048) - Metrics: Fixed mishandling of ImDrawCmd::VtxOffset in wireframe mesh renderer. - Metrics: Rebranded as "Dear ImGui Metrics/Debugger" to clarify its purpose. -- ImDrawList: Added ImDrawList::AddQuadBezierCurve(), ImDrawList::PathQuadBezierCurveTo() quadratic bezier +- ImDrawList: Added ImDrawList::AddQuadBezierCurve(), ImDrawList::PathQuadBezierCurveTo() quadratic bezier helpers. (#3127, #3664, #3665) [@aiekick] - Fonts: Updated GetGlyphRangesJapanese() to include a larger 2999 ideograms selection of Joyo/Jinmeiyo kanjis, from the previous 1946 ideograms selection. This will consume a some more memory but be generally @@ -117,7 +117,10 @@ Other Changes: - Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width. - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] +- Backends: OpenGL2: Backup and restore GL_SHADE_MODAL and disable GL_NORMAL_ARRAY state to increase compatibility + with legacy code. (#3671) - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] +- Backends: OpenGL2, OpenGL3: Backup and restore GL_STENCIL_TEST enable state. (#3668) - Backends: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation. (@3579) [@bdero] - Backends: Win32: Fix setting of io.DisplaySize to invalid/uninitialized data after hwnd has been closed. - Backends: OSX: Fix keypad-enter key not working on MacOS. (#3554) [@rokups, @lfnoise] diff --git a/examples/example_glfw_opengl2/main.cpp b/examples/example_glfw_opengl2/main.cpp index 9683a4d1f..fc25ff7f5 100644 --- a/examples/example_glfw_opengl2/main.cpp +++ b/examples/example_glfw_opengl2/main.cpp @@ -136,7 +136,7 @@ int main(int, char**) glClear(GL_COLOR_BUFFER_BIT); // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!), - // you may need to backup/reset/restore current shader using the commented lines below. + // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below. //GLint last_program; //glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); //glUseProgram(0); From 9bcf77eb814c9a0d90924a92f841e5574e03978d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 4 Jan 2021 19:12:35 +0100 Subject: [PATCH 12/13] Fixed using IsItemEdited() after Combo() not matching the return value from Combo(). (#2034) + fix some PVS warnings, fix typo, blanks. Amend e28b1078 --- backends/imgui_impl_opengl2.cpp | 2 +- backends/imgui_impl_opengl3.cpp | 8 +++++--- docs/CHANGELOG.txt | 5 +++-- imgui.h | 2 +- imgui_demo.cpp | 11 ++++++----- imgui_draw.cpp | 5 +++-- imgui_internal.h | 4 ++-- imgui_widgets.cpp | 3 +++ 8 files changed, 24 insertions(+), 16 deletions(-) diff --git a/backends/imgui_impl_opengl2.cpp b/backends/imgui_impl_opengl2.cpp index 3603a0650..cf860d7e1 100644 --- a/backends/imgui_impl_opengl2.cpp +++ b/backends/imgui_impl_opengl2.cpp @@ -18,7 +18,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODAL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. +// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications. // 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications. // 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index b1339afad..cd9e385c3 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -261,8 +261,8 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid #endif // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT) - bool clip_origin_lower_left = true; #if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) + bool clip_origin_lower_left = true; GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin); if (current_clip_origin == GL_UPPER_LEFT) clip_origin_lower_left = false; @@ -275,7 +275,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; float T = draw_data->DisplayPos.y; float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; +#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__) if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left +#endif const float ortho_projection[4][4] = { { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, @@ -286,12 +288,12 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid glUseProgram(g_ShaderHandle); glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - + #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER if (g_GlVersion >= 330) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise. #endif - + (void)vertex_array_object; #ifndef IMGUI_IMPL_OPENGL_ES2 glBindVertexArray(vertex_array_object); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6536eb9f9..7c6ccc16e 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -90,6 +90,7 @@ Other Changes: - InputText: Fixed updating cursor/selection position when a callback altered the buffer in a way where the byte count is unchanged but the decoded character count changes. (#3587) [@gqw] - InputText: Fixed swiching from single to multi-line while preserving same ID. +- Fixed using IsItemEdited() after Combo() not matching the return value from Combo(). (#2034) - Nav: Fixed IsItemFocused() from returning false when Nav highlight is hidden because mouse has moved. It's essentially been always the case but it doesn't make much sense. Instead we will aim at exposing feedback and control of keyboard/gamepad navigation highlight and mouse hover disable flag. (#787, #2048) @@ -117,8 +118,8 @@ Other Changes: - Demo: Clarify usage of right-aligned items in Demo>Layout>Widgets Width. - Backends: OpenGL3: Use glGetString(GL_VERSION) query instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x). (#3530) [@xndcn] -- Backends: OpenGL2: Backup and restore GL_SHADE_MODAL and disable GL_NORMAL_ARRAY state to increase compatibility - with legacy code. (#3671) +- Backends: OpenGL2: Backup and restore GL_SHADE_MODEL and disable GL_NORMAL_ARRAY state to increase + compatibility with legacy code. (#3671) - Backends: OpenGL3: Backup and restore GL_PRIMITIVE_RESTART state. (#3544) [@Xipiryon] - Backends: OpenGL2, OpenGL3: Backup and restore GL_STENCIL_TEST enable state. (#3668) - Backends: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation. (@3579) [@bdero] diff --git a/imgui.h b/imgui.h index 7bfa5ff48..c4459a0e9 100644 --- a/imgui.h +++ b/imgui.h @@ -1050,7 +1050,7 @@ enum ImGuiTabItemFlags_ // (this is because the visible order of columns have subtle but necessary effects on how they react to manual resizing). // - When ScrollX is on: // - Table defaults to ImGuiTableFlags_SizingPolicyFixed -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto. -// - Columns sizing policy allowed: Fixed/Auto mostly. +// - Columns sizing policy allowed: Fixed/Auto mostly. // - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. // - Using Stretch columns OFTEN DOES NOT MAKE SENSE if ScrollX is on, UNLESS you have specified a value for 'inner_width' in BeginTable(). // If you specify a value for 'inner_width' then effectively the scrolling space is known and Stretch or mixed Fixed/Stretch columns become meaningful again. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 5427dfb8c..398b75848 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1976,18 +1976,18 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } - if (ImGui::TreeNode("Querying Status (Active/Focused/Hovered etc.)")) + if (ImGui::TreeNode("Querying Status (Edited/Active/Focused/Hovered etc.)")) { // Select an item type const char* item_names[] = { "Text", "Button", "Button (w/ repeat)", "Checkbox", "SliderFloat", "InputText", "InputFloat", - "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "ListBox" + "InputFloat3", "ColorEdit4", "MenuItem", "TreeNode", "TreeNode (w/ double-click)", "Combo", "ListBox" }; static int item_type = 1; ImGui::Combo("Item Type", &item_type, item_names, IM_ARRAYSIZE(item_names), IM_ARRAYSIZE(item_names)); ImGui::SameLine(); - HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions."); + HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered()."); // Submit selected item item so we can query their status in the code following it. bool ret = false; @@ -2006,7 +2006,8 @@ static void ShowDemoWindowWidgets() if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. - if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::Combo("ITEM: Combo", ¤t, items, IM_ARRAYSIZE(items)); } + if (item_type == 13){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } // Display the values of IsItemHovered() and other common item state functions. // Note that the ImGuiHoveredFlags_XXX flags can be combined. @@ -6043,7 +6044,7 @@ struct ExampleAppConsole // Portable helpers static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; } static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; } - static char* Strdup(const char* s) { size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } + static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = malloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); } static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; } void ClearLog() diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 71b53837a..947825a9e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2170,10 +2170,11 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) if (cfg.DstFont == atlas->Fonts[output_i]) src_tmp.DstIndex = output_i; - IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? if (src_tmp.DstIndex == -1) + { + IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? return false; - + } // Initialize helper structure for font loading and verify that the TTF/OTF data is correct const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo); IM_ASSERT(font_offset >= 0 && "FontData is incorrect, or FontNo cannot be found."); diff --git a/imgui_internal.h b/imgui_internal.h index a27c82218..d1a478707 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1906,7 +1906,7 @@ typedef ImU8 ImGuiTableDrawChannelIdx; // [Internal] sizeof() ~ 104 // We use the terminology "Enabled" to refer to a column that is not Hidden by user/api. -// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping. +// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping. // This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped". struct ImGuiTableColumn { @@ -2022,7 +2022,7 @@ struct ImGuiTable float ResizeLockMinContentsX2; // Lock minimum contents width while resizing down in order to not create feedback loops. But we allow growing the table. float RefScale; // Reference scale to be able to rescale columns on font/dpi changes. ImRect OuterRect; // Note: for non-scrolling table, OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable(). - ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is + ImRect InnerRect; // InnerRect but without decoration. As with OuterRect, for non-scrolling tables, InnerRect.Max.y is ImRect WorkRect; ImRect InnerClipRect; ImRect BgClipRect; // We use this to cpu-clip cell background color fill diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index c40b7a69e..1f71fa511 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -1713,6 +1713,9 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi } EndCombo(); + if (value_changed) + MarkItemEdited(g.CurrentWindow->DC.LastItemId); + return value_changed; } From 94a432275b8ce29fa1dfb36439cfaf325e12a1ab Mon Sep 17 00:00:00 2001 From: thedmd Date: Sat, 26 May 2018 13:10:04 +0200 Subject: [PATCH 13/13] ImDrawList: Internals: Add ability to scale anti-alias fringe. This enable users to keep geometry sharp while scaling vertex buffer content. --- imgui.h | 1 + imgui_draw.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.h b/imgui.h index c4459a0e9..6fc77321d 100644 --- a/imgui.h +++ b/imgui.h @@ -2333,6 +2333,7 @@ struct ImDrawList ImVector _Path; // [Internal] current path building ImDrawCmdHeader _CmdHeader; // [Internal] template of active commands. Fields should match those of CmdBuffer.back(). ImDrawListSplitter _Splitter; // [Internal] for channels api (note: prefer using your own persistent instance of ImDrawListSplitter!) + float _FringeScale; // [Internal] anti-alias fringe is scaled by this value, this helps to keep things sharp while zooming at vertex buffer content // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) ImDrawList(const ImDrawListSharedData* shared_data) { memset(this, 0, sizeof(*this)); _Data = shared_data; } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 947825a9e..1e6a27f71 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -405,6 +405,7 @@ void ImDrawList::_ResetForNewFrame() _Path.resize(0); _Splitter.Clear(); CmdBuffer.push_back(ImDrawCmd()); + _FringeScale = 1.0f; } void ImDrawList::_ClearFreeMemory() @@ -680,12 +681,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 const ImVec2 opaque_uv = _Data->TexUvWhitePixel; const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw - const bool thick_line = (thickness > 1.0f); + const bool thick_line = (thickness > _FringeScale); if (Flags & ImDrawListFlags_AntiAliasedLines) { // Anti-aliased stroke - const float AA_SIZE = 1.0f; + const float AA_SIZE = _FringeScale; const ImU32 col_trans = col & ~IM_COL32_A_MASK; // Thicknesses <1.0 should behave like thickness 1.0 @@ -696,7 +697,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 // Do we want to draw this line using a texture? // - For now, only draw integer-width lines using textures to avoid issues with the way scaling occurs, could be improved. // - If AA_SIZE is not 1.0f we cannot use the texture path. - const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f); + const bool use_texture = (Flags & ImDrawListFlags_AntiAliasedLinesUseTex) && (integer_thickness < IM_DRAWLIST_TEX_LINES_WIDTH_MAX) && (fractional_thickness <= 0.00001f) && (AA_SIZE == 1.0f); // We should never hit this, because NewFrame() doesn't set ImDrawListFlags_AntiAliasedLinesUseTex unless ImFontAtlasFlags_NoBakedLines is off IM_ASSERT_PARANOID(!use_texture || !(_Data->Font->ContainerAtlas->Flags & ImFontAtlasFlags_NoBakedLines)); @@ -938,7 +939,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun if (Flags & ImDrawListFlags_AntiAliasedFill) { // Anti-aliased Fill - const float AA_SIZE = 1.0f; + const float AA_SIZE = _FringeScale; const ImU32 col_trans = col & ~IM_COL32_A_MASK; const int idx_count = (points_count - 2)*3 + points_count * 6; const int vtx_count = (points_count * 2);