.. index:: pair: page; Native UI Layout Reference
.. _doxid-ui_layout_reference:
Native UI Layout Reference
==========================
This document is the authoritative reference for eepp's **native application UI layout system**.
It describes the behavior of the layout primitives used by normal eepp applications such as ecode, eterm, eproc, dialogs, settings panels, forms, workspaces, toolbars, and application-specific tools.
For the recommended high-level authoring model and conventions, read ```ui_authoring.md``` first.
This document intentionally describes **current eepp behavior**, not Android, browser, Qt, or other framework behavior that may look similar.
HTML formatting contexts such as block, inline, Flexbox, CSS Grid, table layout, floats, and positioned HTML are a separate system primarily used by ``UIWebView``, ``UIMarkdownView``, and the HTML compatibility layer. They are not covered here except where a distinction is important.
.. _doxid-ui_layout_reference_1autotoc_md949:
1. Native layout model
~~~~~~~~~~~~~~~~~~~~~~
The normal eepp layout model consists of:
.. ref-code-block:: cpp
UIWidget
size policy
margins
padding
layout gravity
min/max constraints
optional layout weight
optional relative-position relationship
UILayout
owns or participates in positioning/sizing children
specific layouts
UILinearLayout
UIRelativeLayout
UIGridLayout
UIFlowLayout
UISplitter
The most important idea is:
**The parent layout controls the final allocation and position of its children.**
A child supplies a sizing/placement contract through properties such as:
.. ref-code-block:: cpp
layout_width
layout_height
layout_weight
layout_gravity
margin
min-width
max-width
min-height
max-height
The exact meaning of those properties depends on the parent layout.
.. _doxid-ui_layout_reference_1autotoc_md951:
2. XML and CSS spelling
~~~~~~~~~~~~~~~~~~~~~~~
eepp accepts aliases, but normal project style distinguishes XML attributes from CSS properties.
Preferred XML spelling:
.. ref-code-block:: cpp
Preferred CSS spelling:
.. ref-code-block:: cpp
.form-input {
layout-width: 0dp;
layout-height: wrap_content;
layout-weight: 1;
layout-gravity: center_vertical;
}
Common compact aliases:
.. ref-code-block:: cpp
layout_width -> lw
layout_height -> lh
layout_weight -> lw8
layout_gravity -> lg
match_parent -> mp
wrap_content -> wc
Both full and compact forms are common in production eepp code.
.. _doxid-ui_layout_reference_1autotoc_md953:
3. Default widget layout state
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A newly constructed ``UIWidget`` starts with:
.. ref-code-block:: cpp
layout weight = 0
layout gravity = unset / 0
width policy = WrapContent
height policy = WrapContent
position policy = None
Specific widgets may override their own defaults.
Do not assume every widget behaves identically under ``wrap_content``; intrinsic sizing is widget-specific.
.. _doxid-ui_layout_reference_1autotoc_md955:
4. Size policies
~~~~~~~~~~~~~~~~
The native size-policy enum is:
.. ref-code-block:: cpp
enum class :ref:`SizePolicy ` {
:ref:`Fixed `,
:ref:`MatchParent `,
:ref:`WrapContent `
};
These policies are applied independently to width and height.
.. _doxid-ui_layout_reference_1autotoc_md956:
4.1 wrap_content
-------------------------
XML:
.. ref-code-block:: cpp
layout_width="wrap_content"
layout_height="wrap_content"
Compact:
.. ref-code-block:: cpp
lw="wc"
lh="wc"
A ``WrapContent`` axis asks the widget to derive its size from its intrinsic/content size.
The exact intrinsic size is widget-specific.
Examples:
* text widgets derive size from their text and font metrics;
* image widgets derive size from the drawable;
* buttons derive size from their internal content/theme;
* native layouts may derive their wrapped axis from their visible children.
Padding contributes to normal content sizing where the widget implementation defines it.
``wrap_content`` is the default native size policy for a plain ``UIWidget``.
.. _doxid-ui_layout_reference_1autotoc_md957:
4.2 match_parent
-------------------------
XML:
.. ref-code-block:: cpp
layout_width="match_parent"
layout_height="match_parent"
Compact:
.. ref-code-block:: cpp
lw="mp"
lh="mp"
``MatchParent`` requests the available parent content size on that axis.
The generic match-parent calculation is:
.. ref-code-block:: cpp
parent size
- parent content offsets
- non-auto child margins
Parent content offsets include padding and, where applicable, borders.
``max-width`` / ``max-height`` can cap the resulting match-parent size.
Conceptually:
.. ref-code-block:: cpp
child match-parent width =
parent width
- parent left/right content offsets
- child left/right margins
The exact layout can perform additional sizing rules around this value.
Do not treat ``match_parent`` as a synonym for CSS ``width: 100%``. They may often produce similar geometry, but they belong to different layout systems.
.. _doxid-ui_layout_reference_1autotoc_md958:
4.3 Fixed size
--------------
Any explicit dimension normally selects ``Fixed`` sizing on that axis:
.. ref-code-block:: cpp
layout_width="240dp"
layout_height="32dp"
The value is resolved and stored as the widget size.
The literal value:
.. ref-code-block:: cpp
fixed
can also select the fixed policy without supplying a new dimension.
Use explicit sizes where the dimension itself is meaningful. Do not use arbitrary fixed dimensions to compensate for a parent-layout mistake.
.. _doxid-ui_layout_reference_1autotoc_md959:
4.4 Zero size and weighted LinearLayout children
------------------------------------------------
There is one important special case.
Inside a ``UILinearLayout``, the canonical weighted-child pattern intentionally uses zero on the weighted axis:
Horizontal parent:
.. ref-code-block:: cpp
Vertical parent:
.. ref-code-block:: cpp
When eepp parses a zero layout dimension for a weighted child whose parent is a ``UILinearLayout``, it does not immediately force the stored size in the normal fixed-size path. The linear layout assigns the weighted size during packing.
.. _doxid-ui_layout_reference_1autotoc_md961:
5. Minimum and maximum constraints
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Widgets support:
.. ref-code-block:: cpp
min-width
max-width
min-height
max-height
These can constrain native layout results.
For example, generic ``match_parent`` width calculation applies a ``max-width`` cap when one exists.
Some native layout algorithms also explicitly fit wrapped container sizes against min/max constraints.
Do not assume min/max handling is identical to browser intrinsic-sizing rules. This document describes the native layout system; HTML layout has additional rules.
.. _doxid-ui_layout_reference_1autotoc_md963:
6. Margin and padding
~~~~~~~~~~~~~~~~~~~~~
.. _doxid-ui_layout_reference_1autotoc_md964:
Margin
------
Margins belong to the child and participate in parent layout allocation/positioning.
Example:
.. ref-code-block:: cpp
Margins affect:
* linear packing;
* match-parent available size;
* relative positioning;
* flow wrapping;
* grid placement;
* splitter/container alignment where relevant.
.. _doxid-ui_layout_reference_1autotoc_md965:
Padding
-------
Padding belongs to the container/widget.
Example:
.. ref-code-block:: cpp
...
Native layouts generally place children inside the padded content area.
Conceptually:
.. ref-code-block:: cpp
container border box
padding
child layout area
.. _doxid-ui_layout_reference_1autotoc_md967:
7. gravity and layout_gravity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These are different properties.
.. _doxid-ui_layout_reference_1autotoc_md968:
gravity
----------------
``gravity`` controls the widget's own content or, for layouts that explicitly use it, the layout's internal arrangement.
Examples include:
.. ref-code-block:: cpp
left
right
center_horizontal
top
bottom
center_vertical
center
Widget behavior varies because different widget types own different content.
.. _doxid-ui_layout_reference_1autotoc_md969:
layout_gravity
-----------------------
``layout_gravity`` describes how the widget should be placed by its parent layout when that layout supports gravity.
XML:
.. ref-code-block:: cpp
layout_gravity="right|center_vertical"
CSS:
.. ref-code-block:: cpp
layout-gravity: right|center_vertical;
The distinction is:
.. ref-code-block:: cpp
gravity
content/layout behavior inside this widget
layout_gravity
placement of this widget by its parent
This distinction is especially important in ``UILinearLayout``.
.. _doxid-ui_layout_reference_1autotoc_md971:
8. gravity-owner
~~~~~~~~~~~~~~~~~~~~~~~~~
Layouts normally respect the positioning policy of their parent.
Some parent widgets advertise that they own child positioning with ``UI_OWNS_CHILDREN_POSITION``.
A layout can set:
.. ref-code-block:: cpp
gravity-owner: true
to force its own ``layout_gravity`` alignment against the parent even when the parent normally owns child positions.
This is an advanced escape hatch and should not be a default solution to layout problems.
.. _doxid-ui_layout_reference_1autotoc_md973:
9. Layout invalidation and update behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Native layouts are invalidated when relevant state changes, including:
* child count changes;
* layout-affecting child attributes;
* layout size changes;
* padding changes;
* parent-size changes.
A dirty layout is normally scheduled through the owning ``UISceneNode``.
During an active layout pass, some updates can occur synchronously to avoid waiting for another frame.
Calling ``UILayout::getSize()`` on a dirty layout forces that layout to update before returning its size.
Nested layouts are tracked by their parent ``UILayout`` and participate in layout-tree updates.
This matters mainly when implementing custom layout widgets. Ordinary application code should set properties and allow the scene to perform layout.
.. _doxid-ui_layout_reference_1autotoc_md975:
10. Visibility and native layouts
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Native layouts generally operate on **visible widget children**.
Examples:
* ``UILinearLayout`` ignores invisible children while packing;
* ``UIFlowLayout`` ignores invisible children while creating rows;
* ``UIGridLayout`` ignores invisible children;
* invisible native layouts may collapse their own layout size to zero during their update path.
Do not use invisible children as spacers.
.. _doxid-ui_layout_reference_1autotoc_md977:
11. UILinearLayout
~~~~~~~~~~~~~~~~~~~~~~~~~~~
``UILinearLayout`` is the primary sequential application layout.
XML aliases:
.. ref-code-block:: cpp
C++:
.. ref-code-block:: cpp
UILinearLayout::NewVertical();
UILinearLayout::NewHorizontal();
Default orientation:
.. ref-code-block:: cpp
vertical
.. _doxid-ui_layout_reference_1autotoc_md978:
11.1 Vertical linear layout
---------------------------
A vertical layout packs visible children from top to bottom.
Each child's vertical margins contribute to the consumed main-axis space.
The child's ``layout_gravity`` controls **horizontal** placement inside the layout:
.. ref-code-block:: cpp
left
center_horizontal
right
Example:
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md979:
11.2 Horizontal linear layout
-----------------------------
A horizontal layout packs visible children from left to right.
Each child's horizontal margins contribute to consumed main-axis space.
The child's ``layout_gravity`` controls **vertical** placement:
.. ref-code-block:: cpp
top
center_vertical
bottom
Example:
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md981:
12. LinearLayout size-policy behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before packing, the layout applies child policies on the cross axis.
.. _doxid-ui_layout_reference_1autotoc_md982:
Vertical layout
---------------
For child width:
* ``WrapContent`` : child auto-sizing is enabled;
* ``MatchParent`` : width becomes the layout's content width minus child horizontal margins;
* ``Fixed`` : existing width remains.
A child with ``layout_height="match_parent"`` and zero weight can also be resized to the parent's available height.
.. _doxid-ui_layout_reference_1autotoc_md983:
Horizontal layout
-----------------
For child height:
* ``WrapContent`` : child auto-sizing is enabled;
* ``MatchParent`` : height becomes the layout's content height minus child vertical margins;
* ``Fixed`` : existing height remains.
A child with ``layout_width="match_parent"`` and zero weight can also be resized to the parent's available width.
.. _doxid-ui_layout_reference_1autotoc_md985:
13. LinearLayout weights
~~~~~~~~~~~~~~~~~~~~~~~~
``layout_weight`` distributes remaining space along the layout orientation.
Canonical horizontal use:
.. ref-code-block:: cpp
Canonical vertical use:
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md986:
13.1 Weight calculation
-----------------------
The implementation treats positive weights as **relative weights**.
For all visible children:
.. ref-code-block:: cpp
totalWeight = sum(max(childWeight, 0))
The layout first calculates the main-axis space already consumed by:
* visible non-weighted fixed/wrapped children;
* visible child margins.
Then each positively weighted child gets:
.. ref-code-block:: cpp
remainingSpace * childWeight / totalWeight
Therefore these are equivalent ratios:
.. ref-code-block:: cpp
1, 1
0.5, 0.5
50, 50
and:
.. ref-code-block:: cpp
1, 3
25, 75
produce equivalent proportions.
Current implementation does **not** require weights to be normalized to ``0..1`` or sum to ``1``.
Older documentation that describes weights as normalized should be considered overly restrictive.
.. _doxid-ui_layout_reference_1autotoc_md987:
13.2 Example calculation
------------------------
Container:
.. ref-code-block:: cpp
horizontal content width = 600dp
Children:
.. ref-code-block:: cpp
A = fixed 100dp
B = weight 1
C = weight 3
Ignoring margins:
.. ref-code-block:: cpp
remaining = 600 - 100 = 500
totalWeight = 4
B = 125
C = 375
.. _doxid-ui_layout_reference_1autotoc_md989:
14. LinearLayout wrap-content behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A vertical ``UILinearLayout`` with ``layout_height="wrap_content"`` grows to the visible child heights, vertical margins, and padding.
A horizontal ``UILinearLayout`` with ``layout_width="wrap_content"`` similarly grows from visible child widths, margins, and padding.
The cross-axis wrapped size is based on the maximum visible non-match-parent child extent plus container padding, with min/max constraints considered.
A wrapped linear layout can repack after its cross-axis size changes because that size may affect child alignment or nested layout.
.. _doxid-ui_layout_reference_1autotoc_md991:
15. LinearLayout properties
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Layout-specific:
.. ref-code-block:: cpp
orientation
gravity-owner
``orientation`` values:
.. ref-code-block:: cpp
vertical
horizontal
Default:
.. ref-code-block:: cpp
vertical
Child properties commonly used with a linear layout:
.. ref-code-block:: cpp
layout_width
layout_height
layout_weight
layout_gravity
margin
min-width
max-width
min-height
max-height
.. _doxid-ui_layout_reference_1autotoc_md993:
16. UIRelativeLayout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``UIRelativeLayout`` is a native layout for:
* alignment against the parent;
* positioning one child relative to a sibling.
It owns child positioning.
Use it when sibling relationships are more natural than a nested ``vbox`` / ``hbox`` hierarchy.
Do not choose it merely because it permits more arbitrary positioning.
.. _doxid-ui_layout_reference_1autotoc_md995:
17. RelativeLayout child sizing
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For each widget child:
Width:
.. ref-code-block:: cpp
WrapContent -> enable auto-sizing
MatchParent -> layout width - child horizontal margins - layout horizontal padding
Fixed -> keep existing width
Height:
.. ref-code-block:: cpp
WrapContent -> enable auto-sizing
MatchParent -> layout height - child vertical margins - layout vertical padding
Fixed -> keep existing height
.. _doxid-ui_layout_reference_1autotoc_md997:
18. RelativeLayout parent alignment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When a child has no sibling-relative position policy, ``layout_gravity`` positions it against the ``UIRelativeLayout``.
Horizontal:
.. ref-code-block:: cpp
left
center_horizontal
right
Vertical:
.. ref-code-block:: cpp
top
center_vertical
bottom
Example:
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md999:
19. RelativeLayout sibling relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Supported relationships are:
.. ref-code-block:: cpp
layout_to_left_of
layout_to_right_of
layout_to_top_of
layout_to_bottom_of
The value is the target sibling ID.
Example:
.. ref-code-block:: cpp
The relationship is resolved by finding the referenced node and storing the target widget.
It is used only when target and positioned widget share the same parent.
Only one stored ``PositionPolicy`` is active at a time.
This is not a general constraint solver.
.. _doxid-ui_layout_reference_1autotoc_md1001:
20. RelativeLayout wrap-content caveat
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``UIRelativeLayout::updateLayout()`` applies its own size policy and lays out children, but it does **not** compute a new bounding rectangle from all positioned children.
For application containers, prefer a defined or ``match_parent`` size when using ``UIRelativeLayout``.
Do not assume ``wrap_content`` behaves like a general constraint-layout "measure descendants and fit" pass.
.. _doxid-ui_layout_reference_1autotoc_md1003:
21. UIGridLayout
~~~~~~~~~~~~~~~~~~~~~~~~~
``UIGridLayout`` is eepp's **native repeated-cell grid**.
It is not CSS Grid.
Use it for normal application UI when children should occupy repeated cells with a common row/column size policy.
Do not infer CSS track sizing behavior from this class.
.. _doxid-ui_layout_reference_1autotoc_md1005:
22. GridLayout sizing model
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Grid cells use one column mode and one row mode.
.. ref-code-block:: cpp
column-mode:
size
weight
row-mode:
size
weight
Defaults:
.. ref-code-block:: cpp
column-mode = weight
row-mode = weight
column-weight = 0.25
row-weight = 0.25
column-width = 0
row-height = 0
column-margin = 0
row-margin = 0
When ``column-mode=size``, cell width is ``column-width``.
When ``column-mode=weight``, cell width is approximately:
.. ref-code-block:: cpp
available grid width * column-weight
When ``row-mode=size``, cell height is ``row-height``.
When ``row-mode=weight``, cell height is approximately:
.. ref-code-block:: cpp
available grid height * row-weight
.. _doxid-ui_layout_reference_1autotoc_md1007:
23. GridLayout placement
~~~~~~~~~~~~~~~~~~~~~~~~
Visible widget children are processed sequentially.
For each child:
#. determine target cell size;
#. set child size policy to ``Fixed, Fixed``;
#. resize child to target size;
#. place child at current grid position;
#. advance by cell width plus column margin;
#. wrap to the next row when the next cell no longer fits.
This is a repeated-cell wrapping grid, not a named-track CSS grid.
.. _doxid-ui_layout_reference_1autotoc_md1009:
24. GridLayout child weight override
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``UIGridLayout`` has a special behavior:
If a child has non-zero ``layout_weight``, that child's target **width** becomes:
.. ref-code-block:: cpp
child layout weight
* grid content width
This is not ``UILinearLayout`` 's remaining-space distribution algorithm.
Do not assume ``layout_weight`` means the same algorithm in every layout type.
For straightforward grids, prefer the layout-level row/column sizing properties unless this per-child width override is intentionally needed.
.. _doxid-ui_layout_reference_1autotoc_md1011:
25. GridLayout alignment
~~~~~~~~~~~~~~~~~~~~~~~~
The grid's own horizontal ``gravity`` affects row placement:
.. ref-code-block:: cpp
left
center
right
This is container ``gravity``, not child ``layout_gravity``.
.. _doxid-ui_layout_reference_1autotoc_md1013:
26. GridLayout wrap-content behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With:
.. ref-code-block:: cpp
layout_height="wrap_content"
the layout derives its height from generated rows plus vertical padding.
A match-parent grid width/height is resolved from the parent before cell placement.
Children are converted to fixed cell sizes during grid layout.
.. _doxid-ui_layout_reference_1autotoc_md1015:
27. GridLayout properties
~~~~~~~~~~~~~~~~~~~~~~~~~
.. ref-code-block:: cpp
column-mode
column-weight
column-width
column-margin
row-mode
row-weight
row-height
row-margin
Container ``gravity`` also affects horizontal grid alignment.
.. _doxid-ui_layout_reference_1autotoc_md1017:
28. UIFlowLayout
~~~~~~~~~~~~~~~~~~~~~~~~~
``UIFlowLayout`` is eepp's native horizontal wrapping flow layout.
Conceptually:
.. ref-code-block:: cpp
A B C D
E F G
H I
Children are consumed in order from left to right.
When the next visible child no longer fits the current row, a new row is created.
.. _doxid-ui_layout_reference_1autotoc_md1019:
29. FlowLayout width behavior
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A notable design choice:
When the flow layout itself uses:
.. ref-code-block:: cpp
layout_width="wrap_content"
it initially uses the available match-parent width as its wrapping width.
After layout, if all visible children effectively fit on one row and use less than the available width, the layout can shrink its wrapped width to the used width.
So ``wrap_content`` for ``UIFlowLayout`` is not simply "sum all child widths without a constraint." Available parent width participates in wrapping first.
.. _doxid-ui_layout_reference_1autotoc_md1021:
30. FlowLayout row creation
~~~~~~~~~~~~~~~~~~~~~~~~~~~
For each visible child:
#. apply the child's size policy;
#. test whether the child would exceed the current row;
#. if necessary, create a new row;
#. place the child;
#. include child margins in row consumption;
#. track the row's maximum height.
The implementation can also create a new row after placement when the resulting cursor exceeds the layout width.
.. _doxid-ui_layout_reference_1autotoc_md1023:
31. FlowLayout child size policies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Before rows are built:
.. ref-code-block:: cpp
WrapContent width/height
enable child auto-sizing
MatchParent width
available match-parent width
MatchParent height
available match-parent height
Fixed
retain explicit size
After row heights are known, a child with:
.. ref-code-block:: cpp
layout_height="match_parent"
is resized to that row's maximum height.
.. _doxid-ui_layout_reference_1autotoc_md1025:
32. FlowLayout alignment
~~~~~~~~~~~~~~~~~~~~~~~~
The flow layout's own ``gravity`` controls row-group placement.
Horizontal gravity:
.. ref-code-block:: cpp
left
center
right
controls each row's horizontal displacement.
Vertical gravity:
.. ref-code-block:: cpp
top
center_vertical
bottom
can shift the complete row group inside a container taller than the total flow content.
Within each row, ``row-valign`` controls child vertical alignment.
.. _doxid-ui_layout_reference_1autotoc_md1027:
33. row-valign
~~~~~~~~~~~~~~~~~~~~~~~
Values:
.. ref-code-block:: cpp
top
center
bottom
Default:
.. ref-code-block:: cpp
bottom
Meaning:
.. ref-code-block:: cpp
top
child aligns near row top, respecting top margin
center
child is centered in row maximum height
bottom
child aligns near row bottom, respecting bottom margin
This is separate from the container's vertical ``gravity``.
.. _doxid-ui_layout_reference_1autotoc_md1029:
34. FlowLayout wrap-content height
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With:
.. ref-code-block:: cpp
layout_height="wrap_content"
height becomes:
.. ref-code-block:: cpp
top padding
+ sum(row maximum heights)
+ bottom padding
with child vertical margins contributing to row heights.
.. _doxid-ui_layout_reference_1autotoc_md1031:
35. FlowLayout properties
~~~~~~~~~~~~~~~~~~~~~~~~~
Layout-specific:
.. ref-code-block:: cpp
row-valign
gravity-owner
Important general properties:
.. ref-code-block:: cpp
gravity
layout_width
layout_height
padding
margin
``UIFlowLayout`` does not use child ``layout_weight`` as a remaining-space distribution mechanism.
.. _doxid-ui_layout_reference_1autotoc_md1033:
36. UISplitter
~~~~~~~~~~~~~~~~~~~~~~~
``UISplitter`` is a two-pane resizable layout.
Default orientation:
.. ref-code-block:: cpp
horizontal
Horizontal:
.. ref-code-block:: cpp
[first pane] | [second pane]
Vertical:
.. ref-code-block:: cpp
[first pane]
-------------
[second pane]
The separator is an internal draggable widget.
.. _doxid-ui_layout_reference_1autotoc_md1035:
37. Splitter child model
~~~~~~~~~~~~~~~~~~~~~~~~
``UISplitter`` supports at most two external widget children.
Internally it also owns its separator widget.
The first external child becomes the first pane; the second becomes the last pane.
Additional external children are rejected/closed.
Children placed into the splitter are forced to:
.. ref-code-block:: cpp
Fixed, Fixed
because the splitter owns their exact geometry.
.. _doxid-ui_layout_reference_1autotoc_md1037:
38. Splitter with one child
~~~~~~~~~~~~~~~~~~~~~~~~~~~
If only one pane exists:
* the separator is hidden and disabled;
* the first child fills the splitter's padded content area.
.. _doxid-ui_layout_reference_1autotoc_md1039:
39. Split partition
~~~~~~~~~~~~~~~~~~~
Property:
.. ref-code-block:: cpp
splitter-partition
Default:
.. ref-code-block:: cpp
50%
Meaning:
Desired space occupied by the first pane along the splitter axis.
The separator's own size is removed from available split space when visible.
Conceptually:
.. ref-code-block:: cpp
totalSpace =
splitter content axis size
- visible separator size
first = resolve(splitter-partition, totalSpace)
second = totalSpace - first
.. _doxid-ui_layout_reference_1autotoc_md1041:
40. Splitter minimum sizes
~~~~~~~~~~~~~~~~~~~~~~~~~~
The first pane's minimum size constrains the initial partition.
During dragging, both pane minimum sizes constrain separator movement.
A requested partition may therefore not be achievable when it violates minimum sizes.
Do not assume ``0%`` always produces a physically zero-sized first pane if its minimum size is non-zero.
.. _doxid-ui_layout_reference_1autotoc_md1043:
41. Splitter visibility properties
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. ref-code-block:: cpp
splitter-always-show
Default:
.. ref-code-block:: cpp
true
When true, the divider remains visible whenever two panes exist.
.. ref-code-block:: cpp
splitter-hide-on-edge
Default:
.. ref-code-block:: cpp
false
When enabled and ``splitter-always-show`` is false, percentage partitions exactly at ``0%`` or ``100%`` can hide the divider so one pane consumes the full splitter.
.. _doxid-ui_layout_reference_1autotoc_md1045:
42. Splitter dragging
~~~~~~~~~~~~~~~~~~~~~
Horizontal orientation:
.. ref-code-block:: cpp
separator drags along x
cursor = horizontal resize
Vertical orientation:
.. ref-code-block:: cpp
separator drags along y
cursor = vertical resize
Dragging immediately resizes both children.
After a drag, the stored split partition is recalculated as a percentage of available split space.
.. _doxid-ui_layout_reference_1autotoc_md1047:
43. Splitter properties
~~~~~~~~~~~~~~~~~~~~~~~
.. ref-code-block:: cpp
orientation
splitter-partition
splitter-always-show
splitter-hide-on-edge
Orientation values:
.. ref-code-block:: cpp
horizontal
vertical
.. _doxid-ui_layout_reference_1autotoc_md1049:
44. Choosing the correct native layout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
======================================== =========================
Need Native layout
======================================== =========================
Vertical sequence
Horizontal sequence
Flexible remaining space in a row/column
Child positioned relative to a sibling
Repeated equal/weighted cells
Horizontal items that wrap into rows
Two user-resizable panes
Tabs
Split/tab editor workspace
Web/document formatting HTML compatibility layout
======================================== =========================
``UITabWidget`` and ``UITabWidgetSplitter`` are higher-level containers rather than low-level generic layout algorithms and belong in the widget/application references.
.. _doxid-ui_layout_reference_1autotoc_md1051:
45. Production patterns
~~~~~~~~~~~~~~~~~~~~~~~
.. _doxid-ui_layout_reference_1autotoc_md1052:
Flexible form row
-----------------
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md1053:
Header + flexible content + footer
----------------------------------
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md1054:
Wrapping option group
---------------------
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md1055:
Two-pane workspace
------------------
.. ref-code-block:: cpp
.. _doxid-ui_layout_reference_1autotoc_md1057:
46. Important differences from browser layout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Do not import these as semantic equivalences:
.. ref-code-block:: cpp
match_parent == width:100%
layout_weight == flex-grow
UIGridLayout == CSS Grid
UIFlowLayout == display:flex + flex-wrap
layout_gravity == justify-content / align-items
They can be useful analogies, but native eepp layouts are separate algorithms.
.. _doxid-ui_layout_reference_1autotoc_md1059:
47. Important differences from Android intuition
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eepp deliberately borrows several Android-style concepts, especially:
.. ref-code-block:: cpp
LinearLayout
layout_width
layout_height
match_parent
wrap_content
layout_weight
layout_gravity
RelativeLayout-style sibling relations
dp
Android documentation is not authoritative for eepp.
Notable example:
Current eepp ``UILinearLayout`` weights are arbitrary relative positive values; they do not need to be normalized or sum to ``1``.
Always prefer eepp behavior over external analogy.
.. _doxid-ui_layout_reference_1autotoc_md1061:
48. Inspecting native layout at runtime
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Use the **Runtime UI Inspector & Automation Protocol** rather than guessing geometry.
Typical process:
.. ref-code-block:: cpp
ui.contexts
↓
ui.query target
↓
ui.inspect target geometry/layout properties
↓
inspect parent
↓
inspect relevant siblings
↓
screenshot if useful
Stable debugging questions:
.. ref-code-block:: cpp
What parent layout owns this child?
What are its width/height policies?
What are its actual bounds?
Does it have weight?
What are its margins?
What is the parent's padding?
What gravity is active?
What min/max constraints exist?
For weighted linear layouts, inspect all siblings participating in the same axis.
.. _doxid-ui_layout_reference_1autotoc_md1063:
49. Layout debugging checklist
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When size is wrong:
.. ref-code-block:: cpp
1. identify parent layout type
2. inspect layout_width / layout_height
3. determine Fixed / MatchParent / WrapContent
4. check layout_weight
5. check margins
6. check parent padding/content offsets
7. check min/max constraints
8. check sibling sizes/weights
9. check visibility
10. only then consider an explicit fixed size
When position is wrong:
.. ref-code-block:: cpp
1. identify parent layout
2. check layout_gravity
3. distinguish layout_gravity from gravity
4. check margins
5. check RelativeLayout position relationship
6. check parent gravity where Grid/Flow uses it
7. check gravity-owner only if parent positioning ownership matters
.. _doxid-ui_layout_reference_1autotoc_md1065:
50. Implementation-oriented notes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
These details matter mainly when implementing custom layouts.
.. _doxid-ui_layout_reference_1autotoc_md1066:
Layout dirtiness
----------------
``UILayout`` maintains dirty state and participates in the scene's layout invalidation queue.
.. _doxid-ui_layout_reference_1autotoc_md1067:
Reentrancy guard
----------------
Layouts use ``mPacking`` to prevent recursive packing.
.. _doxid-ui_layout_reference_1autotoc_md1068:
Nested layouts
--------------
A ``UILayout`` tracks direct child layouts and updates the layout tree recursively.
.. _doxid-ui_layout_reference_1autotoc_md1069:
Auto-size children
------------------
A layout can request ``onAutoSize()`` for ordinary children or temporarily update a child layout as wrapping content.
.. _doxid-ui_layout_reference_1autotoc_md1070:
Parent notifications
--------------------
When a layout's wrapped size changes, implementations notify the parent so enclosing layouts can repack.
Custom layout implementations should preserve these lifecycle expectations.
.. _doxid-ui_layout_reference_1autotoc_md1072:
51. Scope boundaries
~~~~~~~~~~~~~~~~~~~~
This document intentionally does not specify:
* HTML Flexbox;
* HTML CSS Grid;
* block/inline formatting;
* HTML table layout;
* floats;
* sticky/fixed/absolute HTML positioning;
* HTML intrinsic min-content/max-content behavior.
See ```ui_html_compatibility.md``` for HTML/web layout semantics.
For related topics:
* ```ui_introduction.md``` — introduction to eepp's UI system.
* ```ui_authoring.md``` — recommended application UI mental model and authoring conventions.
* ```ui_css_for_applications.md``` — CSS behavior and conventions for normal application widgets.
* ```ui_inspector.md``` — runtime UI inspection and automation protocol.
* ```ui_databinding.md``` — UI data binding.
* ```ui_charts.md``` — charting widgets and chart-specific behavior.
.. _doxid-ui_layout_reference_1autotoc_md1074:
52. Source of truth
~~~~~~~~~~~~~~~~~~~
When uncertain about native layout behavior, use this order:
#. current eepp implementation
#. current eepp unit/integration tests
#. production eepp/ecode/eterm/eproc usage
#. this reference
#. ```css_specification.md``` and other general docs
#. Android/browser/other-framework analogy
If a documented rule and the current implementation disagree, treat the implementation as authoritative and update the documentation.