@ -24,7 +24,7 @@ pub struct Margin {
}
}
/// A simple rectangle used in the computation of the layout and to give widgets an hint about the
/// A simple rectangle used in the computation of the layout and to give widgets an hint about the
/// area they are supposed to render to.
/// area they are supposed to render to. (x, y) = (0, 0) is at the top left corner of the screen.
#[ derive(Debug, Clone, Copy, Hash, PartialEq, Eq) ]
#[ derive(Debug, Clone, Copy, Hash, PartialEq, Eq) ]
pub struct Rect {
pub struct Rect {
pub x : u16 ,
pub x : u16 ,
@ -92,6 +92,57 @@ impl Rect {
self . y . saturating_add ( self . height )
self . y . saturating_add ( self . height )
}
}
// Returns a new Rect with width reduced from the left side.
// This changes the `x` coordinate and clamps it to the right
// edge of the original Rect.
pub fn clip_left ( self , width : u16 ) -> Rect {
let width = std ::cmp ::min ( width , self . width ) ;
Rect {
x : self . x . saturating_add ( width ) ,
width : self . width . saturating_sub ( width ) ,
.. self
}
}
// Returns a new Rect with width reduced from the right side.
// This does _not_ change the `x` coordinate.
pub fn clip_right ( self , width : u16 ) -> Rect {
Rect {
width : self . width . saturating_sub ( width ) ,
.. self
}
}
// Returns a new Rect with height reduced from the top.
// This changes the `y` coordinate and clamps it to the bottom
// edge of the original Rect.
pub fn clip_top ( self , height : u16 ) -> Rect {
let height = std ::cmp ::min ( height , self . height ) ;
Rect {
y : self . y . saturating_add ( height ) ,
height : self . height . saturating_sub ( height ) ,
.. self
}
}
// Returns a new Rect with height reduced from the bottom.
// This does _not_ change the `y` coordinate.
pub fn clip_bottom ( self , height : u16 ) -> Rect {
Rect {
height : self . height . saturating_sub ( height ) ,
.. self
}
}
pub fn with_height ( self , height : u16 ) -> Rect {
// new height may make area > u16::max_value, so use new()
Self ::new ( self . x , self . y , self . width , height )
}
pub fn with_width ( self , width : u16 ) -> Rect {
Self ::new ( self . x , self . y , width , self . height )
}
pub fn inner ( self , margin : & Margin ) -> Rect {
pub fn inner ( self , margin : & Margin ) -> Rect {
if self . width < 2 * margin . horizontal | | self . height < 2 * margin . vertical {
if self . width < 2 * margin . horizontal | | self . height < 2 * margin . vertical {
Rect ::default ( )
Rect ::default ( )
@ -495,6 +546,40 @@ mod tests {
assert_eq! ( rect . height , 100 ) ;
assert_eq! ( rect . height , 100 ) ;
}
}
#[ test ]
fn test_rect_chop_from_left ( ) {
let rect = Rect ::new ( 0 , 0 , 20 , 30 ) ;
assert_eq! ( Rect ::new ( 10 , 0 , 10 , 30 ) , rect . clip_left ( 10 ) ) ;
assert_eq! (
Rect ::new ( 20 , 0 , 0 , 30 ) ,
rect . clip_left ( 40 ) ,
"x should be clamped to original width if new width is bigger"
) ;
}
#[ test ]
fn test_rect_chop_from_right ( ) {
let rect = Rect ::new ( 0 , 0 , 20 , 30 ) ;
assert_eq! ( Rect ::new ( 0 , 0 , 10 , 30 ) , rect . clip_right ( 10 ) ) ;
}
#[ test ]
fn test_rect_chop_from_top ( ) {
let rect = Rect ::new ( 0 , 0 , 20 , 30 ) ;
assert_eq! ( Rect ::new ( 0 , 10 , 20 , 20 ) , rect . clip_top ( 10 ) ) ;
assert_eq! (
Rect ::new ( 0 , 30 , 20 , 0 ) ,
rect . clip_top ( 50 ) ,
"y should be clamped to original height if new height is bigger"
) ;
}
#[ test ]
fn test_rect_chop_from_bottom ( ) {
let rect = Rect ::new ( 0 , 0 , 20 , 30 ) ;
assert_eq! ( Rect ::new ( 0 , 0 , 20 , 20 ) , rect . clip_bottom ( 10 ) ) ;
}
fn styles ( ) -> Vec < Style > {
fn styles ( ) -> Vec < Style > {
vec! [
vec! [
Style ::default ( ) ,
Style ::default ( ) ,