pub trait Layout {
fn size_rules(&mut self, size_mgr: SizeMgr<'_>, axis: AxisInfo) -> SizeRules;
fn set_rect(&mut self, mgr: &mut ConfigMgr<'_>, rect: Rect);
fn find_id(&mut self, coord: Coord) -> Option<WidgetId>;
fn draw(&mut self, draw: DrawMgr<'_>);
}
Expand description
Positioning and drawing routines for Widget
s
This trait is related to Widget
, but may be used independently.
Implementing Layout
There are three cases:
- For a non-widget, all methods must be implemented directly.
- For a
Widget
without using thelayout
macro property, theSelf::set_rect
andSelf::find_id
methods gain default implementations (generated via macro). - For a
Widget
where the#[widget{ layout = .. }]
property is set (seemacros::widget
documentation), all methods have a default implementation. Custom implementations may useAutoLayout
to access these default implementations.
Solving layout
Layout is resolved as follows:
Widget::configure
is called (widgets only), and may be used to load assetsSelf::size_rules
is called at least once for each axisSelf::set_rect
is called to position elements. This may use data cached bysize_rules
.Self::find_id
may be used to find the widget under the mouse andSelf::draw
to draw elements.
Usually, Layout::size_rules
methods are called recursively. To instead
solve layout for a single widget/layout object, it may be useful to use
layout::solve_size_rules
or layout::SolveCache
.
Required Methods§
sourcefn size_rules(&mut self, size_mgr: SizeMgr<'_>, axis: AxisInfo) -> SizeRules
fn size_rules(&mut self, size_mgr: SizeMgr<'_>, 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.
Default implementation:
- No default implementation, except,
- For a widget with the
layout
property, callAutoLayout::size_rules
sourcefn set_rect(&mut self, mgr: &mut ConfigMgr<'_>, rect: Rect)
fn set_rect(&mut self, mgr: &mut ConfigMgr<'_>, 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 ConfigMgr::align_feature
.
Another example: Label
uses a Text
object which handles alignment
internally.
Default implementation:
- Independent usage: no default
- For a widget without
layout
property, setrect
field ofwidget_core!()
- For a widget with the
layout
property, callAutoLayout::set_rect
Default: set rect
of widget_core!()
field. If layout = ..
property
is used, also calls <Self as AutoLayout>::set_rect
.
sourcefn find_id(&mut self, coord: Coord) -> Option<WidgetId>
fn find_id(&mut self, coord: Coord) -> Option<WidgetId>
Translate a coordinate to a WidgetId
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
Widget::handle_unused
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)
The implementation is slightly different for widgets and non-widget components:
- Widgets should test
self.rect().contains(coord)
, returningNone
if this test isfalse
; otherwise, they should always return someWidgetId
, either a childs or their own. - Widgets may use a translated coordinate space: recursion uses
child.find_id(coord + self.translation())
.
Default implementation:
- Non-widgets: no default implementation.
- For a widget without the
layout
property,self.rect().contains(coord).then(|| self.id())
. - For a widget with the
layout
property, the following snippet:ⓘif !self.rect().contains(coord) { return None; } let coord = coord + self.translation(); (#layout).find_id(coord).or_else(|| Some(self.id()))
sourcefn draw(&mut self, draw: DrawMgr<'_>)
fn draw(&mut self, draw: DrawMgr<'_>)
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
WidgetId
, allowing drawn components to react to input state. This
implies that when calling draw
on children, the child’s id
must be
supplied via DrawMgr::re_id
or DrawMgr::recurse
.
Default implementation:
- No default implementation, except,
- For a widget with the
layout
property, callAutoLayout::draw