First commit. Version 0.1.0

This commit is contained in:
2026-05-10 09:58:23 +02:00
parent af105b7f7d
commit bbab5e238d
635 changed files with 53627 additions and 175 deletions

108
tests/scroll.rs Normal file
View File

@@ -0,0 +1,108 @@
// 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() );
}