109 lines
3.0 KiB
Rust
109 lines
3.0 KiB
Rust
// 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<Msg>
|
|
{
|
|
scroll(
|
|
column::<Msg>()
|
|
.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::<Msg>( column::<Msg>() );
|
|
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::<Msg>::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::<Msg>::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::<Msg>::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::<Msg>::new( 320, 480 );
|
|
let view: Element<Msg> = scroll( column::<Msg>() ).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::<Msg>::new( 320, 480 );
|
|
let view: Element<Msg> = scroll(
|
|
column::<Msg>()
|
|
.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() );
|
|
}
|