diff --git a/3rdparty/dear-imgui/imgui.cpp b/3rdparty/dear-imgui/imgui.cpp index 6537e6cee..a6eb7fd68 100644 --- a/3rdparty/dear-imgui/imgui.cpp +++ b/3rdparty/dear-imgui/imgui.cpp @@ -5050,18 +5050,24 @@ static ImVec2 CalcWindowSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size return new_size; } -static ImVec2 CalcWindowContentSize(ImGuiWindow* window) +static void CalcWindowContentSizes(ImGuiWindow* window, ImVec2* content_size_current, ImVec2* content_size_ideal) { - if (window->Collapsed) - if (window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) - return window->ContentSize; - if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0) - return window->ContentSize; + bool preserve_old_content_sizes = false; + if (window->Collapsed && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0) + preserve_old_content_sizes = true; + else if (window->Hidden && window->HiddenFramesCannotSkipItems == 0 && window->HiddenFramesCanSkipItems > 0) + preserve_old_content_sizes = true; + if (preserve_old_content_sizes) + { + *content_size_current = window->ContentSize; + *content_size_ideal = window->ContentSizeIdeal; + return; + } - ImVec2 sz; - sz.x = IM_FLOOR((window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); - sz.y = IM_FLOOR((window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); - return sz; + content_size_current->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_FLOOR(window->DC.CursorMaxPos.x - window->DC.CursorStartPos.x); + content_size_current->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_FLOOR(window->DC.CursorMaxPos.y - window->DC.CursorStartPos.y); + content_size_ideal->x = (window->ContentSizeExplicit.x != 0.0f) ? window->ContentSizeExplicit.x : IM_FLOOR(ImMax(window->DC.CursorMaxPos.x, window->DC.IdealMaxPos.x) - window->DC.CursorStartPos.x); + content_size_ideal->y = (window->ContentSizeExplicit.y != 0.0f) ? window->ContentSizeExplicit.y : IM_FLOOR(ImMax(window->DC.CursorMaxPos.y, window->DC.IdealMaxPos.y) - window->DC.CursorStartPos.y); } static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_contents) @@ -5099,10 +5105,12 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont } } -ImVec2 ImGui::CalcWindowExpectedSize(ImGuiWindow* window) +ImVec2 ImGui::CalcWindowNextAutoFitSize(ImGuiWindow* window) { - ImVec2 size_contents = CalcWindowContentSize(window); - ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents); + ImVec2 size_contents_current; + ImVec2 size_contents_ideal; + CalcWindowContentSizes(window, &size_contents_current, &size_contents_ideal); + ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, size_contents_ideal); ImVec2 size_final = CalcWindowSizeAfterConstraint(window, size_auto_fit); return size_final; } @@ -5699,7 +5707,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS // Update contents size from last frame for auto-fitting (or use explicit size) - window->ContentSize = CalcWindowContentSize(window); + CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSizeIdeal); if (window->HiddenFramesCanSkipItems > 0) window->HiddenFramesCanSkipItems--; if (window->HiddenFramesCannotSkipItems > 0) @@ -5722,7 +5730,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->Size.x = window->SizeFull.x = 0.f; if (!window_size_y_set_by_api) window->Size.y = window->SizeFull.y = 0.f; - window->ContentSize = ImVec2(0.f, 0.f); + window->ContentSize = window->ContentSizeIdeal = ImVec2(0.f, 0.f); } } @@ -5768,7 +5776,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // SIZE // Calculate auto-fit size, handle automatic resize - const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSize); + const ImVec2 size_auto_fit = CalcWindowAutoFitSize(window, window->ContentSizeIdeal); bool use_current_size_for_scrollbar_x = window_just_created; bool use_current_size_for_scrollbar_y = window_just_created; if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) @@ -6055,6 +6063,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.CursorPos = window->DC.CursorStartPos; window->DC.CursorPosPrevLine = window->DC.CursorPos; window->DC.CursorMaxPos = window->DC.CursorStartPos; + window->DC.IdealMaxPos = window->DC.CursorStartPos; window->DC.CurrLineSize = window->DC.PrevLineSize = ImVec2(0.0f, 0.0f); window->DC.CurrLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; @@ -6103,7 +6112,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. // Maybe we can support CTRL+C on every element? /* - if (g.ActiveId == move_id) + //if (g.NavWindow == window && g.ActiveId == 0) + if (g.ActiveId == window->MoveId) if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) LogToClipboard(); */ @@ -6699,7 +6709,7 @@ void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasContentSize; - g.NextWindowData.ContentSizeVal = size; + g.NextWindowData.ContentSizeVal = ImFloor(size); } void ImGui::SetNextWindowScroll(const ImVec2& scroll) @@ -10545,10 +10555,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) Separator(); // Debugging enums - enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type - const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentRegionRect" }; - enum { TRT_OuterRect, TRT_InnerRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentFrozen, TRT_ColumnsContentUnfrozen, TRT_Count }; // Tables Rect Type - const char* trt_rects_names[TRT_Count] = { "OuterRect", "InnerRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentFrozen", "ColumnsContentUnfrozen" }; + enum { WRT_OuterRect, WRT_OuterRectClipped, WRT_InnerRect, WRT_InnerClipRect, WRT_WorkRect, WRT_Content, WRT_ContentIdeal, WRT_ContentRegionRect, WRT_Count }; // Windows Rect Type + const char* wrt_rects_names[WRT_Count] = { "OuterRect", "OuterRectClipped", "InnerRect", "InnerClipRect", "WorkRect", "Content", "ContentIdeal", "ContentRegionRect" }; + enum { TRT_OuterRect, TRT_InnerRect, TRT_WorkRect, TRT_HostClipRect, TRT_InnerClipRect, TRT_BackgroundClipRect, TRT_ColumnsRect, TRT_ColumnsWorkRect, TRT_ColumnsClipRect, TRT_ColumnsContentHeadersUsed, TRT_ColumnsContentHeadersIdeal, TRT_ColumnsContentFrozen, TRT_ColumnsContentUnfrozen, TRT_Count }; // Tables Rect Type + const char* trt_rects_names[TRT_Count] = { "OuterRect", "InnerRect", "WorkRect", "HostClipRect", "InnerClipRect", "BackgroundClipRect", "ColumnsRect", "ColumnsWorkRect", "ColumnsClipRect", "ColumnsContentHeadersUsed", "ColumnsContentHeadersIdeal", "ColumnsContentFrozen", "ColumnsContentUnfrozen" }; if (cfg->ShowWindowsRectsType < 0) cfg->ShowWindowsRectsType = WRT_WorkRect; if (cfg->ShowTablesRectsType < 0) @@ -10565,6 +10575,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; } else if (rect_type == TRT_BackgroundClipRect) { return table->BgClipRect; } else if (rect_type == TRT_ColumnsRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MaxX, table->InnerClipRect.Min.y + table->LastOuterHeight); } + else if (rect_type == TRT_ColumnsWorkRect) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->WorkRect.Min.y, c->WorkMaxX, table->WorkRect.Max.y); } else if (rect_type == TRT_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; } else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate else if (rect_type == TRT_ColumnsContentHeadersIdeal){ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->WorkMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersIdeal, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } @@ -10581,7 +10592,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) else if (rect_type == WRT_InnerRect) { return window->InnerRect; } else if (rect_type == WRT_InnerClipRect) { return window->InnerClipRect; } else if (rect_type == WRT_WorkRect) { return window->WorkRect; } - else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } + else if (rect_type == WRT_Content) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSize); } + else if (rect_type == WRT_ContentIdeal) { ImVec2 min = window->InnerRect.Min - window->Scroll + window->WindowPadding; return ImRect(min, min + window->ContentSizeIdeal); } else if (rect_type == WRT_ContentRegionRect) { return window->ContentRegionRect; } IM_ASSERT(0); return ImRect(); @@ -11069,7 +11081,7 @@ void ImGui::DebugNodeWindow(ImGuiWindow* window, const char* label) ImGuiWindowFlags flags = window->Flags; DebugNodeDrawList(window, window->DrawList, "DrawList"); - BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y); + BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), ContentSize (%.1f,%.1f) Ideal (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->ContentSize.x, window->ContentSize.y, window->ContentSizeIdeal.x, window->ContentSizeIdeal.y); BulletText("Flags: 0x%08X (%s%s%s%s%s%s%s%s%s..)", flags, (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : "", diff --git a/3rdparty/dear-imgui/imgui.h b/3rdparty/dear-imgui/imgui.h index db3d1fd64..0e3e9bc91 100644 --- a/3rdparty/dear-imgui/imgui.h +++ b/3rdparty/dear-imgui/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 17909 +#define IMGUI_VERSION_NUM 17912 #define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx)) #define IMGUI_HAS_TABLE @@ -80,7 +80,7 @@ Index of this file: #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR) / sizeof(*(_ARR)))) // Size of a static C-style array. Don't use on pointers! #define IM_UNUSED(_VAR) ((void)(_VAR)) // Used to silence "unused variable warnings". Often useful as asserts may be stripped out from final builds. -#if (__cplusplus >= 201100) +#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100) #define IM_OFFSETOF(_TYPE,_MEMBER) offsetof(_TYPE, _MEMBER) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in C++11 #else #define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Old style macro. @@ -568,7 +568,7 @@ namespace ImGui IMGUI_API void TreePop(); // ~ Unindent()+PopId() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). - IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header + IMGUI_API bool CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags = 0); // when 'p_visible != NULL': if '*p_visible==true' display an additional small close button on upper right of the header which will set the bool to false when clicked, if '*p_visible==false' don't display the header. IMGUI_API void SetNextItemOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. // Widgets: Selectables @@ -656,9 +656,10 @@ namespace ImGui IMGUI_API bool IsPopupOpen(const char* str_id, ImGuiPopupFlags flags = 0); // return true if the popup is open. // Tables - // [BETA API] API may evolve! + // [BETA API] API may evolve slightly! If you use this, please update to the next version when it comes out! // - Full-featured replacement for old Columns API. - // - See Demo->Tables for details. + // - See Demo->Tables for demo code. + // - See top of imgui_tables.cpp for general commentary. // - See ImGuiTableFlags_ and ImGuiTableColumnFlags_ enums for a description of available flags. // The typical call flow is: // - 1. Call BeginTable() @@ -671,25 +672,19 @@ namespace ImGui // you may prefer using TableNextColumn() instead of TableNextRow() + TableSetColumnIndex(). // TableNextColumn() will automatically wrap-around into the next row if needed. // - IMPORTANT: Comparatively to the old Columns() API, we need to call TableNextColumn() for the first column! - // - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing - // width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know - // it is not going to contribute to row height. - // In many situations, you may skip submitting contents for every columns but one (e.g. the first one). // - Summary of possible call flow: - // ---------------------------------------------------------------------------------------------------------- - // TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK - // TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK - // TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! - // TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! - // ---------------------------------------------------------------------------------------------------------- + // -------------------------------------------------------------------------------------------------------- + // TableNextRow() -> TableSetColumnIndex(0) -> Text("Hello 0") -> TableSetColumnIndex(1) -> Text("Hello 1") // OK + // TableNextRow() -> TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK + // TableNextColumn() -> Text("Hello 0") -> TableNextColumn() -> Text("Hello 1") // OK: TableNextColumn() automatically gets to next row! + // TableNextRow() -> Text("Hello 0") // Not OK! Missing TableSetColumnIndex() or TableNextColumn()! Text will not appear! + // -------------------------------------------------------------------------------------------------------- // - 5. Call EndTable() IMGUI_API bool BeginTable(const char* str_id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(-FLT_MIN, 0), float inner_width = 0.0f); IMGUI_API void EndTable(); // only call EndTable() if BeginTable() returns true! IMGUI_API void TableNextRow(ImGuiTableRowFlags row_flags = 0, float min_row_height = 0.0f); // append into the first cell of a new row. IMGUI_API bool TableNextColumn(); // append into the next column (or first column of next row if currently in last column). Return true when column is visible. IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible. - IMGUI_API int TableGetColumnIndex(); // return current column index. - IMGUI_API int TableGetRowIndex(); // return current row index. // Tables: Headers & Columns declaration // - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc. // Important: this will not display anything! The name passed to TableSetupColumn() is used by TableHeadersRow() and context-menus. @@ -697,7 +692,7 @@ namespace ImGui // Headers are required to perform: reordering, sorting, and opening the context menu (but context menu can also be available in columns body using ImGuiTableFlags_ContextMenuInBody). // - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in some advanced cases (e.g. adding custom widgets in header row). // - Use TableSetupScrollFreeze() to lock columns (from the right) or rows (from the top) so they stay visible when scrolled. - IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = -1.0f, ImU32 user_id = 0); + IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImU32 user_id = 0); IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled. IMGUI_API void TableHeadersRow(); // submit all headers cells based on data provided to TableSetupColumn() + submit context menu IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used) @@ -708,10 +703,12 @@ namespace ImGui // Make sure to set 'SpecsDirty = false' after sorting, else you may wastefully sort your data every frame! // Lifetime: don't hold on this pointer over multiple frames or past any subsequent call to BeginTable(). IMGUI_API int TableGetColumnCount(); // return number of columns (value passed to BeginTable) + IMGUI_API int TableGetColumnIndex(); // return current column index. + IMGUI_API int TableGetRowIndex(); // return current row index. IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column. - IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. + IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column. IMGUI_API ImGuiTableSortSpecs* TableGetSortSpecs(); // get latest sort specs for the table (NULL if not sorting). - IMGUI_API void TableSetBgColor(ImGuiTableBgTarget bg_target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details. + IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details. // Legacy Columns API (2020: prefer using Tables!) // - You can also use SameLine(pos_x) to mimic simplified columns. @@ -1035,6 +1032,7 @@ enum ImGuiTabItemFlags_ }; // Flags for ImGui::BeginTable() +// [BETA API] API may evolve slightly! If you use this, please update to the next version when it comes out! // - 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 policies are: @@ -1049,7 +1047,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_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed or ImGuiTableColumnFlags_WidthAuto. +// - Table defaults to ImGuiTableFlags_SizingFixedFit -> all Columns defaults to ImGuiTableColumnFlags_WidthFixed // - Columns sizing policy allowed: Fixed/Auto mostly. // - Fixed Columns can be enlarged as needed. Table will show an horizontal scrollbar if needed. // - When using auto-resizing (non-resizable) fixed columns, querying the content width to use item right-alignment e.g. SetNextItemWidth(-FLT_MIN) doesn't make sense, would create a feedback loop. @@ -1091,7 +1089,7 @@ enum ImGuiTableFlags_ // Clipping ImGuiTableFlags_NoClip = 1 << 19, // Disable clipping rectangle for every individual columns (reduce draw command count, items will be able to overflow into other columns). Generally incompatible with TableSetupScrollFreeze(). // Padding - ImGuiTableFlags_PadOuterX = 1 << 20, // Default if BordersOuterV is on. Enable outer-most padding. + ImGuiTableFlags_PadOuterX = 1 << 20, // Default if BordersOuterV is on. Enable outer-most padding. Generally desirable if you have headers. ImGuiTableFlags_NoPadOuterX = 1 << 21, // Default if BordersOuterV is off. Disable outer-most padding. ImGuiTableFlags_NoPadInnerX = 1 << 22, // Disable inner padding between columns (double inner padding if BordersOuterV is on, single inner padding if BordersOuterV is off). // Scrolling @@ -1106,8 +1104,8 @@ enum ImGuiTableFlags_ // Obsolete names (will be removed soon) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiTableFlags_ColumnsWidthFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_ColumnsWidthStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2020/12 - , ImGuiTableFlags_SizingPolicyFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingPolicyStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2021/01 + //, ImGuiTableFlags_ColumnsWidthFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_ColumnsWidthStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2020/12 + //, ImGuiTableFlags_SizingPolicyFixed = ImGuiTableFlags_SizingFixedFit, ImGuiTableFlags_SizingPolicyStretch = ImGuiTableFlags_SizingStretchSame // WIP Tables 2021/01 #endif }; @@ -1120,7 +1118,6 @@ 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 _SizingStretchSame or _SizingStretchProp). ImGuiTableColumnFlags_WidthFixed = 1 << 3, // Column will not stretch. Preferable with horizontal scrolling enabled (default if table sizing policy is _SizingFixedFit 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 _SizingFixedFit and table is not resizable, or policy is _SizingFixedSame). 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. @@ -1141,10 +1138,15 @@ enum ImGuiTableColumnFlags_ ImGuiTableColumnFlags_IsHovered = 1 << 23, // Status: is hovered by mouse // [Internal] Combinations and masks - ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto, + ImGuiTableColumnFlags_WidthMask_ = ImGuiTableColumnFlags_WidthStretch | ImGuiTableColumnFlags_WidthFixed, 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) + + // Obsolete names (will be removed soon) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + //ImGuiTableColumnFlags_WidthAuto = ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoResize, // Column will not stretch and keep resizing based on submitted contents. +#endif }; // Flags for ImGui::TableNextRow() diff --git a/3rdparty/dear-imgui/imgui_demo.cpp b/3rdparty/dear-imgui/imgui_demo.cpp index ff9050159..13b5931e5 100644 --- a/3rdparty/dear-imgui/imgui_demo.cpp +++ b/3rdparty/dear-imgui/imgui_demo.cpp @@ -1352,9 +1352,149 @@ static void ShowDemoWindowWidgets() ImGui::TreePop(); } - // Plot/Graph widgets are currently fairly limited. - // Consider writing your own plotting widget, or using a third-party one - // (for third-party Plot widgets, see 'Wiki->Useful Widgets' or https://github.com/ocornut/imgui/labels/plot%2Fgraph) + // Tabs + if (ImGui::TreeNode("Tabs")) + { + if (ImGui::TreeNode("Basic")) + { + ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None; + if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) + { + if (ImGui::BeginTabItem("Avocado")) + { + ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Broccoli")) + { + ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + if (ImGui::BeginTabItem("Cucumber")) + { + ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah"); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::Separator(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("Advanced & Close Button")) + { + // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0). + static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable; + ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable); + ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs); + ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); + ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton); + if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) + tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_; + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); + + // Tab Bar + const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" }; + static bool opened[4] = { true, true, true, true }; // Persistent user state + for (int n = 0; n < IM_ARRAYSIZE(opened); n++) + { + if (n > 0) { ImGui::SameLine(); } + ImGui::Checkbox(names[n], &opened[n]); + } + + // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): + // the underlying bool will be set to false when the tab is closed. + if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) + { + for (int n = 0; n < IM_ARRAYSIZE(opened); n++) + if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None)) + { + ImGui::Text("This is the %s tab!", names[n]); + if (n & 1) + ImGui::Text("I am an odd tab."); + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + ImGui::Separator(); + ImGui::TreePop(); + } + + if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags")) + { + static ImVector active_tabs; + static int next_tab_id = 0; + if (next_tab_id == 0) // Initialize with some default tabs + for (int i = 0; i < 3; i++) + active_tabs.push_back(next_tab_id++); + + // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together. + // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags... + // but they tend to make more sense together) + static bool show_leading_button = true; + static bool show_trailing_button = true; + ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button); + ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button); + + // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs + static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown; + ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); + if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) + tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); + + if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) + { + // Demo a Leading TabItemButton(): click the "?" button to open a menu + if (show_leading_button) + if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip)) + ImGui::OpenPopup("MyHelpMenu"); + if (ImGui::BeginPopup("MyHelpMenu")) + { + ImGui::Selectable("Hello!"); + ImGui::EndPopup(); + } + + // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+") + // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end. + if (show_trailing_button) + if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) + active_tabs.push_back(next_tab_id++); // Add new tab + + // Submit our regular tabs + for (int n = 0; n < active_tabs.Size; ) + { + bool open = true; + char name[16]; + snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]); + if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None)) + { + ImGui::Text("This is the %s tab!", name); + ImGui::EndTabItem(); + } + + if (!open) + active_tabs.erase(active_tabs.Data + n); + else + n++; + } + + ImGui::EndTabBar(); + } + ImGui::Separator(); + ImGui::TreePop(); + } + ImGui::TreePop(); + } + + // Plot/Graph widgets are not very good. + // Consider writing your own, or using a third-party one, see: + // - ImPlot https://github.com/epezent/implot + // - others https://github.com/ocornut/imgui/wiki/Useful-Widgets if (ImGui::TreeNode("Plots Widgets")) { static bool animate = true; @@ -2378,144 +2518,6 @@ static void ShowDemoWindowLayout() ImGui::TreePop(); } - if (ImGui::TreeNode("Tabs")) - { - if (ImGui::TreeNode("Basic")) - { - ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_None; - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - if (ImGui::BeginTabItem("Avocado")) - { - ImGui::Text("This is the Avocado tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Broccoli")) - { - ImGui::Text("This is the Broccoli tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - if (ImGui::BeginTabItem("Cucumber")) - { - ImGui::Text("This is the Cucumber tab!\nblah blah blah blah blah"); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("Advanced & Close Button")) - { - // Expose a couple of the available flags. In most cases you may just call BeginTabBar() with no flags (0). - static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_Reorderable; - ImGui::CheckboxFlags("ImGuiTabBarFlags_Reorderable", &tab_bar_flags, ImGuiTabBarFlags_Reorderable); - ImGui::CheckboxFlags("ImGuiTabBarFlags_AutoSelectNewTabs", &tab_bar_flags, ImGuiTabBarFlags_AutoSelectNewTabs); - ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); - ImGui::CheckboxFlags("ImGuiTabBarFlags_NoCloseWithMiddleMouseButton", &tab_bar_flags, ImGuiTabBarFlags_NoCloseWithMiddleMouseButton); - if ((tab_bar_flags & ImGuiTabBarFlags_FittingPolicyMask_) == 0) - tab_bar_flags |= ImGuiTabBarFlags_FittingPolicyDefault_; - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); - - // Tab Bar - const char* names[4] = { "Artichoke", "Beetroot", "Celery", "Daikon" }; - static bool opened[4] = { true, true, true, true }; // Persistent user state - for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - { - if (n > 0) { ImGui::SameLine(); } - ImGui::Checkbox(names[n], &opened[n]); - } - - // Passing a bool* to BeginTabItem() is similar to passing one to Begin(): - // the underlying bool will be set to false when the tab is closed. - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - for (int n = 0; n < IM_ARRAYSIZE(opened); n++) - if (opened[n] && ImGui::BeginTabItem(names[n], &opened[n], ImGuiTabItemFlags_None)) - { - ImGui::Text("This is the %s tab!", names[n]); - if (n & 1) - ImGui::Text("I am an odd tab."); - ImGui::EndTabItem(); - } - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - - if (ImGui::TreeNode("TabItemButton & Leading/Trailing flags")) - { - static ImVector active_tabs; - static int next_tab_id = 0; - if (next_tab_id == 0) // Initialize with some default tabs - for (int i = 0; i < 3; i++) - active_tabs.push_back(next_tab_id++); - - // TabItemButton() and Leading/Trailing flags are distinct features which we will demo together. - // (It is possible to submit regular tabs with Leading/Trailing flags, or TabItemButton tabs without Leading/Trailing flags... - // but they tend to make more sense together) - static bool show_leading_button = true; - static bool show_trailing_button = true; - ImGui::Checkbox("Show Leading TabItemButton()", &show_leading_button); - ImGui::Checkbox("Show Trailing TabItemButton()", &show_trailing_button); - - // Expose some other flags which are useful to showcase how they interact with Leading/Trailing tabs - static ImGuiTabBarFlags tab_bar_flags = ImGuiTabBarFlags_AutoSelectNewTabs | ImGuiTabBarFlags_Reorderable | ImGuiTabBarFlags_FittingPolicyResizeDown; - ImGui::CheckboxFlags("ImGuiTabBarFlags_TabListPopupButton", &tab_bar_flags, ImGuiTabBarFlags_TabListPopupButton); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyResizeDown", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyResizeDown)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyResizeDown); - if (ImGui::CheckboxFlags("ImGuiTabBarFlags_FittingPolicyScroll", &tab_bar_flags, ImGuiTabBarFlags_FittingPolicyScroll)) - tab_bar_flags &= ~(ImGuiTabBarFlags_FittingPolicyMask_ ^ ImGuiTabBarFlags_FittingPolicyScroll); - - if (ImGui::BeginTabBar("MyTabBar", tab_bar_flags)) - { - // Demo a Leading TabItemButton(): click the "?" button to open a menu - if (show_leading_button) - if (ImGui::TabItemButton("?", ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_NoTooltip)) - ImGui::OpenPopup("MyHelpMenu"); - if (ImGui::BeginPopup("MyHelpMenu")) - { - ImGui::Selectable("Hello!"); - ImGui::EndPopup(); - } - - // Demo Trailing Tabs: click the "+" button to add a new tab (in your app you may want to use a font icon instead of the "+") - // Note that we submit it before the regular tabs, but because of the ImGuiTabItemFlags_Trailing flag it will always appear at the end. - if (show_trailing_button) - if (ImGui::TabItemButton("+", ImGuiTabItemFlags_Trailing | ImGuiTabItemFlags_NoTooltip)) - active_tabs.push_back(next_tab_id++); // Add new tab - - // Submit our regular tabs - for (int n = 0; n < active_tabs.Size; ) - { - bool open = true; - char name[16]; - snprintf(name, IM_ARRAYSIZE(name), "%04d", active_tabs[n]); - if (ImGui::BeginTabItem(name, &open, ImGuiTabItemFlags_None)) - { - ImGui::Text("This is the %s tab!", name); - ImGui::EndTabItem(); - } - - if (!open) - active_tabs.erase(active_tabs.Data + n); - else - n++; - } - - ImGui::EndTabBar(); - } - ImGui::Separator(); - ImGui::TreePop(); - } - ImGui::TreePop(); - } - if (ImGui::TreeNode("Groups")) { HelpMarker( @@ -3401,8 +3403,6 @@ 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("_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); @@ -4182,16 +4182,44 @@ static void ShowDemoWindowTables() ImGui::SetNextItemOpen(open_action != 0); if (ImGui::TreeNode("Columns widths")) { - HelpMarker("Using TableSetupColumn() to setup explicit width."); + HelpMarker("Using TableSetupColumn() to setup default width."); - static ImGuiTableFlags flags = ImGuiTableFlags_None; + static ImGuiTableFlags flags1 = ImGuiTableFlags_Borders | ImGuiTableFlags_NoBordersInBodyUntilResize; PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags, ImGuiTableFlags_NoKeepColumnsVisible); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags, ImGuiTableFlags_BordersInnerV); - ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags, ImGuiTableFlags_BordersOuterV); + ImGui::CheckboxFlags("ImGuiTableFlags_Resizable", &flags1, ImGuiTableFlags_Resizable); + ImGui::CheckboxFlags("ImGuiTableFlags_NoBordersInBodyUntilResize", &flags1, ImGuiTableFlags_NoBordersInBodyUntilResize); PopStyleCompact(); + if (ImGui::BeginTable("##table1", 3, flags1)) + { + // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. + ImGui::TableSetupColumn("one", ImGuiTableColumnFlags_WidthFixed, 100.0f); // Default to 100.0f + ImGui::TableSetupColumn("two", ImGuiTableColumnFlags_WidthFixed, 200.0f); // Default to 200.0f + ImGui::TableSetupColumn("three", ImGuiTableColumnFlags_WidthFixed); // Default to auto + ImGui::TableHeadersRow(); + for (int row = 0; row < 4; row++) + { + ImGui::TableNextRow(); + for (int column = 0; column < 3; column++) + { + ImGui::TableSetColumnIndex(column); + if (row == 0) + ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x); + else + ImGui::Text("Hello %d,%d", column, row); + } + } + ImGui::EndTable(); + } - if (ImGui::BeginTable("##table1", 4, flags)) + HelpMarker("Using TableSetupColumn() to setup explicit width.\n\nUnless _NoKeepColumnsVisible is set, fixed columns with set width may still be shrunk down if there's not enough space in the host."); + + static ImGuiTableFlags flags2 = ImGuiTableFlags_None; + PushStyleCompact(); + ImGui::CheckboxFlags("ImGuiTableFlags_NoKeepColumnsVisible", &flags2, ImGuiTableFlags_NoKeepColumnsVisible); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersInnerV", &flags2, ImGuiTableFlags_BordersInnerV); + ImGui::CheckboxFlags("ImGuiTableFlags_BordersOuterV", &flags2, ImGuiTableFlags_BordersOuterV); + PopStyleCompact(); + if (ImGui::BeginTable("##table2", 4, flags2)) { // We could also set ImGuiTableFlags_SizingFixedFit on the table and all columns will default to ImGuiTableColumnFlags_WidthFixed. ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 100.0f); @@ -4205,8 +4233,9 @@ static void ShowDemoWindowTables() { ImGui::TableSetColumnIndex(column); if (row == 0) - ImGui::Text("(%.2f)", ImGui::GetContentRegionAvail().x); - ImGui::Text("Hello %d,%d", column, row); + ImGui::Text("(w: %5.1f)", ImGui::GetContentRegionAvail().x); + else + ImGui::Text("Hello %d,%d", column, row); } } ImGui::EndTable(); @@ -4571,7 +4600,7 @@ static void ShowDemoWindowTables() static ImGuiTableFlags flags1 = ImGuiTableFlags_Resizable | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable | ImGuiTableFlags_Borders | ImGuiTableFlags_ContextMenuInBody; PushStyleCompact(); - ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", (unsigned int*)&flags1, ImGuiTableFlags_ContextMenuInBody); + ImGui::CheckboxFlags("ImGuiTableFlags_ContextMenuInBody", &flags1, ImGuiTableFlags_ContextMenuInBody); PopStyleCompact(); // Context Menus: first example @@ -4744,10 +4773,10 @@ static void ShowDemoWindowTables() // - ImGuiTableColumnFlags_DefaultSort // - ImGuiTableColumnFlags_NoSort / ImGuiTableColumnFlags_NoSortAscending / ImGuiTableColumnFlags_NoSortDescending // - ImGuiTableColumnFlags_PreferSortAscending / ImGuiTableColumnFlags_PreferSortDescending - ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed, -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 | ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Quantity); + ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_ID); + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name); + ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action); + ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending | ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Quantity); ImGui::TableSetupScrollFreeze(0, 1); // Make row always visible ImGui::TableHeadersRow(); @@ -4950,11 +4979,11 @@ static void ShowDemoWindowTables() // Declare columns // We use the "user_id" parameter of TableSetupColumn() to specify a user id that will be stored in the sort specifications. // This is so our sort function can identify a column given our own identifier. We could also identify them based on their index! - ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, -1.0f, MyItemColumnID_ID); - ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Name); - ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, -1.0f, MyItemColumnID_Action); - ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, -1.0f, MyItemColumnID_Quantity); - ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch, -1.0f, MyItemColumnID_Description); + ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_DefaultSort | ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_NoHide, 0.0f, MyItemColumnID_ID); + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Name); + ImGui::TableSetupColumn("Action", ImGuiTableColumnFlags_NoSort | ImGuiTableColumnFlags_WidthFixed, 0.0f, MyItemColumnID_Action); + ImGui::TableSetupColumn("Quantity", ImGuiTableColumnFlags_PreferSortDescending, 0.0f, MyItemColumnID_Quantity); + ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthStretch, 0.0f, MyItemColumnID_Description); ImGui::TableSetupColumn("Hidden", ImGuiTableColumnFlags_DefaultHide | ImGuiTableColumnFlags_NoSort); ImGui::TableSetupScrollFreeze(freeze_cols, freeze_rows); @@ -5552,6 +5581,9 @@ void ImGui::ShowAboutWindow(bool* p_open) #ifdef _MSC_VER ImGui::Text("define: _MSC_VER=%d", _MSC_VER); #endif +#ifdef _MSVC_LANG + ImGui::Text("define: _MSVC_LANG=%d", (int)_MSVC_LANG); +#endif #ifdef __MINGW32__ ImGui::Text("define: __MINGW32__"); #endif diff --git a/3rdparty/dear-imgui/imgui_internal.h b/3rdparty/dear-imgui/imgui_internal.h index 29559a64c..fe804fa37 100644 --- a/3rdparty/dear-imgui/imgui_internal.h +++ b/3rdparty/dear-imgui/imgui_internal.h @@ -178,7 +178,7 @@ namespace ImStb #define IMGUI_DEBUG_LOG_NAV(...) ((void)0) // Disable log // Static Asserts -#if (__cplusplus >= 201100) +#if (__cplusplus >= 201100) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201100) #define IM_STATIC_ASSERT(_COND) static_assert(_COND, "") #else #define IM_STATIC_ASSERT(_COND) typedef char static_assertion_##__line__[(_COND)?1:-1] @@ -1637,7 +1637,8 @@ struct IMGUI_API ImGuiWindowTempData ImVec2 CursorPos; // Current emitting position, in absolute coordinates. ImVec2 CursorPosPrevLine; ImVec2 CursorStartPos; // Initial position after Begin(), generally ~ window position + WindowPadding. - ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Used to calculate window->ContentSize at the beginning of next frame + ImVec2 CursorMaxPos; // Used to implicitly calculate ContentSize at the beginning of next frame. Always growing during the frame. + ImVec2 IdealMaxPos; // Used to implicitly calculate ContentSizeIdeal. ImVec2 CurrLineSize; ImVec2 PrevLineSize; float CurrLineTextBaseOffset; // Baseline offset (0.0f by default on a new line, generally == style.FramePadding.y when a framed item has been added). @@ -1695,6 +1696,7 @@ struct IMGUI_API ImGuiWindow ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 SizeFull; // Size when non collapsed ImVec2 ContentSize; // Size of contents/scrollable client area (calculated from the extents reach of the cursor) from previous frame. Does not include window decoration or window padding. + ImVec2 ContentSizeIdeal; ImVec2 ContentSizeExplicit; // Size of contents/scrollable client area explicitly request by the user via SetNextWindowContentSize(). ImVec2 WindowPadding; // Window padding at the time of Begin(). float WindowRounding; // Window rounding at the time of Begin(). May be clamped lower to avoid rendering artifacts with title bar, menu bar etc. @@ -2081,7 +2083,7 @@ struct ImGuiTable bool IsResetAllRequest; bool IsResetDisplayOrderRequest; 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 IsOuterRectMinFitX; // Set when outer_size.x == 0.0f in BeginTable(), scrolling is disabled, and there are no 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 @@ -2146,7 +2148,7 @@ namespace ImGui IMGUI_API ImGuiWindow* FindWindowByID(ImGuiID id); IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window); - IMGUI_API ImVec2 CalcWindowExpectedSize(ImGuiWindow* window); + IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below); IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); diff --git a/3rdparty/dear-imgui/imgui_tables.cpp b/3rdparty/dear-imgui/imgui_tables.cpp index a574e8c70..d00c609b5 100644 --- a/3rdparty/dear-imgui/imgui_tables.cpp +++ b/3rdparty/dear-imgui/imgui_tables.cpp @@ -80,13 +80,15 @@ Index of this file: // - outer_size.x = 0.0f -> Auto width. Generally use all available width. When NOT using scrolling and NOT using any Stretch column, use only necessary width, otherwise same as -FLT_MIN. // - outer_size.x > 0.0f -> Fixed width. // Y with ScrollX/ScrollY disabled: we output table directly in current window -// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless NoHostExtendV is set) -// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless NoHostExtendV is set) -// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless NoHostExtendV is set) +// - outer_size.y < 0.0f -> Bottom-align (but will auto extend, unless _NoHostExtendY is set). Not meaningful is parent window can vertically scroll. +// - outer_size.y = 0.0f -> No minimum height (but will auto extend, unless _NoHostExtendY is set) +// - outer_size.y > 0.0f -> Set Minimum height (but will auto extend, unless _NoHostExtenY is set) // Y with ScrollX/ScrollY enabled: using a child window for scrolling -// - outer_size.y < 0.0f -> Bottom-align +// - outer_size.y < 0.0f -> Bottom-align. Not meaningful is parent window can vertically scroll. // - outer_size.y = 0.0f -> Bottom-align, consistent with BeginChild(). Not recommended unless table is last item in parent window. // - outer_size.y > 0.0f -> Set Exact height. Recommended when using Scrolling on any axis. +// In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height. +// This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not easily noticeable) //----------------------------------------------------------------------------- // About 'inner_width': // With ScrollX disabled: @@ -108,7 +110,6 @@ Index of this file: //----------------------------------------------------------------------------- // About overriding column sizing policy and 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 @@ -117,11 +118,11 @@ Index of this file: // and you can fit a 100.0f wide item in it without clipping and with full padding. //----------------------------------------------------------------------------- // About default sizing policy (if you don't specify a ImGuiTableColumnFlags_WidthXXXX flag) -// - with Table policy ImGuiTableFlags_SizingFixedFit && (Resizable == 1 || init_width > 0) --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width -// - with Table policy ImGuiTableFlags_SizingFixedFit && (Resizable == 0 && init_width <= 0) --> default Column policy is ImGuiTableColumnFlags_WidthAuto, Width always equal to contents width -// - with Table policy ImGuiTableFlags_SizingFixedSame --> default Column policy is ImGuiTableColumnFlags_WidthAuto, default Width is max of all contents width -// - with Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is 1.0f -// - with Table policy ImGuiTableFlags_SizingStretchWeight --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is proportional to contents +// - with Table policy ImGuiTableFlags_SizingFixedFit --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is equal to contents width +// - with Table policy ImGuiTableFlags_SizingFixedSame --> default Column policy is ImGuiTableColumnFlags_WidthFixed, default Width is max of all contents width +// - with Table policy ImGuiTableFlags_SizingStretchSame --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is 1.0f +// - with Table policy ImGuiTableFlags_SizingStretchWeight --> default Column policy is ImGuiTableColumnFlags_WidthStretch, default Weight is proportional to contents +// Default Width and default Weight can be overriden when calling TableSetupColumn(). //----------------------------------------------------------------------------- // About mixing Fixed/Auto and Stretch columns together: // - the typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns. @@ -130,6 +131,16 @@ Index of this file: // - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the maximum contents width. // - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths. //----------------------------------------------------------------------------- +// About using column width: +// If a column is manual resizable or has a width specified with TableSetupColumn(): +// - you may use GetContentRegionAvail().x to query the width available in a given column. +// - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width. +// If the column is not resizable and has no width specified with TableSetupColumn(): +// - its width will be automatic and be the set to the max of items submitted. +// - therefore you generally cannot have ALL items of the columns use e.g. SetNextItemWidth(-FLT_MIN). +// - but if the column has one or more item of known/fixed size, this will become the reference width used by SetNextItemWidth(-FLT_MIN). +//----------------------------------------------------------------------------- + //----------------------------------------------------------------------------- // TABLES CLIPPING/CULLING @@ -138,11 +149,15 @@ Index of this file: // - 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. +// - Note that auto-resizing columns don't play well with using the clipper. +// By default a table with _ScrollX but without _Resizable will have column auto-resize. +// So, if you want to use the clipper, make sure to either enable _Resizable, either setup columns width explicitly with _WidthFixed. //----------------------------------------------------------------------------- // About clipping/culling of Columns in Tables: +// - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing +// width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know +// it is not going to contribute to row height. +// In many situations, you may skip submitting contents for every columns but one (e.g. the first one). // - Case A: column is not hidden by user, and at least partially in sight (most common case). // - Case B: column is clipped / out of sight (because of scrolling or parent ClipRect): TableNextColumn() return false as a hint but we still allow layout output. // - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.). @@ -320,7 +335,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG table->ColumnsCount = columns_count; table->IsLayoutLocked = false; table->InnerWidth = inner_width; - table->IsOuterRectAutoFitX = (outer_size.x == 0.0f) && (use_child_window == false); + table->IsOuterRectMinFitX = (outer_size.x == 0.0f) && (use_child_window == false); // Will be set to false later if there are any Stretch column. // When not using a child window, WorkRect.Max will grow as we append contents. if (use_child_window) @@ -601,10 +616,9 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I // Sizing Policy if ((flags & ImGuiTableColumnFlags_WidthMask_) == 0) { - // FIXME-TABLE: clarify promotion to WidthAuto? const ImGuiTableFlags table_sizing_policy = (table->Flags & ImGuiTableFlags_SizingMask_); if (table_sizing_policy == ImGuiTableFlags_SizingFixedFit || table_sizing_policy == ImGuiTableFlags_SizingFixedSame) - flags |= ((table->Flags & ImGuiTableFlags_Resizable) && !(flags & ImGuiTableColumnFlags_NoResize)) ? ImGuiTableColumnFlags_WidthFixed : ImGuiTableColumnFlags_WidthAuto; + flags |= ImGuiTableColumnFlags_WidthFixed; else flags |= ImGuiTableColumnFlags_WidthStretch; } @@ -614,7 +628,7 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I } // Resize - if ((flags & ImGuiTableColumnFlags_WidthAuto) != 0 || (table->Flags & ImGuiTableFlags_Resizable) == 0) + if ((table->Flags & ImGuiTableFlags_Resizable) == 0) flags |= ImGuiTableColumnFlags_NoResize; // Sorting @@ -707,7 +721,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) table->IsSortSpecsDirty = true; // Auto-fit unsized columns - const bool start_auto_fit = (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) ? (column->WidthRequest < 0.0f) : (column->StretchWeight < 0.0f); + const bool start_auto_fit = (column->Flags & ImGuiTableColumnFlags_WidthFixed) ? (column->WidthRequest < 0.0f) : (column->StretchWeight < 0.0f); if (start_auto_fit) column->AutoFitQueue = column->CannotSkipItemsQueue = (1 << 3) - 1; // Fit for three frames @@ -777,7 +791,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) ImGuiTableColumn* column = &table->Columns[column_n]; const bool column_is_resizable = (column->Flags & ImGuiTableColumnFlags_NoResize) == 0; - if (column->Flags & (ImGuiTableColumnFlags_WidthFixed | ImGuiTableColumnFlags_WidthAuto)) + if (column->Flags & ImGuiTableColumnFlags_WidthFixed) { // Apply same widths policy float width_auto = column->WidthAuto; @@ -786,7 +800,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) // Apply automatic width // 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) || ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable)) + if (column->AutoFitQueue != 0x00) + column->WidthRequest = width_auto; + else if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !column_is_resizable && (table->RequestOutputMaskByIndex & ((ImU64)1 << column_n))) column->WidthRequest = width_auto; // FIXME-TABLE: Increase minimum size during init frame to avoid biasing auto-fitting widgets @@ -823,7 +839,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) } table->ColumnsEnabledFixedCount = (ImGuiTableColumnIdx)count_fixed; - // [Part 5] Apply final widths based on requested widths + // [Part 4] Apply final widths based on requested widths const ImRect work_rect = table->WorkRect; const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1); const float width_avail = ((table->Flags & ImGuiTableFlags_ScrollX) && table->InnerWidth == 0.0f) ? table->InnerClipRect.GetWidth() : work_rect.GetWidth(); @@ -854,7 +870,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) table->ColumnsGivenWidth += column->WidthGiven; } - // [Part 6] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column). + // [Part 5] Redistribute stretch remainder width due to rounding (remainder width is < 1.0f * number of Stretch column). // Using right-to-left distribution (more likely to match resizing cursor). if (width_remaining_for_stretched_columns >= 1.0f && !(table->Flags & ImGuiTableFlags_PreciseWidths)) for (int order_n = table->ColumnsCount - 1; stretch_sum_weights > 0.0f && width_remaining_for_stretched_columns >= 1.0f && order_n >= 0; order_n--) @@ -874,7 +890,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) const ImRect mouse_hit_rect(table->OuterRect.Min.x, table->OuterRect.Min.y, table->OuterRect.Max.x, ImMax(table->OuterRect.Max.y, table->OuterRect.Min.y + table->LastOuterHeight)); const bool is_hovering_table = ItemHoverable(mouse_hit_rect, 0); - // [Part 7] Setup final position, offset, skip/clip states and clipping rectangles, detect hovered column + // [Part 6] 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); @@ -994,13 +1010,13 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) } if (visible_n < table->FreezeColumnsCount) - host_clip_rect.Min.x = ImMax(host_clip_rect.Min.x, column->MaxX + TABLE_BORDER_SIZE); + host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x); offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f; visible_n++; } - // [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) + // [Part 7] 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 _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); @@ -1012,12 +1028,12 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) if (has_resizable == false && (table->Flags & ImGuiTableFlags_Resizable)) table->Flags &= ~ImGuiTableFlags_Resizable; - // [Part 9] Lock actual OuterRect/WorkRect right-most position. + // [Part 8] Lock actual OuterRect/WorkRect right-most position. // This is done late to handle the case of fixed-columns tables not claiming more widths that they need. // Because of this we are careful with uses of WorkRect and InnerClipRect before this point. if (table->RightMostStretchedColumn != -1) - table->IsOuterRectAutoFitX = false; - if (table->IsOuterRectAutoFitX) + table->IsOuterRectMinFitX = false; + if (table->IsOuterRectMinFitX) { table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1; table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1); @@ -1026,17 +1042,17 @@ void ImGui::TableUpdateLayout(ImGuiTable* table) table->BorderX1 = table->InnerClipRect.Min.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : -1.0f); table->BorderX2 = table->InnerClipRect.Max.x;// +((table->Flags & ImGuiTableFlags_BordersOuter) ? 0.0f : +1.0f); - // [Part 10] Allocate draw channels and setup background cliprect + // [Part 9] Allocate draw channels and setup background cliprect TableSetupDrawChannels(table); - // [Part 11] Hit testing on borders + // [Part 10] Hit testing on borders if (table->Flags & ImGuiTableFlags_Resizable) TableUpdateBorders(table); table->LastFirstRowHeight = 0.0f; table->IsLayoutLocked = true; table->IsUsingHeaders = false; - // [Part 12] Context menu + // [Part 11] Context menu if (table->IsContextPopupOpen && table->InstanceCurrent == table->InstanceInteracted) { const ImGuiID context_menu_id = ImHashStr("##ContextMenu", 0, table->ID); @@ -1162,20 +1178,30 @@ void ImGui::EndTable() inner_window->DC.PrevLineSize = table->HostBackupPrevLineSize; inner_window->DC.CurrLineSize = table->HostBackupCurrLineSize; inner_window->DC.CursorMaxPos = table->HostBackupCursorMaxPos; + const float inner_content_max_y = table->RowPosY2; + IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y); if (inner_window != outer_window) - { - // Both OuterRect/InnerRect are valid from BeginTable - inner_window->DC.CursorMaxPos.y = table->RowPosY2; - } + inner_window->DC.CursorMaxPos.y = inner_content_max_y; else if (!(flags & ImGuiTableFlags_NoHostExtendY)) - { - // Patch OuterRect/InnerRect height - table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_window->DC.CursorPos.y); - inner_window->DC.CursorMaxPos.y = table->RowPosY2; - } + table->OuterRect.Max.y = table->InnerRect.Max.y = ImMax(table->OuterRect.Max.y, inner_content_max_y); // Patch OuterRect/InnerRect height table->WorkRect.Max.y = ImMax(table->WorkRect.Max.y, table->OuterRect.Max.y); table->LastOuterHeight = table->OuterRect.GetHeight(); + // Setup inner scrolling range + // FIXME: This ideally should be done earlier, in BeginTable() SetNextWindowContentSize call, just like writing to inner_window->DC.CursorMaxPos.y, + // but since the later is likely to be impossible to do we'd rather update both axises together. + if (table->Flags & ImGuiTableFlags_ScrollX) + { + const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f; + float max_pos_x = table->InnerWindow->DC.CursorMaxPos.x; + if (table->RightMostEnabledColumn != -1) + max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border); + if (table->ResizedColumn != -1) + max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2); + table->InnerWindow->DC.CursorMaxPos.x = max_pos_x; + } + + // Pop clipping rect if (!(flags & ImGuiTableFlags_NoClip)) inner_window->DrawList->PopClipRect(); inner_window->ClipRect = inner_window->DrawList->_ClipRectStack.back(); @@ -1208,7 +1234,13 @@ void ImGui::EndTable() 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]); + { + ImGuiTableColumn* column = &table->Columns[column_n]; + if ((column->Flags & ImGuiTableColumnFlags_WidthFixed) && !(column->Flags & ImGuiTableColumnFlags_NoResize)) + table->ColumnsAutoFitWidth += column->WidthRequest; + else + table->ColumnsAutoFitWidth += TableGetColumnWidthAuto(table, column); + } // Update scroll if ((table->Flags & ImGuiTableFlags_ScrollX) == 0 && inner_window != outer_window) @@ -1240,15 +1272,8 @@ void ImGui::EndTable() 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); + // Restore window data that we modified + const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos; inner_window->WorkRect = table->HostBackupWorkRect; inner_window->ParentWorkRect = table->HostBackupParentWorkRect; inner_window->SkipItems = table->HostSkipItems; @@ -1256,29 +1281,32 @@ void ImGui::EndTable() outer_window->DC.ItemWidth = table->HostBackupItemWidth; outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize; outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset; - const float outer_width = table->IsOuterRectAutoFitX ? table->WorkRect.GetWidth() : table->ColumnsAutoFitWidth; + + // Layout in outer window + // (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding + // CursorPosPrevLine and CursorMaxPos manually. That should be a more general layout feature, see same problem e.g. #3414) + const float outer_width = table->IsOuterRectMinFitX ? table->WorkRect.GetWidth() : table->ColumnsAutoFitWidth; + const float outer_height = table->OuterRect.GetHeight(); if (inner_window != outer_window) { EndChild(); } else { - ImVec2 item_size(outer_width, table->OuterRect.GetHeight()); - ItemSize(item_size); + ItemSize(ImVec2(outer_width, outer_height)); + outer_window->DC.CursorPosPrevLine.x = table->OuterRect.Max.x; } - // Override EndChild/ItemSize max extent with our own to enable auto-resize on the X axis when possible + // Override declared contents width to enable auto-resize on the X axis when possible. // FIXME-TABLE: This can be improved (e.g. for Fixed columns we don't want to auto AutoFitWidth? or propagate window auto-fit to table?) 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->ColumnsGivenWidth + inner_window->ScrollbarSizes.x); // For scrolling - } + outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsGivenWidth + inner_window->ScrollbarSizes.x); // For outer scrolling else - { - outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos_x, table->WorkRect.Min.x + outer_width); // For auto-fit - outer_window->DC.CursorPosPrevLine.x = table->WorkRect.Max.x; // For consistent reaction to SameLine() // FIXME: Should be a feature of layout/ItemAdd - } + outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->WorkRect.Min.x + outer_width); // For auto-fit + + // Override declared contents height + if (inner_window == outer_window && !(flags & ImGuiTableFlags_NoHostExtendY)) + outer_window->DC.CursorMaxPos.y = ImMax(outer_window->DC.CursorMaxPos.y, inner_content_max_y); // Save settings if (table->IsSettingsDirty) @@ -1292,7 +1320,8 @@ void ImGui::EndTable() outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1; } -// See "COLUMN SIZING POLICIES" comments at the top of this file +// See "COLUMN SIZING POLICIES" comments at the top of this file +// If (init_width_or_weight <= 0.0f) it is ignored void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, float init_width_or_weight, ImGuiID user_id) { ImGuiContext& g = *GImGui; @@ -1320,8 +1349,6 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo flags = column->Flags; // Initialize defaults - if (flags & ImGuiTableColumnFlags_WidthStretch) - IM_ASSERT(init_width_or_weight != 0.0f && "Need to provide a valid weight!"); column->InitStretchWeightOrWidth = init_width_or_weight; if (table->IsInitializing) { @@ -1436,7 +1463,7 @@ ImRect ImGui::TableGetCellBgRect(const ImGuiTable* table, int column_n) // Return the resizing ID for the right-side of the given column. ImGuiID ImGui::TableGetColumnResizeID(const ImGuiTable* table, int column_n, int instance_no) { - IM_ASSERT(column_n < table->ColumnsCount); + IM_ASSERT(column_n >= 0 && column_n < table->ColumnsCount); ImGuiID id = table->ID + 1 + (instance_no * table->ColumnsCount) + column_n; return id; } @@ -1451,17 +1478,17 @@ int ImGui::TableGetHoveredColumn() return (int)table->HoveredColumnBody; } -void ImGui::TableSetBgColor(ImGuiTableBgTarget bg_target, ImU32 color, int column_n) +void ImGui::TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n) { ImGuiContext& g = *GImGui; ImGuiTable* table = g.CurrentTable; - IM_ASSERT(bg_target != ImGuiTableBgTarget_None); + IM_ASSERT(target != ImGuiTableBgTarget_None); if (color == IM_COL32_DISABLE) color = 0; // We cannot draw neither the cell or row background immediately as we don't know the row height at this point in time. - switch (bg_target) + switch (target) { case ImGuiTableBgTarget_CellBg: { @@ -1484,7 +1511,7 @@ void ImGui::TableSetBgColor(ImGuiTableBgTarget bg_target, ImU32 color, int colum if (table->RowPosY1 > table->InnerClipRect.Max.y) // Discard return; IM_ASSERT(column_n == -1); - int bg_idx = (bg_target == ImGuiTableBgTarget_RowBg1) ? 1 : 0; + int bg_idx = (target == ImGuiTableBgTarget_RowBg1) ? 1 : 0; table->RowBgColor[bg_idx] = color; break; } @@ -2324,7 +2351,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table) void ImGui::TableDrawBorders(ImGuiTable* table) { ImGuiWindow* inner_window = table->InnerWindow; - if (inner_window->Hidden || !table->HostClipRect.Overlaps(table->InnerClipRect)) + if (!table->OuterWindow->ClipRect.Overlaps(table->OuterRect)) return; ImDrawList* inner_drawlist = inner_window->DrawList; @@ -2335,7 +2362,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table) const float border_size = TABLE_BORDER_SIZE; const float draw_y1 = table->InnerRect.Min.y; const float draw_y2_body = table->InnerRect.Max.y; - const float draw_y2_head = table->IsUsingHeaders ? ((table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1; + const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1; if (table->Flags & ImGuiTableFlags_BordersInnerV) { for (int order_n = 0; order_n < table->ColumnsCount; order_n++) @@ -2353,7 +2380,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table) if (column->MaxX > table->InnerClipRect.Max.x && !is_resized) continue; if (column->NextEnabledColumn == -1 && !is_resizable) - if ((table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || table->IsOuterRectAutoFitX) + if ((table->Flags & ImGuiTableFlags_SizingMask_) != ImGuiTableFlags_SizingFixedSame || table->IsOuterRectMinFitX) continue; if (column->MaxX <= column->ClipRect.Min.x) // FIXME-TABLE FIXME-STYLE: Assume BorderSize==1, this is problematic if we want to increase the border size.. continue; @@ -3367,7 +3394,7 @@ void ImGui::DebugNodeTable(ImGuiTable* table) "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..", + "Sort: %d%s, UserID: 0x%08X, Flags: 0x%04X: %s%s%s..", 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 > 0.0f ? (column->StretchWeight / sum_weights) * 100.0f : 0.0f, @@ -3376,7 +3403,6 @@ 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_WidthAuto) ? "WidthAuto " : "", (column->Flags & ImGuiTableColumnFlags_NoResize) ? "NoResize " : ""); Bullet(); Selectable(buf); diff --git a/3rdparty/dear-imgui/imgui_widgets.cpp b/3rdparty/dear-imgui/imgui_widgets.cpp index acdcba34d..10edea5db 100644 --- a/3rdparty/dear-imgui/imgui_widgets.cpp +++ b/3rdparty/dear-imgui/imgui_widgets.cpp @@ -1614,7 +1614,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (popup_window->WasActive) { // Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us. - ImVec2 size_expected = CalcWindowExpectedSize(popup_window); + ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window); if (flags & ImGuiComboFlags_PopupAlignLeft) popup_window->AutoPosLastDirection = ImGuiDir_Left; // "Below, Toward Left" else @@ -5913,21 +5913,25 @@ bool ImGui::CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags) return TreeNodeBehavior(window->GetID(label), flags | ImGuiTreeNodeFlags_CollapsingHeader, label); } -bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags) +// p_visible == NULL : regular collapsing header +// p_visible != NULL && *p_visible == true : show a small close button on the corner of the header, clicking the button will set *p_visible = false +// p_visible != NULL && *p_visible == false : do not show the header at all +// Do not mistake this with the Open state of the header itself, which you can adjust with SetNextItemOpen() or ImGuiTreeNodeFlags_DefaultOpen. +bool ImGui::CollapsingHeader(const char* label, bool* p_visible, ImGuiTreeNodeFlags flags) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; - if (p_open && !*p_open) + if (p_visible && !*p_visible) return false; ImGuiID id = window->GetID(label); flags |= ImGuiTreeNodeFlags_CollapsingHeader; - if (p_open) + if (p_visible) flags |= ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton; bool is_open = TreeNodeBehavior(id, flags, label); - if (p_open != NULL) + if (p_visible != NULL) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. @@ -5939,7 +5943,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags float button_y = window->DC.LastItemRect.Min.y; ImGuiID close_button_id = GetIDWithSeed("#CLOSE", NULL, id); if (CloseButton(close_button_id, ImVec2(button_x, button_y))) - *p_open = false; + *p_visible = false; last_item_backup.Restore(); } @@ -6244,6 +6248,11 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v // - PlotLines() // - PlotHistogram() //------------------------------------------------------------------------- +// Plot/Graph widgets are not very good. +// Consider writing your own, or using a third-party one, see: +// - ImPlot https://github.com/epezent/implot +// - others https://github.com/ocornut/imgui/wiki/Useful-Widgets +//------------------------------------------------------------------------- int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size) { @@ -7247,7 +7256,8 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) // Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame) ImGuiWindow* window = g.CurrentWindow; window->DC.CursorPos = tab_bar->BarRect.Min; - ItemSize(ImVec2(tab_bar->WidthAllTabsIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y); + ItemSize(tab_bar->BarRect.GetSize(), tab_bar->FramePadding.y); + window->DC.IdealMaxPos.x = ImMax(window->DC.IdealMaxPos.x, tab_bar->BarRect.Min.x + tab_bar->WidthAllTabsIdeal); } // Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.