From d0ca2fdf5211eecdc2178401ebdc0561bbf78b1a Mon Sep 17 00:00:00 2001 From: DanS Date: Tue, 21 Jul 2026 16:03:36 -0500 Subject: [PATCH] feat(settings): wrap crammed checkbox rows + cleanup (sweep) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Step 5. The Wallet privacy/daemon checkbox row and the Advanced-Effects checkbox row shrank their text (SetWindowFontScale) to cram onto one line — they now wrap to new rows at full size instead, so nothing clips on narrow windows (the lite "Animate avatars" was being cut off). Also drop two now-unused locals left over from the Node/Daemon rebuild. (The Explorer row, the RPC collapsible header, and the secondary/compact effects layout are left for a later polish pass.) Co-Authored-By: Claude Opus 4.8 (1M context) --- src/ui/pages/settings_page.cpp | 82 ++++++++++++++++------------------ 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/src/ui/pages/settings_page.cpp b/src/ui/pages/settings_page.cpp index 7d36984..6941bb1 100644 --- a/src/ui/pages/settings_page.cpp +++ b/src/ui/pages/settings_page.cpp @@ -878,7 +878,17 @@ void RenderSettingsPage(App* app) { if (s_settingsState.effects_expanded) { ImGui::PushFont(body2); - // Checkbox row: Low-spec | Console scanline | Theme effects | Gradient background + // Effects checkboxes — wrap to new rows instead of overflowing on narrow windows. + const float efFh = ImGui::GetFrameHeight(); + const float efInner = ImGui::GetStyle().ItemInnerSpacing.x; + float efX = 0.0f; bool efFirst = true; + auto efFlow = [&](const char* label) { + const float w = efFh + efInner + ImGui::CalcTextSize(label).x; + if (efFirst) { efFirst = false; efX = w; } + else if (efX + Layout::spacingLg() + w <= contentW) { ImGui::SameLine(0, Layout::spacingLg()); efX += Layout::spacingLg() + w; } + else { efX = w; } + }; + efFlow(TR("low_spec_mode")); if (ImGui::Checkbox(TrId("low_spec_mode", "low_spec").c_str(), &s_settingsState.low_spec_mode)) { effects::setLowSpecMode(s_settingsState.low_spec_mode); if (s_settingsState.low_spec_mode) { @@ -890,14 +900,14 @@ void RenderSettingsPage(App* app) { } if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_low_spec")); - ImGui::SameLine(0, Layout::spacingLg()); + efFlow(TR("simple_background")); if (ImGui::Checkbox(TrId("simple_background", "simple_bg").c_str(), &s_settingsState.gradient_background)) { schema::SkinManager::instance().setGradientMode(s_settingsState.gradient_background); saveSettingsPageState(app->settings()); } if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_simple_bg")); - ImGui::SameLine(0, Layout::spacingLg()); + efFlow(TR("reduce_motion")); if (ImGui::Checkbox(TrId("reduce_motion", "reduce_motion").c_str(), &s_settingsState.reduce_motion)) { saveSettingsPageState(app->settings()); } @@ -905,7 +915,7 @@ void RenderSettingsPage(App* app) { ImGui::BeginDisabled(s_settingsState.low_spec_mode); - ImGui::SameLine(0, Layout::spacingLg()); + efFlow(TR("console_scanline")); if (ImGui::Checkbox(TrId("console_scanline", "scanline").c_str(), &s_settingsState.scanline_enabled)) { ConsoleTab::s_scanline_enabled = s_settingsState.scanline_enabled; app->settings()->setScanlineEnabled(s_settingsState.scanline_enabled); @@ -913,14 +923,14 @@ void RenderSettingsPage(App* app) { } if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_scanline")); - ImGui::SameLine(0, Layout::spacingLg()); + efFlow(TR("theme_effects")); if (ImGui::Checkbox(TrId("theme_effects", "effects").c_str(), &s_settingsState.theme_effects_enabled)) { effects::ThemeEffects::instance().setEnabled(s_settingsState.theme_effects_enabled); saveSettingsPageState(app->settings()); } if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_theme_effects")); - ImGui::SameLine(0, Layout::spacingLg()); + efFlow(TR("animate_avatars")); { bool anim = app->settings()->getAnimateAvatars(); if (ImGui::Checkbox(TrId("animate_avatars", "animate_avatars").c_str(), &anim)) { @@ -1294,61 +1304,48 @@ void RenderSettingsPage(App* app) { ImGui::Dummy(ImVec2(0, Layout::spacingXs())); material::GlassCardScope card(dl, availWidth, pad, bottomPad, glassSpec); - const ImVec2& cardMin = card.cardMin; float contentW = availWidth - pad * 2; - // Privacy, Network & Daemon checkboxes — all on one line, shrink text to fit + // Privacy, Network & Daemon checkboxes — wrap to new rows instead of shrinking the text. { const bool showDaemonOptions = app->supportsFullNodeLifecycleActions(); - float cbSpacing = Layout::spacingMd(); - float fh = ImGui::GetFrameHeight(); - float inner = ImGui::GetStyle().ItemInnerSpacing.x; - auto cbW = [&](const char* label) { return fh + inner + ImGui::CalcTextSize(label).x; }; - - float totalW = cbW(TR("save_z_transactions")) + cbSpacing - + cbW(TR("auto_shield")) + cbSpacing - + cbW(TR("use_tor")) + cbSpacing; - if (showDaemonOptions) { - totalW += cbW(TR("keep_daemon")) + cbSpacing - + cbW(TR("stop_external")) + cbSpacing; - } - totalW += cbW(TR("verbose_logging")); - float scale = (totalW > contentW) ? contentW / totalW : 1.0f; - if (scale < 1.0f) ImGui::SetWindowFontScale(scale); - float sp = cbSpacing * scale; - + const float cbSpacing = Layout::spacingLg(); + const float fh = ImGui::GetFrameHeight(); + const float inner = ImGui::GetStyle().ItemInnerSpacing.x; + float cbX = 0.0f; bool cbFirst = true; + // Position the next checkbox: SameLine if it fits on the current row, else wrap. + auto cbFlow = [&](const char* label) { + const float w = fh + inner + ImGui::CalcTextSize(label).x; + if (cbFirst) { cbFirst = false; cbX = w; } + else if (cbX + cbSpacing + w <= contentW) { ImGui::SameLine(0, cbSpacing); cbX += cbSpacing + w; } + else { cbX = w; } + }; + cbFlow(TR("save_z_transactions")); ImGui::Checkbox(TrId("save_z_transactions", "save_ztx").c_str(), &s_settingsState.save_ztxs); if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_save_ztx")); - ImGui::SameLine(0, sp); + cbFlow(TR("auto_shield")); ImGui::Checkbox(TrId("auto_shield", "auto_shld").c_str(), &s_settingsState.auto_shield); if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_auto_shield")); - ImGui::SameLine(0, sp); + cbFlow(TR("use_tor")); ImGui::Checkbox(TrId("use_tor", "tor").c_str(), &s_settingsState.use_tor); if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_tor")); if (showDaemonOptions) { - ImGui::SameLine(0, sp); - if (ImGui::Checkbox(TrId("keep_daemon", "keep_dmn").c_str(), &s_settingsState.keep_daemon_running)) { + cbFlow(TR("keep_daemon")); + if (ImGui::Checkbox(TrId("keep_daemon", "keep_dmn").c_str(), &s_settingsState.keep_daemon_running)) saveSettingsPageState(app->settings()); - } - if (ImGui::IsItemHovered()) - material::Tooltip("%s", TR("tt_keep_daemon")); - ImGui::SameLine(0, sp); - if (ImGui::Checkbox(TrId("stop_external", "stop_ext").c_str(), &s_settingsState.stop_external_daemon)) { + if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_keep_daemon")); + cbFlow(TR("stop_external")); + if (ImGui::Checkbox(TrId("stop_external", "stop_ext").c_str(), &s_settingsState.stop_external_daemon)) saveSettingsPageState(app->settings()); - } - if (ImGui::IsItemHovered()) - material::Tooltip("%s", TR("tt_stop_external")); + if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_stop_external")); } - ImGui::SameLine(0, sp); + cbFlow(TR("verbose_logging")); if (ImGui::Checkbox(TrId("verbose_logging", "verbose").c_str(), &s_settingsState.verbose_logging)) { dragonx::util::Logger::instance().setVerbose(s_settingsState.verbose_logging); saveSettingsPageState(app->settings()); } - if (ImGui::IsItemHovered()) - material::Tooltip("%s", TR("tt_verbose")); - - if (scale < 1.0f) ImGui::SetWindowFontScale(1.0f); + if (ImGui::IsItemHovered()) material::Tooltip("%s", TR("tt_verbose")); } ImGui::Dummy(ImVec2(0, Layout::spacingSm())); @@ -2152,7 +2149,6 @@ void RenderSettingsPage(App* app) { // -------------------- DAEMON BINARY -------------------- if (app->supportsFullNodeLifecycleActions()) { - ImFont* dbBtnFont = S.resolveFont("button"); if (!s_settingsState.daemon_info_loaded) { s_settingsState.installed_daemon = dragonx::resources::getInstalledDaemonInfo(); s_settingsState.bundled_daemon = dragonx::resources::getBundledDaemonInfo();