feat(settings): two-column NODE & SECURITY card (B) — fill the empty right side

The NODE & SECURITY card stacked Node / RPC / Security / Daemon-binary in one
full-width column, packing everything on the left. Split it into two columns when
the card is wide enough: Node + RPC + Security on the left, Daemon binary on the
right — which fills the previously-empty right half and roughly halves the card's
height. Falls back to a single column on narrow windows (and when there's no
daemon section). Implemented by shadowing contentW + sectionOrigin per column
(renderSecuritySection already takes an explicit width/origin), so every
sub-section lays out within its column; the card auto-sizes to the taller column.
Full-node only for now; the lite Node section stays single-column.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-21 17:15:32 -05:00
parent d0ca2fdf52
commit 77a0ad64b0

View File

@@ -1986,6 +1986,17 @@ void RenderSettingsPage(App* app) {
const float spMd = Layout::spacingMd();
// Two-column layout when wide enough: Node / RPC / Security on the left, Daemon binary on
// the right (fills the empty right side + shortens the card). One column when narrow.
const bool nsHasDaemon = app->supportsFullNodeLifecycleActions();
const float nsColGap = Layout::spacingXl();
const bool nsTwoCol = nsHasDaemon && contentW > 760.0f * Layout::dpiScale();
const float nsColW = nsTwoCol ? (contentW - nsColGap) * 0.5f : contentW;
const ImVec2 nsColTop = ImGui::GetCursorScreenPos();
{ // ---- left column (Node / RPC / Security) ----
const float contentW = nsColW;
const ImVec2 sectionOrigin(nsColTop.x, nsColTop.y);
// -------------------- NODE / DATA --------------------
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("node"));
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
@@ -2146,6 +2157,13 @@ void RenderSettingsPage(App* app) {
Type().textColored(TypeStyle::Overline, OnSurfaceMedium(), TR("security"));
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
renderSecuritySection(sectionOrigin.x, contentW, /*includeRpcEncrypt=*/true);
} // ---- end left column ----
const float nsLeftBottom = ImGui::GetCursorScreenPos().y;
if (nsTwoCol) ImGui::SetCursorScreenPos(ImVec2(nsColTop.x + nsColW + nsColGap, nsColTop.y));
{ // ---- right column (Daemon binary) ----
const float contentW = nsColW;
const ImVec2 sectionOrigin(nsTwoCol ? nsColTop.x + nsColW + nsColGap : nsColTop.x,
nsTwoCol ? nsColTop.y : ImGui::GetCursorScreenPos().y);
// -------------------- DAEMON BINARY --------------------
if (app->supportsFullNodeLifecycleActions()) {
@@ -2295,11 +2313,11 @@ void RenderSettingsPage(App* app) {
ImGui::EndDisabled();
}
}
} // ---- end right column ----
const float nsRightBottom = ImGui::GetCursorScreenPos().y;
ImGui::SetCursorScreenPos(ImVec2(nsColTop.x, nsTwoCol ? std::max(nsLeftBottom, nsRightBottom) : nsRightBottom));
ImGui::PopFont();
// Advance to the true bottom of the single column.
ImGui::SetCursorScreenPos(ImVec2(sectionOrigin.x, ImGui::GetCursorScreenPos().y));
}
}
}