Updated ImGui.

This commit is contained in:
Бранимир Караџић 2021-01-15 20:30:58 -08:00
parent 9e7273506a
commit 630263d1cb
6 changed files with 381 additions and 297 deletions

View File

@ -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 " : "",

View File

@ -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()

View File

@ -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<int> 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<int> 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

View File

@ -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);

View File

@ -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);

View File

@ -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.