# llimphi-widget-grid 2D virtualized grid for Llimphi. Sibling of `llimphi-widget-list`, but tiled: clickable cells laid out in `cols` columns × rows, with selection, optional caption/hint and overflow clipping. Designed as the base for thumbnail galleries in the gThumb / FastStone vein — able to list thousands of files without mounting them all: the caller renders **only the visible window**. Like `list`, the widget does **not** scroll by itself. Virtualization belongs to the caller, which keeps `scroll_row` (the first visible row of cells) in its state and updates it with the wheel. The difference from `list` is that in 2D computing the window is not trivial — how many columns fit depends on the viewport width — so this crate provides it as a pure, testable function: `ventana_visible`. The widget is **content-agnostic**: each `GridCell` carries a `View` the caller builds (a `peniko::Image` thumbnail, a skeleton while decoding, an icon…). That way the thumbnail pipeline (async queue + cache) lives outside and merely fills the cell with an image or a placeholder. Typical caller flow: ```ignore let v = ventana_visible(total, viewport_w, viewport_h, scroll_row, &metrics); let cells: Vec> = (v.first..v.first + v.count) .map(|i| GridCell { content: thumb_or_placeholder(i), // the caller decides label: Some(name(i)), selected: i == selected, on_click: Msg::Select(i), }) .collect(); let grid = grid_view(GridSpec { cells, cols: v.cols, metrics, caption: Some(format!("{total} images")), truncated_hint: (v.first + v.count < total) .then(|| format!("… and {} more", total - (v.first + v.count))), palette: GridPalette::default(), }); ``` --- Part of **llimphi** — see [llimphi](../../README.md).