zoodex/src/ui/collatable_container/mod.rs

177 lines
5.4 KiB
Rust

mod collated_grid ;
mod collation_menu ;
use gtk4 :: { Box , ScrolledWindow } ;
use gtk4 :: Orientation :: * ;
use gtk4 :: prelude :: * ;
use relm4_macros :: * ;
use std :: cmp :: * ;
use std :: fmt :: * ;
use crate :: data_manager :: * ;
use crate :: ui :: component :: * ;
use crate :: ui :: utility :: * ;
use crate :: ui :: collatable_container :: collated_grid :: * ;
use crate :: ui :: collatable_container :: collation_menu :: * ;
use crate :: utility :: * ;
pub trait MediaSorting < P : MediaProperty > : Clone + Copy + Debug + Default {
fn new ( property : P , direction : SortingDirection ) -> Self ;
fn get_property ( & self ) -> P ;
fn get_direction ( & self ) -> SortingDirection ;
}
pub trait MediaProperty : Clone + Copy + Debug + PartialEq {}
# [ derive ( Clone , Copy , Debug , Default , PartialEq ) ] pub enum FilmProperty {
# [default] Name , ReleaseDate , Runtime ,
}
# [ derive ( Clone , Copy , Debug , Default , PartialEq ) ] pub enum SeriesProperty {
# [default] Name , FirstReleaseDate ,
}
# [ derive ( Clone , Copy , Debug , Default , PartialEq ) ] pub enum SortingDirection {
# [default] Ascending , Descending ,
}
# [ derive ( Clone , Copy , Debug , Default ) ] pub struct FilmsSorting {
property : FilmProperty ,
direction : SortingDirection ,
}
# [ derive ( Clone , Copy , Debug , Default ) ] pub struct SeriesSorting {
property : SeriesProperty ,
direction : SortingDirection ,
}
impl MediaSorting <FilmProperty> for FilmsSorting {
fn new ( property : FilmProperty , direction : SortingDirection ) -> Self {
Self { property , direction }
}
fn get_property ( & self ) -> FilmProperty { self . property }
fn get_direction ( & self ) -> SortingDirection { self . direction }
}
impl MediaSorting <SeriesProperty> for SeriesSorting {
fn new ( property : SeriesProperty , direction : SortingDirection ) -> Self {
Self { property , direction }
}
fn get_property ( & self ) -> SeriesProperty { self . property }
fn get_direction ( & self ) -> SortingDirection { self . direction }
}
impl MediaProperty for FilmProperty {}
impl MediaProperty for SeriesProperty {}
pub struct CollatableMediaContainer < A : MediaAdapter > {
collated_grid : & 'static CollatedMediaGrid <A> ,
widget : Box ,
}
impl < A : MediaAdapter > CollatableMediaContainer <A> {
pub fn new ( on_media_selected : impl Fn ( A :: Overview ) + 'static ) -> Self {
let collated_grid = leak ( CollatedMediaGrid :: new (on_media_selected) ) ;
let collation_menu = MediaCollationMenu :: new :: <A> (
|sorting| collated_grid . set_sorting (sorting) ,
) ;
view ! {
widget = gtk4 :: Box {
set_orientation : Vertical ,
append : collation_menu . get_widget () ,
append : & view_expr ! {
ScrolledWindow {
set_propagate_natural_height : true ,
set_child : Some ( & vertical_filler ( collated_grid . get_widget () ) ) ,
}
} ,
}
}
Self { collated_grid, widget }
}
pub async fn set_media ( & self , media : Vec < A :: Overview > ) {
self . collated_grid . set_media ( media , A :: Sorting :: default () ) . await ;
}
}
pub trait MediaAdapter : 'static {
type Overview : MediaOverview ;
type Sorting : MediaSorting < Self :: Property > ;
type Property : MediaProperty ;
fn compare_by (
media_1 : & Self :: Overview ,
media_2 : & Self :: Overview ,
sorting : Self :: Sorting ,
) -> Ordering ;
fn get_property_descriptions () -> & 'static [ ( Self :: Property , & 'static str ) ] ;
}
impl < A : MediaAdapter > Component for CollatableMediaContainer <A> {
fn get_widget ( & self ) -> & Box { & self . widget }
}
pub struct FilmsAdapter {}
pub struct SeriesAdapter {}
impl MediaAdapter for FilmsAdapter {
type Overview = FilmOverview ;
type Sorting = FilmsSorting ;
type Property = FilmProperty ;
fn compare_by (
film_1 : & FilmOverview ,
film_2 : & FilmOverview ,
sorting : FilmsSorting ,
) -> Ordering {
let ordering = match sorting . property {
FilmProperty :: Name =>
film_1 . name . cmp ( & film_2 . name ) ,
FilmProperty :: ReleaseDate =>
film_1 . release_date . cmp ( & film_2 . release_date ) ,
FilmProperty :: Runtime =>
film_1 . runtime_minutes . cmp ( & film_2 . runtime_minutes ) ,
} ;
match sorting . direction {
SortingDirection :: Ascending => ordering ,
SortingDirection :: Descending => ordering . reverse () ,
}
}
fn get_property_descriptions () -> & 'static [ ( FilmProperty , & 'static str ) ] {
leak ( [
( FilmProperty :: Name , "Name" ) ,
( FilmProperty :: ReleaseDate , "Release date" ) ,
( FilmProperty :: Runtime , "Runtime" ) ,
] )
}
}
impl MediaAdapter for SeriesAdapter {
type Overview = SeriesOverview ;
type Sorting = SeriesSorting ;
type Property = SeriesProperty ;
fn compare_by (
series_1 : & SeriesOverview ,
series_2 : & SeriesOverview ,
sorting : SeriesSorting ,
) -> Ordering {
let ordering = match sorting . property {
SeriesProperty :: Name =>
series_1 . name . cmp ( & series_2 . name ) ,
SeriesProperty :: FirstReleaseDate =>
series_1 . first_release_date . cmp ( & series_2 . first_release_date ) ,
} ;
match sorting . direction {
SortingDirection :: Ascending => ordering ,
SortingDirection :: Descending => ordering . reverse () ,
}
}
fn get_property_descriptions () -> & 'static [ ( SeriesProperty , & 'static str ) ] {
leak ( [
( SeriesProperty :: Name , "Name" ) ,
( SeriesProperty :: FirstReleaseDate , "First release date" ) ,
] )
}
}