mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 18:50:16 +03:00
Fix flex items losing their stretched cross size
Preserve the final cross-axis size assigned to auto-sized stretched flex items when their block layout runs. Keep intrinsic flex measurement separate so content changes can still update item sizing correctly. Add an HTML regression test covering a short sidebar stretched alongside taller content.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include <eepp/core/containers.hpp>
|
||||
#include <eepp/graphics/richtext.hpp>
|
||||
#include <eepp/ui/blocklayouter.hpp>
|
||||
#include <eepp/ui/flexlayouter.hpp>
|
||||
#include <eepp/ui/uihtmltable.hpp>
|
||||
#include <eepp/ui/uihtmlwidget.hpp>
|
||||
#include <eepp/ui/uirichtext.hpp>
|
||||
@@ -10,13 +11,21 @@
|
||||
|
||||
namespace EE { namespace UI {
|
||||
|
||||
static bool isStretchedFlexItem( UIHTMLWidget* widget ) {
|
||||
static bool isStretchedFlexItemInAxis( UIHTMLWidget* widget, bool horizontalAxis ) {
|
||||
Node* parent = widget->getParent();
|
||||
if ( !parent || !parent->isWidget() || !parent->isType( UI_TYPE_HTML_WIDGET ) )
|
||||
return false;
|
||||
UIHTMLWidget* parentHtml = parent->asType<UIHTMLWidget>();
|
||||
if ( !parentHtml->isFlex() )
|
||||
return false;
|
||||
if ( static_cast<FlexLayouter*>( parentHtml->getLayouter() )->isMeasuringItems() )
|
||||
return false;
|
||||
|
||||
CSSFlexDirection direction = parentHtml->getFlexDirection();
|
||||
bool crossAxisIsHorizontal =
|
||||
direction == CSSFlexDirection::Column || direction == CSSFlexDirection::ColumnReverse;
|
||||
if ( horizontalAxis != crossAxisIsHorizontal )
|
||||
return false;
|
||||
|
||||
CSSAlignSelf alignSelf = widget->getAlignSelf();
|
||||
if ( alignSelf == CSSAlignSelf::Stretch )
|
||||
@@ -179,9 +188,11 @@ void BlockLayouter::updateLayout() {
|
||||
}
|
||||
}
|
||||
|
||||
if ( totW != mContainer->getPixelsSize().getWidth() ||
|
||||
( mContainer->getLayoutWidthPolicy() == SizePolicy::WrapContent &&
|
||||
!isStretchedFlexItem( widget ) ) )
|
||||
bool preserveStretchedWidth = mContainer->getLayoutWidthPolicy() == SizePolicy::WrapContent &&
|
||||
isStretchedFlexItemInAxis( widget, true );
|
||||
if ( !preserveStretchedWidth &&
|
||||
( totW != mContainer->getPixelsSize().getWidth() ||
|
||||
mContainer->getLayoutWidthPolicy() == SizePolicy::WrapContent ) )
|
||||
mContainer->setInternalPixelsWidth( totW );
|
||||
|
||||
Float totH = mContainer->getPixelsSize().getHeight();
|
||||
@@ -207,9 +218,11 @@ void BlockLayouter::updateLayout() {
|
||||
}
|
||||
}
|
||||
|
||||
if ( totH != mContainer->getPixelsSize().getHeight() ||
|
||||
( mContainer->getLayoutHeightPolicy() == SizePolicy::WrapContent &&
|
||||
!isStretchedFlexItem( widget ) ) )
|
||||
bool preserveStretchedHeight = mContainer->getLayoutHeightPolicy() == SizePolicy::WrapContent &&
|
||||
isStretchedFlexItemInAxis( widget, false );
|
||||
if ( !preserveStretchedHeight &&
|
||||
( totH != mContainer->getPixelsSize().getHeight() ||
|
||||
mContainer->getLayoutHeightPolicy() == SizePolicy::WrapContent ) )
|
||||
mContainer->setInternalPixelsHeight( totH );
|
||||
|
||||
mContainer->endAttributesTransaction();
|
||||
|
||||
@@ -1223,8 +1223,8 @@ void FlexLayouter::updateLayout() {
|
||||
return;
|
||||
|
||||
RichText* richText = widget->isType( UI_TYPE_RICHTEXT )
|
||||
? widget->asType<UIRichText>()->getRichTextPtr()
|
||||
: nullptr;
|
||||
? widget->asType<UIRichText>()->getRichTextPtr()
|
||||
: nullptr;
|
||||
bool preserveFloatConstrainedBFCWidth =
|
||||
widget->establishesBlockFormattingContext() &&
|
||||
widget->getLayoutWidthPolicy() == SizePolicy::MatchParent && richText != nullptr &&
|
||||
@@ -1387,6 +1387,7 @@ void FlexLayouter::updateLayout() {
|
||||
bool indefiniteMainSize = ( mainAxis.horizontal && widthPolicy == SizePolicy::WrapContent ) ||
|
||||
( !mainAxis.horizontal && heightPolicy == SizePolicy::WrapContent );
|
||||
|
||||
mMeasuringItems = true;
|
||||
measureFlexItems( mainAxis, crossAxis, containerCrossSize, containerWidth, containerHeight,
|
||||
containerPadding, indefiniteMainSize, indefiniteCrossSize );
|
||||
|
||||
@@ -1410,6 +1411,7 @@ void FlexLayouter::updateLayout() {
|
||||
alignMainAxis( line, containerMainSize, mColumnGap );
|
||||
resolveCrossSizes( line, crossAxis, mainAxis );
|
||||
}
|
||||
mMeasuringItems = false;
|
||||
|
||||
alignCrossAxis( lines, containerCrossSize, mRowGap, crossAxis );
|
||||
|
||||
|
||||
@@ -5136,6 +5136,47 @@ UTEST( UIHTML, FlexLiItemsWrapContentWidth ) {
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTML, FlexStretchPreservesAutoCrossSizeAfterChildLayout ) {
|
||||
Engine::instance()->createWindow(
|
||||
WindowSettings( 1024, 768, "Flex Stretch Auto Cross Size Test", WindowStyle::Default,
|
||||
WindowBackend::Default, 32, {}, 1, false, true ),
|
||||
ContextSettings( false, 0, 0, GLv_default, true, false ) );
|
||||
|
||||
UISceneNode* sceneNode = init_test_inline_block();
|
||||
sceneNode->loadLayoutFromString( HTMLFormatter::HTMLtoXML( R"html(
|
||||
<html><head><style>
|
||||
.container { display: flex; width: 600px; }
|
||||
.short { width: 200px; padding: 10px; }
|
||||
.tall { width: 200px; height: 300px; }
|
||||
</style></head><body>
|
||||
<div class="container">
|
||||
<aside class="short"><p>Short content</p></aside>
|
||||
<main class="tall"></main>
|
||||
</div>
|
||||
</body></html>
|
||||
)html" ) );
|
||||
|
||||
sceneNode->update( Seconds( 1 ) );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
auto* containerNode = sceneNode->getRoot()->findByClass( "container" );
|
||||
auto* shortItemNode = sceneNode->getRoot()->findByClass( "short" );
|
||||
auto* tallItemNode = sceneNode->getRoot()->findByClass( "tall" );
|
||||
ASSERT_TRUE( containerNode != nullptr );
|
||||
ASSERT_TRUE( shortItemNode != nullptr );
|
||||
ASSERT_TRUE( tallItemNode != nullptr );
|
||||
auto* container = containerNode->asType<UIWidget>();
|
||||
auto* shortItem = shortItemNode->asType<UIWidget>();
|
||||
auto* tallItem = tallItemNode->asType<UIWidget>();
|
||||
|
||||
EXPECT_NEAR( container->getPixelsSize().getHeight(), tallItem->getPixelsSize().getHeight(),
|
||||
1.f );
|
||||
EXPECT_NEAR( shortItem->getPixelsSize().getHeight(), tallItem->getPixelsSize().getHeight(),
|
||||
1.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTML, ImagePercentageWidthRespectsParentMaxWidth ) {
|
||||
auto win = Engine::instance()->createWindow(
|
||||
WindowSettings( 1024, 768, "img pct width respects parent max-width", WindowStyle::Default,
|
||||
|
||||
Reference in New Issue
Block a user