diff --git a/imgui_internal.h b/imgui_internal.h index 6aece7cc..eb753fe5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -2019,7 +2019,8 @@ struct ImGuiTable ImRect WorkRect; ImRect InnerClipRect; ImRect BgClipRect; // We use this to cpu-clip cell background color fill - ImRect BgClipRectForDrawCmd; + 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 + 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. 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() diff --git a/imgui_tables.cpp b/imgui_tables.cpp index f35a3aa5..1c347b68 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -1601,7 +1601,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->BgClipRectForDrawCmd.ToVec4(); + window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4(); table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0); } @@ -1657,10 +1657,10 @@ void ImGui::TableEndRow(ImGuiTable* table) // BgClipRect starts as table->InnerClipRect, reduce it now and make BgClipRectForDrawCmd == BgClipRect float y0 = ImMax(table->RowPosY2 + 1, window->InnerClipRect.Min.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; + table->BgClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y = ImMin(y0, window->InnerClipRect.Max.y); + table->BgClipRect.Max.y = table->Bg2ClipRectForDrawCmd.Max.y = window->InnerClipRect.Max.y; table->Bg2DrawChannelCurrent = table->Bg2DrawChannelUnfrozen; - IM_ASSERT(table->BgClipRectForDrawCmd.Min.y <= table->BgClipRectForDrawCmd.Max.y); + IM_ASSERT(table->Bg2ClipRectForDrawCmd.Min.y <= table->Bg2ClipRectForDrawCmd.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; @@ -1669,7 +1669,7 @@ void ImGui::TableEndRow(ImGuiTable* table) { ImGuiTableColumn* column = &table->Columns[column_n]; column->DrawChannelCurrent = column->DrawChannelUnfrozen; - column->ClipRect.Min.y = table->BgClipRectForDrawCmd.Min.y; + column->ClipRect.Min.y = table->Bg2ClipRectForDrawCmd.Min.y; } // Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y @@ -2019,7 +2019,7 @@ void ImGui::TablePushBackgroundChannel() // Optimization: avoid SetCurrentChannel() + PushClipRect() table->HostBackupInnerClipRect = window->ClipRect; - SetWindowClipRectBeforeSetChannel(window, table->BgClipRectForDrawCmd); + SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd); table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent); } @@ -2046,7 +2046,7 @@ void ImGui::TablePopBackgroundChannel() // - We allocate 1 or 2 background draw channels. This is because we know TablePushBackgroundChannel() is only used for // horizontal spanning. If we allowed vertical spanning we'd need one background draw channel per merge group (1-4). // Draw channel allocation (before merging): -// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == 1 draw call) (FIXME-TABLE: could merge bg2 and foreground?) +// - NoClip --> 2+D+1 channels: bg0/1 + bg2 + foreground (same clip rect == always 1 draw call) // - Clip --> 2+D+N channels // - FreezeRows --> 2+D+N*2 (unless scrolling value is zero) // - FreezeRows || FreezeColunns --> 3+D+N*2 (unless scrolling value is zero) @@ -2085,7 +2085,8 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table) // All our cell highlight are manually clipped with BgClipRect. When unfreezing it will be made smaller to fit scrolling rect. // (This technically isn't part of setting up draw channels, but is reasonably related to be done here) table->BgClipRect = table->InnerClipRect; - table->BgClipRectForDrawCmd = table->HostClipRect; + table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect; + table->Bg2ClipRectForDrawCmd = table->HostClipRect; IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y); } @@ -2288,19 +2289,17 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table) void ImGui::TableDrawBorders(ImGuiTable* table) { ImGuiWindow* inner_window = table->InnerWindow; - ImGuiWindow* outer_window = table->OuterWindow; table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_BG0); if (inner_window->Hidden || !table->HostClipRect.Overlaps(table->InnerClipRect)) return; ImDrawList* inner_drawlist = inner_window->DrawList; - ImDrawList* outer_drawlist = outer_window->DrawList; + inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false); // Draw inner border and resizing feedback 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; - if (table->Flags & ImGuiTableFlags_BordersInnerV) { for (int order_n = 0; order_n < table->ColumnsCount; order_n++) @@ -2351,23 +2350,21 @@ void ImGui::TableDrawBorders(ImGuiTable* table) // parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part // of it in inner window, and the part that's over scrollbars in the outer window..) // Either solution currently won't allow us to use a larger border size: the border would clipped. - ImRect outer_border = table->OuterRect; + const ImRect outer_border = table->OuterRect; const ImU32 outer_col = table->BorderColorStrong; - if (inner_window != outer_window) // FIXME-TABLE - outer_border.Expand(1.0f); if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter) { - outer_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size); + inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, ~0, border_size); } else if (table->Flags & ImGuiTableFlags_BordersOuterV) { - outer_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size); - outer_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size); + inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size); + inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size); } else if (table->Flags & ImGuiTableFlags_BordersOuterH) { - outer_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size); - outer_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size); + inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size); + inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size); } } if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y) @@ -2377,6 +2374,8 @@ void ImGui::TableDrawBorders(ImGuiTable* table) 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); } + + inner_drawlist->PopClipRect(); } //------------------------------------------------------------------------- @@ -2638,7 +2637,6 @@ void ImGui::TableHeadersRow() // Emit a column header (text + optional sort order) // We cpu-clip text here so that all columns headers can be merged into a same draw call. // Note that because of how we cpu-clip and display sorting indicators, you _cannot_ use SameLine() after a TableHeader() -// FIXME-TABLE: Style confusion between CellPadding.y and FramePadding.y void ImGui::TableHeader(const char* label) { ImGuiContext& g = *GImGui; @@ -2660,7 +2658,7 @@ void ImGui::TableHeader(const char* label) ImVec2 label_pos = window->DC.CursorPos; // If we already got a row height, there's use that. - // FIXME-TABLE-PADDING: Problem if the correct outer-padding CellBgRect strays off our ClipRect + // FIXME-TABLE: Padding problem if the correct outer-padding CellBgRect strays off our ClipRect? ImRect cell_r = TableGetCellBgRect(table, column_n); float label_height = ImMax(label_size.y, table->RowMinHeight - table->CellPaddingY * 2.0f); @@ -2671,7 +2669,7 @@ void ImGui::TableHeader(const char* label) const float ARROW_SCALE = 0.65f; if ((table->Flags & ImGuiTableFlags_Sortable) && !(column->Flags & ImGuiTableColumnFlags_NoSort)) { - w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x);// table->CellPadding.x); + w_arrow = ImFloor(g.FontSize * ARROW_SCALE + g.Style.FramePadding.x); if (column->SortOrder > 0) { ImFormatString(sort_order_suf, IM_ARRAYSIZE(sort_order_suf), "%d", column->SortOrder + 1);