pub trait Widget: Layout {
type Data;
// Provided methods
fn as_node<'a>(&'a mut self, data: &'a Self::Data) -> Node<'a> { ... }
fn for_child_node(
&mut self,
data: &Self::Data,
index: usize,
closure: Box<dyn FnOnce(Node<'_>) + '_>
) { ... }
}
Expand description
The Widget trait
The primary widget trait covers event handling over super trait Layout
which governs layout, drawing, child enumeration and identification.
Most methods of Widget
are hidden and only for use within the Kas library.
Widget
is dyn-safe given a type parameter, e.g. dyn Widget<Data = ()>
.
Layout
is dyn-safe without a type parameter. Node
is a dyn-safe
abstraction over a &dyn Widget<Data = T>
plus a &T
data parameter.
Widget lifecycle
- The widget is configured (
Events::configure
) and immediately updated (Events::update
). - The widget has its size-requirements checked by calling
Layout::size_rules
for each axis. Layout::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::handle_event
,Layout::find_id
,Layout::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.
Implementing Widget
To implement a widget, use the #widget
macro within an
impl_scope
. This is the only supported method of
implementing Widget
.
Explicit (partial) implementations of Widget
, Layout
and Events
are optional. The #widget
macro completes implementations.
Synopsis:
impl_scope! {
#[widget {
// macro properties (all optional)
Data = T;
layout = self.foo;
}]
struct MyWidget {
core: widget_core!(),
#[widget] foo: impl Widget<Data = T> = make_foo(),
// ...
}
// Optional implementations:
impl Layout for Self { /* ... */ }
impl Events for Self { /* ... */ }
impl Self { /* ... */ }
}
Details may be categorised as follows:
- Data: the type
Widget::Data
must be specified exactly once, but this type may be given in any of three locations: as a property of the#widget
macro or asWidget::Data
. - Core methods of
Layout
are always implemented via the#widget
macro, whether or not animpl Layout { ... }
item is present. - Introspection methods
Layout::num_children
,Layout::get_child
andWidget::for_child_node
are implemented by the#widget
macro in most cases: child widgets embedded within a layout descriptor or included as fields marked with#[widget]
are enumerated. - Introspection methods
Layout::find_child_index
andEvents::make_child_id
have default implementations which usually suffice. - Layout is specified either via layout syntax
or via implementation of at least
Layout::size_rules
andLayout::draw
(optionally alsoset_rect
,nav_next
,translation
andfind_id
). - Event handling is optional, implemented through
Events
.
For examples, check the source code of widgets in the widgets library or examples apps. (Check that the code uses the same Kas version since the widget traits are not yet stable.)
Required Associated Types§
Provided Methods§
sourcefn as_node<'a>(&'a mut self, data: &'a Self::Data) -> Node<'a>
fn as_node<'a>(&'a mut self, data: &'a Self::Data) -> Node<'a>
Erase type
This method is implemented by the #[widget]
macro.
sourcefn for_child_node(
&mut self,
data: &Self::Data,
index: usize,
closure: Box<dyn FnOnce(Node<'_>) + '_>
)
fn for_child_node( &mut self, data: &Self::Data, index: usize, closure: Box<dyn FnOnce(Node<'_>) + '_> )
Call closure on child with given index
, if index < self.num_children()
.
Widgets with no children or using the #[widget]
attribute on fields do
not need to implement this. Widgets with an explicit implementation of
Layout::num_children
also need to implement this.
It is recommended to use the methods on Node
instead of calling this method.