mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-05-28 17:16:29 +03:00
margin: auto support.
background from body to html when html background is transparent.
This commit is contained in:
@@ -125,6 +125,8 @@ enum UINodeType {
|
||||
UI_TYPE_DROPDOWNMODELLIST,
|
||||
UI_TYPE_DIFF_VIEW,
|
||||
UI_TYPE_BR,
|
||||
UI_TYPE_HTML_HTML,
|
||||
UI_TYPE_HTML_BODY,
|
||||
UI_TYPE_MODULES = 10000,
|
||||
UI_TYPE_TERMINAL = 10001,
|
||||
UI_TYPE_USER = 200000,
|
||||
|
||||
@@ -30,6 +30,10 @@ class EE_API UIRichText : public UILayout {
|
||||
|
||||
static UIRichText* NewHr();
|
||||
|
||||
static UIRichText* NewHtml();
|
||||
|
||||
static UIRichText* NewBody();
|
||||
|
||||
static UIRichText* NewDiv() { return UIRichText::NewWithTag( "div" ); };
|
||||
|
||||
static UIRichText* NewPre() { return UIRichText::NewWithTag( "pre" ); };
|
||||
@@ -157,6 +161,29 @@ class EE_API UIRichText : public UILayout {
|
||||
void updateDefaultSpansStyle();
|
||||
};
|
||||
|
||||
class EE_API UIHTMLHtml : public UIRichText {
|
||||
public:
|
||||
static UIHTMLHtml* New( const std::string& tag );
|
||||
virtual Uint32 getType() const override;
|
||||
bool isType( const Uint32& type ) const override;
|
||||
|
||||
protected:
|
||||
UIHTMLHtml( const std::string& tag = "html" );
|
||||
};
|
||||
|
||||
class EE_API UIHTMLBody : public UIRichText {
|
||||
public:
|
||||
static UIHTMLBody* New( const std::string& tag );
|
||||
virtual Uint32 getType() const override;
|
||||
bool isType( const Uint32& type ) const override;
|
||||
bool applyProperty( const StyleSheetProperty& attribute ) override;
|
||||
|
||||
protected:
|
||||
bool mPropagatedBackground{ false };
|
||||
|
||||
UIHTMLBody( const std::string& tag = "body" );
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
#endif
|
||||
|
||||
@@ -303,6 +303,24 @@ class EE_API UIWidget : public UINode {
|
||||
*/
|
||||
UIWidget* setLayoutMarginBottom( const Float& marginBottom );
|
||||
|
||||
UIWidget* setLayoutMarginLeftAuto( bool isAuto );
|
||||
|
||||
UIWidget* setLayoutMarginRightAuto( bool isAuto );
|
||||
|
||||
UIWidget* setLayoutMarginTopAuto( bool isAuto );
|
||||
|
||||
UIWidget* setLayoutMarginBottomAuto( bool isAuto );
|
||||
|
||||
UIWidget* setLayoutMarginAuto( bool left, bool right, bool top, bool bottom );
|
||||
|
||||
bool hasLayoutMarginLeftAuto() const;
|
||||
|
||||
bool hasLayoutMarginRightAuto() const;
|
||||
|
||||
bool hasLayoutMarginTopAuto() const;
|
||||
|
||||
bool hasLayoutMarginBottomAuto() const;
|
||||
|
||||
/**
|
||||
* @brief Sets the layout margin for all sides in pixels.
|
||||
*
|
||||
@@ -1330,6 +1348,14 @@ class EE_API UIWidget : public UINode {
|
||||
mutable Float mMinIntrinsicWidth{ 0 };
|
||||
mutable Float mMaxIntrinsicWidth{ 0 };
|
||||
mutable bool mIntrinsicWidthsDirty{ true };
|
||||
Uint8 mMarginAuto{ 0 };
|
||||
|
||||
static constexpr Uint8 MarginAutoLeft = ( 1 << 0 );
|
||||
static constexpr Uint8 MarginAutoRight = ( 1 << 1 );
|
||||
static constexpr Uint8 MarginAutoTop = ( 1 << 2 );
|
||||
static constexpr Uint8 MarginAutoBottom = ( 1 << 3 );
|
||||
|
||||
void calculateAutoMargin();
|
||||
|
||||
/**
|
||||
* @brief Default constructor.
|
||||
@@ -1680,6 +1706,8 @@ class EE_API UIWidget : public UINode {
|
||||
|
||||
/* @return The size of the widget when size policy is match_parent */
|
||||
Sizef getSizeFromLayoutPolicy();
|
||||
|
||||
UIWidget* setLayoutMarginAuto( Uint32 dir, bool isAuto );
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -28,6 +28,72 @@ class UILineBreak : public UIRichText {
|
||||
}
|
||||
};
|
||||
|
||||
UIHTMLHtml* UIHTMLHtml::New( const std::string& tag ) {
|
||||
return eeNew( UIHTMLHtml, ( tag ) );
|
||||
}
|
||||
|
||||
UIHTMLHtml::UIHTMLHtml( const std::string& tag ) : UIRichText( tag ) {}
|
||||
|
||||
Uint32 UIHTMLHtml::getType() const {
|
||||
return UI_TYPE_HTML_HTML;
|
||||
}
|
||||
|
||||
bool UIHTMLHtml::isType( const Uint32& type ) const {
|
||||
return UIHTMLHtml::getType() == type ? true : UIRichText::isType( type );
|
||||
}
|
||||
|
||||
UIHTMLBody* UIHTMLBody::New( const std::string& tag ) {
|
||||
return eeNew( UIHTMLBody, ( tag ) );
|
||||
}
|
||||
|
||||
UIHTMLBody::UIHTMLBody( const std::string& tag ) : UIRichText( tag ) {}
|
||||
|
||||
Uint32 UIHTMLBody::getType() const {
|
||||
return UI_TYPE_HTML_BODY;
|
||||
}
|
||||
|
||||
bool UIHTMLBody::isType( const Uint32& type ) const {
|
||||
return UIHTMLBody::getType() == type ? true : UIRichText::isType( type );
|
||||
}
|
||||
|
||||
bool UIHTMLBody::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
if ( !checkPropertyDefinition( attribute ) )
|
||||
return false;
|
||||
|
||||
switch ( attribute.getPropertyDefinition()->getPropertyId() ) {
|
||||
case PropertyId::BackgroundColor:
|
||||
case PropertyId::BackgroundImage:
|
||||
case PropertyId::BackgroundTint:
|
||||
case PropertyId::BackgroundPositionX:
|
||||
case PropertyId::BackgroundPositionY:
|
||||
case PropertyId::BackgroundRepeat:
|
||||
case PropertyId::BackgroundSize: {
|
||||
if ( getParent() && getParent()->isType( UI_TYPE_HTML_HTML ) ) {
|
||||
UIWidget* htmlParent = getParent()->asType<UIWidget>();
|
||||
if ( htmlParent->getBackgroundColor() == Color::Transparent ||
|
||||
mPropagatedBackground ) {
|
||||
mPropagatedBackground = true;
|
||||
htmlParent->applyProperty( attribute );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return UIRichText::applyProperty( attribute );
|
||||
}
|
||||
|
||||
UIRichText* UIRichText::NewHtml() {
|
||||
return UIHTMLHtml::New( "html" );
|
||||
}
|
||||
|
||||
UIRichText* UIRichText::NewBody() {
|
||||
return UIHTMLBody::New( "body" );
|
||||
}
|
||||
|
||||
UIRichText* UIRichText::NewBr() {
|
||||
return UILineBreak::New( "br" );
|
||||
};
|
||||
@@ -554,7 +620,7 @@ void UIRichText::rebuildRichText( RichText& richText, IntrinsicMode mode ) {
|
||||
|
||||
richText.addCustomSize( Sizef( w + margin.Left + margin.Right,
|
||||
size.getHeight() + margin.Top + margin.Bottom ),
|
||||
isBlock );
|
||||
isBlock );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -156,6 +156,60 @@ UIWidget* UIWidget::setLayoutMarginBottom( const Float& marginBottom ) {
|
||||
return this;
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutMarginAuto( Uint32 dir, bool isAuto ) {
|
||||
if ( isAuto != ( ( mMarginAuto & dir ) != 0 ) ) {
|
||||
if ( isAuto ) {
|
||||
mMarginAuto |= dir;
|
||||
calculateAutoMargin();
|
||||
} else {
|
||||
mMarginAuto &= ~dir;
|
||||
notifyLayoutAttrChange();
|
||||
notifyLayoutAttrChangeParent();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutMarginLeftAuto( bool isAuto ) {
|
||||
return setLayoutMarginAuto( MarginAutoLeft, isAuto );
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutMarginRightAuto( bool isAuto ) {
|
||||
return setLayoutMarginAuto( MarginAutoRight, isAuto );
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutMarginTopAuto( bool isAuto ) {
|
||||
return setLayoutMarginAuto( MarginAutoTop, isAuto );
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutMarginBottomAuto( bool isAuto ) {
|
||||
return setLayoutMarginAuto( MarginAutoTop, isAuto );
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutMarginAuto( bool left, bool right, bool top, bool bottom ) {
|
||||
setLayoutMarginLeftAuto( left );
|
||||
setLayoutMarginRightAuto( right );
|
||||
setLayoutMarginTopAuto( top );
|
||||
setLayoutMarginBottomAuto( bottom );
|
||||
return this;
|
||||
}
|
||||
|
||||
bool UIWidget::hasLayoutMarginLeftAuto() const {
|
||||
return mMarginAuto & MarginAutoLeft;
|
||||
}
|
||||
|
||||
bool UIWidget::hasLayoutMarginRightAuto() const {
|
||||
return mMarginAuto & MarginAutoRight;
|
||||
}
|
||||
|
||||
bool UIWidget::hasLayoutMarginTopAuto() const {
|
||||
return mMarginAuto & MarginAutoTop;
|
||||
}
|
||||
|
||||
bool UIWidget::hasLayoutMarginBottomAuto() const {
|
||||
return mMarginAuto & MarginAutoBottom;
|
||||
}
|
||||
|
||||
UIWidget* UIWidget::setLayoutPixelsMargin( const Rectf& margin ) {
|
||||
if ( mLayoutMargin != margin ) {
|
||||
mLayoutMarginPx = margin;
|
||||
@@ -533,8 +587,83 @@ UITooltip* UIWidget::getTooltip() {
|
||||
return mTooltip;
|
||||
}
|
||||
|
||||
void UIWidget::calculateAutoMargin() {
|
||||
if ( !mMarginAuto || !getParent() || !getParent()->isWidget() )
|
||||
return;
|
||||
|
||||
UIWidget* parent = getParent()->asType<UIWidget>();
|
||||
Sizef parentSize = parent->getPixelsSize();
|
||||
Rectf parentPadding = parent->getPixelsPadding();
|
||||
|
||||
bool changed = false;
|
||||
if ( ( mMarginAuto & MarginAutoLeft ) && ( mMarginAuto & MarginAutoRight ) ) {
|
||||
Float availableWidth = parentSize.getWidth() - parentPadding.Left - parentPadding.Right -
|
||||
getPixelsSize().getWidth();
|
||||
Float newMarginLeft = availableWidth > 0 ? availableWidth / 2.f : 0.f;
|
||||
Float newMarginRight = availableWidth > 0 ? availableWidth / 2.f : 0.f;
|
||||
if ( mLayoutMarginPx.Left != newMarginLeft || mLayoutMarginPx.Right != newMarginRight ) {
|
||||
mLayoutMarginPx.Left = newMarginLeft;
|
||||
mLayoutMarginPx.Right = newMarginRight;
|
||||
changed = true;
|
||||
}
|
||||
} else if ( mMarginAuto & MarginAutoLeft ) {
|
||||
Float availableWidth = parentSize.getWidth() - parentPadding.Left - parentPadding.Right -
|
||||
getPixelsSize().getWidth() - mLayoutMarginPx.Right;
|
||||
Float newMarginLeft = std::max( 0.f, availableWidth );
|
||||
if ( mLayoutMarginPx.Left != newMarginLeft ) {
|
||||
mLayoutMarginPx.Left = newMarginLeft;
|
||||
changed = true;
|
||||
}
|
||||
} else if ( mMarginAuto & MarginAutoRight ) {
|
||||
Float availableWidth = parentSize.getWidth() - parentPadding.Left - parentPadding.Right -
|
||||
getPixelsSize().getWidth() - mLayoutMarginPx.Left;
|
||||
Float newMarginRight = std::max( 0.f, availableWidth );
|
||||
if ( mLayoutMarginPx.Right != newMarginRight ) {
|
||||
mLayoutMarginPx.Right = newMarginRight;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( mMarginAuto & MarginAutoTop ) && ( mMarginAuto & MarginAutoBottom ) ) {
|
||||
Float availableHeight = parentSize.getHeight() - parentPadding.Top - parentPadding.Bottom -
|
||||
getPixelsSize().getHeight();
|
||||
Float newMarginTop = availableHeight > 0 ? availableHeight / 2.f : 0.f;
|
||||
Float newMarginBottom = availableHeight > 0 ? availableHeight / 2.f : 0.f;
|
||||
if ( mLayoutMarginPx.Top != newMarginTop || mLayoutMarginPx.Bottom != newMarginBottom ) {
|
||||
mLayoutMarginPx.Top = newMarginTop;
|
||||
mLayoutMarginPx.Bottom = newMarginBottom;
|
||||
changed = true;
|
||||
}
|
||||
} else if ( mMarginAuto & MarginAutoTop ) {
|
||||
Float availableHeight = parentSize.getHeight() - parentPadding.Top - parentPadding.Bottom -
|
||||
getPixelsSize().getHeight() - mLayoutMarginPx.Bottom;
|
||||
Float newMarginTop = std::max( 0.f, availableHeight );
|
||||
if ( mLayoutMarginPx.Top != newMarginTop ) {
|
||||
mLayoutMarginPx.Top = newMarginTop;
|
||||
changed = true;
|
||||
}
|
||||
} else if ( mMarginAuto & MarginAutoBottom ) {
|
||||
Float availableHeight = parentSize.getHeight() - parentPadding.Top - parentPadding.Bottom -
|
||||
getPixelsSize().getHeight() - mLayoutMarginPx.Top;
|
||||
Float newMarginBottom = std::max( 0.f, availableHeight );
|
||||
if ( mLayoutMarginPx.Bottom != newMarginBottom ) {
|
||||
mLayoutMarginPx.Bottom = newMarginBottom;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( changed ) {
|
||||
mLayoutMargin = PixelDensity::pxToDp( mLayoutMarginPx );
|
||||
onMarginChange();
|
||||
notifyLayoutAttrChange();
|
||||
notifyLayoutAttrChangeParent();
|
||||
}
|
||||
}
|
||||
|
||||
void UIWidget::onParentSizeChange( const Vector2f& sizeChange ) {
|
||||
updateAnchors( sizeChange );
|
||||
if ( mMarginAuto != 0 )
|
||||
calculateAutoMargin();
|
||||
UINode::onParentSizeChange( sizeChange );
|
||||
}
|
||||
|
||||
@@ -551,6 +680,8 @@ void UIWidget::onVisibilityChange() {
|
||||
}
|
||||
|
||||
void UIWidget::onSizeChange() {
|
||||
if ( mMarginAuto != 0 )
|
||||
calculateAutoMargin();
|
||||
UINode::onSizeChange();
|
||||
|
||||
if ( mBorder != NULL )
|
||||
@@ -1845,18 +1976,46 @@ bool UIWidget::applyProperty( const StyleSheetProperty& attribute ) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PropertyId::MarginLeft:
|
||||
setLayoutMarginLeft( lengthFromValueAsDp( attribute ) );
|
||||
case PropertyId::MarginLeft: {
|
||||
if ( attribute.asString() == "auto" ) {
|
||||
mMarginAuto |= MarginAutoLeft;
|
||||
calculateAutoMargin();
|
||||
} else {
|
||||
mMarginAuto &= ~MarginAutoLeft;
|
||||
setLayoutMarginLeft( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
break;
|
||||
case PropertyId::MarginRight:
|
||||
setLayoutMarginRight( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
case PropertyId::MarginRight: {
|
||||
if ( attribute.asString() == "auto" ) {
|
||||
mMarginAuto |= MarginAutoRight;
|
||||
calculateAutoMargin();
|
||||
} else {
|
||||
mMarginAuto &= ~MarginAutoRight;
|
||||
setLayoutMarginRight( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
break;
|
||||
case PropertyId::MarginTop:
|
||||
setLayoutMarginTop( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
case PropertyId::MarginTop: {
|
||||
if ( attribute.asString() == "auto" ) {
|
||||
mMarginAuto |= MarginAutoTop;
|
||||
calculateAutoMargin();
|
||||
} else {
|
||||
mMarginAuto &= ~MarginAutoTop;
|
||||
setLayoutMarginTop( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
break;
|
||||
case PropertyId::MarginBottom:
|
||||
setLayoutMarginBottom( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
case PropertyId::MarginBottom: {
|
||||
if ( attribute.asString() == "auto" ) {
|
||||
mMarginAuto |= MarginAutoBottom;
|
||||
calculateAutoMargin();
|
||||
} else {
|
||||
mMarginAuto &= ~MarginAutoBottom;
|
||||
setLayoutMarginBottom( lengthFromValueAsDp( attribute ) );
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PropertyId::Tooltip: {
|
||||
String text = getTranslatorString( attribute.value() );
|
||||
setTooltipText( text );
|
||||
@@ -2410,12 +2569,14 @@ Float UIWidget::getMatchParentWidth() const {
|
||||
if ( getParent()->isWidget() )
|
||||
padding = static_cast<UIWidget*>( getParent() )->getPixelsPadding();
|
||||
|
||||
Float width = getParent()->getPixelsSize().getWidth() - mLayoutMarginPx.Left -
|
||||
mLayoutMarginPx.Right - padding.Left - padding.Right;
|
||||
Float marginLeft = ( mMarginAuto & MarginAutoLeft ) ? 0.f : mLayoutMarginPx.Left;
|
||||
Float marginRight = ( mMarginAuto & MarginAutoRight ) ? 0.f : mLayoutMarginPx.Right;
|
||||
|
||||
Float width = getParent()->getPixelsSize().getWidth() - marginLeft - marginRight -
|
||||
padding.Left - padding.Right;
|
||||
|
||||
if ( !mMaxWidthEq.empty() ) {
|
||||
Float maxWidth( getMaxSizePx().getWidth() - mLayoutMarginPx.Left - mLayoutMarginPx.Right -
|
||||
padding.Left - padding.Right );
|
||||
Float maxWidth( getMaxSizePx().getWidth() );
|
||||
if ( maxWidth > 0 && maxWidth < width )
|
||||
width = maxWidth;
|
||||
}
|
||||
@@ -2427,14 +2588,16 @@ Float UIWidget::getMatchParentHeight() const {
|
||||
Rectf padding = Rectf::Zero;
|
||||
|
||||
if ( getParent()->isWidget() )
|
||||
padding = static_cast<UIWidget*>( getParent() )->getPadding();
|
||||
padding = static_cast<UIWidget*>( getParent() )->getPixelsPadding();
|
||||
|
||||
Float height = getParent()->getPixelsSize().getHeight() - mLayoutMarginPx.Top -
|
||||
mLayoutMarginPx.Bottom - padding.Top - padding.Bottom;
|
||||
Float marginTop = ( mMarginAuto & MarginAutoTop ) ? 0.f : mLayoutMarginPx.Top;
|
||||
Float marginBottom = ( mMarginAuto & MarginAutoBottom ) ? 0.f : mLayoutMarginPx.Bottom;
|
||||
|
||||
Float height = getParent()->getPixelsSize().getHeight() - marginTop - marginBottom -
|
||||
padding.Top - padding.Bottom;
|
||||
|
||||
if ( !mMaxHeightEq.empty() ) {
|
||||
Float maxHeight( getMaxSizePx().getHeight() - mLayoutMarginPx.Left - mLayoutMarginPx.Right -
|
||||
padding.Left - padding.Right );
|
||||
Float maxHeight( getMaxSizePx().getHeight() );
|
||||
if ( maxHeight > 0 && maxHeight < height )
|
||||
height = maxHeight;
|
||||
}
|
||||
|
||||
@@ -173,9 +173,9 @@ void UIWidgetCreator::createBaseWidgetList() {
|
||||
registeredWidget["section"] = [] { return UIRichText::NewWithTag( "section" ); };
|
||||
registeredWidget["nav"] = [] { return UIRichText::NewWithTag( "nav" ); };
|
||||
registeredWidget["center"] = [] { return UIRichText::NewWithTag( "center" ); };
|
||||
registeredWidget["html"] = [] { return UIRichText::NewWithTag( "html" ); };
|
||||
registeredWidget["html"] = UIRichText::NewHtml;
|
||||
registeredWidget["head"] = [] { return UIWidget::NewWithTag( "head" ); };
|
||||
registeredWidget["body"] = [] { return UIRichText::NewWithTag( "body" ); };
|
||||
registeredWidget["body"] = UIRichText::NewBody;
|
||||
registeredWidget["form"] = [] { return UIRichText::NewWithTag( "form" ); };
|
||||
registeredWidget["table"] = UIHTMLTable::New;
|
||||
registeredWidget["tr"] = UIHTMLTableRow::New;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <eepp/scene/scenemanager.hpp>
|
||||
#include <eepp/system/filesystem.hpp>
|
||||
#include <eepp/system/sys.hpp>
|
||||
#include <eepp/ui/css/stylesheetparser.hpp>
|
||||
#include <eepp/ui/htmlinput.hpp>
|
||||
#include <eepp/ui/htmltextarea.hpp>
|
||||
#include <eepp/ui/htmltextinput.hpp>
|
||||
@@ -429,3 +430,139 @@ UTEST( UIHTMLTable, tableLayoutFixed ) {
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLBody, backgroundColorPropagation ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 650, "HTML Tables Test",
|
||||
WindowStyle::Default, WindowBackend::Default,
|
||||
32, {}, 1, false, true ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
|
||||
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
|
||||
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
|
||||
ASSERT_TRUE( font != nullptr && font->loaded() );
|
||||
FontFamily::loadFromRegular( font );
|
||||
|
||||
UI::UISceneNode* sceneNode = UI::UISceneNode::New();
|
||||
SceneManager::instance()->add( sceneNode );
|
||||
UI::UIThemeManager* themeManager = sceneNode->getUIThemeManager();
|
||||
themeManager->setDefaultFont( font );
|
||||
|
||||
sceneNode->loadLayoutFromString(
|
||||
R"(<html id="html_el">
|
||||
<body id="body_el" style="background-color: red; max-width: 960px;">
|
||||
</body>
|
||||
</html>)" );
|
||||
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
auto html_el = sceneNode->getRoot()->find( "html_el" );
|
||||
auto body_el = sceneNode->getRoot()->find( "body_el" );
|
||||
|
||||
ASSERT_TRUE( html_el != nullptr );
|
||||
ASSERT_TRUE( body_el != nullptr );
|
||||
|
||||
// HTML element should have inherited the red background color, and body should be transparent
|
||||
EXPECT_TRUE( html_el->asType<UIWidget>()->getBackgroundColor() == Color::Red );
|
||||
EXPECT_TRUE( body_el->asType<UIWidget>()->getBackgroundColor() == Color::Transparent );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLBody, maxWidthResizingBug ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 768, "HTML Resize Bug",
|
||||
WindowStyle::Default, WindowBackend::Default,
|
||||
32, {}, 1, false, true ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
|
||||
UI::UISceneNode* sceneNode = UI::UISceneNode::New();
|
||||
SceneManager::instance()->add( sceneNode );
|
||||
|
||||
UI::CSS::StyleSheetParser parser;
|
||||
parser.loadFromFile( "/tmp/style.css" );
|
||||
sceneNode->setStyleSheet( parser.getStyleSheet() );
|
||||
|
||||
std::string htmlContent;
|
||||
FileSystem::fileGet( "/tmp/dwarmstrong.html", htmlContent );
|
||||
sceneNode->loadLayoutFromString( htmlContent );
|
||||
|
||||
sceneNode->getRoot()->setSize( 1024, 768 );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
auto body_el = sceneNode->getRoot()->findByType( UI_TYPE_HTML_BODY )->asType<UIWidget>();
|
||||
ASSERT_TRUE( body_el != nullptr );
|
||||
Float widthAt1024 = body_el->getPixelsSize().getWidth();
|
||||
EXPECT_NEAR( widthAt1024, 960.f, 10.f ); // It should be around 960px (minus some margins if any)
|
||||
|
||||
sceneNode->getRoot()->setSize( 2048, 768 );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
Float widthAt2048 = body_el->getPixelsSize().getWidth();
|
||||
EXPECT_NEAR( widthAt2048, 960.f, 10.f ); // Body should stay 960px even when parent is huge
|
||||
|
||||
sceneNode->getRoot()->setSize( 1024, 768 );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
Float widthAfterResize = body_el->getPixelsSize().getWidth();
|
||||
EXPECT_NEAR( widthAt1024, widthAfterResize, 1.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UILayout, marginAuto ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 650, "Margin Auto Test",
|
||||
WindowStyle::Default, WindowBackend::Default,
|
||||
32, {}, 1, false, true ) );
|
||||
FileSystem::changeWorkingDirectory( Sys::getProcessPath() );
|
||||
|
||||
FontTrueType* font = FontTrueType::New( "NotoSans-Regular" );
|
||||
font->loadFromFile( "../assets/fonts/NotoSans-Regular.ttf" );
|
||||
ASSERT_TRUE( font != nullptr && font->loaded() );
|
||||
FontFamily::loadFromRegular( font );
|
||||
|
||||
UI::UISceneNode* sceneNode = UI::UISceneNode::New();
|
||||
SceneManager::instance()->add( sceneNode );
|
||||
UI::UIThemeManager* themeManager = sceneNode->getUIThemeManager();
|
||||
themeManager->setDefaultFont( font );
|
||||
|
||||
auto* container = sceneNode->loadLayoutFromString(
|
||||
R"(<vbox id="container">
|
||||
<widget id="child" style="margin: 0 auto;" />
|
||||
</vbox>)" );
|
||||
|
||||
auto child = sceneNode->getRoot()->find( "child" );
|
||||
ASSERT_TRUE( child != nullptr );
|
||||
|
||||
UIWidget* childWidget = child->asType<UIWidget>();
|
||||
UIWidget* contWidget = container->asType<UIWidget>();
|
||||
|
||||
contWidget->setSize( 500, 500 );
|
||||
childWidget->setSize( 100, 100 );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
Float expectedMarginX = ( contWidget->getPixelsSize().getWidth() - childWidget->getPixelsSize().getWidth() ) / 2.f;
|
||||
|
||||
// Margin left/right should be auto computed to expectedMarginX
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Left, expectedMarginX, 1.f );
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Right, expectedMarginX, 1.f );
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Top, 0.f, 1.f );
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Bottom, 0.f, 1.f );
|
||||
|
||||
// Resize parent and see if margins re-evaluate automatically
|
||||
contWidget->setSize( 800, 800 );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
expectedMarginX = ( contWidget->getPixelsSize().getWidth() - childWidget->getPixelsSize().getWidth() ) / 2.f;
|
||||
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Left, expectedMarginX, 1.f );
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Right, expectedMarginX, 1.f );
|
||||
|
||||
// Now test resize of child
|
||||
childWidget->setSize( 200, 100 );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
expectedMarginX = ( contWidget->getPixelsSize().getWidth() - childWidget->getPixelsSize().getWidth() ) / 2.f;
|
||||
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Left, expectedMarginX, 1.f );
|
||||
EXPECT_NEAR( childWidget->getLayoutPixelsMargin().Right, expectedMarginX, 1.f );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
@@ -3095,7 +3095,7 @@ void LLMChatUI::updateTabTitle() {
|
||||
}
|
||||
|
||||
if ( hasPendingPermissions )
|
||||
title += "- ✋ " + i18n( "action_required", "Action Required" ) + " - " + title;
|
||||
title = " - ✋ " + i18n( "action_required", "Action Required" ) + " - " + title;
|
||||
|
||||
if ( !mSummary.empty() )
|
||||
title += " - " + mSummary;
|
||||
|
||||
5
test_auto_margin_bug.html
Normal file
5
test_auto_margin_bug.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body style="max-width: 960px; margin: 0 auto; background-color: red;">
|
||||
<div style="width: 100px; height: 100px; background-color: blue;"></div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user