zoodex/src/ui/collated_grid.rs

167 lines
3.8 KiB
Rust

use {
gtk4 :: {
* ,
Align :: * ,
Orientation :: * ,
gdk :: Texture ,
glib :: * ,
prelude :: * ,
} ,
std :: path :: * ,
} ;
use crate :: collection :: * ;
pub struct CollatedFilmsGrid { widget : FlowBox }
pub struct CollatedSeriesGrid { widget : FlowBox }
impl CollatedFilmsGrid {
pub fn new ( films : & [Film] ) -> Self {
let widget = create_collection_flow_box () ;
for film in films {
widget . append ( & create_film_item (film) ) ;
}
Self { widget }
}
pub fn set_films ( & self , films : & [Film] ) {
self . widget . remove_all () ;
for film in films {
let widget = self . widget . clone () ;
let film = film . clone () ;
spawn_future_local ( async move {
widget . append ( & create_film_item ( & film ) ) ;
} ) ;
}
}
pub fn get_widget ( & self ) -> & FlowBox { & self . widget }
}
impl CollatedSeriesGrid {
pub fn new ( series : & [Series] ) -> Self {
let widget = create_collection_flow_box () ;
for series in series {
widget . append ( & create_series_item (series) ) ;
}
Self { widget }
}
pub fn set_series ( & self , series : & [Series] ) {
self . widget . remove_all () ;
for series in series {
self . widget . append ( & create_series_item (series) ) ;
}
}
pub fn get_widget ( & self ) -> & FlowBox { & self . widget }
}
fn create_collection_flow_box () -> FlowBox {
FlowBox :: builder ()
. orientation (Horizontal)
. homogeneous (true)
. selection_mode ( SelectionMode :: None )
. build ()
}
pub fn create_film_item ( film : & Film ) -> gtk4 :: Box {
create_collection_item (
film . name . as_str () ,
film . original_name . as_deref () ,
film . poster_file_path . as_deref () ,
& create_film_details (film) ,
)
}
pub fn create_series_item ( series : & Series ) -> gtk4 :: Box {
create_collection_item (
series . name . as_str () ,
series . original_name . as_deref () ,
series . poster_file_path . as_deref () ,
& create_series_details (series) ,
)
}
fn create_collection_item (
name : & str ,
original_name : Option < & str > ,
poster_file_path : Option < & Path > ,
details_widget : & gtk4 :: Box ,
) -> gtk4 :: Box {
let container = gtk4 :: Box :: builder ()
. orientation (Vertical)
. margin_top (20)
. margin_bottom (20)
. build () ;
if let Some (poster_file_path) = poster_file_path {
let poster_texture = Texture :: from_filename (poster_file_path) . unwrap () ;
container . append (
& Image :: builder ()
. paintable ( & poster_texture )
. width_request (300)
. height_request (300)
. margin_bottom (10)
. build ()
) ;
}
container . append (
& Label :: builder ()
. label ( format ! ( "<span size='large' weight='bold'>{}</span>" , name ) )
. use_markup (true)
. justify ( Justification :: Center )
. wrap (true)
. max_width_chars (1) // Not the actual limit, used instead to wrap more aggressively
. build ()
) ;
if let Some (original_name) = original_name {
container . append (
& Label :: builder ()
. label (original_name)
. justify ( Justification :: Center )
. wrap (true)
. max_width_chars (1) // Not the actual limit, used instead to wrap more aggressively
. build ()
) ;
}
container . append (details_widget) ;
container
}
fn create_film_details ( film : & Film ) -> gtk4 :: Box {
let container = gtk4 :: Box :: builder ()
. orientation (Horizontal)
. halign (Center)
. spacing (20)
. build () ;
container . append (
& Label :: builder () . label ( & film . release_date ) . build ()
) ;
container . append (
& Label :: builder () . label ( format ! ( "{}m" , film . runtime_minutes ) ) . build ()
) ;
container
}
fn create_series_details ( series : & Series ) -> gtk4 :: Box {
let container = gtk4 :: Box :: builder ()
. orientation (Horizontal)
. halign (Center)
. spacing (20)
. build () ;
// TODO
container
}