pub trait Layout {
Show 13 methods
// Required methods
fn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules;
fn draw(&mut self, draw: DrawCx<'_>);
// Provided methods
fn as_layout(&self) -> &dyn Layout { ... }
fn id_ref(&self) -> &Id { ... }
fn rect(&self) -> Rect { ... }
fn widget_name(&self) -> &'static str { ... }
fn num_children(&self) -> usize { ... }
fn get_child(&self, index: usize) -> Option<&dyn Layout> { ... }
fn find_child_index(&self, id: &Id) -> Option<usize> { ... }
fn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect) { ... }
fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize> { ... }
fn translation(&self) -> Offset { ... }
fn find_id(&mut self, coord: Coord) -> Option<Id> { ... }
}
Expand description
Positioning and drawing routines for Widget
s
Layout
is a super-trait of Widget
which:
- Has no
Data
parameter - Supports read-only tree reflection:
Self::get_child
- Provides some basic operations:
Self::id_ref
,Self::rect
- Covers sizing and drawing operations (“layout”)
Implementing Layout
See Widget
documentation and the #widget
macro.
Layout
may not be implemented independently.
Widget lifecycle
- The widget is configured (
Events::configure
) and immediately updated (Events::update
). - The widget has its size-requirements checked by calling
Self::size_rules
for each axis (usually via recursion, sometimes vialayout::solve_size_rules
orlayout::SolveCache
). Self::set_rect
is called to position elements. This may use data cached bysize_rules
.- The widget is updated again after any data change (see
ConfigCx::update
). - The widget is ready for event-handling and drawing (
Events
,Self::find_id
,Self::draw
).
Widgets are responsible for ensuring that their children may observe this lifecycle. Usually this simply involves inclusion of the child in layout operations. Steps of the lifecycle may be postponed until a widget becomes visible.
Tree reflection
Layout
offers a reflection API over the widget tree via
Layout::get_child
. This is limited to read-only functions, and thus
cannot directly violate the widget lifecycle, however note that the
id_ref
could be invalid or could be valid but refer to a
node which has not yet been sized and positioned (and thus which it is not
valid to send events to).
Required Methods§
sourcefn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules
fn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules
Get size rules for the given axis
Typically, this method is called twice: first for the horizontal axis,
second for the vertical axis (with resolved width available through
the axis
parameter allowing content wrapping).
For a description of the widget size model, see SizeRules
.
This method is expected to cache any size requirements calculated from
children which would be required for space allocations in
Self::set_rect
. As an example, the horizontal SizeRules
for a
row layout is the sum of the rules for each column (plus margins);
these per-column SizeRules
are also needed to calculate column
widths in Self::size_rules
once the available size is known.
For row/column/grid layouts, a crate::layout::RulesSolver
engine
may be useful.
Required: self
is configured (ConfigCx::configure
) before this
method is called, and that size_rules
is called for the
horizontal axis before it is called for the vertical axis.
Further, Self::set_rect
must be called after this method before
drawing or event handling.
sourcefn draw(&mut self, draw: DrawCx<'_>)
fn draw(&mut self, draw: DrawCx<'_>)
Draw a widget and its children
This method is invoked each frame to draw visible widgets. It should draw itself and recurse into all visible children.
It is expected that Self::set_rect
is called before this method,
but failure to do so should not cause a fatal error.
The draw
parameter is pre-parameterized with this widget’s
Id
, allowing drawn components to react to input state. This
implies that when calling draw
on children, the child’s id
must be
supplied via DrawCx::re_id
or DrawCx::recurse
.
Provided Methods§
sourcefn as_layout(&self) -> &dyn Layout
fn as_layout(&self) -> &dyn Layout
Get as a dyn Layout
This method is implemented by the #[widget]
macro.
sourcefn id_ref(&self) -> &Id
fn id_ref(&self) -> &Id
Get the widget’s identifier
Note that the default-constructed Id
is invalid: any
operations on this value will cause a panic. A valid identifier is
assigned when the widget is configured (immediately before calling
Events::configure
).
This method is implemented by the #[widget]
macro.
sourcefn rect(&self) -> Rect
fn rect(&self) -> Rect
Get the widget’s region, relative to its parent.
This method is implemented by the #[widget]
macro.
sourcefn widget_name(&self) -> &'static str
fn widget_name(&self) -> &'static str
Get the name of the widget struct
This method is implemented by the #[widget]
macro.
sourcefn num_children(&self) -> usize
fn num_children(&self) -> usize
Get the number of child widgets
Every value in the range 0..self.num_children()
is a valid child
index.
This method is usually implemented automatically by the #[widget]
macro. It should be implemented directly if and only if
Layout::get_child
and Widget::for_child_node
are
implemented directly.
sourcefn get_child(&self, index: usize) -> Option<&dyn Layout>
fn get_child(&self, index: usize) -> Option<&dyn Layout>
Access a child as a dyn Layout
This method is usually implemented automatically by the #[widget]
macro.
sourcefn find_child_index(&self, id: &Id) -> Option<usize>
fn find_child_index(&self, id: &Id) -> Option<usize>
Find the child which is an ancestor of this id
, if any
If Some(index)
is returned, this is probably but not guaranteed
to be a valid child index.
The default implementation simply uses Id::next_key_after
.
Widgets may choose to assign children custom keys by overriding this
method and Events::make_child_id
.
sourcefn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect)
fn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect)
Set size and position
This method is called after Self::size_rules
and may use values
cached by size_rules
(in the case size_rules
is not called first,
the widget may exhibit incorrect layout but should not panic). This
method should not write over values cached by size_rules
since
set_rect
may be called multiple times consecutively.
After set_rect
is called, the widget must be ready for drawing and event handling.
The size of the assigned rect
is normally at least the minimum size
requested by Self::size_rules
, but this is not guaranteed. In case
this minimum is not met, it is permissible for the widget to draw
outside of its assigned rect
and to not function as normal.
The assigned rect
may be larger than the widget’s size requirements,
regardless of the Stretch
policy used. If the widget should never
stretch, it must align itself.
Example: the CheckBox
widget uses an AlignPair
(set from
size_rules
’s AxisInfo
) and uses ConfigCx::align_feature
.
Another example: Label
uses a Text
object which handles alignment
internally.
Required: Self::size_rules
is called for both axes before this
method is called, and that this method has been called after the last
call to Self::size_rules
before any of the following methods:
Layout::find_id
, Layout::draw
, Events::handle_event
.
Default implementation when not using the layout
property: set rect
field of widget_core!()
to the input rect
.
Navigation in spatial order
Controls Tab navigation order of children. This method should:
- Return
None
if there is no next child - Determine the next child after
from
(if provided) or the whole range, optionally inreverse
order - Ensure that the selected widget is addressable through
Layout::get_child
Both from
and the return value use the widget index, as used by
Layout::get_child
.
Default implementation:
- Generated from
#[widget]
’s layout property, if used (not always possible!) - Otherwise, iterate through children in order of definition
sourcefn translation(&self) -> Offset
fn translation(&self) -> Offset
Get translation of children relative to this widget
Usually this is zero; only widgets with scrollable or offset content
and child widgets need to implement this.
Such widgets must also implement Events::handle_scroll
.
Affects event handling via Layout::find_id
and affects the positioning
of pop-up menus. Layout::draw
must be implemented directly using
DrawCx::with_clip_region
to offset contents.
Default implementation: return Offset::ZERO
sourcefn find_id(&mut self, coord: Coord) -> Option<Id>
fn find_id(&mut self, coord: Coord) -> Option<Id>
Translate a coordinate to an Id
This method is used to determine which widget reacts to the mouse cursor
or a touch event. The result affects mouse-hover highlighting, event
handling by the target, and potentially also event handling by other
widgets (e.g. a Label
widget will not handle touch events, but if it
is contained by a ScrollRegion
, that widget may capture these via
Events::handle_event
to implement touch scrolling).
The result is usually the widget which draws at the given coord
, but
does not have to be. For example, a Button
widget will return its own
id
for coordinates drawn by internal content, while the CheckButton
widget uses an internal component for event handling and thus reports
this component’s id
even over its own area.
It is expected that Layout::set_rect
is called before this method,
but failure to do so should not cause a fatal error.
The default implementation suffices for widgets without children as well
as widgets using the layout
property of #[widget]
.
Custom implementations may be required if:
- A custom
Layout
implementation is used - Event stealing or donation is desired (but note that
layout = button: ..;
does this already)
When writing a custom implementation:
- Widgets should test
self.rect().contains(coord)
, returningNone
if this test isfalse
; otherwise, they should always return someId
, either a childs or their own. - If the Widget uses a translated coordinate space (i.e.
self.translation() != Offset::ZERO
) then passcoord + self.translation()
to children.
The default implementation is non-trivial:
if !self.rect().contains(coord) {
return None;
}
let coord = coord + self.translation();
for child in ITER_OVER_CHILDREN {
if let Some(id) = child.find_id(coord) {
return Some(id);
}
}
Some(self.id())
Implementations on Foreign Types§
source§impl<T> Layout for &mut T
impl<T> Layout for &mut T
fn as_layout(&self) -> &dyn Layout
fn id_ref(&self) -> &Id
fn rect(&self) -> Rect
fn widget_name(&self) -> &'static str
fn num_children(&self) -> usize
fn get_child(&self, index: usize) -> Option<&dyn Layout>
fn find_child_index(&self, id: &Id) -> Option<usize>
fn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules
fn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect)
fn translation(&self) -> Offset
fn find_id(&mut self, coord: Coord) -> Option<Id>
fn draw(&mut self, draw: DrawCx<'_>)
source§impl<T> Layout for Box<T>
impl<T> Layout for Box<T>
fn as_layout(&self) -> &dyn Layout
fn id_ref(&self) -> &Id
fn rect(&self) -> Rect
fn widget_name(&self) -> &'static str
fn num_children(&self) -> usize
fn get_child(&self, index: usize) -> Option<&dyn Layout>
fn find_child_index(&self, id: &Id) -> Option<usize>
fn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules
fn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect)
fn translation(&self) -> Offset
fn find_id(&mut self, coord: Coord) -> Option<Id>
fn draw(&mut self, draw: DrawCx<'_>)
Implementors§
impl Layout for Svg
impl Layout for TextEdit
impl Layout for AccessLabel
impl Layout for EventConfig
impl Layout for Filler
impl Layout for GripPart
This implementation is unusual in that:
size_rules
always returnsSizeRules::EMPTY
set_rect
sets the track within which this grip may move; the parent should callGripPart::set_size_and_offset
afterset_rect
(otherwise the grip’s position will not be updated)draw
does nothing: the parent is expected to do all drawing