perf(contacts): clip off-screen rows in the Cards and List views
The contacts Cards/List row loop submitted every contact every frame. It now runs through an ImGuiListClipper, so only the on-screen rows are built; the fixed step (row height plus the item spacing pushed above) matches the per-row cursor exactly, so the scroll extent, fade, hover actions, selection and keyboard navigation are unchanged. Table view is left unclipped (its rows can wrap). Verified on DX11 (Windows) at normal and large window sizes and at font scale 1.5, in both Cards and List views. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1310,8 +1310,15 @@ void RenderContactsTab(App* app)
|
|||||||
const float lblSz = lblF->LegacySize * sc; // scaled label + address text
|
const float lblSz = lblF->LegacySize * sc; // scaled label + address text
|
||||||
const float adrSz = adrF->LegacySize * sc;
|
const float adrSz = adrF->LegacySize * sc;
|
||||||
bool rowDeleteRequested = false; // per-row delete is deferred until after the loop
|
bool rowDeleteRequested = false; // per-row delete is deferred until after the loop
|
||||||
for (size_t vi = 0; vi < visibleRows.size(); ++vi) {
|
// C183(c): clip the Cards/List rows. Fixed step = the Selectable height (rowH) plus the
|
||||||
size_t i = visibleRows[vi];
|
// ItemSpacing.y pushed above (8*dp card mode, 0 list mode); each row restores the cursor to
|
||||||
|
// `afterRow`, so the step is exact and the scroll extent is unchanged. (Table mode is NOT
|
||||||
|
// clipped -- its rows can wrap.)
|
||||||
|
ImGuiListClipper rowClipper;
|
||||||
|
rowClipper.Begin(static_cast<int>(visibleRows.size()), rowH + (asCard ? 8.0f * dp : 0.0f));
|
||||||
|
while (rowClipper.Step()) {
|
||||||
|
for (int vi = rowClipper.DisplayStart; vi < rowClipper.DisplayEnd; ++vi) {
|
||||||
|
size_t i = visibleRows[static_cast<size_t>(vi)];
|
||||||
const auto& entry = book.entries()[i];
|
const auto& entry = book.entries()[i];
|
||||||
ImGui::PushID(static_cast<int>(i));
|
ImGui::PushID(static_cast<int>(i));
|
||||||
const bool selected = (s_selected_index == static_cast<int>(i));
|
const bool selected = (s_selected_index == static_cast<int>(i));
|
||||||
@@ -1424,6 +1431,7 @@ void RenderContactsTab(App* app)
|
|||||||
ImGui::SetCursorScreenPos(afterRow); // undo the action buttons' cursor moves
|
ImGui::SetCursorScreenPos(afterRow); // undo the action buttons' cursor moves
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
}
|
}
|
||||||
|
} // while (rowClipper.Step())
|
||||||
// Run the deferred per-row delete now that the loop over book.entries() has finished
|
// Run the deferred per-row delete now that the loop over book.entries() has finished
|
||||||
// (doDelete's two-stage confirm arms on the first click and removes on the second).
|
// (doDelete's two-stage confirm arms on the first click and removes on the second).
|
||||||
if (rowDeleteRequested) doDelete();
|
if (rowDeleteRequested) doDelete();
|
||||||
|
|||||||
Reference in New Issue
Block a user