mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
Out of flow positioning fixes.
This commit is contained in:
@@ -50,7 +50,8 @@ void UIHTMLWidget::setDisplay( CSSDisplay display ) {
|
||||
if ( getLayoutWidthPolicy() == SizePolicy::MatchParent )
|
||||
setLayoutWidthPolicy( SizePolicy::WrapContent );
|
||||
} else if ( mDisplay == CSSDisplay::Block || mDisplay == CSSDisplay::ListItem ) {
|
||||
if ( getLayoutWidthPolicy() == SizePolicy::WrapContent )
|
||||
if ( getLayoutWidthPolicy() == SizePolicy::WrapContent &&
|
||||
mPosition != CSSPosition::Absolute && mPosition != CSSPosition::Fixed )
|
||||
setLayoutWidthPolicy( SizePolicy::MatchParent );
|
||||
}
|
||||
onDisplayChange();
|
||||
@@ -60,6 +61,10 @@ void UIHTMLWidget::setDisplay( CSSDisplay display ) {
|
||||
void UIHTMLWidget::setCSSPosition( CSSPosition position ) {
|
||||
if ( mPosition != position ) {
|
||||
mPosition = position;
|
||||
if ( position == CSSPosition::Absolute || position == CSSPosition::Fixed ) {
|
||||
if ( getLayoutWidthPolicy() == SizePolicy::MatchParent )
|
||||
setLayoutWidthPolicy( SizePolicy::WrapContent );
|
||||
}
|
||||
onPositionChange();
|
||||
}
|
||||
}
|
||||
@@ -203,22 +208,51 @@ void UIHTMLWidget::positionOutOfFlowChildren() {
|
||||
if ( pos == CSSPosition::Absolute || pos == CSSPosition::Fixed ) {
|
||||
UIWidget* cb = htmlChild->getContainingBlock();
|
||||
if ( cb ) {
|
||||
Float top = htmlChild->mTopEq == "auto"
|
||||
? 0
|
||||
: htmlChild->lengthFromValue(
|
||||
htmlChild->mTopEq,
|
||||
CSS::PropertyRelativeTarget::ContainingBlockHeight, 0 );
|
||||
Float left = htmlChild->mLeftEq == "auto"
|
||||
? 0
|
||||
: htmlChild->lengthFromValue(
|
||||
htmlChild->mLeftEq,
|
||||
CSS::PropertyRelativeTarget::ContainingBlockWidth, 0 );
|
||||
Rectf cbContentOffset = cb->getPixelsContentOffset();
|
||||
Float cbContentWidth = cb->getPixelsSize().getWidth() - cbContentOffset.Left -
|
||||
cbContentOffset.Right;
|
||||
Float cbContentHeight = cb->getPixelsSize().getHeight() - cbContentOffset.Top -
|
||||
cbContentOffset.Bottom;
|
||||
|
||||
top += htmlChild->getLayoutPixelsMargin().Top;
|
||||
left += htmlChild->getLayoutPixelsMargin().Left;
|
||||
Rectf margin = htmlChild->getLayoutPixelsMargin();
|
||||
Float childWidth = htmlChild->getPixelsSize().getWidth();
|
||||
Float childHeight = htmlChild->getPixelsSize().getHeight();
|
||||
|
||||
Vector2f cbPos( cb->getPixelsContentOffset().Left,
|
||||
cb->getPixelsContentOffset().Top );
|
||||
Float top = 0;
|
||||
Float left = 0;
|
||||
|
||||
bool useTop = htmlChild->mTopEq != "auto";
|
||||
bool useBottom = htmlChild->mBottomEq != "auto";
|
||||
bool useLeft = htmlChild->mLeftEq != "auto";
|
||||
bool useRight = htmlChild->mRightEq != "auto";
|
||||
|
||||
if ( useLeft ) {
|
||||
left = htmlChild->lengthFromValue(
|
||||
htmlChild->mLeftEq, CSS::PropertyRelativeTarget::ContainingBlockWidth,
|
||||
0 );
|
||||
} else if ( useRight ) {
|
||||
Float rightVal = htmlChild->lengthFromValue(
|
||||
htmlChild->mRightEq, CSS::PropertyRelativeTarget::ContainingBlockWidth,
|
||||
0 );
|
||||
left = cbContentWidth - childWidth - margin.Left - margin.Right - rightVal;
|
||||
}
|
||||
|
||||
if ( useTop ) {
|
||||
top = htmlChild->lengthFromValue(
|
||||
htmlChild->mTopEq, CSS::PropertyRelativeTarget::ContainingBlockHeight,
|
||||
0 );
|
||||
} else if ( useBottom ) {
|
||||
Float bottomVal = htmlChild->lengthFromValue(
|
||||
htmlChild->mBottomEq,
|
||||
CSS::PropertyRelativeTarget::ContainingBlockHeight, 0 );
|
||||
top =
|
||||
cbContentHeight - childHeight - margin.Top - margin.Bottom - bottomVal;
|
||||
}
|
||||
|
||||
top += margin.Top;
|
||||
left += margin.Left;
|
||||
|
||||
Vector2f cbPos( cbContentOffset.Left, cbContentOffset.Top );
|
||||
cbPos.x += left;
|
||||
cbPos.y += top;
|
||||
|
||||
|
||||
@@ -270,3 +270,84 @@ UTEST( UIHTMLWidget, positionOutOfFlow_ComplexHTML ) {
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLWidget, positionOutOfFlow_ShrinkToFit ) {
|
||||
init_ui_test();
|
||||
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
UIRichText* relContainer = UIRichText::New();
|
||||
relContainer->setParent( sceneNode->getRoot() );
|
||||
relContainer->setCSSPosition( CSSPosition::Relative );
|
||||
relContainer->setPixelsSize( 800, 600 );
|
||||
relContainer->setPixelsPosition( 0, 0 );
|
||||
|
||||
UIRichText* absoluteChild = UIRichText::New();
|
||||
absoluteChild->setParent( relContainer );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "position", "absolute" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "display", "block" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "padding", "4px" ) );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
EXPECT_EQ( SizePolicy::WrapContent, absoluteChild->getLayoutWidthPolicy() );
|
||||
|
||||
// With no text content, the element should shrink to just padding
|
||||
Float childWidth = absoluteChild->getPixelsSize().getWidth();
|
||||
EXPECT_LT( childWidth, 20.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLWidget, positionOutOfFlow_RightBottomPositioning ) {
|
||||
init_ui_test();
|
||||
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
UIHTMLWidget* relContainer = UIHTMLWidget::New();
|
||||
relContainer->setParent( sceneNode->getRoot() );
|
||||
relContainer->setCSSPosition( CSSPosition::Relative );
|
||||
relContainer->setPixelsSize( 800, 600 );
|
||||
relContainer->setPixelsPosition( 0, 0 );
|
||||
|
||||
UIHTMLWidget* absoluteChild = UIHTMLWidget::New();
|
||||
absoluteChild->setParent( relContainer );
|
||||
absoluteChild->setPixelsSize( 100, 50 );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "position", "absolute" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "right", "0px" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "bottom", "0px" ) );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
Vector2f worldPos = absoluteChild->convertToWorldSpace( { 0, 0 } );
|
||||
EXPECT_NEAR( 700.f, worldPos.x, 1.f );
|
||||
EXPECT_NEAR( 550.f, worldPos.y, 1.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLWidget, positionOutOfFlow_RightBottomWithMargin ) {
|
||||
init_ui_test();
|
||||
UISceneNode* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
|
||||
UIHTMLWidget* relContainer = UIHTMLWidget::New();
|
||||
relContainer->setParent( sceneNode->getRoot() );
|
||||
relContainer->setCSSPosition( CSSPosition::Relative );
|
||||
relContainer->setPixelsSize( 800, 600 );
|
||||
relContainer->setPixelsPosition( 0, 0 );
|
||||
|
||||
UIHTMLWidget* absoluteChild = UIHTMLWidget::New();
|
||||
absoluteChild->setParent( relContainer );
|
||||
absoluteChild->setPixelsSize( 100, 50 );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "position", "absolute" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "right", "10px" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "bottom", "20px" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "margin-right", "5px" ) );
|
||||
absoluteChild->applyProperty( StyleSheetProperty( "margin-bottom", "5px" ) );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
Vector2f worldPos = absoluteChild->convertToWorldSpace( { 0, 0 } );
|
||||
EXPECT_NEAR( 685.f, worldPos.x, 1.f );
|
||||
EXPECT_NEAR( 525.f, worldPos.y, 1.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user