perf(market): clip off-screen rows in the portfolio editor

The portfolio-editor address list drew every row every frame inside the
fade-scroll child. It now runs through an ImGuiListClipper; the fixed
step (the InvisibleButton height plus item spacing) keeps each row's
cursor exactly where the unclipped loop put it, so the scroll extent for
the fade shader, the check marks, the selection and the "selected rows
float to the top" ordering are all unchanged.

Verified on DX11 (Windows) at normal and large window sizes and at
font scale 1.5, including skin switch and resize with the dialog open.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-10-14 16:55:07 -05:00
co-authored by Claude Opus 4.8
parent 4d95ef68f6
commit e40c6c0a7c
+9 -2
View File
@@ -694,8 +694,14 @@ static void pfDrawAddressSection(App* app)
float lw = ImGui::GetContentRegionAvail().x;
if (filtered.empty())
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("portfolio_no_addr_match"));
for (const PfPick& pk : filtered) {
const AddressInfo& a = *pk.a;
// C181: clip the portfolio-editor rows. Fixed step = InvisibleButton height (rowH) + ItemSpacing.y,
// so each row's cursor (and the Layout density tokens that read the content region) is exactly where
// the unclipped loop put it; the scroll extent stays exact for the fade shader.
ImGuiListClipper rowClipper;
rowClipper.Begin(static_cast<int>(filtered.size()), rowH + ImGui::GetStyle().ItemSpacing.y);
while (rowClipper.Step()) {
for (int ri = rowClipper.DisplayStart; ri < rowClipper.DisplayEnd; ++ri) {
const AddressInfo& a = *filtered[static_cast<size_t>(ri)].a;
bool inSet = selSet.count(a.address) != 0;
ImVec2 rmn = ImGui::GetCursorScreenPos();
ImVec2 rmx(rmn.x + lw, rmn.y + rowH);
@@ -750,6 +756,7 @@ static void pfDrawAddressSection(App* app)
}
ImGui::PopID();
}
} // while (rowClipper.Step())
material::EndFadeScrollChild(s_pfEdit.addrFade, ldl);
}