Skip to content

Commit 22ace44

Browse files
committed
Tables: clarify assumption that rendering of bg/borders in bg0/bg1 are cpu-clipped allowing frozen/unfrozen to share drawcmd + remove offset on outer borders of scrolling tables.
1 parent 3046882 commit 22ace44

File tree

2 files changed

+22
-23
lines changed

2 files changed

+22
-23
lines changed

imgui_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2019,7 +2019,8 @@ struct ImGuiTable
20192019
ImRect WorkRect;
20202020
ImRect InnerClipRect;
20212021
ImRect BgClipRect; // We use this to cpu-clip cell background color fill
2022-
ImRect BgClipRectForDrawCmd;
2022+
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
2023+
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
20232024
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
20242025
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
20252026
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()

imgui_tables.cpp

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1601,7 +1601,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
16011601
// In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is
16021602
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
16031603
if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
1604-
window->DrawList->_CmdHeader.ClipRect = table->BgClipRectForDrawCmd.ToVec4();
1604+
window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4();
16051605
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
16061606
}
16071607

@@ -1657,10 +1657,10 @@ void ImGui::TableEndRow(ImGuiTable* table)
16571657

16581658
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
16591659
float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
1660-
table->BgClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
1661-
table->BgClipRect.Max.y = table->BgClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
1660+
table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
1661+
table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
16621662
table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen;
1663-
IM_ASSERT(table->BgClipRectForDrawCmd.Min.y <= table->BgClipRectForDrawCmd.Max.y);
1663+
IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.Max.y);
16641664

16651665
float row_height = table->RowPosY2 - table->RowPosY1;
16661666
table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
@@ -1669,7 +1669,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
16691669
{
16701670
ImGuiTableColumn* column = &table->Columns[column_n];
16711671
column->DrawChannelCurrent = column->DrawChannelUnfrozen;
1672-
column->ClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y;
1672+
column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y;
16731673
}
16741674

16751675
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
@@ -2019,7 +2019,7 @@ void ImGui::TablePushBackgroundChannel()
20192019

20202020
// Optimization: avoid SetCurrentChannel() + PushClipRect()
20212021
table->HostBackupInnerClipRect = window->ClipRect;
2022-
SetWindowClipRectBeforeSetChannel(window, table->BgClipRectForDrawCmd);
2022+
SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd);
20232023
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
20242024
}
20252025

@@ -2046,7 +2046,7 @@ void ImGui::TablePopBackgroundChannel()
20462046
// - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for
20472047
// horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4).
20482048
// Draw channel allocation (before merging):
2049-
// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == 1 draw call) (FIXME-TABLE: could merge bg2 and foreground?)
2049+
// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call)
20502050
// - Clip --> 2+D+N channels
20512051
// - FreezeRows --> 2+D+N*2 (unless scrolling value is zero)
20522052
// - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero)
@@ -2085,7 +2085,8 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
20852085
// All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect.
20862086
// (This technically isn't part of setting up draw channels, but is reasonably related to be done here)
20872087
table->BgClipRect = table->InnerClipRect;
2088-
table->BgClipRectForDrawCmd = table->HostClipRect;
2088+
table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect;
2089+
table->Bg2ClipRectForDrawCmd = table->HostClipRect;
20892090
IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
20902091
}
20912092

@@ -2288,19 +2289,17 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
22882289
void ImGui::TableDrawBorders(ImGuiTable* table)
22892290
{
22902291
ImGuiWindow* inner_window = table->InnerWindow;
2291-
ImGuiWindow* outer_window = table->OuterWindow;
22922292
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_BG0);
22932293
if (inner_window->Hidden || !table->HostClipRect.Overlaps(table->InnerClipRect))
22942294
return;
22952295
ImDrawList* inner_drawlist = inner_window->DrawList;
2296-
ImDrawList* outer_drawlist = outer_window->DrawList;
2296+
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
22972297

22982298
// Draw inner border and resizing feedback
22992299
const float border_size = TABLE_BORDER_SIZE;
23002300
const float draw_y1 = table->InnerRect.Min.y;
23012301
const float draw_y2_body = table->InnerRect.Max.y;
23022302
const float draw_y2_head = table->IsUsingHeaders ? ((table->FreezeRowsCount >= 1 ? table->OuterRect.Min.y : table->WorkRect.Min.y) + table->LastFirstRowHeight) : draw_y1;
2303-
23042303
if (table->Flags & ImGuiTableFlags_BordersInnerV)
23052304
{
23062305
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
@@ -2351,23 +2350,21 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
23512350
// parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part
23522351
// of it in inner window, and the part that's over scrollbars in the outer window..)
23532352
// Either solution currently won't allow us to use a larger border size: the border would clipped.
2354-
ImRect outer_border = table->OuterRect;
2353+
const ImRect outer_border = table->OuterRect;
23552354
const ImU32 outer_col = table->BorderColorStrong;
2356-
if (inner_window != outer_window) // FIXME-TABLE
2357-
outer_border.Expand(1.0f);
23582355
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
23592356
{
2360-
outer_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size);
2357+
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size);
23612358
}
23622359
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
23632360
{
2364-
outer_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
2365-
outer_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
2361+
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
2362+
inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
23662363
}
23672364
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
23682365
{
2369-
outer_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
2370-
outer_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
2366+
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
2367+
inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
23712368
}
23722369
}
23732370
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
@@ -2377,6 +2374,8 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
23772374
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
23782375
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
23792376
}
2377+
2378+
inner_drawlist->PopClipRect();
23802379
}
23812380

23822381
//-------------------------------------------------------------------------
@@ -2638,7 +2637,6 @@ void ImGui::TableHeadersRow()
26382637
// Emit a column header (text + optional sort order)
26392638
// We cpu-clip text here so that all columns headers can be merged into a same draw call.
26402639
// Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader()
2641-
// FIXME-TABLE: Style confusion between CellPadding.y and FramePadding.y
26422640
void ImGui::TableHeader(const char* label)
26432641
{
26442642
ImGuiContext& g = *GImGui;
@@ -2660,7 +2658,7 @@ void ImGui::TableHeader(const char* label)
26602658
ImVec2 label_pos = window->DC.CursorPos;
26612659

26622660
// If we already got a row height, there's use that.
2663-
// FIXME-TABLE-PADDING: Problem if the correct outer-padding CellBgRect strays off our ClipRect
2661+
// FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect?
26642662
ImRect cell_r = TableGetCellBgRect(table, column_n);
26652663
float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f);
26662664

@@ -2671,7 +2669,7 @@ void ImGui::TableHeader(const char* label)
26712669
const float ARROW_SCALE = 0.65f;
26722670
if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort))
26732671
{
2674-
w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);// table->CellPadding.x);
2672+
w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);
26752673
if (column->SortOrder > 0)
26762674
{
26772675
ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);

0 commit comments

Comments
 (0)