// Integration coverage for `scroll`. The pure clamping math already lives in // `widget::scroll::tests`; these tests exercise the wiring: `preferred_size` // claims remaining space, and interactive children inside the viewport remain // reachable through `UiSurface`'s widget rects. use ltk::core::{ Canvas, RenderOptions, UiSurface }; use ltk::{ button, column, scroll, text, Color, Element, Point }; #[ derive( Clone, Debug, PartialEq, Eq ) ] enum Msg { Pressed( u32 ), } fn list_view() -> Element { scroll( column::() .padding( 0.0 ) .spacing( 4.0 ) .push( button( "A" ).on_press( Msg::Pressed( 0 ) ) ) .push( button( "B" ).on_press( Msg::Pressed( 1 ) ) ) .push( button( "C" ).on_press( Msg::Pressed( 2 ) ) ), ).into() } #[ test ] fn scroll_preferred_size_returns_zero_height_to_act_as_filler() { let canvas = Canvas::new( 800, 600 ); let s = scroll::( column::() ); let ( w, h ) = s.preferred_size( 320.0, &canvas ); assert_eq!( w, 320.0 ); assert_eq!( h, 0.0 ); } #[ test ] fn scroll_with_buttons_exposes_them_through_widget_rects() { let mut surface = UiSurface::::new( 320, 480 ); let _ = surface.render( &list_view(), RenderOptions::full_canvas( 320, 480 ).background( Color::rgb( 0.1, 0.1, 0.1 ) ), ); // Three interactive buttons are visible inside the scroll viewport. assert_eq!( surface.widget_rects().len(), 3 ); } #[ test ] fn buttons_inside_scroll_dispatch_their_press_messages() { let mut surface = UiSurface::::new( 320, 480 ); let _ = surface.render( &list_view(), RenderOptions::full_canvas( 320, 480 ), ); let first = &surface.widget_rects()[ 0 ]; let msg = surface.handlers( first.flat_idx ).and_then( |h| h.press_msg() ); assert_eq!( msg, Some( Msg::Pressed( 0 ) ) ); } #[ test ] fn hit_test_inside_scroll_returns_button_under_pointer() { let mut surface = UiSurface::::new( 320, 480 ); let _ = surface.render( &list_view(), RenderOptions::full_canvas( 320, 480 ), ); let first = &surface.widget_rects()[ 0 ]; let centre = Point { x: first.rect.x + first.rect.width * 0.5, y: first.rect.y + first.rect.height * 0.5, }; assert_eq!( surface.hit_test( centre ), Some( first.flat_idx ) ); } #[ test ] fn empty_scroll_renders_without_panic() { let mut surface = UiSurface::::new( 320, 480 ); let view: Element = scroll( column::() ).into(); let out = surface.render( &view, RenderOptions::full_canvas( 320, 480 ), ); assert!( out.full_redraw ); assert!( surface.widget_rects().is_empty(), "no buttons inside → no interactive widgets" ); } #[ test ] fn scroll_around_text_only_child_produces_no_interactive_widgets() { let mut surface = UiSurface::::new( 320, 480 ); let view: Element = scroll( column::() .push( text( "header" ) ) .push( text( "body" ) ), ).into(); let _ = surface.render( &view, RenderOptions::full_canvas( 320, 480 ), ); // Text is non-interactive — widget_rects only tracks focusable / hittable // widgets. assert!( surface.widget_rects().is_empty() ); }