ltk/widget/tab_strip/
cards.rsuse crate::render::Canvas;
use crate::types::{ Length, Rect };
use crate::widget::Element;
use super::motion::TabMotion;
pub struct TabCards<Msg: Clone>
{
pub( crate ) cards: Vec<( u64, Element<Msg> )>,
pub( crate ) columns: usize,
pub( crate ) spacing: Length,
pub( crate ) motion: TabMotion,
}
impl<Msg: Clone> TabCards<Msg>
{
pub( crate ) fn child( &self, idx: usize ) -> &Element<Msg>
{
&self.cards[ idx ].1
}
fn columns( &self ) -> usize
{
self.columns.max( 1 )
}
fn cell( &self, width: f32, canvas: &Canvas ) -> ( f32, f32 )
{
let gap = canvas.resolve_geom( self.spacing );
let columns = self.columns() as f32;
let width = ( ( width - gap * ( columns - 1.0 ) ) / columns ).max( 0.0 );
let height = self.cards.iter().map( |( _, card )| card.preferred_size( width, canvas ).1 ).fold( 0.0_f32, f32::max );
( width, height )
}
pub fn preferred_size( &self, max_width: f32, canvas: &Canvas ) -> ( f32, f32 )
{
let gap = canvas.resolve_geom( self.spacing );
let height = self.cell( max_width, canvas ).1;
let rows = self.cards.len().div_ceil( self.columns() ) as f32;
( max_width, rows * height + ( rows - 1.0 ).max( 0.0 ) * gap )
}
pub fn layout( &self, rect: Rect, canvas: &Canvas ) -> Vec<( Rect, usize )>
{
let gap = canvas.resolve_geom( self.spacing );
let keys = self.cards.iter().map( |( key, _ )| *key ).collect::<Vec<_>>();
self.motion.lay_cards( &keys, rect, self.columns(), self.cell( rect.width, canvas ), gap ).into_iter()
.filter_map( |laid| keys.iter().position( |&key| key == laid.key ).map( |idx| ( laid.rect, idx ) ) )
.collect()
}
pub( crate ) fn map_msg<U>( self, f: &crate::widget::MapFn<Msg, U> ) -> TabCards<U>
where
U: Clone + 'static,
Msg: 'static,
{
TabCards
{
cards: self.cards.into_iter().map( |( key, card )| ( key, card.map_arc( f ) ) ).collect(),
columns: self.columns,
spacing: self.spacing,
motion: self.motion,
}
}
}
impl<Msg: Clone> From<TabCards<Msg>> for Element<Msg>
{
fn from( cards: TabCards<Msg> ) -> Self
{
Element::TabCards( cards )
}
}