//! `cargo run --example scroll` //! //! Demonstrates the two main scroll use cases: //! //! - **List mode** — a long vertical list inside a `scroll(column(...))`. //! - **Grid mode** — a grid of buttons inside a `scroll(grid(4))` (app-drawer style). //! //! Press the "List" / "Grid" toggle at the top to switch between modes. //! Drag the content area to scroll. Esc exits. //! //! NOTE: ltk is a Wayland layer-shell toolkit. This example requires a running //! Wayland compositor (e.g. sway, labwc, or a full desktop session). use ltk::{ App, Element, Keysym, ButtonVariant, button, column, row, text, scroll, grid, spacer, }; // ── Messages ────────────────────────────────────────────────────────────────── #[ derive( Clone ) ] enum Message { ShowList, ShowGrid, ItemPressed( usize ), } // ── App state ───────────────────────────────────────────────────────────────── #[ derive( PartialEq ) ] enum Mode { List, Grid } struct ScrollApp { mode: Mode, last_pressed: Option, } impl ScrollApp { fn new() -> Self { Self { mode: Mode::List, last_pressed: None } } } // ── App trait ───────────────────────────────────────────────────────────────── const ITEM_COUNT: usize = 64; impl App for ScrollApp { type Message = Message; fn view( &self ) -> Element { let palette = ltk::theme_palette(); let primary = palette.text_primary; let secondary = palette.text_secondary; let status = match self.last_pressed { Some( i ) => format!( "Pressed item {}", i + 1 ), None => String::from( "Drag to scroll · click an item" ), }; // Top bar: toggle buttons + status let toggle_list = button::( "List" ) .variant( if self.mode == Mode::List { ButtonVariant::Primary } else { ButtonVariant::Secondary } ) .on_press( Message::ShowList ); let toggle_grid = button::( "Grid" ) .variant( if self.mode == Mode::Grid { ButtonVariant::Primary } else { ButtonVariant::Secondary } ) .on_press( Message::ShowGrid ); let top_bar = row::() .spacing( 8.0 ) .push( toggle_list ) .push( toggle_grid ) .push( spacer() ) .push( text( &status ).size( 14.0 ).color( secondary ) ); // Scrollable content area let content: Element = match self.mode { Mode::List => { // A long list of labeled buttons in a scrollable column let mut col = column::().padding( 8.0 ).spacing( 6.0 ); for i in 0..ITEM_COUNT { col = col.push( button::( format!( "List item {} — click me", i + 1 ) ) .variant( ButtonVariant::Secondary ) .on_press( Message::ItemPressed( i ) ), ); } scroll( col ).into() } Mode::Grid => { // A grid of labeled buttons in a scrollable 4-column grid let mut g = grid::( 4 ).padding( 8.0 ).spacing( 6.0 ); for i in 0..ITEM_COUNT { g = g.push( button::( format!( "Item {}", i + 1 ) ) .variant( ButtonVariant::Secondary ) .on_press( Message::ItemPressed( i ) ), ); } scroll( g ).into() } }; column::() .padding( 16.0 ) .spacing( 12.0 ) .push( text( "ltk — scroll showcase" ).size( 22.0 ).color( primary ).align_center() ) .push( top_bar ) .push( content ) .push( text( "Drag = scroll · Esc = quit" ) .size( 12.0 ) .color( secondary ) .align_center(), ) .into() } fn update( &mut self, msg: Message ) { match msg { Message::ShowList => self.mode = Mode::List, Message::ShowGrid => self.mode = Mode::Grid, Message::ItemPressed( i ) => self.last_pressed = Some( i ), } } fn on_key( &mut self, keysym: Keysym ) -> Option { if keysym == Keysym::Escape { std::process::exit( 0 ); } None } } // ── Entry point ─────────────────────────────────────────────────────────────── fn main() { ltk::run( ScrollApp::new() ); }