mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-07 13:35:49 +02:00
Tables: Initial commit. [Squashed 123+5 commits from tables_wip/]
This commit is contained in:
141
imgui.cpp
141
imgui.cpp
@ -947,6 +947,7 @@ ImGuiStyle::ImGuiStyle()
|
||||
FrameBorderSize = 0.0f; // Thickness of border around frames. Generally set to 0.0f or 1.0f. Other values not well tested.
|
||||
ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
|
||||
ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
|
||||
CellPadding = ImVec2(4,2); // Padding within a table cell
|
||||
TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
|
||||
IndentSpacing = 21.0f; // Horizontal spacing when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2).
|
||||
ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns. Preferably > (FramePadding.x + 1).
|
||||
@ -987,6 +988,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
||||
FrameRounding = ImFloor(FrameRounding * scale_factor);
|
||||
ItemSpacing = ImFloor(ItemSpacing * scale_factor);
|
||||
ItemInnerSpacing = ImFloor(ItemInnerSpacing * scale_factor);
|
||||
CellPadding = ImFloor(CellPadding * scale_factor);
|
||||
TouchExtraPadding = ImFloor(TouchExtraPadding * scale_factor);
|
||||
IndentSpacing = ImFloor(IndentSpacing * scale_factor);
|
||||
ColumnsMinSpacing = ImFloor(ColumnsMinSpacing * scale_factor);
|
||||
@ -2135,6 +2137,14 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
|
||||
// the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// FIXME-TABLE: This prevents us from using ImGuiListClipper _inside_ a table cell.
|
||||
// The problem we have is that without a Begin/End scheme for rows using the clipper is ambiguous.
|
||||
static bool GetSkipItemForListClipping()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
return (g.CurrentTable ? g.CurrentTable->BackupSkipItems : g.CurrentWindow->SkipItems);
|
||||
}
|
||||
|
||||
// Helper to calculate coarse clipping of large list of evenly sized items.
|
||||
// NB: Prefer using the ImGuiListClipper higher-level helper if you can! Read comments and instructions there on how those use this sort of pattern.
|
||||
// NB: 'items_count' is only used to clamp the result, if you don't know your count you can use INT_MAX
|
||||
@ -2149,7 +2159,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items
|
||||
*out_items_display_end = items_count;
|
||||
return;
|
||||
}
|
||||
if (window->SkipItems)
|
||||
if (GetSkipItemForListClipping())
|
||||
{
|
||||
*out_items_display_start = *out_items_display_end = 0;
|
||||
return;
|
||||
@ -2185,12 +2195,20 @@ static void SetCursorPosYAndSetupForPrevLine(float pos_y, float line_height)
|
||||
// The clipper should probably have a 4th step to display the last item in a regular manner.
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
float off_y = pos_y - window->DC.CursorPos.y;
|
||||
window->DC.CursorPos.y = pos_y;
|
||||
window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y);
|
||||
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
|
||||
window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
|
||||
if (ImGuiOldColumns* columns = window->DC.CurrentColumns)
|
||||
columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
|
||||
columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly // FIXME-TABLE
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
{
|
||||
if (table->IsInsideRow)
|
||||
ImGui::TableEndRow(table);
|
||||
table->RowPosY2 = window->DC.CursorPos.y;
|
||||
table->RowBgColorCounter += (int)((off_y / line_height) + 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiListClipper::ImGuiListClipper()
|
||||
@ -2212,6 +2230,10 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->IsInsideRow)
|
||||
ImGui::TableEndRow(table);
|
||||
|
||||
StartPosY = window->DC.CursorPos.y;
|
||||
ItemsHeight = items_height;
|
||||
ItemsCount = items_count;
|
||||
@ -2237,8 +2259,12 @@ bool ImGuiListClipper::Step()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
if (table && table->IsInsideRow)
|
||||
ImGui::TableEndRow(table);
|
||||
|
||||
// Reached end of list
|
||||
if (DisplayEnd >= ItemsCount || window->SkipItems)
|
||||
if (DisplayEnd >= ItemsCount || GetSkipItemForListClipping())
|
||||
{
|
||||
End();
|
||||
return false;
|
||||
@ -2266,7 +2292,17 @@ bool ImGuiListClipper::Step()
|
||||
if (StepNo == 1)
|
||||
{
|
||||
IM_ASSERT(ItemsHeight <= 0.0f);
|
||||
ItemsHeight = window->DC.CursorPos.y - StartPosY;
|
||||
if (table)
|
||||
{
|
||||
const float pos_y1 = table->RowPosY1; // Using this instead of StartPosY to handle clipper straddling the frozen row
|
||||
const float pos_y2 = table->RowPosY2; // Using this instead of CursorPos.y to take account of tallest cell.
|
||||
ItemsHeight = pos_y2 - pos_y1;
|
||||
window->DC.CursorPos.y = pos_y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ItemsHeight = window->DC.CursorPos.y - StartPosY;
|
||||
}
|
||||
IM_ASSERT(ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");
|
||||
StepNo = 2;
|
||||
}
|
||||
@ -2405,6 +2441,7 @@ static const ImGuiStyleVarInfo GStyleVarInfo[] =
|
||||
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing
|
||||
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing
|
||||
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, CellPadding) }, // ImGuiStyleVar_CellPadding
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding
|
||||
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize
|
||||
@ -2512,6 +2549,9 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||
case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered";
|
||||
case ImGuiCol_PlotHistogram: return "PlotHistogram";
|
||||
case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
|
||||
case ImGuiCol_TableHeaderBg: return "TableHeaderBg";
|
||||
case ImGuiCol_TableRowBg: return "TableRowBg";
|
||||
case ImGuiCol_TableRowBgAlt: return "TableRowBgAlt";
|
||||
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
|
||||
case ImGuiCol_DragDropTarget: return "DragDropTarget";
|
||||
case ImGuiCol_NavHighlight: return "NavHighlight";
|
||||
@ -3998,6 +4038,10 @@ void ImGui::Shutdown(ImGuiContext* context)
|
||||
g.CurrentTabBarStack.clear();
|
||||
g.ShrinkWidthBuffer.clear();
|
||||
|
||||
g.Tables.Clear();
|
||||
g.CurrentTableStack.clear();
|
||||
g.DrawChannelsTempMergeBuffer.clear();
|
||||
|
||||
g.ClipboardHandlerData.clear();
|
||||
g.MenusIdSubmittedThisFrame.clear();
|
||||
g.InputTextState.ClearFreeMemory();
|
||||
@ -7374,7 +7418,7 @@ ImVec2 ImGui::GetContentRegionMax()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImVec2 mx = window->ContentRegionRect.Max - window->Pos;
|
||||
if (window->DC.CurrentColumns)
|
||||
if (window->DC.CurrentColumns || g.CurrentTable)
|
||||
mx.x = window->WorkRect.Max.x - window->Pos.x;
|
||||
return mx;
|
||||
}
|
||||
@ -7385,7 +7429,7 @@ ImVec2 ImGui::GetContentRegionMaxAbs()
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImVec2 mx = window->ContentRegionRect.Max;
|
||||
if (window->DC.CurrentColumns)
|
||||
if (window->DC.CurrentColumns || g.CurrentTable)
|
||||
mx.x = window->WorkRect.Max.x;
|
||||
return mx;
|
||||
}
|
||||
@ -10459,6 +10503,23 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
|
||||
struct Funcs
|
||||
{
|
||||
static ImRect GetTableRect(ImGuiTable* table, int rect_type, int n)
|
||||
{
|
||||
if (rect_type == TRT_OuterRect) { return table->OuterRect; }
|
||||
else if (rect_type == TRT_WorkRect) { return table->WorkRect; }
|
||||
else if (rect_type == TRT_HostClipRect) { return table->HostClipRect; }
|
||||
else if (rect_type == TRT_InnerClipRect) { return table->InnerClipRect; }
|
||||
else if (rect_type == TRT_BackgroundClipRect) { return table->BackgroundClipRect; }
|
||||
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_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
|
||||
else if (rect_type == TRT_ColumnsContentHeadersUsed) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthHeadersUsed, 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->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthHeadersDesired, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // "
|
||||
else if (rect_type == TRT_ColumnsContentRowsFrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y, c->MinX + c->ContentWidthRowsFrozen, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // "
|
||||
else if (rect_type == TRT_ColumnsContentRowsUnfrozen) { ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->MinX, table->InnerClipRect.Min.y + table->LastFirstRowHeight, c->MinX + c->ContentWidthRowsUnfrozen, table->InnerClipRect.Max.y); } // "
|
||||
IM_ASSERT(0);
|
||||
return ImRect();
|
||||
}
|
||||
|
||||
static ImRect GetWindowRect(ImGuiWindow* window, int rect_type)
|
||||
{
|
||||
if (rect_type == WRT_OuterRect) { return window->Rect(); }
|
||||
@ -10500,6 +10561,49 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
}
|
||||
Checkbox("Show ImDrawCmd mesh when hovering", &cfg->ShowDrawCmdMesh);
|
||||
Checkbox("Show ImDrawCmd bounding boxes when hovering", &cfg->ShowDrawCmdBoundingBoxes);
|
||||
|
||||
Checkbox("Show tables rectangles", &cfg->ShowTablesRects);
|
||||
SameLine();
|
||||
SetNextItemWidth(GetFontSize() * 12);
|
||||
cfg->ShowTablesRects |= Combo("##show_table_rects_type", &cfg->ShowTablesRectsType, trt_rects_names, TRT_Count, TRT_Count);
|
||||
if (cfg->ShowTablesRects && g.NavWindow != NULL)
|
||||
{
|
||||
for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++)
|
||||
{
|
||||
ImGuiTable* table = g.Tables.GetByIndex(table_n);
|
||||
if (table->LastFrameActive < g.FrameCount - 1 || table->OuterWindow != g.NavWindow)
|
||||
continue;
|
||||
|
||||
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList()->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
|
||||
Indent();
|
||||
for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
|
||||
{
|
||||
if (rect_n >= TRT_ColumnsRect)
|
||||
{
|
||||
if (rect_n != TRT_ColumnsRect && rect_n != TRT_ColumnsClipRect)
|
||||
continue;
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImRect r = Funcs::GetTableRect(table, rect_n, column_n);
|
||||
Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImRect r = Funcs::GetTableRect(table, rect_n, -1);
|
||||
Text("(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList()->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f);
|
||||
}
|
||||
}
|
||||
Unindent();
|
||||
}
|
||||
}
|
||||
|
||||
TreePop();
|
||||
}
|
||||
|
||||
@ -10533,7 +10637,6 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
}
|
||||
|
||||
// Details for Tables
|
||||
IM_UNUSED(trt_rects_names);
|
||||
#ifdef IMGUI_HAS_TABLE
|
||||
if (TreeNode("Tables", "Tables (%d)", g.Tables.GetSize()))
|
||||
{
|
||||
@ -10584,8 +10687,8 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
#ifdef IMGUI_HAS_TABLE
|
||||
if (TreeNode("SettingsTables", "Settings packed data: Tables: %d bytes", g.SettingsTables.size()))
|
||||
{
|
||||
for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
|
||||
DebugNodeTableSettings(settings);
|
||||
//for (ImGuiTableSettings* settings = g.SettingsTables.begin(); settings != NULL; settings = g.SettingsTables.next_chunk(settings))
|
||||
// DebugNodeTableSettings(settings);
|
||||
TreePop();
|
||||
}
|
||||
#endif // #ifdef IMGUI_HAS_TABLE
|
||||
@ -10664,11 +10767,29 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
|
||||
#ifdef IMGUI_HAS_TABLE
|
||||
// Overlay: Display Tables Rectangles
|
||||
if (show_tables_rects)
|
||||
if (cfg->ShowTablesRects)
|
||||
{
|
||||
for (int table_n = 0; table_n < g.Tables.GetSize(); table_n++)
|
||||
{
|
||||
ImGuiTable* table = g.Tables.GetByIndex(table_n);
|
||||
if (table->LastFrameActive < g.FrameCount - 1)
|
||||
continue;
|
||||
ImDrawList* draw_list = GetForegroundDrawList(table->OuterWindow);
|
||||
if (cfg->ShowTablesRectsType >= TRT_ColumnsRect)
|
||||
{
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
|
||||
ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
|
||||
float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
|
||||
draw_list->AddRect(r.Min, r.Max, col, 0.0f, ~0, thickness);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, -1);
|
||||
draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #ifdef IMGUI_HAS_TABLE
|
||||
|
Reference in New Issue
Block a user