refactor(market): extract pfSegmentedControl helper

Collapse the two identical equal-width segmented controls (the detail section
switcher Appearance/Price/Addresses and the address type filter
All/Shielded/Transparent) into one pfSegmentedControl(dl, origin, w, h, labels,
count, selected, font, idBase, dp) that returns the clicked index. Same track /
active-pill / centered-label drawing and per-cell hit-test as before; the
variable-width chart-interval strip is left as-is. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-03 23:56:51 -05:00
parent d689b02de9
commit 14b08d1358

View File

@@ -286,6 +286,40 @@ static void pfRightAlignX(float w)
if (avail > w) ImGui::SetCursorPosX(ImGui::GetCursorPosX() + avail - w);
}
// Draw an equal-width segmented control (rounded track + N cells, each with a centered label and an
// active pill) at screen-space `origin`, spanning `totalW` x `height`. Every cell is a hit-tested
// InvisibleButton (Hand cursor on hover), disambiguated by `idBase`. Does NOT move the layout cursor
// afterward — the caller positions the next content. Returns the clicked cell index, or -1.
static int pfSegmentedControl(ImDrawList* dl, ImVec2 origin, float totalW, float height,
const char* const* labels, int count, int selected,
ImFont* font, const char* idBase, float dp)
{
int clicked = -1;
float cellW = totalW / (float)count;
dl->AddRectFilled(origin, ImVec2(origin.x + totalW, origin.y + height),
WithAlpha(OnSurface(), 20), height * 0.5f);
for (int i = 0; i < count; i++) {
ImVec2 cMin(origin.x + i * cellW, origin.y), cMax(cMin.x + cellW, origin.y + height);
bool active = (selected == i);
bool hov = ImGui::IsMouseHoveringRect(cMin, cMax);
if (active)
dl->AddRectFilled(ImVec2(cMin.x + 2.0f * dp, cMin.y + 2.0f * dp),
ImVec2(cMax.x - 2.0f * dp, cMax.y - 2.0f * dp),
WithAlpha(Primary(), 210), (height - 4.0f * dp) * 0.5f);
ImVec2 ts = font->CalcTextSizeA(font->LegacySize, FLT_MAX, 0, labels[i]);
dl->AddText(font, font->LegacySize,
ImVec2(cMin.x + (cellW - ts.x) * 0.5f, cMin.y + (height - ts.y) * 0.5f),
active ? IM_COL32(255, 255, 255, 255) : (hov ? OnSurface() : OnSurfaceMedium()),
labels[i]);
ImGui::PushID(i);
ImGui::SetCursorScreenPos(cMin);
if (ImGui::InvisibleButton(idBase, ImVec2(cellW, height))) clicked = i;
if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
ImGui::PopID();
}
return clicked;
}
static void pfDrawSparkline(ImDrawList* dl, ImVec2 mn, ImVec2 mx,
const std::vector<double>& hist, ImU32 col)
{
@@ -757,29 +791,10 @@ static void RenderPortfolioEditor(App* app)
TR("portfolio_addresses_hdr") };
float segH = 30.0f * dp;
float segW = ImGui::GetContentRegionAvail().x;
float cellW = segW / 3.0f;
ImVec2 sMin = ImGui::GetCursorScreenPos();
ImDrawList* sdl = ImGui::GetWindowDrawList();
sdl->AddRectFilled(sMin, ImVec2(sMin.x + segW, sMin.y + segH), WithAlpha(OnSurface(), 20), segH * 0.5f);
for (int s = 0; s < 3; s++) {
ImVec2 cMin(sMin.x + s * cellW, sMin.y), cMax(cMin.x + cellW, sMin.y + segH);
bool active = (s_pf_section == s);
bool hov = ImGui::IsMouseHoveringRect(cMin, cMax);
if (active)
sdl->AddRectFilled(ImVec2(cMin.x + 2.0f * dp, cMin.y + 2.0f * dp),
ImVec2(cMax.x - 2.0f * dp, cMax.y - 2.0f * dp),
WithAlpha(Primary(), 210), (segH - 4.0f * dp) * 0.5f);
ImVec2 ts = body2f->CalcTextSizeA(body2f->LegacySize, FLT_MAX, 0, secs[s]);
sdl->AddText(body2f, body2f->LegacySize,
ImVec2(cMin.x + (cellW - ts.x) * 0.5f, cMin.y + (segH - ts.y) * 0.5f),
active ? IM_COL32(255, 255, 255, 255) : (hov ? OnSurface() : OnSurfaceMedium()),
secs[s]);
ImGui::PushID(s);
ImGui::SetCursorScreenPos(cMin);
if (ImGui::InvisibleButton("##pfseg", ImVec2(cellW, segH))) s_pf_section = s;
if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
ImGui::PopID();
}
int clk = pfSegmentedControl(ImGui::GetWindowDrawList(), sMin, segW, segH,
secs, 3, s_pf_section, body2f, "##pfseg", dp);
if (clk >= 0) s_pf_section = clk;
ImGui::SetCursorScreenPos(ImVec2(sMin.x, sMin.y + segH));
ImGui::Dummy(ImVec2(segW, 0));
}
@@ -1016,29 +1031,9 @@ static void RenderPortfolioEditor(App* app)
ImVec2 rowStart = ImGui::GetCursorScreenPos();
// Segmented type filter (left), vertically centered in the row.
float segY = rowStart.y + (rowH - segH) * 0.5f;
float cellW = segW / 3.0f;
ImDrawList* fdl = ImGui::GetWindowDrawList();
fdl->AddRectFilled(ImVec2(rowStart.x, segY), ImVec2(rowStart.x + segW, segY + segH),
WithAlpha(OnSurface(), 20), segH * 0.5f);
for (int f = 0; f < 3; f++) {
ImVec2 cMin(rowStart.x + f * cellW, segY), cMax(cMin.x + cellW, segY + segH);
bool active = (s_pf_type_filter == f);
bool hov = ImGui::IsMouseHoveringRect(cMin, cMax);
if (active)
fdl->AddRectFilled(ImVec2(cMin.x + 2.0f * dp, cMin.y + 2.0f * dp),
ImVec2(cMax.x - 2.0f * dp, cMax.y - 2.0f * dp),
WithAlpha(Primary(), 210), (segH - 4.0f * dp) * 0.5f);
ImVec2 ts = capF->CalcTextSizeA(capF->LegacySize, FLT_MAX, 0, flabels[f]);
fdl->AddText(capF, capF->LegacySize,
ImVec2(cMin.x + (cellW - ts.x) * 0.5f, cMin.y + (segH - ts.y) * 0.5f),
active ? IM_COL32(255, 255, 255, 255) : (hov ? OnSurface() : OnSurfaceMedium()),
flabels[f]);
ImGui::PushID(3100 + f);
ImGui::SetCursorScreenPos(cMin);
if (ImGui::InvisibleButton("##pftf", ImVec2(cellW, segH))) s_pf_type_filter = f;
if (ImGui::IsItemHovered()) ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
ImGui::PopID();
}
int tclk = pfSegmentedControl(ImGui::GetWindowDrawList(), ImVec2(rowStart.x, segY),
segW, segH, flabels, 3, s_pf_type_filter, capF, "##pftf", dp);
if (tclk >= 0) s_pf_type_filter = tclk;
// Select all / Clear (rounded pills) + Funded toggle (right), vertically centered.
float grpX = rowStart.x + std::max(0.0f, rowW - groupW);
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.0f * dp);