Fix text span attribute changes not updating the layout.

Fix UIHTMLBody.maxWidthResizingBug.
This commit is contained in:
Martín Lucas Golini
2026-04-14 01:24:50 -03:00
parent 16579dad0e
commit 04db5aa2f7
4 changed files with 305 additions and 9 deletions

View File

@@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Daniel Wayne Armstrong">
<meta name="description" content="Libre all the things">
<link rel="stylesheet" href="/style.css">
<link rel="stylesheet" href="/fonts/yanone_kaffeesatz/style.css" type="text/css" media="all">
<link rel="icon" href="/favicon.ico" type="image/x-icon">
<title>Daniel Wayne Armstrong</title>
</head>
<body>
<header id="mainMenu">
<nav>
<a href="/" class="author">Daniel Wayne Armstrong</a>
<span class="separator">&bull;</span> <a href="/archive/">Archive</a>
<span class="separator">&bull;</span> <a href="/feed.xml" target="_blank">RSS</a>
<span class="separator">&bull;</span> <a href="https:&#x2F;&#x2F;fosstodon.org&#x2F;@dwarmstrong" target="_blank">Fediverse</a>
</nav>
</header>
<main>
<div id="greeting">
<p><img src="/img/me2-240px.jpg" alt="me" width="110" height="110" class="me" />Hello! I'm <span class="author">Daniel</span>. Welcome to my blog. Here are <a href="/archive/">all my posts</a>.
</p>
<p>I love <a href="https://en.wikipedia.org/wiki/Free_and_open-source_software" target="_blank">free/libre software</a>, run <a href="/tags/linux/">Linux</a> or <a href="/tags/bsd/">BSD</a> on every computer I get my hands on, and think a good book paired with a cup of coffee is a little piece of Heaven.
</p>
<div class="clear-float">
<h2>Latest Posts</h2>
<ul class="latest-list">
<li>
<a href="https://www.dwarmstrong.org/netbsd-encrypt-install/">NetBSD Installation with Disk Encryption</a>
<br /><span class="meta">Last edited on 2026-04-12</span>
</li>
<li>
<a href="https://www.dwarmstrong.org/netbsd-ssh-keys/">Configure SSH on NetBSD for Passwordless Logins to Servers</a>
<br /><span class="meta">Last edited on 2026-04-06</span>
</li>
<li>
<a href="https://www.dwarmstrong.org/chimera-install-zfs/">Just Enough Chimera Linux</a>
<br /><span class="meta">Last edited on 2026-04-03</span>
</li>
</ul>
</div>
</div>
</main>
<footer>
<hr>
<p><em>The impediment to action advances action. What stands in the way becomes the Way.</em> &mdash; Marcus Aurelius<br />
&copy; 2026 Daniel Wayne Armstrong
<span class="separator">&bull;</span> <a href="/contact/">Contact</a>
<span class="separator">&bull;</span> Created with <span class="love">&hearts;</span> using <a href="https://www.getzola.org/" target="_blank">Zola</a>
</p>
</footer>
</body>
</html>

View File

@@ -0,0 +1,212 @@
/*
* Reaction Time Is A Factor In This
*/
body {
background-color: #000;
color: #d8dee9;
max-width: 960px;
margin: 1.5rem auto !important;
padding: 0 1.5rem;
float: none !important;
font-family: system-ui, sans-serif;
font-size: 1.2rem;
line-height: 1.45em;
}
h1, h2, h3, h4, h5, h6 {
font-family: "yanone_kaffeesatz", sans-serif;
color: #8fbcbb;
}
h1 {
font-size: 2.75rem;
line-height: 2.25rem;
margin: 1.9rem 0 0 0;
}
h2 {font-size: 2.25rem; line-height: 2.15rem;}
h3, h4, h5, h6 {font-size: 1.75rem;}
p.breadcrumbs {color: #8fbcbb;}
p.mastodon {
text-align: center;
}
p.page-next {
text-align: right;
margin-top: 0.65rem;
margin-bottom: -0.5rem;
}
p.tags {font-size: 1.25rem; line-height: 2rem;}
a {
color: #81a1c1;
text-decoration: none;
border-bottom: 2px dashed #4c566a;
}
a:hover {color: #bf616a; border-bottom: none;}
header a {
font-family: "yanone_kaffeesatz", sans-serif;
font-size: 1.5rem;
text-decoration: none;
border-bottom: none;
}
blockquote {
border-left: 0.4rem solid #8fbcbb;
font-style: italic;
padding: 0 1.0em;
}
code {
background-color: #2e3440;
padding: 0.1rem 0.2rem;
font-family: monospace;
font-size: 1rem;
}
pre code {
border-left: 0.4rem solid #8fbcbb;
page-break-inside: avoid;
padding: .5rem 1rem;
line-height: 1.2rem;
font-size: 1.1rem;
max-width: 100%;
display: block;
overflow: auto;
overflow-x: auto;
}
img {max-width: 100%;}
img.centre {display: block; margin: 1rem auto;}
img.floatleft {float: left; margin: 0 1rem 1rem 0;}
img.floatright {float: right; margin: 0 0 1rem 1rem;}
/* margin: top/right/bottom/left */
/* img.me {float: right; margin: 0 0 1rem 1rem; border-radius: 5%;} */
img.me {float: left; margin: 0 1rem 1rem 0; border-radius: 5%;}
.clear-float {
clear: both; /* This element will appear below the floated image */
}
ul {list-style: square; padding-left: 1.2rem;}
ul li {padding-bottom: 0.5rem;}
ul.latest-list {
font-size: 1.2rem;
line-height: 1.45em;
}
ul.page-list a, ul.latest-list a {
font-size: 1.85rem;
font-family: "yanone_kaffeesatz", sans-serif;
line-height: 2rem;
}
hr {color: #8fbcbb;}
footer {
text-align: center;
font-size: 1rem;
margin-top: 1.5em;
}
#greeting {
font-size: 1.35rem;
line-height: 1.3em;
}
#fossBanner {
background-image: url(img/foss-banner.png);
display: block;
/* text-indent: -9999px; */
width: 880px;
height: 120px;
margin: 0 auto;
border-bottom: none;
}
#fossSubtitle p {
font-family: monospace;
font-size: 1.1rem;
text-align: center;
margin-top: 0;
color: #ff3131;
}
#fossQuote p {
text-align: right;
margin-top: 1.5rem;
}
#mainMenu {
font-size: 1.45rem;
margin-bottom: 1.2rem;
}
.author {font-weight: bold; color: #ebcb8b;}
.rss {color: #f26522;}
.boldWords {font-weight: bold;}
.clear {clear: both;}
.bottomMenu {margin-top: 2em;}
.feed {color: #d08770;}
.love {color: #ff3131;}
.meta {margin-top: 0.5rem; color: #5d6d7e;}
.separator {color: #8fbcbb; padding: 0 0.4rem;}
.tag-count{vertical-align: super; font-size: 1rem;}
/* Separators */
/* See https://stackoverflow.com/a/26634224 */
.readMore {
display: flex;
align-items: center;
text-align: center;
color: #8fbcbb;
margin-top: 1.5rem;
}
.readMore::before,
.readMore::after {
content: '';
flex: 1;
border-bottom: 1px solid #8fbcbb;
}
.readMore:not(:empty)::before {margin-right: .25em;}
.readMore:not(:empty)::after {margin-left: .25em;}
/* Footnotes */
.footnote-definition p{display:inline}
.footnote-definition+.footnote-definition{margin-top:1em}
.footnote-reference,.footnote-definition-label{text-decoration:none}
.footnote-reference:before,.footnote-definition-label:before{content:"["}
.footnote-reference:after,.footnote-definition-label:after{content:"]"}
.footnote-reference a{text-decoration:none}

View File

@@ -330,15 +330,18 @@ void UITextSpan::onAlphaChange() {
void UITextSpan::onFontChanged() {
sendCommonEvent( Event::OnFontChanged );
notifyLayoutAttrChange();
}
void UITextSpan::onFontStyleChanged() {
sendCommonEvent( Event::OnFontStyleChanged );
notifyLayoutAttrChange();
}
void UITextSpan::onTextChanged() {
sendCommonEvent( Event::OnTextChanged );
sendCommonEvent( Event::OnValueChange );
notifyLayoutAttrChange();
}
void UITextSpan::onChildCountChange( Node* child, const bool& removed ) {

View File

@@ -478,11 +478,11 @@ UTEST( UIHTMLBody, maxWidthResizingBug ) {
SceneManager::instance()->add( sceneNode );
UI::CSS::StyleSheetParser parser;
parser.loadFromFile( "/tmp/style.css" );
parser.loadFromFile( "assets/html/dwarmstrong/style.css" );
sceneNode->setStyleSheet( parser.getStyleSheet() );
std::string htmlContent;
FileSystem::fileGet( "/tmp/dwarmstrong.html", htmlContent );
FileSystem::fileGet( "assets/html/dwarmstrong/dwarmstrong.html", htmlContent );
sceneNode->loadLayoutFromString( htmlContent );
sceneNode->getRoot()->setSize( 1024, 768 );
@@ -491,19 +491,20 @@ UTEST( UIHTMLBody, maxWidthResizingBug ) {
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)
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();
}
@@ -538,7 +539,8 @@ UTEST( UILayout, marginAuto ) {
childWidget->setSize( 100, 100 );
sceneNode->updateDirtyLayouts();
Float expectedMarginX = ( contWidget->getPixelsSize().getWidth() - childWidget->getPixelsSize().getWidth() ) / 2.f;
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 );
@@ -550,7 +552,8 @@ UTEST( UILayout, marginAuto ) {
contWidget->setSize( 800, 800 );
sceneNode->updateDirtyLayouts();
expectedMarginX = ( contWidget->getPixelsSize().getWidth() - childWidget->getPixelsSize().getWidth() ) / 2.f;
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 );
@@ -559,7 +562,8 @@ UTEST( UILayout, marginAuto ) {
childWidget->setSize( 200, 100 );
sceneNode->updateDirtyLayouts();
expectedMarginX = ( contWidget->getPixelsSize().getWidth() - childWidget->getPixelsSize().getWidth() ) / 2.f;
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 );