pub struct Layout { /* private fields */ }Implementations§
Source§impl Layout
impl Layout
Sourcepub fn vertical<C>(constraints: C) -> Self
pub fn vertical<C>(constraints: C) -> Self
Creates a vertical layout with the given constraints.
A vertical layout splits the available area from top to bottom into multiple horizontal slices.
In other words:
Constraintvalues are applied to theheight- All resulting rectangles share the same
xandwidth - Rectangles are stacked along the
Y axis
This method is equivalent to Layout::default().direction(Direction::Vertical)
and effectively replaces the use of Layout::new(...) for vertical layouts.
§Visual representation
+----------------------+
| Rect 0 | ← Constraint[0]
+----------------------+
| Rect 1 | ← Constraint[1]
+----------------------+
| Rect 2 | ← Constraint[2]
+----------------------+§Example
use altui_core::layout::{Rect, Constraint::*, Layout};
let chunks = Layout::vertical([Length(2),Min(0)])
.split(Rect {
x: 0,
y: 0,
width: 10,
height: 6,
});
// Splits the area into two rows:
// height = 2 and height = 4
assert_eq!(chunks.len(), 2);
assert_eq!(chunks[0].height, 2);
assert_eq!(chunks[1].height, 4);See also Layout::horizontal for left-to-right layouts.
Sourcepub fn horizontal<C>(constraints: C) -> Self
pub fn horizontal<C>(constraints: C) -> Self
Creates a horizontal layout with the given constraints.
A horizontal layout splits the available area from left to right into multiple vertical slices.
In other words:
- Constraint values are applied to the
width - All resulting rectangles share the same
yandheight - Rectangles are stacked along the
X axis
This method is equivalent to
Layout::default().direction(Direction::Horizontal)
and effectively replaces the use of Layout::new(...) for horizontal layouts.
§Visual representation
+---------+---------+---------+
| Rect 0 | Rect 1 | Rect 2 |
| | | |
+---------+---------+---------+
↑ ↑
Constraint[0] Constraint[1]§Example
use altui_core::layout::{Rect, Constraint::*, Layout};
let chunks = Layout::horizontal([Length(3),Min(0)])
.split(Rect {
x: 0,
y: 0,
width: 10,
height: 4,
});
// Splits the area into two columns:
// width = 3 and width = 7
assert_eq!(chunks.len(), 2);
assert_eq!(chunks[0].width, 3);
assert_eq!(chunks[1].width, 7);See also Layout::vertical for top-to-bottom layouts.
pub fn constraints<C>(self, constraints: C) -> Layout
pub fn margin(self, margin: u16) -> Layout
pub fn horizontal_margin(self, horizontal: u16) -> Layout
pub fn vertical_margin(self, vertical: u16) -> Layout
pub fn direction(self, direction: Direction) -> Layout
Sourcepub fn overlap(self, overlap: u16) -> Layout
pub fn overlap(self, overlap: u16) -> Layout
Sets the amount of allowed overlap between adjacent elements along the main axis.
The overlap value specifies how many neighboring characters are
allowed to overlap between adjacent layout items.
Useful for compact layouts with shared borders.
┌────────┌────────┌────────┐
│ Item 1 │ Item 2 │ Item 3 │
└────────└────────└────────┘§Warning: Unstable API
⚠️ Known Issue: This method may cause incorrect rendering
when used together with Layout::split_ext, Flex::SpaceBetween
or Flex::SpaceAround.
Sourcepub fn cross_overlap(self, cross_overlap: u16) -> Layout
pub fn cross_overlap(self, cross_overlap: u16) -> Layout
Sets the amount of allowed overlap between adjacent elements along the cross axis.
The overlap value specifies how many neighboring symbols are
allowed to overlap between adjacent layout items.
Useful for compact layouts with shared borders.
┌────────┐
│ Item 1 │
┌────────┐
│ Item 2 │
┌────────┐
│ Item 3 │
└────────┘§Warning: Unstable API
⚠️ Known Issue: This method may cause incorrect rendering
when used together with Layout::split_ext, Flex::SpaceBetween
or Flex::SpaceAround.
Sourcepub fn flex(self, flex: Flex) -> Layout
pub fn flex(self, flex: Flex) -> Layout
Sets how free space is distributed between elements along the main axis.
Flex controls the alignment and spacing of elements after all constraints
have been resolved.
This affects only the main axis:
- horizontal layouts → X axis
- vertical layouts → Y axis
The default value is Flex::Start.
See Flex for a detailed description of each mode.
Sourcepub fn cross_flex(self, flex: Flex) -> Layout
pub fn cross_flex(self, flex: Flex) -> Layout
Sets how free space is distributed between elements along the cross axis.
Flex controls the alignment and spacing of elements after all constraints
have been resolved.
This affects only the cross axis:
- horizontal layouts → Y axis
- vertical layouts → X axis
The default value is Flex::Start.
Sourcepub fn boxed(self, boxed: bool) -> Layout
pub fn boxed(self, boxed: bool) -> Layout
Enables or disables boxed layout mode.
When boxed is set to true, fixed-size constraints
(Constraint::Length, Constraint::Min) take precedence and are resolved first.
Remaining space is then distributed between:
Constraint::RatioConstraint::Percentage
When boxed is false (default), all constraints participate in layout
solving on equal terms.
§Important notes
- Using
boxed = truetogether with scrolling or wrapping may produce unintuitive results. - Percentage and ratio constraints are strongly discouraged when
boxedis enabled.
§Default
false
Sourcepub fn external_scroll(self) -> Layout
pub fn external_scroll(self) -> Layout
Marks the layout as externally scroll-controlled.
When enabled, the layout does not compute its own scroll bounds. Instead, the scroll size is assumed to be managed by the caller.
This is mainly useful when:
- multiple layouts share a single scroll state
- scroll limits are computed elsewhere
This option is only meaningful when using Layout::split_ext.
Sourcepub fn wrap(self, cross_size: Constraint) -> Layout
pub fn wrap(self, cross_size: Constraint) -> Layout
Enables wrapping into multiple lines when the accumulated main-axis length exceeds the given value. Sets line/column size on cross-axis.
Wrapping splits elements into multiple lines/columns, similar to text wrapping.
- Wrapping is performed based on main-axis length
- Line/column size along the cross-axis is fixed (Min/Max Constraints work as Length)
- Enabling wrapping implicitly changes the scroll direction
§Scroll direction
-
Without wrapping:
- horizontal layout → horizontal scroll
- vertical layout → vertical scroll
-
With wrapping enabled:
- horizontal layout → vertical scroll
- vertical layout → horizontal scroll
§Example
Wrapping a horizontal layout into multiple rows:
[A][B][C] → wrap
[A][B]
[C]See also cross_size.
Sourcepub fn cross_size(self, cross_size: Constraint) -> Layout
pub fn cross_size(self, cross_size: Constraint) -> Layout
Sets the size of Rect along the cross-axis (or cross-direction) without wrapping
Note!
Min/Maxconstraints work asLength- Default is
Percentage(100)
pub fn cache_eq(&self, other: &Layout) -> bool
Sourcepub fn split(&self, area: Rect) -> Vec<Rect>
pub fn split(&self, area: Rect) -> Vec<Rect>
Splits the given area into multiple Rects according to the layout
configuration, direction, wrapping rules and constraints.
This function is a high-level wrapper around an internal Cassowary-based solver. The layout process consists of two distinct phases:
- Line/column construction (preparation phase)
- Constraint solving (layout phase)
§Wrapping behavior
- Wrapping is enabled when
Layout::wrapmethod is used. - Each line/column has a fixed cross size determined in the method parameter.
- When wrapping is enabled, a new line/column is started whenever adding the next constraint would exceed the available main axis (direction) size.
- Elements with
Maxconstraint andPercentageandRatioconstraints if layout isboxeddo not contribute to line/column size and will be collapsed by the solver.
§Examples
§Vertical layout
use altui_core::layout::{Rect, Constraint, Layout};
let chunks = Layout::vertical([Constraint::Length(5), Constraint::Min(0)])
.split(Rect {
x: 2,
y: 2,
width: 10,
height: 10,
});
assert_eq!(
chunks,
vec![
Rect {
x: 2,
y: 2,
width: 10,
height: 5
},
Rect {
x: 2,
y: 7,
width: 10,
height: 5
}
]
);§Horizontal layout with ratios
use altui_core::layout::{Rect, Constraint, Layout};
let chunks = Layout::horizontal([Constraint::Ratio(1, 3), Constraint::Ratio(2, 3)])
.split(Rect {
x: 0,
y: 0,
width: 9,
height: 2,
});
assert_eq!(
chunks,
vec![
Rect {
x: 0,
y: 0,
width: 3,
height: 2
},
Rect {
x: 3,
y: 0,
width: 6,
height: 2
}
]
);§Wrapping into multiple lines by length
use altui_core::layout::{Rect, Constraint, Layout};
let chunks = Layout::horizontal([
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
])
.wrap(Constraint::Length(2))
.split(Rect {
x: 0,
y: 0,
width: 6,
height: 4,
});
// Produces two rows with height `2` each:
// [3][3]
// [3]
assert_eq!(
chunks,
vec![
Rect { x: 0, y: 0, width: 3, height: 2 },
Rect { x: 3, y: 0, width: 3, height: 2 },
Rect { x: 0, y: 2, width: 3, height: 2 },
]
);§Wrapping into multiple lines by percentage
use altui_core::layout::{Rect, Constraint, Layout};
let chunks = Layout::horizontal([
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
])
.wrap(Constraint::Percentage(50))
.split(Rect {
x: 0,
y: 0,
width: 6,
height: 8,
});
// Produces two rows with height `4` each:
// [3][3]
// [3]
assert_eq!(
chunks,
vec![
Rect { x: 0, y: 0, width: 3, height: 4 },
Rect { x: 3, y: 0, width: 3, height: 4 },
Rect { x: 0, y: 4, width: 3, height: 4 },
]
);Sourcepub fn split_ext(
&self,
area: Rect,
scrollstate: &mut u16,
scroll: &mut u16,
) -> Vec<Rect>
pub fn split_ext( &self, area: Rect, scrollstate: &mut u16, scroll: &mut u16, ) -> Vec<Rect>
Splits the given area into multiple Rects with scrolling support.
This method extends Layout::split by introducing a scroll offset and
automatically computing the scrollable range based on the layout
configuration.
The layout process is identical to split, but the final positioning is shifted by a computed scroll offset along the active scroll axis.
§Scrolling model
Scrolling is single-axis and its direction depends on whether wrapping is enabled:
-
Without wrapping:
- Scrolling occurs along the main axis of the layout.
- For example:
- Direction::Horizontal → horizontal scrolling
- Direction::Vertical → vertical scrolling
-
With wrapping enabled:
- Scrolling occurs along the cross axis.
- The layout grows by adding multiple lines/columns, and scrolling moves between those lines/columns.
This behavior mirrors common UI patterns where wrapping turns a one-dimensional layout into a multi-line structure with perpendicular scrolling.
§Scroll parameters
-
scroll — total scrollable length (output)
- Updated by this function unless external_scroll is enabled.
- Represents the full scroll range in layout units.
-
scrollstate — current scroll position (input/output)
- Clamped automatically to the valid scroll range.
- Used to compute the effective scroll offset.
§Wrapping and scrolling interaction
-
When wrapping is enabled:
- The scroll range is computed from the total cross-axis size of all lines/columns.
-
When wrapping is disabled:
- The scroll range is computed from the total content length along the main axis.
§External scrolling
If external_scroll is enabled:
- The scroll range is taken from the scroll parameter.
- This allows integrating the layout with an external scrolling container.
§Constraints and limitations
⚠️ Important: Do not use the following constraint combinations with split_ext:
Constraint::PercentageorConstraint::Ratiowhen the layout is boxedConstraint::Maxwhen relying on internal scrolling
These combinations may produce undefined or unintuitive scrolling behavior.
§Notes
- Line construction and wrapping are performed before scrolling is applied.
- The solver does not decide the scroll direction.
- Margins are applied before layout and scrolling.
- Scrolling offsets are quantized to integer values.
§Examples
§Horizontal scrolling without wrapping
use altui_core::layout::{Rect, Constraint, Layout};
let mut scroll = 0;
let mut scrollstate = 0;
let chunks = Layout::horizontal([
Constraint::Length(5),
Constraint::Length(5),
Constraint::Length(5),
])
.split_ext(
Rect { x: 0, y: 0, width: 8, height: 2 },
&mut scrollstate,
&mut scroll,
);
// Content width exceeds available width, so scrolling is horizontal.
assert!(scroll == 15);§Vertical scrolling with wrapping enabled
use altui_core::layout::{Rect, Constraint, Layout};
let mut scroll = 0;
let mut scrollstate = 0;
let chunks = Layout::horizontal([
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
])
.wrap(Constraint::Length(8))
.split_ext(
Rect { x: 0, y: 0, width: 6, height: 8 },
&mut scrollstate,
&mut scroll,
);
// Wrapping creates multiple rows; scrolling is now vertical.
assert!(scroll == 16);See Layout::split for a non-scrolling variant.