use iris::prelude::*; use winit::{dpi::LogicalSize, window::WindowAttributes}; fn main() { DefaultApp::::run(); } #[derive(DefaultUiState)] struct State { ui_state: DefaultUiState, } const ROWS: usize = 800; const IMAGE_EVERY: usize = 12; fn row_text(i: usize) -> String { const SENTENCE: &str = "Iris lays out this row once and moves it on scroll, never re-laying it out. "; let repeats = 1 + (i * 7) % 5; format!("Message {i}: {}", SENTENCE.repeat(repeats)) } fn row_image(i: usize) -> image::DynamicImage { let hue = ((i * 47) % 255) as u8; image::RgbaImage::from_pixel(48, 48, image::Rgba([hue, 128, 255 - hue, 255])).into() } fn build_row(rsc: &mut Rsc, i: usize) -> StrongWidget { let tint = if i.is_multiple_of(2) { Srgba8::rgb(120, 130, 170) } else { Srgba8::rgb(70, 80, 140) }; let text_color = PaintId::BLACK; if i.is_multiple_of(IMAGE_EVERY) { let text = wtext(row_text(i)) .wrap(true) .color(text_color) .add_strong(rsc) .any(); let img = image::(row_image(i))(rsc); let img = rsc.widgets_mut().add_strong(img).any(); let mut span = Span::empty(Dir::DOWN); span.push(text); span.push(img); span.pad(dp(8.0)) .background(rect(tint)) .add_strong(rsc) .any() } else { wtext(row_text(i)) .wrap(true) .color(text_color) .pad(dp(8.0)) .background(rect(tint)) .add_strong(rsc) .any() } } impl DefaultAppState for State { fn window_attributes() -> WindowAttributes { WindowAttributes::default().with_inner_size(LogicalSize::new(420.0, 900.0)) } fn new( mut ui_state: DefaultUiState, rsc: &mut DefaultRsc, _: Proxy, ) -> Self { let mut list = LazySpan::new(Dir::DOWN, Pin::End); for i in 0..ROWS { let row = build_row(rsc, i); list.push_back(LazyItem::new(i as u64, row)); } let root = list .scrollable() .masked() .background(rect(PaintId::WHITE)) .add_strong(rsc); ui_state.set_root(root.any()); Self { ui_state } } }