Tables: work on background draw channel handling (amend "create a separate background draw channel") + Selectable disable spacing when spanning.

This commit is contained in:
ocornut 2020-11-04 22:17:58 +01:00
parent fe6131168a
commit 507db499e4
4 changed files with 31 additions and 24 deletions

View File

@ -10522,7 +10522,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
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_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_ColumnsClipRect) { ImGuiTableColumn* c = &table->Columns[n]; return c->ClipRect; }
else if (rect_type == TRT_ColumnsContentHeadersUsed){ ImGuiTableColumn* c = &table->Columns[n]; return ImRect(c->ContentMinX, table->InnerClipRect.Min.y, c->ContentMaxXHeadersUsed, table->InnerClipRect.Min.y + table->LastFirstRowHeight); } // Note: y1/y2 not always accurate

View File

@ -2000,7 +2000,8 @@ struct ImGuiTable
ImRect OuterRect; // Note: OuterRect.Max.y is often FLT_MAX until EndTable(), unless a height has been specified in BeginTable().
ImRect WorkRect;
ImRect InnerClipRect;
ImRect BackgroundClipRect; // We use this to cpu-clip cell background color fill
ImRect BgClipRect; // We use this to cpu-clip cell background color fill
ImRect BgClipRectForDrawCmd;
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.
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()

View File

@ -319,8 +319,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width
table->InnerClipRect.ClipWithFull(table->HostClipRect);
table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : inner_window->ClipRect.Max.y;
table->BackgroundClipRect = table->InnerClipRect;
IM_ASSERT(table->BackgroundClipRect.Min.y <= table->BackgroundClipRect.Max.y);
// Initial draw cmd starts with a BgClipRect that matches the one of its host, to facilitate merge draw commands by default.
// This is because all our cell highlight are manually clipped with BgClipRect
// Larger at first, if/after unfreezing will become same as tight
table->BgClipRect = table->InnerClipRect;
table->BgClipRectForDrawCmd = table->HostClipRect;
IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
table->FreezeRowsRequest = table->FreezeRowsCount = 0; // This will be setup by TableSetupScrollFreeze(), if any
@ -1203,7 +1209,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
// Draw bottom-most row border
// FIXME-TABLE: could use AddRect or explicit VLine/HLine helper?
const float border_y = table->RowPosY2;
if (border_y >= table->BackgroundClipRect.Min.y && border_y < table->BackgroundClipRect.Max.y)
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
}
}
@ -1495,6 +1501,8 @@ void ImGui::TableReorderDrawChannelsForMerge(ImGuiTable* table)
remaining_mask.SetBitRange(1, splitter->_Count - 1); // Background channel 0 == table->BgDrawChannlFrozen, not part of the merge (see channel allocation in TableUpdateDrawChannels)
remaining_mask.ClearBit(table->BgDrawChannelUnfrozen);
int remaining_count = splitter->_Count - ((table->BgDrawChannelUnfrozen == 0) ? 1 : 2);
//ImRect host_rect = (table->InnerWindow == table->OuterWindow) ? table->InnerClipRect : table->HostClipRect;
ImRect host_rect = table->HostClipRect;
for (int merge_group_n = 0; merge_group_n < IM_ARRAYSIZE(merge_groups); merge_group_n++)
{
if (int merge_channels_count = merge_groups[merge_group_n].ChannelsCount)
@ -1510,13 +1518,13 @@ void ImGui::TableReorderDrawChannelsForMerge(ImGuiTable* table)
// FIXME-TABLE FIXME-WORKRECT: We are wasting a merge opportunity on tables without scrolling if column doesn't fit
// within host clip rect, solely because of the half-padding difference between window->WorkRect and window->InnerClipRect.
if ((merge_group_n & 1) == 0 || !has_freeze_h)
merge_clip_rect.Min.x = ImMin(merge_clip_rect.Min.x, table->HostClipRect.Min.x);
merge_clip_rect.Min.x = ImMin(merge_clip_rect.Min.x, host_rect.Min.x);
if ((merge_group_n & 2) == 0 || !has_freeze_v)
merge_clip_rect.Min.y = ImMin(merge_clip_rect.Min.y, table->HostClipRect.Min.y);
merge_clip_rect.Min.y = ImMin(merge_clip_rect.Min.y, host_rect.Min.y);
if ((merge_group_n & 1) != 0)
merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, table->HostClipRect.Max.x);
merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x);
if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0)
merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, table->HostClipRect.Max.y);
merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y);
#if 0
GetOverlayDrawList()->AddRect(merge_group->ClipRect.Min, merge_group->ClipRect.Max, IM_COL32(255, 0, 0, 200), 0.0f, ~0, 1.0f);
GetOverlayDrawList()->AddLine(merge_group->ClipRect.Min, merge_clip_rect.Min, IM_COL32(255, 100, 0, 200));
@ -1757,7 +1765,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
// In theory we could call SetWindowClipRectBeforeSetChannel() but since we know TableEndRow() is
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
window->DrawList->_CmdHeader.ClipRect = ((table->IsUnfrozen && table->BgDrawChannelUnfrozen != 0) ? table->BackgroundClipRect : table->HostClipRect).ToVec4();
window->DrawList->_CmdHeader.ClipRect = table->BgClipRectForDrawCmd.ToVec4();
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->IsUnfrozen ? table->BgDrawChannelUnfrozen : 0);
}
@ -1766,7 +1774,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
if (bg_col0 || bg_col1)
{
ImRect row_rect(table->WorkRect.Min.x, bg_y1, table->WorkRect.Max.x, bg_y2);
row_rect.ClipWith(table->BackgroundClipRect);
row_rect.ClipWith(table->BgClipRect);
if (bg_col0 != 0 && row_rect.Min.y < row_rect.Max.y)
window->DrawList->AddRectFilled(row_rect.Min, row_rect.Max, bg_col0);
if (bg_col1 != 0 && row_rect.Min.y < row_rect.Max.y)
@ -1780,7 +1788,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
for (ImGuiTableCellData* cell_data = &table->RowCellData[0]; cell_data <= cell_data_end; cell_data++)
{
ImRect cell_bg_rect = TableGetCellBgRect(table, cell_data->Column);
cell_bg_rect.ClipWith(table->BackgroundClipRect);
cell_bg_rect.ClipWith(table->BgClipRect);
cell_bg_rect.Min.x = ImMax(cell_bg_rect.Min.x, table->Columns[cell_data->Column].ClipRect.Min.x);
cell_bg_rect.Max.x = ImMin(cell_bg_rect.Max.x, table->Columns[cell_data->Column].ClipRect.Max.x);
window->DrawList->AddRectFilled(cell_bg_rect.Min, cell_bg_rect.Max, cell_data->BgColor);
@ -1788,13 +1796,12 @@ void ImGui::TableEndRow(ImGuiTable* table)
}
// Draw top border
if (border_col && bg_y1 >= table->BackgroundClipRect.Min.y && bg_y1 < table->BackgroundClipRect.Max.y)
if (border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), border_col, border_size);
// Draw bottom border at the row unfreezing mark (always strong)
if (draw_strong_bottom_border)
if (bg_y2 >= table->BackgroundClipRect.Min.y && bg_y2 < table->BackgroundClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size);
if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y)
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size);
}
// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
@ -1812,11 +1819,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
table->IsUnfrozen = true;
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->BgDrawChannelUnfrozen);
// BackgroundClipRect starts as table->InnerClipRect, reduce it now
// BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect
float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.y);
table->BackgroundClipRect.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
table->BackgroundClipRect.Max.y = window->InnerClipRect.Max.y;
IM_ASSERT(table->BackgroundClipRect.Min.y <= table->BackgroundClipRect.Max.y);
table->BgClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y);
table->BgClipRect.Max.y = table->BgClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y;
IM_ASSERT(table->BgClipRectForDrawCmd.Min.y <= table->BgClipRectForDrawCmd.Max.y);
float row_height = table->RowPosY2 - table->RowPosY1;
table->RowPosY2 = window->DC.CursorPos.y = table->WorkRect.Min.y + table->RowPosY2 - table->OuterRect.Min.y;
@ -1825,7 +1832,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
{
ImGuiTableColumn* column = &table->Columns[column_n];
column->DrawChannelCurrent = column->DrawChannelUnfrozen;
column->ClipRect.Min.y = table->BackgroundClipRect.Min.y;
column->ClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y;
}
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
@ -2034,8 +2041,7 @@ void ImGui::PushTableBackground()
// Optimization: avoid SetCurrentChannel() + PushClipRect()
table->HostBackupClipRect = window->ClipRect;
SetWindowClipRectBeforeSetChannel(window, table->BackgroundClipRect);
//SetWindowClipRectBeforeSetChannel(window, table->HostClipRect);
SetWindowClipRectBeforeSetChannel(window, table->BgClipRectForDrawCmd);
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->IsUnfrozen ? table->BgDrawChannelUnfrozen : 0);
}

View File

@ -5953,7 +5953,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
ImRect bb(min_x, pos.y, text_max.x, text_max.y);
if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0)
{
const float spacing_x = style.ItemSpacing.x;
const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x;
const float spacing_y = style.ItemSpacing.y;
const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
const float spacing_U = IM_FLOOR(spacing_y * 0.50f);