Expand description
Repeater — non-virtualized dynamic widget list driven by a ListModel<T>.
Repeater creates one child widget per item in a ListModel<T>
using a caller-supplied factory closure, arranging them along one axis
(RepeaterLayout::Vertical by default) or as a wrapping flow
(RepeaterLayout::Wrap). It is not virtualized: every item has a live
widget at all times. That is a deliberate trade — it is what lets the
children keep real, stateful widgets (text editors, forms) mounted, which a
virtualizing ListView cannot do because it recycles
off-screen rows.
§Repeater::new — reconciling (the default)
The factory takes &item and each child widget is reused across model
changes. When the model mutates, Repeater reads the
DataChange it emits and applies the minimal edit to its child set: an
insert builds one new widget, a remove reaps one, a move reorders, an
in-place update rebuilds only that item — every other child keeps its
existing widget, and with it its focus, selection, caret, scroll offset,
in-flight text edit, and undo history.
This makes Repeater a fit for a stack of editors — e.g. a document
rendered as a column of RichTextEditors,
one per scene/block:
Repeater::new(scenes, |scene| {
Box::new(RichTextEditor::editor(scene.document()))
})Inserting, deleting, or reordering a scene costs one widget’s worth of work
instead of reshaping every editor in the document, and the editor the user is
typing in keeps its caret. Because the factory has no index, position shifts
are safe by construction: reuse can never leave a widget showing content
derived from a stale position. The one requirement is that an item’s
content only changes through the model (via set/replace_all), which is
always true for a ListModel.
let model: ListModel<u32> = ListModel::from_vec(vec![1, 2, 3]);
let _w = Repeater::new(model, |item| {
Box::new(TextWidget::new(lit!(format!("item {item}"))))
})
.spacing(4.0);§Repeater::indexed — full rebuild (position-in-content)
When the content genuinely depends on position — a numbered list, “N of M”,
a ranking that must renumber on reorder — use indexed.
Its factory takes (index, &item), and on any model change the whole
child subtree is torn down and rebuilt, so the index every widget shows is
always current. This is the right pick for cheap, stateless, position-derived
rows; it does not preserve per-child state across changes (that is the
reason to prefer new whenever the index isn’t content).
§Accessibility
Repeater imposes no accessibility semantics of its own — it is a
transparent layout wrapper, so its children surface directly into the
surrounding AT subtree and their own roles decide how they read. When the
children genuinely form a named list, menu, or toolbar, opt in with the
standard builder overrides that every widget supports — these stay
locale-reactive:
use teksilo_core::accesskit::Role;
Repeater::new(tags, factory)
.access_role(Role::List)
.access_label(tr!(tags()))Structs§
- Repeater
- A non-virtualized dynamic collection that creates one child widget per item in a
ListModel<T>.
Enums§
- Repeater
Layout - How a
Repeaterarranges its item widgets.