ltk/widget/tab_strip/
desktop.rsuse crate::layout::row::row;
use crate::types::{ Corners, Length, WidgetId };
use crate::widget::flex::flex;
use crate::widget::pressable::pressable;
use crate::widget::scroll::scroll;
use crate::widget::viewport::viewport;
use crate::widget::{ container, text, Element };
use super::row::{ TabCells, TabRow };
use super::theme::{ EDGE_WIDTH, GAP, ICON_SIZE, LABEL_SIZE, TAB_CLOSE_ICON, TAB_ID, TAB_RADIUS };
use super::{ parts, IndexMsg, TabItem, TabStrip, TabStripColors };
pub( super ) fn build<Msg: Clone + 'static>( strip: TabStrip<Msg> ) -> Element<Msg>
{
let TabStrip { tabs, selected, on_select, on_close, reorderable, leading, after, trailing, colors, motion, .. } = strip;
let keys = tabs.iter().map( |tab| tab.key ).collect();
let current = tabs.get( selected ).map( |tab| tab.key );
let handles = tabs.into_iter().enumerate()
.map( |( idx, tab )| ( tab.key, handle( tab, idx, idx == selected, reorderable, &colors, on_select.as_ref(), on_close.as_ref() ) ) )
.collect();
let cells = TabCells { tabs: handles, after, motion: motion.clone() };
let tab_row = TabRow { child: Box::new( scroll( cells ).horizontal().into() ), keys, selected: current, motion };
let mut bar = row().spacing( Length::widget( GAP ) );
for button in leading
{
bar = bar.push( button );
}
bar = bar.push( flex( tab_row ) );
for button in trailing
{
bar = bar.push( button );
}
container( bar )
.background( colors.strip )
.padding_h( Length::widget( 6.0 ) )
.padding_top( Length::widget( 4.0 ) )
.into()
}
fn handle<Msg: Clone + 'static>(
tab: TabItem,
idx: usize,
active: bool,
draggable: bool,
colors: &TabStripColors,
on_select: Option<&IndexMsg<Msg>>,
on_close: Option<&IndexMsg<Msg>>,
) -> Element<Msg>
{
let ( fill, edge, ink ) = colors.of( active );
let mut body = row().spacing( Length::widget( 8.0 ) );
if let Some( icon ) = parts::icon( &tab, Length::widget( ICON_SIZE ), ink )
{
body = body.push( icon );
}
body = body.push( flex( text( tab.label ).size( LABEL_SIZE ).weight( 400 ).color( ink ) ) );
if let Some( close ) = on_close.filter( |_| tab.closable )
{
body = body.push( parts::close( close( idx ), ink, TAB_CLOSE_ICON ) );
}
let face = container( body )
.background( fill )
.border( edge, EDGE_WIDTH )
.radius( Corners::top( TAB_RADIUS ) )
.padding_left( Length::widget( 10.0 ) )
.padding_right( Length::widget( 4.0 ) )
.padding_v( Length::widget( 3.0 ) );
let mut press = pressable( face ).id( WidgetId::keyed( TAB_ID, tab.key ) );
if let Some( select ) = on_select
{
press = press.on_press( select( idx ) );
if draggable { press = press.on_drag_start( select( idx ) ); }
}
viewport( press ).into()
}