Layout
Overview
The Elements Library provides a comprehensive set of elements for laying out elements in the view.
Limits
Each element provides information on how it wants to be sized by means of
min
and max
limits: a hint that determine its actual extent and how it
will be placed in the view depending on available window space. The element’s
limits
member function determines the minimum and maximum extents of an
element:
view_limits limits(basic_context const& ctx) const;
See Context for information about basic_context
. view_limits
is a struct that gives us the min
and max
information:
struct view_limits
{
point min = {0.0, 0.0};
point max = {full_extent, full_extent};
};
For the purpose of this document, we will use these terms and expressions:
- limits
-
The limits of an element
- limits.min
-
The minimum limits of an element
- limits.min.x
-
The minimum horizontal limit of an element
- limits.min.y
-
The minimum vertical limit of an element
- limits.max
-
The maximum limits of an element
- limits.max.x
-
The maximum horizontal limit of an element
- limits.max.y
-
The maximum vertical limit of an element
- horizontal limits
-
(limits.min.x, limits.max.x)
- vertical limits
-
(limits.min.y, limits.max.y)
- minimum limits
-
(limits.min.x, limits.min.y)
- maximum limits
-
(limits.max.x, limits.max.y)
- minimum horizontal limit
-
limits.min.x
- maximum horizontal limit
-
limits.max.x
- minimum vertical limit
-
limits.min.y
- maximum vertical limit
-
limits.max.y
By default, an element has full limits: it is infinitely resizable:
constexpr view_limits full_limits = {
{0.0, 0.0}
, {full_extent, full_extent}
};
An element with full_limits
can be resized from an empty point (zero x and
y size) up to the full extent of the screen, and beyond (if possible).
full_extent is actually an implementation defined huge
number near the maximum limits of the coordinate’s data type (also
implementation defined).
|
-
An element has a fixed horizontal size if this expression is true:
limits.min.x == limits.max.x
. -
An element has a fixed vertical size if this expression is true:
limits.min.y == limits.max.y
.
Examples
{{100, 100}, {100, 100}}; // Fixed size
{{100, 100}, {100, full_extent}}; // Fixed width, flexible height
{{100, 100}, {100, 200}}; // Fixed width, semi-flexible height (100 to 200)
Size Elements
Size elements override the limits of an enclosed element. There is a comprehensive list of size related elements in the Elements Library that can be used for various purposes. This section catalogues all the available size elements.
limit
Overrides the limits of an element.
Notation
|
Instance of |
|
Instance of |
Stretch Elements
Resizable elements are elements with minimum limits that are less than the
maximum limits in either x or y dimensions or both. Resizable elements can
therefore stretch if there is extra available space allocated to it beyond
its minimum limit. When two or more resizable elements are placed side by
side in an htile or vtile, the element’s "stretchiness"
determines how much extra space is given to it. The element’s "stretchiness"
is determined by the element’s stretch
member function:
virtual view_stretch stretch() const;
where view_stretch
is a struct declared as:
struct view_stretch
{
float x = 1.0;
float y = 1.0;
};
The view_stretch
x
and y
members determine how much an element can
stretch in the x or y dimensions. The default is 1.0. A stretchiness value of
2.0 means that the element is able to stretch twice as much compared to its
siblings in an htile or vtile, assuming they have the
default 1.0 stretchiness.
hstretch
Overrides the horizontal stretchiness of an an enclosed element (subject
).
Semantics
-
The
subject
will assume the givenstretch
value. -
The stretch value has no effect to elements with fixed horizontal size.
-
Returns instance of
Proxy
.
For example, the image below shows how three elements are laid out in an
htile
, with stretch values of 1.0
, 1.0
and 2.0
, respectively:
The element with the 2.0
stretch value stretches twice as much compared to
its siblings.
vstretch
Overrides the vertical stretchiness of an an enclosed element (subject
).
Semantics
-
The
subject
will assume the givenstretch
value. -
The stretch value has no effect to elements with fixed vertical limits.
-
Returns instance of
Proxy
.
For example, the image below shows how three elements are laid out in an
htile
, with stretch values of 0.5
, 1.0
and 1.5
, respectively:
The element with the 0.5
stretch value stretches half less, while the
element with the 1.5
stretches half more than the default.
Scale Element
Align Elements
An element can be aligned arbitrarily from 0.0 to 1.0 in either the x or y dimensions, or both. There is a comprehensive list of align elements in The Elements Library that can be used for various purposes. This section catalogues all the available align elements.
halign
Aligns the an enclosed element (subject
) in the x-axis.
valign
Aligns the an enclosed element (subject
) in the y-axis.
Margin Elements
Margins add some space around elements. There is a comprehensive list of margin elements in the Elements Library that can be used for various purposes. This section catalogues all the available margin elements.
margin
Adds a margin all around an enclosed element (subject
).
Semantics
-
Space is added to the left, top, right, and bottom of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
margin
does not violate the natural limits of the subject.margin
will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_left
Adds a margin to the left of an enclosed element (subject
).
Semantics
-
Space is added to the left of the subject with the given parameter.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_left
does not violate the natural limits of the subject.margin_left
will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_right
Adds a margin to the right of an enclosed element (subject
).
Semantics
-
Space is added to the right of the subject with the given parameter.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_right
does not violate the natural limits of the subject.margin_right
will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_top
Adds a margin to the top of an enclosed element (subject
).
Semantics
-
Space is added to the top of the subject with the given parameter.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_top
does not violate the natural limits of the subject.margin_top
will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_bottom
Adds a margin to the bottom of an enclosed element (subject
).
Semantics
-
Space is added to the to the bottom of the subject with the given parameter.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_bottom
does not violate the natural limits of the subject.margin_bottom
will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
hmargin
(same as margin_left_right
)
Adds a margin to the left and right sides of an enclosed element (subject
).
Expressions
// variant 1
hmargin({left, right}, subject)
// variant 2
hmargin(left, right, subject)
// variant 3
margin_left_right({left, right}, subject)
// variant 4
margin_left_right(left, right, subject)
Semantics
-
Space is added to the to the left and right sides of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
hmargin
(and variants) does not violate the natural limits of the subject.hmargin
(and variants) will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
vmargin
(same as margin_top_bottom
)
Adds a margin to the top and bottom sides of an enclosed element (subject
).
Expressions
// variant 1
vmargin({top, bottom}, subject)
// variant 2
vmargin(top, bottom, subject)
// variant 3
margin_top_bottom({top, bottom}, subject)
// variant 4
margin_top_bottom(top, bottom, subject)
Semantics
-
Space is added to the to the top and bottom sides of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
vmargin
(and variants) does not violate the natural limits of the subject.vmargin
(and variants) will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_left_top
Adds a margin to the left and top sides of an enclosed element (subject
).
Expressions
// variant 1
margin_left_top({left, top}, subject)
// variant 2
margin_left_top(left, top, subject)
Semantics
-
Space is added to the to the left and top sides of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_left_top
(and variant) does not violate the natural limits of the subject.margin_left_top
(and variant) will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_left_bottom
Adds a margin to the left and bottom sides of an enclosed element (subject
).
Expressions
// variant 1
margin_left_bottom({left, bottom}, subject)
// variant 2
margin_left_bottom(left, bottom, subject)
Semantics
-
Space is added to the to the left and bottom sides of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_left_bottom
(and variant) does not violate the natural limits of the subject.margin_left_bottom
(and variant) will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_right_top
Adds a margin to the right and top sides of an enclosed element (subject
).
Expressions
// variant 1
margin_right_top({right, top}, subject)
// variant 2
margin_right_top(right, top, subject)
Semantics
-
Space is added to the to the right and top sides of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_right_top
(and variant) does not violate the natural limits of the subject.margin_right_top
(and variant) will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
margin_right_bottom
Adds a margin to the right and bottom sides of an enclosed element (subject
).
Expressions
// variant 1
margin_right_bottom({right, bottom}, subject)
// variant 2
margin_right_bottom(right, bottom, subject)
Semantics
-
Space is added to the to the right and bottom sides of the subject with the given parameters.
-
The element’s limits is overridden to account for the additional space.
-
The
margin_right_bottom
(and variant) does not violate the natural limits of the subject.margin_right_bottom
(and variant) will respect the subject’s min-max constraints and resizability. -
Returns instance of
Proxy
.
Floating Element
A floating element allows arbitrary placement of an enclosed element
(subject
) in the main view.
Expression
floating({left, top, right, bottom}, subject)
Notation
|
|
|
Instance of |
Semantics
-
The element will be placed exactly to the specified position in the main view, constrained to the subject’s natural limits.
-
The floating element does not violate the natural limits of the subject.
-
Returns instance of
Proxy
.
Tiles and Grids
Tiles are the most useful layout elements, followed by by Grids. Tiles are
used everywhere for composing hierarchical elements in rows and columns,
typical to all GUIs. Grids are similar to tiles. Both tiles and grids allow
elements to fluidly adjust depending on available space. Tiles compute the
layout of its elements using the children elements' size limits
while grids
lay out its elements using an externally supplied fractional coordinates that
specify positions of the elements in the allocated space.
Tiles are best used for composing UI elements while grids are best for composing tables.
Horizontal Grids
Horizontal Grids are composites that lay out one or more child elements in a
row following externally supplied horizontal fractional positions. Horizontal
Grids have computed horizontal and vertical sizes following the natural
limits
of its children.
Semantics
-
The elements are laid out in a single row, left to right, immediately next to each other with no intervening space.
-
The elements are positioned horizontally using the supplied fractional positions. The fractional positions values range from 0.0 to 1.0, which specify the child element’s horizontal position from left (0.0) to right (1.0).
-
The grid’s minimum vertical limit is computed as the maximum of the children elements' minimum vertical limits.
-
The grid’s maximum vertical limit is computed as the minimum of the children elements' maximum vertical limits.
-
The final computed minimum limit is clamped to ensure it is not greater than the computed maximum limit. Likewise the computed maximum limit is clamped to ensure it is not less than the computed minimum limit.
-
The supplied (horizontal) positions and computed (vertical) coordinates may violate the limits of its children elements.
-
If the allocated size of a child element is lower than the element’s minimum limits in either dimension, the element will be cropped.
-
If a child element’s maximum limits in either dimension is exceeded, the element will be aligned to the top-left.
-
hgrid
Build a horizontal grid with a fixed number of elements.
Notation
|
The number of items |
|
One or more child elements, instances of |
|
External container of fractional positions (more below) |
The external container, positions
, can either be a plain array of type
float[N]
or std::array<float, N>
. Elements e1,...eN
are held in a
std::array<element_ptr, N>
managed by the horizontal grid element.
Example
static float positions[] = {0.25, 0.5, 0.75, 1.0};
//...
hgrid(positions, item1, item2, item3, item4)
If the number of elements is not fixed, you can use an
hgrid_composite (see below).
|
Requirements
-
The number of supplied positions and elements should match, otherwise, compiler error (no matching function for call to
hgrid
). -
The positions assume the first element is at
x=0
(it is at the left-most position in the row). The fractional position of the second element is at index0
, the third at index1
, and so on. -
The externally supplied positions should be sorted with increasing values such that positions[n] <= positions[n+1]. The behavior is undefined if this is violated.
hgrid_composite
Create a horizontal grid with an indeterminate (dynamic) number of elements.
Notation
|
External container of fractional positions, |
|
Instance of type |
The hgrid_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use hgrid_composite
just as you would a std::vector
, such as push_back
a child element. Just
keep in mind that we are dealing with element_ptr
items.
Example
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in hgrid_composite .
|
hgrid_composite
is itself also an element
and while it has std::vector
's
interface, it can also be share
d like any element, which allows you to
build complex hierarchical structures.
Requirements
-
The number of items in the external coordinates vector
positions
must match with the number of elements at any given time. -
The positions assume the first element is at
x=0
(it is at the left-most position in the row). The fractional position of the second element is at index0
, the third at index1
, and so on. -
The externally supplied positions should be sorted with increasing values such that positions[n] <= positions[n+1]. The behavior is undefined if this is violated.
Horizontal Tiles
Horizontal Tiles are similar to Horizontal Grids, but allow elements to fluidly adjust horizontally depending on available space. Horizontal Tiles are best used for composing UI elements while Horizontal Grids are best for composing tables.
Semantics
-
The elements are laid out in a single row, left to right, immediately next to each other with no intervening space.
-
The elements are positioned horizontally using the children’s natural limits.
-
Horizontal space is allocated using this algorithm:
-
Space is allocated for each child element following the child’s natural minimum horizontal limit.
-
If the allocated space exceeds the sum of all children elements' minimum horizontal limits, the extra space is given to each horizontally resizable element (
limits.min.x < limits.max.x
). -
The element’s "stretchiness" determines how much extra space is given to it according to the element’s
stretch()
member function. A stretch value of1.0
is default. A stretchiness value of 2.0 means that the element is able to stretch twice as much compared to its siblings. Horizontally fixed-sized elements will not be stretched (element d in the diagram). (Also see Stretch Elements).
-
-
The tile’s minimum vertical limit is computed as the maximum of the children elements' minimum vertical limits.
-
The grid’s maximum vertical limit is computed as the minimum of the children elements' maximum vertical limits.
-
The final computed minimum limit is clamped to ensure it is not greater than the computed maximum limit. Likewise the computed maximum limit is clamped to ensure it is not less than the computed minimum limit.
-
The supplied (horizontal) and computed (vertical) coordinates may violate the limits of its children elements.
-
If the allocated size of a child element is lower than the element’s minimum limits in either dimension, the element will be cropped.
-
If a child element’s maximum limits in either dimension is exceeded, the element will be aligned to the top-left.
-
htile
Build a horizontal tile with a fixed number of elements.
Notation
|
The number of items |
|
One or more child elements, instances of |
Elements e1,...eN
are held in a std::array<element_ptr, N>
managed by the
horizontal tile element.
htile_composite
Create a horizontal tile with an indeterminate (dynamic) number of elements.
Notation
|
Instance of type |
The htile_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use htile_composite
just as you would a std::vector
, such as push_back
a child element. Just
keep in mind that we are dealing with element_ptr
items.
Example
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in htile_composite .
|
htile_composite
is itself also an element
and while it has std::vector
's
interface, it can also be share
d like any element, which allows you to
build complex hierarchical structures.
Vertical Grids
Vertical Grids are composites that lay out one or more child elements in a
column following externally supplied vertical fractional positions. Vertical
Grids have computed horizontal and vertical sizes following the natural
limits
of its children.
Semantics
-
The elements are laid out in a single column, top to bottom, immediately next to each other with no intervening space.
-
The elements are positioned vertically using the supplied fractional positions. The fractional positions values range from 0.0 to 1.0, which specify the child element’s vertical position from top (0.0) to bottom (1.0).
-
The grid’s minimum horizontal limit is computed as the maximum of the children elements' minimum horizontal limits.
-
The grid’s maximum horizontal limit is computed as the minumum of the children elements' maximum horizontal limits.
-
The final computed minimum limit is clamped to ensure it is not greater than the computed maximum limit. Likewise the computed maximum limit is clamped to ensure it is not less than the computed minimum limit.
-
The supplied (vertical) positions and computed (horizontal) coordinates may violate the limits of its children elements.
-
If the allocated size of a child element is lower than the element’s minimum limits in either dimension, the element will be cropped.
-
If a child element’s maximum limits in either dimension is exceeded, the element will be aligned to the top-left.
-
vgrid
Build a vertical grid with a fixed number of elements.
Notation
|
The number of items |
|
One or more child elements, instances of |
|
External container of fractional positions (more below) |
The External container, positions
is an external can either be a plain array
of type float[N]
or std::array<float, N>
. Elements e1,...eN
are held in
a std::array<element_ptr, N>
managed by the vertical grid element.
Example
static float positions[] = {0.25, 0.5, 0.75, 1.0};
//...
vgrid(positions, item1, item2, item3, item4)
If the number of elements is not fixed, you can use an
vgrid_composite (see below).
|
Requirements
-
The number of supplied coordinates and elements should match, otherwise, compiler error (no matching function for call to
vgrid
). -
The positions assume the first element is at
x=0
(it is at the top-most position in the column). The fractional position of the second element is at index0
, the third at index1
, and so on. -
The externally supplied positions should be sorted with increasing values such that positions[n] <= positions[n+1]. The behavior is undefined if this is violated.
vgrid_composite
Create a vertical grid with an indeterminate (dynamic) number of elements.
Notation
|
External container of fractional positions, |
|
Instance of type |
The vgrid_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use vgrid_composite
just as you would a std::vector
, such as push_back
a child element. Just
keep in mind that we are dealing with element_ptr
items. Example:
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in vgrid_composite .
|
vgrid_composite
is itself also an element
and while it has std::vector
's
interface, it can also be share
d like any element, which allows you to
build complex hierarchical structures.
Requirements
-
The number of items in the external coordinates vector
positions
must match with the number of elements at any given time. -
The positions assume the first element is at
x=0
(it is at the top-most position in the column). The fractional position of the second element is at index0
, the third at index1
, and so on. -
The externally supplied positions should be sorted with increasing values such that positions[n] <= positions[n+1]. The behavior is undefined if this is violated.
Vertical Tiles
Vertical Tiles are similar to Vertical Grids, but allow elements to fluidly adjust vertically depending on available space. Vertical Tiles are best used for composing UI elements while Vertical Grids are best for composing tables.
Semantics
-
The elements are laid out in a single column, left to right, immediately next to each other with no intervening space.
-
The elements are positioned vertically using the children’s natural limits.
-
Vertical space is allocated using this algorithm:
-
Space is allocated for each child element following the child’s natural minimum vertical limit.
-
If the allocated space exceeds the sum of all children elements' minimum vertical limits, the extra space is given to each vertically resizable element (
limits.min.y < limits.max.y
). -
The element’s "stretchiness" determines how much extra space is given to it according to the element’s
stretch()
member function. A stretch value of1.0
is default. A stretchiness value of 2.0 means that the element is able to stretch twice as much compared to its siblings. Vertically fixed-sized elements will not be stretched (element b in the diagram). (Also see Stretch Elements).
-
-
The tile’s minimum horizontal limit is computed as the maximum of the children elements' minimum horizontal limits.
-
The grid’s maximum horizontal limit is computed as the minumum of the children elements' maximum horizontal limits.
-
The final computed minimum limit is clamped to ensure it is not greater than the computed maximum limit. Likewise the computed maximum limit is clamped to ensure it is not less than the computed minimum limit.
-
The supplied (vertical) and computed (horizontal) coordinates may violate the limits of its children elements.
-
If the allocated size of a child element is lower than the element’s minimum limits in either dimension, the element will be cropped.
-
If a child element’s maximum limits in either dimension is exceeded, the element will be aligned to the top-left.
-
vtile
Build a vertical tile with a fixed number of elements.
Notation
|
The number of items |
|
One or more child elements, instances of |
Elements e1,...eN
are held in a std::array<element_ptr, N>
managed by the
vertical tile element.
vtile_composite
Create a vertical tile with an indeterminate (dynamic) number of elements:
Notation
|
Instance of type |
The vtile_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use vtile_composite
just as you would a std::vector
, such as push_back
a child element. Just
keep in mind that we are dealing with element_ptr
items.
Example
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in vtile_composite .
|
vtile_composite
is itself also an element
and while it has
std::vector
's interface, it can also be share
d like any element, which
allows you to build complex hierarchical structures.
Layers
The Elements Library is 2D, but the z-axis pertains to top-to-bottom layering. Layers allow groups of elements to be placed in the z-axis where higher-level elements obscure or hide lower-level elements.
Semantics
-
The elements are laid out in the z-axis, top to bottom.
-
Rendering is done bottom-up; the bottom-most elements are drawn first.
-
UI control (such as mouse clicks) proceeds from top to bottom. Higher-level elements are given control priority. If a higher-level element does not process the event, lower-level elements are given a chance.
-
The layer’s minimum limit is computed as the maximum of the children elements' minimum limits.
-
The layer’s maximum limit is computed as the minimum of the children elements' maximum limits.
-
The final computed minimum limit is clamped to ensure it is not greater than the computed maximum limit. Likewise the computed maximum limit is clamped to ensure it is not less than the computed minimum limit.
-
The computed (vertical) and (horizontal) coordinates may violate the limits of its children elements.
-
If the allocated size of a child element is lower than the element’s minimum limits in either dimension, the element will be cropped.
-
If a child element’s maximum limits in either dimension is exceeded, the element will be aligned to the top-left.
-
layer
Create a layer composite with a fixed number of elements.
Notation
|
The number of items |
|
One or more child elements, instances of |
Elements e1,...eN
are held in a std::array<element_ptr, N>
managed by the
layer element.
layer_composite
Create a layer with an indeterminate (dynamic) number of elements:
layer_composite c;
Notation
|
Instance of type |
The layer_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use layer_composite
just as you would a std::vector
, such as push_back
a child element. Just
keep in mind that we are dealing with element_ptr
items.
Example
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in layer_composite .
|
layer_composite
is itself also an element
and while it has
std::vector
's interface, it can also be share
d like any element, which
allows you to build complex hierarchical structures.
Decks
The Deck is very similar to layers. Elements are placed in the z-axis. But unlike layers, only the selected element is active (top-most by default).
deck
Create a deck composite with a fixed number of elements.
Notation
|
The number of items |
|
One or more child elements, instances of |
Elements e1,...eN
are held in a std::array<element_ptr, N>
managed by the
deck element.
deck_composite
Create a deck with an indeterminate (dynamic) number of elements:
Notation
|
Instance of type |
The deck_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use deck_composite
just as you would a std::vector
, such as push_back
a child element. Just
keep in mind that we are dealing with element_ptr
items.
Example
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in deck_composite .
|
deck_composite
is itself also an element
and while it has std::vector
's
interface, it can also be share
d like any element, which allows you to
build complex hierarchical structures.
Flow Element
The flow element, is a composite that lays out its children much like the way
text is laid out: lay out each element from left to right, fitting as much
elements as possible following each child’s maximum horizontal limit. Once
a row is full, move to the next row and do the same until the end of the row
is filled. Repeat the procedure until all the elements are laid out. The
height of each row is determined by the maximum vertical limit of all the
elements to be laid out in that row. The following graphic depicts a
simplified layout scenario for child elements a
to r
.
The child elements arranged in a flow
composite are automatically re-flowed
(re-lay-out) when the view size changes.
To have elements laid out using flow
, you need to make a flow_composite
.
flow_composite
Create a flow_composite
with an indeterminate (dynamic) number of elements.
Notation
|
Instance of type |
The flow_composite
is basically a std::vector<element_ptr>
that the
client uses to manage the composite’s elements. The lifetime of the
container, c
, is the client’s responsibility. You use flow_composite
just
as you would a std::vector
, such as push_back
a child element, child
.
Just keep in mind that we are dealing with element_ptr
items.
Example
c.push_back(share(child));
share turns an element object into an element_ptr held by
the std::vector<element_ptr> in flow_composite .
|
flow_composite
is itself also an element
and while it has std::vector
's
interface, it can also be share
d like any element, which allows you to
build complex hierarchical structures.
flow
Once we have a flow_composite
, we can place its contents in a flow
element.
Semantics
-
Returns instance of
Composite
.
Copyright (c) 2014-2024 Joel de Guzman. All rights reserved. Distributed under the MIT License