From ff96ef10c5f5a2e3ee000b87b2d7f3e4268f3993 Mon Sep 17 00:00:00 2001 From: Pierre Dittgen Date: Fri, 1 May 2026 15:51:41 +0200 Subject: [PATCH 1/2] fix and update french translations (#177) --- bin/assets/i18n/fr.xml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/assets/i18n/fr.xml b/bin/assets/i18n/fr.xml index 41bcd62fe..d27b72aef 100644 --- a/bin/assets/i18n/fr.xml +++ b/bin/assets/i18n/fr.xml @@ -407,7 +407,7 @@ Redémarrez ecode pour voir les changements. Indenter Alignement de l'indentation Caractère à utiliser pour l'indentation - Largeur d'indentation + Taille d'indentation Type d'indentation Nœud-i Insérer la requête de recherche @@ -775,8 +775,8 @@ La valeur minimale est 1 et le maximum est 6. Nécessite un redémarrage. Schéma de couleurs syntaxique Système - Largeur des onglets - Onglets + Taille des tabulations + Tabulations Terminal Schéma de couleurs du terminal Schéma de couleurs du terminal : %s @@ -881,7 +881,7 @@ dans l'arborescence de répertoires ainsi que dans les boites de dialogues de s Nom de la variable Variables Vue - Viewport + Fenêtre d'affichage VSync Vsync : configuration mise à jour. Redémarrer ecode pour voir les changements. @@ -894,10 +894,10 @@ Redémarrer ecode pour voir les changements. Répertoire de travail %s Rechercher les symboles dans l'espace de travail... - Letter wrap - Wrap Mode - Wrap Against - Word wrap + Au caractère + Mode de retour à la ligne + Retour à la ligne + Au mot Écrire le BOM Unicode Vous n'avez pas encore ouvert de dossier. Zoomer From d64638d989e7e5f384e682f06882c2f36ebf61e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Fri, 1 May 2026 11:30:22 -0300 Subject: [PATCH 2/2] Out of flow positioning fixes. --- bin/assets/ui/breeze.css | 7 +- src/eepp/ui/uihtmlwidget.cpp | 64 +++++++++++---- .../unit_tests/uihtml_position_tests.cpp | 81 +++++++++++++++++++ 3 files changed, 131 insertions(+), 21 deletions(-) diff --git a/bin/assets/ui/breeze.css b/bin/assets/ui/breeze.css index dadd802b8..bd5268976 100644 --- a/bin/assets/ui/breeze.css +++ b/bin/assets/ui/breeze.css @@ -129,11 +129,6 @@ center { text-align: center; } -ul > li, -ol > li { - padding-left: 2em; -} - ul { list-style-type: disc; } @@ -178,7 +173,7 @@ MarkdownView blockquote { MarkdownView ul, MarkdownView ol { - padding-left: 0; + padding-left: 21dp; } MarkdownView ul ul, diff --git a/src/eepp/ui/uihtmlwidget.cpp b/src/eepp/ui/uihtmlwidget.cpp index d6758c853..ada6f9ef8 100644 --- a/src/eepp/ui/uihtmlwidget.cpp +++ b/src/eepp/ui/uihtmlwidget.cpp @@ -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; diff --git a/src/tests/unit_tests/uihtml_position_tests.cpp b/src/tests/unit_tests/uihtml_position_tests.cpp index 52572fddb..235622f3c 100644 --- a/src/tests/unit_tests/uihtml_position_tests.cpp +++ b/src/tests/unit_tests/uihtml_position_tests.cpp @@ -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(); +}