> Flexbox finally!

Flexbox finally!

22-08-2025

Table Of Contents

FLEXBOX

FINALLY!!! I finally got around to implementing FlexBox. It took me chugging an entire pitcher of black coffee (Don't judge me, I like doing that.) Granted, it's not fully functional, or maybe it is, I don't know, my unit tests are comprehensive enough to say yet.

To accomplish this, I knew I'd need to layout algorithm in a place that didn't require me to have a server running, so I moved all the layout code into its own module, named nlayout. And instead of it meaning "New Layout", the name now means "Narcissine Layout Engine", because to believe I can competently mimic web layout standards has got to be narcissistic.

When I transferred all the code over to the new module, I ditched whatever the hell code structure I had before and instead adopted a tree structure made out of LayoutNodes and LayoutBoxes. I had to do a quick bit of messing around with the Flow algorithm's previous implementation to get it to adapt.

But it worked, then, I implemented FlexBox. I had written pieces of the algorithm beforehand, adding a couple lines once a week here and there. But now, loaded up on a literal pitcher of black coffee, I wrote the entire algorithm in one afternoon and IT RAN, I AM THE GOAT

It worked in game as well, as you can see here:

Major hiccups

I soon however encountered an issue. I attempted to open the "Meta" page on Devtools, just to see if it rendered correctly. The server soon crashed because my ported-over Flow algorithm began looping infinitely. At this point it was late and I went to sleep.

The next day, after an hour or two of wrangling I managed to recreate the circumstance of the infinite loop in a Layout test file. It turns out the issue was caused by a width: auto; element having a width: 100% element as a child. During first time layout, the auto element's size is set to the screen's size, and then, after its child element's sizes are measured, the size of the auto element is adjusted.

The issue with this, is that the child element's size is set to the screen's size, then the parent element grows to adapt, then during the next measurement stabilization run, the child element grows again, and this repeats until the server stalls and crashes.

It took me an entire day to figure out how to handle and prevent this. I have to thank the W3C standards for coming in clutch, after about 8 hours I busted open the specs and found this section: Intrinsic Contributions of Percentage-Sized Boxes . Of course, just handle the percent values as auto if the parent's size isn't explicitly set. I don't know why or how, but yeah... this fixed it.

Thoughts

When I initially started writing the layout engine, I felt like I was in the dark, I didn't know what I was doing and everything I read either in the spec or from other people's own implementations or guides seemed to confuse me more.

One big thing that confused me was how you can perform layout without knowing the state of everything, the parent size may be auto, but the size you're trying to figure out is percentage based. How do you operate in that area of uncertainty?

Now though, I just write the layout code with the assumption of "I know everything about the state of the layout at this moment :)" And it works, and I'm much more familiar with the concepts and algorithms.

That being said, I still have a ways to go, Delphi at the moment does not support any kind of writing system other than left-to-write. I assume this already means this plugin cannot be used for languages like Arabic, which write right-to-left, or Japanese, which can be either left-to-right or vertical.

I wouldn't even know where to start with those languages, I only speak my own native language and English.

Other stuff

I also updated the NLayout documentation itself to reflect the new engine.

If you want to get the latest version of the plugin (at time of writing), the download link is here (Modrinth)!

Future stuff

I'm starting to feel the plugin is almost at a stage where I can call it ready for release. (That's a lie.)

I want to implement 2 more major features before it: Positioned Layout, and non-module based menus.

Positioned Layout

It feels like such a vital part for menus, that final touch, on top of Flow and Flexbox. Being able to position elements as you want on the page without it really affecting the current layout engine feels crucial for any release version of this plugin.

That being said. When it came to Flexbox and Flow, I started out with some knowledge of how they worked and their basics. I know almost nothing about Positioned layout. I've rarely used it, but each time I have used it, it has been powerful and provided features Flow and Flex cannot.

Non-module based menus

Currently, in order to create a menu, even programmatically, you need to register either a IoModule or a ApiModule that opens menus from a provided ResourcePath.

This system feels cumbersome and sometimes like it could get in the way. The big + it provides however, is the ability to open a menu anywhere, as long as you know the command, path and any optional query params that the menu might require. In fact, that's how I opened the Devtools before I added the /delphi devtools command. I used /delphi open @s devtools?:target=delphi-page-0. It's a bit cumbersome, but I could it anywhere and for whatever page.

The reason I feel non-module based should be added is because I think it'll be easier for developers to work with. If you can just create a Document anywhere and just open it, no need for a registered Module instance.

For now, as well, I think the creation of non-module based menus, or rather, pure programmatic menus would only be possible only through the Delphi plugin's API.