WebFlexLayoutManager is a custom layout manager component for Xojo Web, designed to bring CSS Flexbox-like layout capabilities natively to Xojo Web controls. It is a direct port from a Desktop version, allowing developers to create responsive, dynamic layouts without needing to write custom CSS or JavaScript.
The main idea behind WebFlexLayoutManager is to allow Xojo Web UI controls to be automatically positioned and sized according to flexbox rules (Row/Column direction, alignment, justification, growing, and gap spacing), recalculating positions automatically on browser resize or control visibility changes.
- Flexbox-like Algorithm: Implements a subset of CSS Flexbox logic directly in Xojo code.
- Direction Support: Arrange controls in a
Row(horizontal) orColumn(vertical). - Justify Content (Main Axis): Support for
FlexStart,FlexEnd,Center,SpaceBetween,SpaceAround, andStretch. - Align Items (Cross Axis): Support for
FlexStart,FlexEnd,Center, andStretch. - Flex Grow: Controls can be assigned a grow factor (via
AddControl(control, growFactor)orSetFlexGrow(control, factor)) to proportionally share remaining available space. - Spacing Control: Define a specific pixel
Gapbetween items. - Padding Boundaries: Supports
PaddingLeft,PaddingRight,PaddingTop, andPaddingBottomfor the container. - Dynamic Updates: Automatically recalculates layout when the browser window is resized (via
Resizedevent) or when control properties are updated. - Visibility Handling: Automatically ignores invisible controls (
Visible = False) and recalculates the layout for remaining visible items.
- Flex Wrap: Support wrapping controls to a new line/column when they exceed the available container space.
- Align Self: Allow individual controls to override the container's
AlignItemsproperty. - Nested Layouts Support: Improve support and testing for placing
WebFlexLayoutManagerinstances inside otherWebFlexLayoutManagerinstances. - Max/Min Constraints: Respect minimum and maximum width/height constraints of managed controls during layout calculation.
Problem: Xojo Web controls rely on absolute positioning or basic locking, making complex responsive layouts difficult without writing custom WebSDK controls or injecting raw CSS.
Solution: Ported the desktop FlexLayoutManager to Xojo Web by subclassing WebRectangle. Implemented a 5-step mathematical layout algorithm entirely in Xojo code to calculate absolute Left, Top, Width, and Height properties for child controls.
Problem: The layout needs to update automatically when the browser window changes size.
Solution: Utilized the WebRectangle.Resized event to trigger ApplyLayout().
Problem: Sometimes the layout wouldn't apply correctly on initial page load because control dimensions weren't fully realized by the browser.
Solution: Added a JavaScript workaround in the Shown event: Me.ExecuteJavaScript("setTimeout(function(){ window.dispatchEvent(new Event('resize')); }, 50);") to force a resize event shortly after the control is rendered on the client side.
Problem: Distributing fractional remaining space among multiple growing controls could leave empty gaps due to integer rounding.
Solution: Implemented a floating-point calculation Round((grow / totalFlexGrow) * remainingSpace) to minimize rounding errors during distribution.
Problem: When the first control in a container had growFactor = 0 and subsequent controls had growFactor > 0, the layout rendered sizes incorrectly. This occurred because AddControl() calls ApplyLayout() after each addition. When only grow=0 controls existed, the Justify = Stretch path would inflate them to fill the entire container. On subsequent AddControl() calls that introduced grow>0 controls, the inflated size was read back as the "fixed" space, consuming all available room and leaving grow>0 controls with zero size. This bug manifested regardless of whether the container direction was Row or Column.
Solution: Introduced a flex-basis mechanism (BasisWidthMap and BasisHeightMap) that stores each control's original Width and Height at the time it is added via AddControl(). The layout algorithm now uses these stored basis values instead of the live c.Width/c.Height when calculating fixed space for grow=0 controls. This prevents intermediate layout passes from corrupting control sizes.