mirror of
https://github.com/noctalia-dev/noctalia-shell.git
synced 2026-05-11 17:08:27 +08:00
fix(layout): propagate wrap length from flex constraints to label
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user