GridView

Virtualized 2D tile grid bound to a ListModel<T> / ListDataSource.
GridView is the photo-gallery / icon-view / file-manager-grid /
collection-view widget — the 2D sibling of ListView
and TableView. It realizes only the
tiles currently visible (plus a buffer), reflows on resize, supports
single / multi selection with 2D keyboard navigation, and is fully
accessible (Role::Grid → Role::GridCell).
The layout is pluggable via GridLayoutStrategy;
the stock UniformGrid gives fixed tile size /
fixed column count / adaptive min-width grids. (Variable-row-height and
waterfall strategies, plus marquee selection, drag-reorder, sections and
sticky headers, are layered on in later phases.)
GridView::new(model, |tc| {
Box::new(Card::new().child(TextWidget::new(lit!(&tc.item.name))))
})
.sizing(GridSizing::Adaptive { min_width: 120.0, max_width: None, height: 140.0 })
.spacing(8.0)
.selection(selection_model)
Builder methods at a glance
from_source, enabled, sizing, tile_size, column_count, variable_row_heights, item_height, waterfall, column_spacing, row_spacing, spacing, content_inset, selection, on_selection_changed, marquee_selection, wrap_navigation, tab_traversal, show_scrollbar, overscroll_behavior, smooth_scrolling, smooth_scroll_duration, scroll_bar_style, scroll_y_signal, max_scroll_y_signal, viewport_ratio_y_signal, ensure_index_visible, scroll_to_index, sections, section_header_delegate, section_header_height, pinned_section_headers, a11y_label, style, empty_view, loading_view, is_loading, reorderable, exportable, export_external, on_rows_transferred_out, accept_foreign_rows, on_rows_received, on_item_drop, on_tile_activate, activate_on, tile_context_menu, type_ahead_label, tile_a11y_label, type_ahead_timeout
API reference
📖 Full rustdoc API for this module
pub struct TileContext
Context passed to the tile delegate for each realized tile.
Richer than ListView's (index, &item, selected) — carries the 2D
grid coordinates and focus state (mirrors TableView's CellContext).
There is intentionally no is_hovered: hover changes on every
mouse-move and is handled per-tile inside the delegate's own widget
(its interaction signal), never by rebuilding the grid.
#![allow(unused)] fn main() { pub struct TileContext<'a, T: 'static> { /* fields */ } }
pub struct GridView
A virtualized 2D tile grid backed by a ListModel<T>.
#![allow(unused)] fn main() { pub struct GridView<T: 'static> { /* fields */ } }
Methods
pub fn new( model: ListModel<T>, delegate: impl Fn(&TileContext<'_, T>) -> Box<dyn Widget> + 'static, ) -> Self
Create a grid backed by a ListModel<T>. The delegate builds the
widget for each tile from a TileContext.
pub fn from_source<S: teksilo_data::ListDataSource<Item = T>>( source: S, delegate: impl Fn(&TileContext<'_, T>) -> Box<dyn Widget> + 'static, ) -> Self
Create a grid backed by any ListDataSource (large / external data).
pub fn enabled(mut self, enabled: impl Into<Prop<bool>>) -> Self
Enable or disable the whole view. A disabled view greys out and stops accepting focus / selection / keyboard input (arena-gated).
pub fn sizing(mut self, sizing: impl Into<Prop<GridSizing>>) -> Self
Set the tile sizing / column-count policy.
Accepts a plain GridSizing (static) or a Signal<GridSizing>
(reactive). A bound signal is observed at [BindingLevel::Rebuild]: when
it changes, build() rebuilds the cached layout strategy and reflows —
the internal scroll_y / focused_index / selection are field signals on
the same widget instance, so they survive the rebuild (no scroll jump).
This is the card-size-slider path; mirrors
TabWidget::sizing.
pub fn tile_size(mut self, width: f32, height: f32) -> Self
Sugar for GridSizing::Fixed — every tile is exactly width × height.
pub fn column_count(mut self, count: usize, tile_height: f32) -> Self
Sugar for GridSizing::FixedColumnCount — exactly count columns.
pub fn variable_row_heights(mut self, estimated: f32) -> Self
Switch to variable row heights: each row is sized to its tallest
tile (SwiftUI LazyVGrid semantics). estimated seeds rows that
haven't been measured yet; the scroll position is anchored when an
estimate is later corrected. Combine with
item_height for exact heights.
pub fn item_height(mut self, f: impl Fn(usize) -> f32 + 'static) -> Self
Supply an exact per-item natural height. Width-independent, so it
doesn't depend on the runtime column count: VariableRowGrid sizes
each row to max(item_height(i)) over its items. Implies variable row
heights, gives an exact scrollbar, and removes anchoring jitter.
pub fn waterfall(mut self, estimated: f32) -> Self
Switch to a Pinterest-style waterfall: per-item variable heights flow
into the currently-shortest column. Column count comes from the
configured sizing; heights are auto-measured (or
exact via item_height). estimated seeds
unmeasured items.
pub fn column_spacing(mut self, spacing: f32) -> Self
Horizontal gap between tiles (default 8).
pub fn row_spacing(mut self, spacing: f32) -> Self
Vertical gap between tile rows (default 8).
pub fn spacing(mut self, spacing: f32) -> Self
Set both column and row spacing.
pub fn content_inset(mut self, inset: EdgeInsets) -> Self
Inset from the scroll-content edge to the tiles.
pub fn selection(mut self, sel: SelectionModel) -> Self
Set the selection model (modes None / Single / Multi).
pub fn on_selection_changed(mut self, f: impl Fn(&BTreeSet<usize>) + 'static) -> Self
Called whenever the selection set changes — including programmatic changes — with the new set of selected indices.
pub fn marquee_selection(mut self, enabled: bool) -> Self
Enable / disable rubber-band marquee selection (default enabled; only
active when the selection model is in Multi mode).
pub fn wrap_navigation(mut self, enabled: bool) -> Self
Whether arrow navigation wraps across row/grid edges (default false).
pub fn tab_traversal(mut self, traversal: GridTabTraversal) -> Self
How Tab moves out of (or within) the grid (default OutOfGrid).
pub fn show_scrollbar(mut self, show: bool) -> Self
Suppress the internal scrollbar (mount your own via the signal accessors so it survives rebuilds).
pub fn overscroll_behavior(mut self, behavior: OverscrollBehavior) -> Self
Scroll-chaining behavior at the boundary (default Chain).
pub fn smooth_scrolling(mut self, enabled: bool) -> Self
Enable or disable animated wheel scrolling (enabled by default).
pub fn smooth_scroll_duration(mut self, duration: Duration) -> Self
Duration of the smooth scroll animation (default 150 ms).
pub fn scroll_bar_style(mut self, style: ScrollBarMode) -> Self
How the scroll bar is displayed (default Permanent). Overlay
and Thin float the bar over the content instead of reserving a
layout column, mirroring ScrollArea::scroll_bar_style.
pub fn scroll_y_signal(&self) -> &Signal<f32>
The vertical scroll offset signal.
pub fn max_scroll_y_signal(&self) -> &Signal<f32>
The maximum scroll offset signal (content_height - viewport_height).
pub fn viewport_ratio_y_signal(&self) -> &Signal<f32>
The vertical viewport-to-content ratio signal (drives the thumb size).
pub fn ensure_index_visible(&self, index: usize, anchor: ScrollAnchor)
Scroll the minimum distance to bring index into view per anchor.
pub fn scroll_to_index(&self, index: usize, anchor: ScrollAnchor)
Scroll to index, forcing the viewport position per anchor
(Auto behaves like ensure_index_visible).
pub fn sections<P: SectionProvider>(mut self, provider: P) -> Self
Group the flat model into sections, rendering a header above each section's tile band. Sections compose with the uniform tile layout.
pub fn section_header_delegate( mut self, f: impl Fn(usize, &str) -> Box<dyn Widget> + 'static, ) -> Self
Custom section-header widget builder (section_index, title). Without
it a default bold-text header is used.
pub fn section_header_height(mut self, height: f32) -> Self
Height of each section header row (default 28).
pub fn pinned_section_headers(mut self, enabled: bool) -> Self
Keep the current section's header pinned to the top while scrolling
through it (SwiftUI pinnedViews:[.sectionHeaders]).
pub fn a11y_label(mut self, label: impl Into<String>) -> Self
Accessible label for the grid container.
pub fn style(mut self, style: impl GridViewStyle) -> Self
Per-call Tier-3 decoration style override (focus ring, marquee,
insertion bar, pinned-header surface). Precedence: this override →
theme.style_slots.grid_view → the stock RecipeGridViewStyle.
pub fn empty_view(mut self, f: impl Fn() -> Box<dyn Widget> + 'static) -> Self
Widget shown when the model is empty.
pub fn loading_view(mut self, f: impl Fn() -> Box<dyn Widget> + 'static) -> Self
Widget overlaid while is_loading reads true.
pub fn is_loading(mut self, flag: impl Into<Prop<bool>>) -> Self
Reactive loading flag; when true the loading_view
is shown above the grid.
pub fn reorderable(mut self, enabled: bool) -> Self
Enable intra-grid drag reordering (and keyboard Alt+Arrow). The move is
routed through the source's accept_drop (a built-in ListModel
reorders via move_item; an external source applies its own command).
pub fn exportable(mut self, mode: DragTransferMode) -> Self where T: Clone,
Make tiles droppable outside this view — on a
DropTarget, another data view, or the OS.
A dragged tile (or the whole selection, when the pressed tile is part of
a multi-selection) carries clones of its items in a public
RowDragData<T>, so a foreign receiver can pull
them out with payload.get_typed::<RowDragData<T>>() /
DropTarget::on_drop_typed::<RowDragData<T>>() — no serialization. This
also makes tiles a drag source even without reorderable.
mode chooses what happens to the origin rows once a foreign target
accepts them: DragTransferMode::Move removes them (via the source's
on_drag_out, or on_rows_transferred_out),
DragTransferMode::Copy leaves them. A same-view reorder is never a
transfer, so mode never affects it. Requires T: Clone.
pub fn export_external(mut self, f: impl Fn(&[T]) -> Vec<(String, Vec<u8>)> + 'static) -> Self where T: Clone,
Additionally advertise the dragged tiles as MIME data so they can be
dropped on a DropZone or exported to another
application / window via the OS. f maps the dragged items to
(mime_type, bytes) pairs (e.g. text/plain, text/uri-list, an
app-specific application/x-…). Implies exportable
(defaulting to DragTransferMode::Move if not already set). Requires
T: Clone.
pub fn on_rows_transferred_out( mut self, f: impl Fn(&[usize], &mut teksilo_core::widget::EventContext) + 'static, ) -> Self
Override how rows moved out to a foreign target are removed from this
view. Receives the dragged rows' indices (descending-safe) and the live
context. Without this, an exportable
Move drag removes them through the source's
on_drag_out (works out of the box for a ListModel).
pub fn accept_foreign_rows(mut self, accept: bool) -> Self
Accept exported rows dropped from a different view or source without
writing a custom ListDataSource. Pair with
on_rows_received, which is handed the dropped
items and the insertion index. (Same-view reorder is
reorderable; a custom ListDataSource can still
accept foreign drops through its can_accept/accept_drop instead.)
pub fn on_rows_received( mut self, f: impl Fn(Vec<T>, usize, &mut teksilo_core::widget::EventContext) + 'static, ) -> Self
Handler for rows accepted via accept_foreign_rows:
(items, insertion_index, ctx). Insert them into your model at the
index.
pub fn on_item_drop( mut self, f: impl Fn( teksilo_core::drag_payload::DragPayload, usize, &mut teksilo_core::widget::EventContext, ) -> bool + 'static, ) -> Self
Accept external drops at a flat insertion index. Returns true when
the drop is accepted.
pub fn on_tile_activate( mut self, f: impl Fn(usize, &mut teksilo_core::widget::EventContext) + 'static, ) -> Self
Called when a tile is activated (a click per activate_on,
or Enter on the focused tile) — the "open / default action", distinct
from selection.
pub fn activate_on(mut self, mode: crate::data_views::ActivateOn) -> Self
Choose single- vs double-click tile activation (default
ActivateOn::DoubleClick). Enter activates in either
mode.
pub fn tile_context_menu( mut self, f: impl Fn(usize, Point, &mut teksilo_core::widget::EventContext) -> Option<Box<dyn Widget>> + 'static, ) -> Self
Per-tile context-menu factory: (index, pointer_position, ctx) →
optional menu widget.
pub fn type_ahead_label(mut self, f: impl Fn(usize) -> String + 'static) -> Self
Supply a per-item label for type-ahead navigation (typing letters jumps to the first matching item). Required to enable type-ahead.
pub fn tile_a11y_label(mut self, f: impl Fn(usize) -> String + 'static) -> Self
Supply a per-item accessible name applied to each tile's GridCell
(Node::label), so a screen reader announces a concise item name in
addition to the row/column position. Without it, the cell's name is left
to its contents.
pub fn type_ahead_timeout(mut self, timeout: std::time::Duration) -> Self
Type-ahead reset timeout (default 500 ms; ZERO disables).
pub enum GridTabTraversal
How Tab moves out of (or within) the grid.
#![allow(unused)] fn main() { pub enum GridTabTraversal { /* variants */ } }
Variants
OutOfGrid— Tab releases focus to the next focusable widget in the window.WithinGrid— Tab advances to the next tile (wrapping rows); Shift+Tab the previous.
pub struct GroupingSections
A SectionProvider built by partitioning consecutive equal-key runs of
an (already ordered) model. The titles come from each run's key.
#![allow(unused)] fn main() { pub struct GroupingSections { /* fields */ } }