fix(layout): propagate wrap length from flex constraints to label

This commit is contained in:
Lemmy
2026-05-03 17:05:59 -04:00
parent 1c2e0fbbd8
commit 9f48d4da21
6 changed files with 43 additions and 37 deletions
+7 -12
View File
@@ -439,7 +439,6 @@ void OverviewTab::doLayout(Renderer& renderer, float contentWidth, float bodyHei
return std::max(1.0f, card->width() - (card->paddingLeft() + card->paddingRight()));
};
const float dateTimeWrap = innerWidth(m_dateTimeCard);
const float mediaWrap = innerWidth(m_mediaCard);
for (Label* label : {m_timeLabel, m_dateLabel, m_weatherLine}) {
if (label != nullptr) {
@@ -467,19 +466,15 @@ void OverviewTab::doLayout(Renderer& renderer, float contentWidth, float bodyHei
}
}
if (m_mediaCard != nullptr && m_mediaArtSlot != nullptr && m_mediaText != nullptr) {
const float textWidth = std::max(1.0f, mediaWrap - m_mediaArtSlot->width() - (Style::spaceSm * contentScale()));
for (Label* label : {m_mediaArtist, m_mediaStatus, m_mediaProgress}) {
if (label != nullptr) {
label->setMaxWidth(textWidth);
label->setMaxLines(1);
}
}
if (m_mediaTrack != nullptr) {
m_mediaTrack->setMaxWidth(textWidth);
m_mediaTrack->setMaxLines(2);
// Labels auto-wrap to mediaText's assigned width via Flex stretch propagation.
for (Label* label : {m_mediaArtist, m_mediaStatus, m_mediaProgress}) {
if (label != nullptr) {
label->setMaxLines(1);
}
}
if (m_mediaTrack != nullptr) {
m_mediaTrack->setMaxLines(2);
}
if (m_userCard != nullptr && m_userFacts != nullptr) {
const float userWrap = innerWidth(m_userCard);
+1 -10
View File
@@ -318,16 +318,7 @@ void SystemTab::doLayout(Renderer& renderer, float contentWidth, float bodyHeigh
sizeGraph(m_ramGraph, m_ramCard);
sizeGraph(m_netGraph, m_netCard);
const auto innerWidth = [](Flex* card) {
if (card == nullptr) {
return 1.0f;
}
return std::max(1.0f, card->width() - (card->paddingLeft() + card->paddingRight()));
};
if (m_infoLabel != nullptr && m_infoCard != nullptr) {
m_infoLabel->setMaxWidth(innerWidth(m_infoCard));
}
// m_infoLabel auto-wraps via Flex Stretch (m_infoCard uses applySectionCardStyle → align=Stretch).
// Apply width constraints in the same frame they are set so System Info
// reaches its final card height immediately on open.
+1 -10
View File
@@ -156,16 +156,7 @@ void PolkitPanel::doLayout(Renderer& renderer, float width, float height) {
return;
}
m_rootLayout->setSize(width, height);
const float contentWidth = std::max(0.0f, width - (Style::spaceLg * contentScale() * 2.0f));
if (m_messageLabel != nullptr) {
m_messageLabel->setMaxWidth(contentWidth);
}
if (m_promptLabel != nullptr) {
m_promptLabel->setMaxWidth(contentWidth);
}
if (m_supplementaryLabel != nullptr) {
m_supplementaryLabel->setMaxWidth(contentWidth);
}
// Labels auto-wrap via Flex Stretch propagation (root → topContent/bottomContent → labels).
m_rootLayout->layout(renderer);
}
+18 -2
View File
@@ -50,6 +50,16 @@ namespace {
}
}
// Soft cross-axis upper bound. Lets children (esp. labels) discover a wrap budget
// even when align != Stretch, without forcing them to fill the full cross extent.
void setCrossMaxConstraint(LayoutConstraints& constraints, bool horizontal, float value) {
if (horizontal) {
constraints.setMaxHeight(value);
} else {
constraints.setMaxWidth(value);
}
}
LayoutSize sizeFromAxes(bool horizontal, float main, float cross) {
return horizontal ? LayoutSize{.width = main, .height = cross} : LayoutSize{.width = cross, .height = main};
}
@@ -387,8 +397,14 @@ LayoutSize Flex::runLayout(Renderer& renderer, const LayoutConstraints& constrai
if (exactMain) {
setMainConstraint(childConstraints, horizontal, assignedMain);
}
if (m_align == FlexAlign::Stretch && crossKnown) {
setCrossConstraint(childConstraints, horizontal, innerCross);
if (crossKnown) {
if (m_align == FlexAlign::Stretch) {
setCrossConstraint(childConstraints, horizontal, innerCross);
} else {
// Even without stretch, advertise the available cross extent as an upper bound so
// children that need it (text wrapping, max-width caps) get a budget for free.
setCrossMaxConstraint(childConstraints, horizontal, innerCross);
}
}
item.measured = item.node->measure(renderer, childConstraints);
item.main = mainSize(item.measured, horizontal);
+15 -2
View File
@@ -328,7 +328,10 @@ void Label::doArrange(Renderer& renderer, const LayoutRect& rect) {
setPosition(rect.x, rect.y);
LayoutConstraints constraints;
constraints.setExactWidth(rect.width);
const LayoutSize measured = measureWithConstraints(renderer, constraints);
// fromArrange=true: do not overwrite the text node's wrap budget here. Arrange's
// exact width is the label's own (rounded) measured width fed back, not a parent
// wrap-intent — feeding it to Pango as maxWidth can trigger sub-pixel ellipsis.
const LayoutSize measured = measureWithConstraints(renderer, constraints, true);
setSize(rect.width, rect.height > 0.0f ? rect.height : measured.height);
}
@@ -342,7 +345,7 @@ void Label::measure(Renderer& renderer) {
measureWithConstraints(renderer, constraints);
}
LayoutSize Label::measureWithConstraints(Renderer& renderer, const LayoutConstraints& constraints) {
LayoutSize Label::measureWithConstraints(Renderer& renderer, const LayoutConstraints& constraints, bool fromArrange) {
const float configuredMaxWidth = m_userMaxWidth;
float measureMaxWidth = configuredMaxWidth;
if (constraints.hasMaxWidth) {
@@ -366,6 +369,16 @@ LayoutSize Label::measureWithConstraints(Renderer& renderer, const LayoutConstra
}
syncTextNodeConstraints();
// Override the default with the constraint-aware wrap budget so paint uses the same
// wrap width that was used to measure metrics. Without this, a Label inside a Flex
// with stretch-derived width would measure correctly but paint unwrapped.
// Skipped on the arrange path: arrange's exact width is the label's own already-measured
// width fed back to itself, not a parent wrap-intent. Feeding it to Pango as maxWidth
// can spuriously ellipsize when the rounded box width sits a fraction below natural.
if (!m_autoScroll && !fromArrange) {
m_textNode->setMaxWidth(measureMaxWidth);
m_textNode->setMaxLines(effectiveMaxLines);
}
auto metrics = renderer.measureText(m_plainText, m_textNode->fontSize(), m_textNode->bold(), measureMaxWidth,
effectiveMaxLines, align);
+1 -1
View File
@@ -62,7 +62,7 @@ private:
LayoutSize doMeasure(Renderer& renderer, const LayoutConstraints& constraints) override;
void doArrange(Renderer& renderer, const LayoutRect& rect) override;
void applyPalette();
LayoutSize measureWithConstraints(Renderer& renderer, const LayoutConstraints& constraints);
LayoutSize measureWithConstraints(Renderer& renderer, const LayoutConstraints& constraints, bool fromArrange = false);
void syncTextNodeConstraints();
void restartScrollIfNeeded();
void stopMarqueeAnimation();