177 lines
5.4 KiB
Rust
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" ) ,
|
|
] )
|
|
}
|
|
}
|