Skip to content

Commit 791e557

Browse files
fix(ui): preserve fractional button content centering (#4036)
* fix(ui): preserve fractional button centering * Remove comments from button.cpp centering logic Removed comments explaining the centering logic for button content alignment. --------- Co-authored-by: Lemmy <studio@quadbyte.net>
1 parent b3bd560 commit 791e557

3 files changed

Lines changed: 95 additions & 2 deletions

File tree

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,7 @@ if build_tests
11231123
'app_identity',
11241124
'audio_glyphs',
11251125
'battery_hook_state',
1126+
'button_layout',
11261127
'cairo_text_renderer',
11271128
'calendar_cache_permissions',
11281129
'cli_help',

src/ui/controls/button.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -778,12 +778,12 @@ void Button::doLayout(Renderer& renderer) {
778778
const float contentHeight = contentBottom - contentTop;
779779
float targetLeft = 0.0F;
780780
if (m_contentAlign == ButtonContentAlign::Center) {
781-
targetLeft = std::round((width() - contentWidth) * 0.5F);
781+
targetLeft = (width() - contentWidth) * 0.5F;
782782
} else { // End
783783
targetLeft = std::round(Style::rtl() ? paddingLeft() : width() - contentWidth - paddingRight());
784784
}
785785
const float shiftX = targetLeft - contentLeft;
786-
const float targetTop = std::round((height() - contentHeight) * 0.5F);
786+
const float targetTop = (height() - contentHeight) * 0.5F;
787787
const float shiftY = targetTop - contentTop;
788788
if (std::abs(shiftX) > 0.01F || std::abs(shiftY) > 0.01F) {
789789
for (auto& child : children()) {

tests/button_layout_test.cpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include "render/core/renderer.h"
2+
#include "render/core/texture_manager.h"
3+
#include "ui/controls/button.h"
4+
#include "ui/controls/glyph.h"
5+
6+
#include <cmath>
7+
#include <cstdlib>
8+
#include <print>
9+
#include <string_view>
10+
#include <vector>
11+
12+
namespace {
13+
14+
class StubRenderer final : public Renderer {
15+
public:
16+
TextMetrics measureText(
17+
std::string_view, float fontSize, FontWeight, float, int, TextAlign, std::string_view, TextEllipsize, bool
18+
) override {
19+
return TextMetrics{.bottom = fontSize};
20+
}
21+
22+
TextMetrics measureFont(float fontSize, FontWeight) override { return TextMetrics{.bottom = fontSize}; }
23+
24+
void measureTextCursorStops(
25+
std::string_view, float, const std::vector<std::size_t>&, std::vector<float>&, FontWeight
26+
) override {}
27+
28+
void measureTextCursorStopsWrapped(
29+
std::string_view, float, const std::vector<std::size_t>&, float, std::vector<TextCursorStop>&, FontWeight
30+
) override {}
31+
32+
TextMetrics measureGlyph(char32_t, float) override {
33+
return TextMetrics{
34+
.width = 18.0F,
35+
.left = 1.5F,
36+
.right = 19.5F,
37+
.top = -15.0F,
38+
.bottom = 3.0F,
39+
.inkTop = -15.0F,
40+
.inkBottom = 3.0F,
41+
.inkLeft = 1.5F,
42+
.inkRight = 19.5F,
43+
};
44+
}
45+
46+
TextureManager& textureManager() override { std::abort(); }
47+
[[nodiscard]] float renderScale() const noexcept override { return 1.0F; }
48+
};
49+
50+
bool near(float actual, float expected) { return std::abs(actual - expected) < 0.001F; }
51+
52+
} // namespace
53+
54+
int main() {
55+
StubRenderer renderer;
56+
Button button;
57+
button.setGlyph("home");
58+
button.setGlyphSize(21.0F);
59+
button.setContentAlign(ButtonContentAlign::Center);
60+
button.setPadding(4.0F);
61+
button.setSize(32.0F, 32.0F);
62+
button.layout(renderer);
63+
64+
const Glyph* glyph = button.glyph();
65+
if (glyph == nullptr) {
66+
std::println(stderr, "button_layout_test: glyph was not created");
67+
return 1;
68+
}
69+
70+
const float glyphCenterX = glyph->x() + glyph->width() * 0.5F;
71+
const float glyphCenterY = glyph->y() + glyph->height() * 0.5F;
72+
const float buttonCenterX = button.width() * 0.5F;
73+
const float buttonCenterY = button.height() * 0.5F;
74+
75+
if (!near(glyphCenterX, buttonCenterX) || !near(glyphCenterY, buttonCenterY)) {
76+
std::println(
77+
stderr, "button_layout_test: centered glyph mismatch: glyph center=({}, {}), button center=({}, {})",
78+
glyphCenterX, glyphCenterY, buttonCenterX, buttonCenterY
79+
);
80+
return 1;
81+
}
82+
83+
if (!near(glyph->x(), 5.5F) || !near(glyph->y(), 5.5F)) {
84+
std::println(
85+
stderr, "button_layout_test: expected a 21px glyph in a 32px button at (5.5, 5.5), got ({}, {})", glyph->x(),
86+
glyph->y()
87+
);
88+
return 1;
89+
}
90+
91+
return 0;
92+
}

0 commit comments

Comments
 (0)