improved font scaling text and window adjustment, added ctrl + scroll hotkey for font scaling
This commit is contained in:
84
src/main.cpp
84
src/main.cpp
@@ -957,6 +957,10 @@ int main(int argc, char* argv[])
|
||||
// resizing on a 200% screen doesn't clobber the 100% size.
|
||||
std::map<int, std::pair<int,int>> savedSizeForScale;
|
||||
bool dpiResizePending = false;
|
||||
bool fontScaleResizePending = false;
|
||||
// Font-scale window reference: size at scale 1.0 (updated on user resize)
|
||||
float fontScaleRefFS = 0.0f;
|
||||
int fontScaleRefW = 0, fontScaleRefH = 0;
|
||||
// Track last known window size at the current DPI scale.
|
||||
// Updated on user-initiated resizes (not DPI auto-resizes).
|
||||
// When DISPLAY_SCALE_CHANGED fires, SDL_GetWindowSize() already
|
||||
@@ -1140,7 +1144,28 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Poll remaining events
|
||||
SDL_Event event;
|
||||
// Deferred font-scale commit: smooth visual update during Alt+scroll,
|
||||
// atlas rebuild after scrolling stops (~200ms idle).
|
||||
static Uint64 fontScaleCommitTick = 0; // 0 = nothing pending
|
||||
|
||||
while (SDL_PollEvent(&event)) {
|
||||
// Alt + scroll wheel: smooth font scale adjustment
|
||||
if (event.type == SDL_EVENT_MOUSE_WHEEL) {
|
||||
SDL_Keymod mods = SDL_GetModState();
|
||||
if (mods & SDL_KMOD_ALT) {
|
||||
float step = 0.05f * event.wheel.y;
|
||||
float cur = dragonx::ui::Layout::userFontScale();
|
||||
float next = std::max(1.0f, std::min(1.5f, cur + step));
|
||||
if (next != cur) {
|
||||
// Smooth preview — no atlas rebuild yet
|
||||
dragonx::ui::Layout::setUserFontScaleVisual(next);
|
||||
// Schedule atlas rebuild after scrolling stops
|
||||
fontScaleCommitTick = SDL_GetTicks() + 200;
|
||||
}
|
||||
// Don't pass Alt+scroll to ImGui (would scroll windows)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ImGui_ImplSDL3_ProcessEvent(&event);
|
||||
|
||||
if (event.type == SDL_EVENT_QUIT) {
|
||||
@@ -1167,11 +1192,20 @@ int main(int argc, char* argv[])
|
||||
bool isDpiResize = dpiResizePending ||
|
||||
std::abs(actualScale - storedScale) > 0.01f;
|
||||
if (dpiResizePending) dpiResizePending = false;
|
||||
bool isFSResize = fontScaleResizePending;
|
||||
if (fontScaleResizePending) fontScaleResizePending = false;
|
||||
if (!isDpiResize) {
|
||||
int pct = (int)lroundf(storedScale * 100.0f);
|
||||
savedSizeForScale[pct] = {event.window.data1, event.window.data2};
|
||||
lastKnownW = event.window.data1;
|
||||
lastKnownH = event.window.data2;
|
||||
// User manually resized — update the font-scale reference
|
||||
// so the next scale change is relative to this size.
|
||||
if (!isFSResize) {
|
||||
float fs = dragonx::ui::Layout::userFontScale();
|
||||
fontScaleRefW = (int)lroundf((float)event.window.data1 / fs);
|
||||
fontScaleRefH = (int)lroundf((float)event.window.data2 / fs);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Window restored from minimized — trigger immediate data refresh
|
||||
@@ -1279,6 +1313,15 @@ int main(int argc, char* argv[])
|
||||
// --- PerfLog: begin frame ---
|
||||
dragonx::util::PerfLog::instance().beginFrame();
|
||||
|
||||
// Commit deferred font-scale change once scrolling has stopped.
|
||||
if (fontScaleCommitTick != 0 && SDL_GetTicks() >= fontScaleCommitTick) {
|
||||
fontScaleCommitTick = 0;
|
||||
float fs = dragonx::ui::Layout::userFontScale();
|
||||
dragonx::ui::Layout::setUserFontScale(fs);
|
||||
app.settings()->setFontScale(fs);
|
||||
app.settings()->save();
|
||||
}
|
||||
|
||||
// Pre-frame: font atlas rebuilds and schema hot-reload must
|
||||
// happen BEFORE NewFrame() because NewFrame() caches font ptrs.
|
||||
app.preFrame();
|
||||
@@ -1294,25 +1337,24 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// If font scale changed, resize window proportionally.
|
||||
// anchorW/H = the window size at the moment the anchor was set.
|
||||
// anchorFS = the font scale at that moment.
|
||||
// target = anchorW * curFS / anchorFS (symmetric, no drift).
|
||||
// Reference size (at scale 1.0) is updated on user-initiated resizes
|
||||
// so the next scale change is relative to the current window, not a
|
||||
// stale snapshot. target = ref * curFS — no rounding drift.
|
||||
{
|
||||
static float anchorFS = 0.0f;
|
||||
static int anchorW = 0, anchorH = 0;
|
||||
float curFS = dragonx::ui::Layout::userFontScale();
|
||||
|
||||
if (anchorFS < 0.001f) {
|
||||
// First frame: the current window IS the reference for
|
||||
// whatever font scale is loaded — no resize.
|
||||
anchorFS = curFS;
|
||||
SDL_GetWindowSize(window, &anchorW, &anchorH);
|
||||
if (fontScaleRefFS < 0.001f) {
|
||||
// First frame — record reference, no resize.
|
||||
fontScaleRefFS = curFS;
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
fontScaleRefW = (int)lroundf((float)w / curFS);
|
||||
fontScaleRefH = (int)lroundf((float)h / curFS);
|
||||
}
|
||||
|
||||
if (std::fabs(curFS - anchorFS) > 0.001f) {
|
||||
float ratio = curFS / anchorFS;
|
||||
int newW = (int)lroundf((float)anchorW * ratio);
|
||||
int newH = (int)lroundf((float)anchorH * ratio);
|
||||
if (std::fabs(curFS - fontScaleRefFS) > 0.001f) {
|
||||
int newW = (int)lroundf((float)fontScaleRefW * curFS);
|
||||
int newH = (int)lroundf((float)fontScaleRefH * curFS);
|
||||
|
||||
// Clamp to display work area
|
||||
SDL_DisplayID did = SDL_GetDisplayForWindow(window);
|
||||
@@ -1325,21 +1367,15 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
float hwDpi = dragonx::ui::Layout::rawDpiScale();
|
||||
// Update minimum size BEFORE resizing so the window can
|
||||
// actually shrink when the font scale decreases.
|
||||
SDL_SetWindowMinimumSize(window,
|
||||
(int)(1024 * hwDpi * curFS),
|
||||
(int)(720 * hwDpi * curFS));
|
||||
(int)(1024 * hwDpi),
|
||||
(int)(720 * hwDpi));
|
||||
fontScaleResizePending = true;
|
||||
SDL_SetWindowSize(window, newW, newH);
|
||||
lastKnownW = newW;
|
||||
lastKnownH = newH;
|
||||
|
||||
// Update anchor so we don't re-fire every frame.
|
||||
// The new anchor becomes the current size/scale so
|
||||
// subsequent slider movements are relative to here.
|
||||
anchorW = newW;
|
||||
anchorH = newH;
|
||||
anchorFS = curFS;
|
||||
fontScaleRefFS = curFS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +70,10 @@ inline void setFontAtlasScale(float v) { detail::fontAtlasScaleRef() = v; }
|
||||
*/
|
||||
inline void setUserFontScale(float v) {
|
||||
v = std::max(1.0f, std::min(1.5f, v));
|
||||
if (v != detail::userFontScaleRef()) {
|
||||
detail::userFontScaleRef() = v;
|
||||
detail::userFontScaleRef() = v;
|
||||
// Compare against the atlas scale, not the live ref — setUserFontScaleVisual
|
||||
// may have already updated the ref during slider drag.
|
||||
if (v != detail::fontAtlasScaleRef()) {
|
||||
detail::fontReloadNeededRef() = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -916,6 +916,8 @@ void RenderSettingsPage(App* app) {
|
||||
float fontSliderW = std::max(S.drawElement("components.settings-page", "effects-input-min-width").size,
|
||||
availWidth - pad * 2);
|
||||
ImGui::SetNextItemWidth(fontSliderW);
|
||||
// Sync from Layout so Alt+scroll hotkey changes are reflected
|
||||
sp_font_scale = Layout::userFontScale();
|
||||
float prev_font_scale = sp_font_scale;
|
||||
{
|
||||
char fs_fmt[16];
|
||||
@@ -923,10 +925,11 @@ void RenderSettingsPage(App* app) {
|
||||
ImGui::SliderFloat("##FontScale", &sp_font_scale, 1.0f, 1.5f, fs_fmt,
|
||||
ImGuiSliderFlags_AlwaysClamp);
|
||||
}
|
||||
// Smooth continuous scaling while dragging.
|
||||
// Snap to 0.05 increments for consistent stepping.
|
||||
// Visual scaling uses FontScaleMain (no atlas rebuild),
|
||||
// atlas rebuild is deferred to slider release for crisp text.
|
||||
sp_font_scale = std::max(1.0f, std::min(1.5f, sp_font_scale));
|
||||
sp_font_scale = std::max(1.0f, std::min(1.5f,
|
||||
std::round(sp_font_scale * 20.0f) / 20.0f));
|
||||
if (sp_font_scale != prev_font_scale) {
|
||||
// While dragging: update layout scale without atlas rebuild
|
||||
Layout::setUserFontScaleVisual(sp_font_scale);
|
||||
|
||||
@@ -388,9 +388,10 @@ static void RenderBalanceClassic(App* app)
|
||||
float classicCardH = S.drawElement("tabs.balance.classic", "card-height").size;
|
||||
float cardH;
|
||||
if (classicCardH >= 0.0f) {
|
||||
cardH = classicCardH; // explicit override from ui.toml
|
||||
// TOML override scaled by dp so it grows with DPI + user font scale
|
||||
cardH = std::max(classicCardH * dp, marketContentH);
|
||||
} else {
|
||||
float minH = S.drawElement("tabs.balance.classic", "card-min-height").sizeOr(70.0f);
|
||||
float minH = S.drawElement("tabs.balance.classic", "card-min-height").sizeOr(70.0f) * dp;
|
||||
cardH = std::max(StatCardHeight(vs, minH), marketContentH);
|
||||
}
|
||||
|
||||
@@ -814,7 +815,7 @@ static void RenderBalanceClassic(App* app)
|
||||
float classicAddrH = S.drawElement("tabs.balance.classic", "address-table-height").size;
|
||||
float addrListH;
|
||||
if (classicAddrH >= 0.0f) {
|
||||
addrListH = classicAddrH; // explicit override from ui.toml
|
||||
addrListH = classicAddrH * dp; // scaled for DPI + font scale
|
||||
} else {
|
||||
addrListH = ImGui::GetContentRegionAvail().y - recentTxReserve;
|
||||
}
|
||||
@@ -1881,14 +1882,20 @@ static void RenderBalanceDonut(App* app) {
|
||||
|
||||
// --- Donut + legend panel ---
|
||||
{
|
||||
ImFont* donutOv = Type().overline();
|
||||
ImFont* donutCap = Type().caption();
|
||||
// Font-content floor: legend needs overline + 3 caption lines + spacing
|
||||
float donutFontFloor = Layout::spacingLg() * 2
|
||||
+ donutOv->LegacySize + Layout::spacingMd()
|
||||
+ donutCap->LegacySize * 3 + Layout::spacingSm() * 3;
|
||||
float donutCardH = S.drawElement("tabs.balance.donut", "card-height").size;
|
||||
float panelH;
|
||||
if (donutCardH >= 0.0f) {
|
||||
panelH = donutCardH; // explicit override from ui.toml
|
||||
panelH = std::max(donutCardH * dp, donutFontFloor);
|
||||
} else {
|
||||
panelH = std::max(
|
||||
S.drawElement("tabs.balance.donut", "panel-min-height").sizeOr(80.0f),
|
||||
contentAvail.y * S.drawElement("tabs.balance.donut", "panel-height-ratio").sizeOr(0.20f));
|
||||
panelH = std::max({donutFontFloor,
|
||||
S.drawElement("tabs.balance.donut", "panel-min-height").sizeOr(80.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.donut", "panel-height-ratio").sizeOr(0.20f)});
|
||||
}
|
||||
ImVec2 panelMin = ImGui::GetCursorScreenPos();
|
||||
ImVec2 panelMax(panelMin.x + availW, panelMin.y + panelH);
|
||||
@@ -1985,7 +1992,7 @@ static void RenderBalanceDonut(App* app) {
|
||||
// --- Shared address list + recent tx ---
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float donutAddrOverride = S.drawElement("tabs.balance.donut", "address-table-height").size;
|
||||
float addrH = (donutAddrOverride >= 0.0f) ? donutAddrOverride
|
||||
float addrH = (donutAddrOverride >= 0.0f) ? donutAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -2016,14 +2023,25 @@ static void RenderBalanceConsolidated(App* app) {
|
||||
if (consTopMargin >= 0.0f)
|
||||
ImGui::Dummy(ImVec2(0, consTopMargin));
|
||||
|
||||
ImFont* heroFont = Type().h2();
|
||||
ImFont* sub1 = Type().subtitle1();
|
||||
ImFont* capFont = Type().caption();
|
||||
ImFont* ovFont = Type().overline();
|
||||
float consPadOverride = S.drawElement("tabs.balance.consolidated", "card-padding").size;
|
||||
float pad = (consPadOverride >= 0.0f) ? consPadOverride : Layout::spacingLg();
|
||||
// Font-content floor: pad + overline + hero + caption + subtitle + pad
|
||||
float consFontFloor = pad + ovFont->LegacySize + Layout::spacingSm()
|
||||
+ heroFont->LegacySize + Layout::spacingSm()
|
||||
+ capFont->LegacySize + Layout::spacingSm()
|
||||
+ sub1->LegacySize + pad;
|
||||
float consCardH = S.drawElement("tabs.balance.consolidated", "card-height").size;
|
||||
float cardH;
|
||||
if (consCardH >= 0.0f) {
|
||||
cardH = consCardH; // explicit override from ui.toml
|
||||
cardH = std::max(consCardH * dp, consFontFloor);
|
||||
} else {
|
||||
cardH = std::max(
|
||||
S.drawElement("tabs.balance.consolidated", "card-min-height").sizeOr(90.0f),
|
||||
contentAvail.y * S.drawElement("tabs.balance.consolidated", "card-height-ratio").sizeOr(0.22f));
|
||||
cardH = std::max({consFontFloor,
|
||||
S.drawElement("tabs.balance.consolidated", "card-min-height").sizeOr(90.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.consolidated", "card-height-ratio").sizeOr(0.22f)});
|
||||
}
|
||||
ImVec2 cardMin = ImGui::GetCursorScreenPos();
|
||||
ImVec2 cardMax(cardMin.x + availW, cardMin.y + cardH);
|
||||
@@ -2031,17 +2049,11 @@ static void RenderBalanceConsolidated(App* app) {
|
||||
spec.rounding = glassRound;
|
||||
DrawGlassPanel(dl, cardMin, cardMax, spec);
|
||||
|
||||
float consPadOverride = S.drawElement("tabs.balance.consolidated", "card-padding").size;
|
||||
float pad = (consPadOverride >= 0.0f) ? consPadOverride : Layout::spacingLg();
|
||||
float cx = cardMin.x + pad;
|
||||
float cy = cardMin.y + pad;
|
||||
|
||||
// Coin logo
|
||||
ImTextureID logoTex = app->getCoinLogoTexture();
|
||||
ImFont* heroFont = Type().h2();
|
||||
ImFont* sub1 = Type().subtitle1();
|
||||
ImFont* capFont = Type().caption();
|
||||
ImFont* ovFont = Type().overline();
|
||||
|
||||
float logoSz = heroFont->LegacySize + capFont->LegacySize + 4.0f * dp;
|
||||
if (logoTex != 0) {
|
||||
@@ -2157,7 +2169,7 @@ static void RenderBalanceConsolidated(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float consAddrOverride = S.drawElement("tabs.balance.consolidated", "address-table-height").size;
|
||||
float addrH = (consAddrOverride >= 0.0f) ? consAddrOverride
|
||||
float addrH = (consAddrOverride >= 0.0f) ? consAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -2199,22 +2211,28 @@ static void RenderBalanceDashboard(App* app) {
|
||||
: (int)S.drawElement("tabs.balance.dashboard", "tile-num-cols").sizeOr(4.0f);
|
||||
int numRows = (numCols == 2) ? 2 : 1;
|
||||
float tileW = (availW - (numCols - 1) * cGap) / numCols;
|
||||
ImFont* ovFont = Type().overline();
|
||||
ImFont* sub1 = Type().subtitle1();
|
||||
ImFont* capFont = Type().caption();
|
||||
// Font-content floor: pad + overline + subtitle1 + caption + pad
|
||||
float dashFontFloor = Layout::spacingLg()
|
||||
+ ovFont->LegacySize + Layout::spacingSm()
|
||||
+ sub1->LegacySize + Layout::spacingSm()
|
||||
+ capFont->LegacySize
|
||||
+ Layout::spacingLg();
|
||||
float dashCardH = S.drawElement("tabs.balance.dashboard", "card-height").size;
|
||||
float tileH;
|
||||
if (dashCardH >= 0.0f) {
|
||||
tileH = dashCardH; // explicit override from ui.toml
|
||||
tileH = std::max(dashCardH * dp, dashFontFloor);
|
||||
} else {
|
||||
tileH = std::max(
|
||||
S.drawElement("tabs.balance.dashboard", "tile-min-height").sizeOr(70.0f),
|
||||
contentAvail.y * S.drawElement("tabs.balance.dashboard", "tile-height-ratio").sizeOr(0.16f) / numRows);
|
||||
tileH = std::max({dashFontFloor,
|
||||
S.drawElement("tabs.balance.dashboard", "tile-min-height").sizeOr(70.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.dashboard", "tile-height-ratio").sizeOr(0.16f) / numRows});
|
||||
}
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
|
||||
GlassPanelSpec tileSpec;
|
||||
tileSpec.rounding = glassRound;
|
||||
ImFont* ovFont = Type().overline();
|
||||
ImFont* sub1 = Type().subtitle1();
|
||||
ImFont* capFont = Type().caption();
|
||||
|
||||
struct TileInfo {
|
||||
const char* label;
|
||||
@@ -2299,7 +2317,7 @@ static void RenderBalanceDashboard(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float dashAddrOverride = S.drawElement("tabs.balance.dashboard", "address-table-height").size;
|
||||
float addrH = (dashAddrOverride >= 0.0f) ? dashAddrOverride
|
||||
float addrH = (dashAddrOverride >= 0.0f) ? dashAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -2329,23 +2347,28 @@ static void RenderBalanceVerticalStack(App* app) {
|
||||
if (vstackTopMargin >= 0.0f)
|
||||
ImGui::Dummy(ImVec2(0, vstackTopMargin));
|
||||
|
||||
float vstackCardH = S.drawElement("tabs.balance.vertical-stack", "card-height").size;
|
||||
float stackH;
|
||||
if (vstackCardH >= 0.0f) {
|
||||
stackH = vstackCardH; // explicit override from ui.toml
|
||||
} else {
|
||||
stackH = std::max(
|
||||
S.drawElement("tabs.balance.vertical-stack", "stack-min-height").sizeOr(80.0f),
|
||||
contentAvail.y * S.drawElement("tabs.balance.vertical-stack", "stack-height-ratio").sizeOr(0.16f));
|
||||
}
|
||||
float rowGap = S.drawElement("tabs.balance.vertical-stack", "row-gap").sizeOr(2.0f);
|
||||
float rowH = (stackH - 3 * rowGap) / 4.0f;
|
||||
float rowMinH = S.drawElement("tabs.balance.vertical-stack", "row-min-height").sizeOr(20.0f);
|
||||
if (rowH < rowMinH) rowH = rowMinH;
|
||||
|
||||
ImFont* capFont = Type().caption();
|
||||
ImFont* body2 = Type().body2();
|
||||
ImFont* sub1 = Type().subtitle1();
|
||||
// Font-content floor per row: icon + label + value must fit
|
||||
float vstackRowFontFloor = std::max(body2->LegacySize, capFont->LegacySize)
|
||||
+ Layout::spacingSm() * 2;
|
||||
float rowGap = S.drawElement("tabs.balance.vertical-stack", "row-gap").sizeOr(2.0f);
|
||||
float vstackFontFloor = vstackRowFontFloor * 4 + rowGap * 3;
|
||||
float vstackCardH = S.drawElement("tabs.balance.vertical-stack", "card-height").size;
|
||||
float stackH;
|
||||
if (vstackCardH >= 0.0f) {
|
||||
stackH = std::max(vstackCardH * dp, vstackFontFloor);
|
||||
} else {
|
||||
stackH = std::max({vstackFontFloor,
|
||||
S.drawElement("tabs.balance.vertical-stack", "stack-min-height").sizeOr(80.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.vertical-stack", "stack-height-ratio").sizeOr(0.16f)});
|
||||
}
|
||||
float rowH = (stackH - 3 * rowGap) / 4.0f;
|
||||
float rowMinH = std::max(
|
||||
S.drawElement("tabs.balance.vertical-stack", "row-min-height").sizeOr(20.0f) * dp,
|
||||
vstackRowFontFloor);
|
||||
if (rowH < rowMinH) rowH = rowMinH;
|
||||
|
||||
float total = (float)s_dispTotal;
|
||||
float shieldRatio = (total > 1e-9f) ? (float)(s_dispShielded / total) : 0.5f;
|
||||
@@ -2473,7 +2496,7 @@ static void RenderBalanceVerticalStack(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float vstackAddrOverride = S.drawElement("tabs.balance.vertical-stack", "address-table-height").size;
|
||||
float addrH = (vstackAddrOverride >= 0.0f) ? vstackAddrOverride
|
||||
float addrH = (vstackAddrOverride >= 0.0f) ? vstackAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -2505,26 +2528,30 @@ static void RenderBalanceVertical2x2(App* app) {
|
||||
if (topMargin >= 0.0f)
|
||||
ImGui::Dummy(ImVec2(0, topMargin));
|
||||
|
||||
ImFont* capFont = Type().caption();
|
||||
ImFont* iconFont = Type().iconSmall();
|
||||
// Font-content floor per row: caption text + vertical padding
|
||||
float v2x2RowFontFloor = capFont->LegacySize + Layout::spacingSm() * 2;
|
||||
float rowGap = S.drawElement(cfgSec, "row-gap").sizeOr(2.0f);
|
||||
float colGap = S.drawElement(cfgSec, "col-gap").sizeOr(8.0f);
|
||||
float v2x2FontFloor = v2x2RowFontFloor * 2 + rowGap;
|
||||
float cardHOverride = S.drawElement(cfgSec, "card-height").size;
|
||||
float stackH;
|
||||
if (cardHOverride >= 0.0f) {
|
||||
stackH = cardHOverride;
|
||||
stackH = std::max(cardHOverride * dp, v2x2FontFloor);
|
||||
} else {
|
||||
stackH = std::max(
|
||||
S.drawElement(cfgSec, "stack-min-height").sizeOr(60.0f),
|
||||
contentAvail.y * S.drawElement(cfgSec, "stack-height-ratio").sizeOr(0.12f));
|
||||
stackH = std::max({v2x2FontFloor,
|
||||
S.drawElement(cfgSec, "stack-min-height").sizeOr(60.0f) * dp,
|
||||
contentAvail.y * S.drawElement(cfgSec, "stack-height-ratio").sizeOr(0.12f)});
|
||||
}
|
||||
float rowGap = S.drawElement(cfgSec, "row-gap").sizeOr(2.0f);
|
||||
float colGap = S.drawElement(cfgSec, "col-gap").sizeOr(8.0f);
|
||||
float rowH = (stackH - rowGap) / 2.0f;
|
||||
float rowMinH = S.drawElement(cfgSec, "row-min-height").sizeOr(24.0f);
|
||||
float rowMinH = std::max(
|
||||
S.drawElement(cfgSec, "row-min-height").sizeOr(24.0f) * dp,
|
||||
v2x2RowFontFloor);
|
||||
if (rowH < rowMinH) rowH = rowMinH;
|
||||
|
||||
float colW = (availW - colGap) / 2.0f;
|
||||
|
||||
ImFont* capFont = Type().caption();
|
||||
ImFont* iconFont = Type().iconSmall();
|
||||
|
||||
float padOverride = S.drawElement(cfgSec, "card-padding").size;
|
||||
float rowPad = (padOverride >= 0.0f) ? padOverride : Layout::spacingLg();
|
||||
float rowBgAlpha = S.drawElement(cfgSec, "row-bg-alpha").sizeOr(8.0f);
|
||||
@@ -2664,7 +2691,7 @@ static void RenderBalanceVertical2x2(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float addrOverride = S.drawElement(cfgSec, "address-table-height").size;
|
||||
float addrH = (addrOverride >= 0.0f) ? addrOverride
|
||||
float addrH = (addrOverride >= 0.0f) ? addrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -2722,14 +2749,20 @@ static void RenderBalanceShield(App* app) {
|
||||
|
||||
// Shield gauge panel
|
||||
{
|
||||
ImFont* shieldCap = Type().caption();
|
||||
ImFont* shieldSub1 = Type().subtitle1();
|
||||
// Font-content floor: gauge area + legend text (subtitle + 2 captions)
|
||||
float shieldFontFloor = Layout::spacingLg() * 2
|
||||
+ shieldSub1->LegacySize + Layout::spacingSm()
|
||||
+ shieldCap->LegacySize * 2 + Layout::spacingSm() * 2;
|
||||
float shieldCardH = S.drawElement("tabs.balance.shield", "card-height").size;
|
||||
float gaugeH;
|
||||
if (shieldCardH >= 0.0f) {
|
||||
gaugeH = shieldCardH; // explicit override from ui.toml
|
||||
gaugeH = std::max(shieldCardH * dp, shieldFontFloor);
|
||||
} else {
|
||||
gaugeH = std::max(
|
||||
S.drawElement("tabs.balance.shield", "gauge-min-height").sizeOr(80.0f),
|
||||
contentAvail.y * S.drawElement("tabs.balance.shield", "gauge-height-ratio").sizeOr(0.18f));
|
||||
gaugeH = std::max({shieldFontFloor,
|
||||
S.drawElement("tabs.balance.shield", "gauge-min-height").sizeOr(80.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.shield", "gauge-height-ratio").sizeOr(0.18f)});
|
||||
}
|
||||
ImVec2 panelMin = ImGui::GetCursorScreenPos();
|
||||
ImVec2 panelMax(panelMin.x + availW, panelMin.y + gaugeH);
|
||||
@@ -2834,7 +2867,7 @@ static void RenderBalanceShield(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float shieldAddrOverride = S.drawElement("tabs.balance.shield", "address-table-height").size;
|
||||
float addrH = (shieldAddrOverride >= 0.0f) ? shieldAddrOverride
|
||||
float addrH = (shieldAddrOverride >= 0.0f) ? shieldAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -2895,10 +2928,10 @@ static void RenderBalanceTimeline(App* app) {
|
||||
float tlChartH = S.drawElement("tabs.balance.timeline", "chart-height").size;
|
||||
float chartH;
|
||||
if (tlChartH >= 0.0f) {
|
||||
chartH = tlChartH; // explicit override from ui.toml
|
||||
chartH = tlChartH * dp; // scaled by dp for DPI + font scale
|
||||
} else {
|
||||
chartH = std::max(
|
||||
S.drawElement("tabs.balance.timeline", "chart-min-height").sizeOr(80.0f),
|
||||
S.drawElement("tabs.balance.timeline", "chart-min-height").sizeOr(80.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.timeline", "chart-height-ratio").sizeOr(0.20f));
|
||||
}
|
||||
ImVec2 chartMin = ImGui::GetCursorScreenPos();
|
||||
@@ -2935,21 +2968,25 @@ static void RenderBalanceTimeline(App* app) {
|
||||
// Compact 3 summary cards
|
||||
ImGui::Dummy(ImVec2(0, cGap));
|
||||
{
|
||||
ImFont* ovFont = Type().overline();
|
||||
ImFont* capFont = Type().caption();
|
||||
// Font-content floor: pad + overline + gap + caption + pad
|
||||
float tlPadVal = S.drawElement("tabs.balance.timeline", "card-padding").size;
|
||||
float tlPad = (tlPadVal >= 0.0f) ? tlPadVal : Layout::spacingXs();
|
||||
float tlFontFloor = tlPad + ovFont->LegacySize + 2.0f * dp + capFont->LegacySize + tlPad;
|
||||
float tlSummaryH = S.drawElement("tabs.balance.timeline", "summary-card-height").size;
|
||||
float cardH;
|
||||
if (tlSummaryH >= 0.0f) {
|
||||
cardH = tlSummaryH; // explicit override from ui.toml
|
||||
cardH = std::max(tlSummaryH * dp, tlFontFloor);
|
||||
} else {
|
||||
cardH = std::max(
|
||||
S.drawElement("tabs.balance.timeline", "summary-min-height").sizeOr(44.0f),
|
||||
contentAvail.y * S.drawElement("tabs.balance.timeline", "summary-height-ratio").sizeOr(0.08f));
|
||||
cardH = std::max({tlFontFloor,
|
||||
S.drawElement("tabs.balance.timeline", "summary-min-height").sizeOr(44.0f) * dp,
|
||||
contentAvail.y * S.drawElement("tabs.balance.timeline", "summary-height-ratio").sizeOr(0.08f)});
|
||||
}
|
||||
float cardW = (availW - 2 * cGap) / 3.0f;
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
GlassPanelSpec spec;
|
||||
spec.rounding = glassRound;
|
||||
ImFont* ovFont = Type().overline();
|
||||
ImFont* capFont = Type().caption();
|
||||
|
||||
struct SumCard { const char* label; ImU32 col; double val; bool isMoney; };
|
||||
SumCard cards[3] = {
|
||||
@@ -2983,7 +3020,7 @@ static void RenderBalanceTimeline(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float tlAddrOverride = S.drawElement("tabs.balance.timeline", "address-table-height").size;
|
||||
float addrH = (tlAddrOverride >= 0.0f) ? tlAddrOverride
|
||||
float addrH = (tlAddrOverride >= 0.0f) ? tlAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -3055,14 +3092,17 @@ static void RenderBalanceTwoRow(App* app) {
|
||||
|
||||
// Row 2: 3 mini-cards inline
|
||||
{
|
||||
ImFont* twoRowCap = Type().caption();
|
||||
// Font-content floor: caption centered + vertical padding
|
||||
float twoRowFontFloor = twoRowCap->LegacySize + Layout::spacingSm() * 2;
|
||||
float twoRowCardH = S.drawElement("tabs.balance.two-row", "card-height").size;
|
||||
float miniH;
|
||||
if (twoRowCardH >= 0.0f) {
|
||||
miniH = twoRowCardH; // explicit override from ui.toml
|
||||
miniH = std::max(twoRowCardH * dp, twoRowFontFloor);
|
||||
} else {
|
||||
miniH = std::max(
|
||||
S.drawElement("tabs.balance.two-row", "mini-min-height").sizeOr(28.0f),
|
||||
S.drawElement("tabs.balance.two-row", "mini-base-height").sizeOr(36.0f) * vs);
|
||||
miniH = std::max({twoRowFontFloor,
|
||||
S.drawElement("tabs.balance.two-row", "mini-min-height").sizeOr(28.0f) * dp,
|
||||
S.drawElement("tabs.balance.two-row", "mini-base-height").sizeOr(36.0f) * vs});
|
||||
}
|
||||
float miniW = (availW - 2 * cGap) / 3.0f;
|
||||
ImVec2 origin = ImGui::GetCursorScreenPos();
|
||||
@@ -3170,7 +3210,7 @@ static void RenderBalanceTwoRow(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float twoRowAddrOverride = S.drawElement("tabs.balance.two-row", "address-table-height").size;
|
||||
float addrH = (twoRowAddrOverride >= 0.0f) ? twoRowAddrOverride
|
||||
float addrH = (twoRowAddrOverride >= 0.0f) ? twoRowAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
@@ -3191,6 +3231,7 @@ static void RenderBalanceMinimal(App* app) {
|
||||
float hs = Layout::hScale(availW);
|
||||
float vs = Layout::vScale(contentAvail.y);
|
||||
float glassRound = Layout::glassRounding();
|
||||
const float dp = Layout::dpiScale();
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
char buf[64];
|
||||
|
||||
@@ -3262,7 +3303,7 @@ static void RenderBalanceMinimal(App* app) {
|
||||
|
||||
float recentReserve = contentAvail.y * S.drawElement("tabs.balance", "recent-tx-reserve-ratio").sizeOr(0.18f);
|
||||
float minAddrOverride = S.drawElement("tabs.balance.minimal", "address-table-height").size;
|
||||
float addrH = (minAddrOverride >= 0.0f) ? minAddrOverride
|
||||
float addrH = (minAddrOverride >= 0.0f) ? minAddrOverride * dp
|
||||
: ImGui::GetContentRegionAvail().y - recentReserve
|
||||
- Layout::spacingXl() - Type().h6()->LegacySize - Layout::spacingMd();
|
||||
RenderSharedAddressList(app, addrH, availW, glassRound, hs, vs);
|
||||
|
||||
Reference in New Issue
Block a user