Trait kas::Layout

source ·
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 Widgets

Layout is a super-trait of Widget which:

Implementing Layout

See Widget documentation and the #widget macro. Layout may not be implemented independently.

Widget lifecycle

  1. The widget is configured (Events::configure) and immediately updated (Events::update).
  2. The widget has its size-requirements checked by calling Self::size_rules for each axis (usually via recursion, sometimes via layout::solve_size_rules or layout::SolveCache).
  3. Self::set_rect is called to position elements. This may use data cached by size_rules.
  4. The widget is updated again after any data change (see ConfigCx::update).
  5. 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§

source

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.

source

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§

source

fn as_layout(&self) -> &dyn Layout

Get as a dyn Layout

This method is implemented by the #[widget] macro.

source

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.

source

fn rect(&self) -> Rect

Get the widget’s region, relative to its parent.

This method is implemented by the #[widget] macro.

source

fn widget_name(&self) -> &'static str

Get the name of the widget struct

This method is implemented by the #[widget] macro.

source

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.

source

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.

source

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.

source

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.

source

fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize>

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 in reverse 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
source

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

source

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), returning None if this test is false; otherwise, they should always return some Id, either a childs or their own.
  • If the Widget uses a translated coordinate space (i.e. self.translation() != Offset::ZERO) then pass coord + 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
where T: Layout + ?Sized,

source§

fn as_layout(&self) -> &dyn Layout

source§

fn id_ref(&self) -> &Id

source§

fn rect(&self) -> Rect

source§

fn widget_name(&self) -> &'static str

source§

fn num_children(&self) -> usize

source§

fn get_child(&self, index: usize) -> Option<&dyn Layout>

source§

fn find_child_index(&self, id: &Id) -> Option<usize>

source§

fn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules

source§

fn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect)

source§

fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize>

source§

fn translation(&self) -> Offset

source§

fn find_id(&mut self, coord: Coord) -> Option<Id>

source§

fn draw(&mut self, draw: DrawCx<'_>)

source§

impl<T> Layout for Box<T>
where T: Layout + ?Sized,

source§

fn as_layout(&self) -> &dyn Layout

source§

fn id_ref(&self) -> &Id

source§

fn rect(&self) -> Rect

source§

fn widget_name(&self) -> &'static str

source§

fn num_children(&self) -> usize

source§

fn get_child(&self, index: usize) -> Option<&dyn Layout>

source§

fn find_child_index(&self, id: &Id) -> Option<usize>

source§

fn size_rules(&mut self, sizer: SizeCx<'_>, axis: AxisInfo) -> SizeRules

source§

fn set_rect(&mut self, cx: &mut ConfigCx<'_>, rect: Rect)

source§

fn nav_next(&self, reverse: bool, from: Option<usize>) -> Option<usize>

source§

fn translation(&self) -> Offset

source§

fn find_id(&mut self, coord: Coord) -> Option<Id>

source§

fn draw(&mut self, draw: DrawCx<'_>)

Implementors§

source§

impl Layout for Svg

source§

impl Layout for TextEdit

source§

impl Layout for AccessLabel

source§

impl Layout for EventConfig

source§

impl Layout for Filler

source§

impl Layout for GripPart

This implementation is unusual in that:

  1. size_rules always returns SizeRules::EMPTY
  2. set_rect sets the track within which this grip may move; the parent should call GripPart::set_size_and_offset after set_rect (otherwise the grip’s position will not be updated)
  3. draw does nothing: the parent is expected to do all drawing
source§

impl Layout for Image

source§

impl Layout for Label<String>

source§

impl Layout for Mark

source§

impl Layout for Tab

source§

impl<'a> Layout for Label<&'a str>

source§

impl<'a, A> Layout for Text<A, &'a str>

source§

impl<A> Layout for MenuToggle<A>

source§

impl<A> Layout for CheckBox<A>

source§

impl<A> Layout for CheckButton<A>

source§

impl<A> Layout for RadioBox<A>

source§

impl<A> Layout for RadioButton<A>

source§

impl<A> Layout for Separator<A>

source§

impl<A> Layout for Text<A, String>

source§

impl<A, D> Layout for ProgressBar<A, D>
where D: Directional,

source§

impl<A, F, W> Layout for FilterList<A, F, W>
where A: ListData + 'static, F: Filter<<A as SharedData>::Item, Value = String>, W: Widget<Data = UnsafeFilteredList<A>>,

source§

impl<A, F, W, G> Layout for FilterBoxList<A, F, W, G>
where A: ListData + 'static, F: Filter<<A as SharedData>::Item, Value = String>, W: Widget<Data = UnsafeFilteredList<A>>, G: EditGuard<Data = ()>,

source§

impl<A, T> Layout for ScrollText<A, T>
where T: Default + FormattableText + 'static,

source§

impl<A, T> Layout for Spinner<A, T>
where T: SpinnerValue,

source§

impl<A, T> Layout for Text<A, T>
where T: Default + FormattableText + 'static,

source§

impl<A, T, D> Layout for Slider<A, T, D>
where T: SliderValue, D: Directional,

source§

impl<A, V> Layout for MatrixView<A, V>
where A: MatrixData, V: Driver<<A as SharedData>::Item, A>,

source§

impl<A, V> Layout for ComboBox<A, V>
where V: Clone + Debug + Eq + 'static,

source§

impl<A, V, D> Layout for ListView<A, V, D>
where A: ListData, V: Driver<<A as SharedData>::Item, A>, D: Directional,

source§

impl<A, W> Layout for MapAny<A, W>
where W: Widget<Data = ()>,

source§

impl<A, W, F> Layout for Map<A, W, F>
where W: Widget, F: for<'a> Fn(&'a A) -> &'a <W as Widget>::Data,

source§

impl<A, W, S> Layout for Adapt<A, W, S>
where W: Widget<Data = S>, S: Debug,

source§

impl<D> Layout for ScrollBar<D>
where D: Directional,

source§

impl<Data> Layout for Window<Data>
where Data: 'static,

source§

impl<Data> Layout for SubMenu<Data>

source§

impl<Data, D> Layout for MenuBar<Data, D>
where D: Directional,

source§

impl<G> Layout for EditBox<G>
where G: EditGuard,

source§

impl<G> Layout for EditField<G>
where G: EditGuard,

source§

impl<M> Layout for MenuEntry<M>
where M: Clone + Debug + 'static,

source§

impl<M> Layout for MarkButton<M>
where M: Clone + Debug + 'static,

source§

impl<P> Layout for Canvas<P>
where P: CanvasProgram,

source§

impl<T> Layout for MessageBox<T>
where T: FormattableText + 'static,

source§

impl<T> Layout for Label<T>
where T: FormattableText + 'static,

source§

impl<T> Layout for ScrollLabel<T>
where T: FormattableText + 'static,

source§

impl<W> Layout for Popup<W>
where W: Widget,

source§

impl<W> Layout for AdaptEvents<W>
where W: Widget,

source§

impl<W> Layout for Reserve<W>
where W: Widget,

source§

impl<W> Layout for Button<W>
where W: Widget,

source§

impl<W> Layout for Frame<W>
where W: Widget,

source§

impl<W> Layout for Grid<W>
where W: Widget,

source§

impl<W> Layout for NavFrame<W>
where W: Widget,

source§

impl<W> Layout for ScrollBarRegion<W>
where W: Widget,

source§

impl<W> Layout for ScrollBars<ScrollRegion<W>>
where W: Widget,

source§

impl<W> Layout for ScrollBars<W>
where W: Scrollable + Widget,

source§

impl<W> Layout for ScrollRegion<W>
where W: Widget,

source§

impl<W> Layout for Stack<W>
where W: Widget,

source§

impl<W> Layout for TabStack<W>
where W: Widget,

source§

impl<W, D> Layout for WithLabel<W, D>
where W: Widget, D: Directional,

source§

impl<W, D> Layout for List<W, D>
where W: Widget, D: Directional,

source§

impl<W, D> Layout for Splitter<W, D>
where W: Widget, D: Directional,