Header & view stack are now components, introduced Component trait

This commit is contained in:
Reinout Meliesie 2024-11-27 15:22:55 +01:00
parent 64fc8ba425
commit 4778d879f4
Signed by: zedfrigg
GPG key ID: 3AFCC06481308BC6
8 changed files with 184 additions and 100 deletions

View file

@ -0,0 +1,29 @@
use libadwaita :: { * , ViewSwitcherPolicy :: * } ;
use crate :: ui :: { collection_view_stack :: * , component :: * } ;
pub struct ApplicationHeaderBar { widget : HeaderBar }
impl ApplicationHeaderBar {
pub fn new ( collection_view_stack : & CollectionViewStack ) -> Self {
let widget = HeaderBar :: builder ()
. title_widget ( & create_collection_view_switcher (
collection_view_stack . get_widget () ) )
. build () ;
Self { widget }
}
}
impl Component <HeaderBar> for ApplicationHeaderBar {
fn get_widget ( & self ) -> & HeaderBar { & self . widget }
}
fn create_collection_view_switcher ( stack : & ViewStack ) -> ViewSwitcher {
ViewSwitcher :: builder ()
. policy (Wide)
. stack (stack)
. build ()
}

View file

@ -2,7 +2,12 @@ use gtk4 :: { * , prelude :: * } ;
use crate :: { use crate :: {
collection :: * , collection :: * ,
ui :: { collated_grid :: * , collation_menu :: * , utility :: * } , ui :: {
collated_grid :: * ,
collation_menu :: * ,
component :: * ,
utility :: * ,
} ,
utility :: * , utility :: * ,
} ; } ;
@ -10,20 +15,23 @@ use crate :: {
pub struct CollatableFilmsContainer { pub struct CollatableFilmsContainer {
collated_grid : & 'static CollatedFilmsGrid , collated_grid : & 'static CollatedFilmsGrid ,
widget : gtk4 :: Box , widget : Box ,
} }
pub struct CollatableSeriesContainer { pub struct CollatableSeriesContainer {
collated_grid : & 'static CollatedSeriesGrid , collated_grid : & 'static CollatedSeriesGrid ,
widget : gtk4 :: Box , widget : Box ,
} }
impl CollatableFilmsContainer { impl CollatableFilmsContainer {
pub fn new ( films : Vec <Film> ) -> Self { pub fn new ( films : Vec <Film> ) -> Self {
let collated_grid = leak ( CollatedFilmsGrid :: new ( films , FilmsSortedBy :: Name ) ) ; let collated_grid = leak (
CollatedFilmsGrid :: new ( films , FilmsSortedBy :: Name ) ) ;
let film_collation_menu = FilmCollationMenu :: new ( |sorted_by| {
collated_grid . set_sorting (sorted_by) ;
} ) ;
let widget = create_vertical_box ! ( let widget = create_vertical_box ! (
& create_film_collection_menu ( |sorted_by| { film_collation_menu . get_widget () ,
collated_grid . set_sorting (sorted_by) ;
} ) ,
& create_collection_scrolled_window ( collated_grid . get_widget () ) , & create_collection_scrolled_window ( collated_grid . get_widget () ) ,
) ; ) ;
@ -33,16 +41,17 @@ impl CollatableFilmsContainer {
pub fn set_films ( & self , films : Vec <Film> ) { pub fn set_films ( & self , films : Vec <Film> ) {
self . collated_grid . set_films ( films , FilmsSortedBy :: Name ) ; self . collated_grid . set_films ( films , FilmsSortedBy :: Name ) ;
} }
pub fn get_widget ( & self ) -> & gtk4 :: Box { & self . widget }
} }
impl CollatableSeriesContainer { impl CollatableSeriesContainer {
pub fn new ( series : Vec <Series> ) -> Self { pub fn new ( series : Vec <Series> ) -> Self {
let collated_grid = leak ( CollatedSeriesGrid :: new ( series , SeriesSortedBy :: Name ) ) ; let collated_grid = leak (
CollatedSeriesGrid :: new ( series , SeriesSortedBy :: Name ) ) ;
let series_collation_menu = SeriesCollationMenu :: new ( |sorted_by| {
collated_grid . set_sorting (sorted_by) ;
} ) ;
let widget = create_vertical_box ! ( let widget = create_vertical_box ! (
& create_series_collection_menu ( |sorted_by| { series_collation_menu . get_widget () ,
collated_grid . set_sorting (sorted_by) ;
} ) ,
& create_collection_scrolled_window ( collated_grid . get_widget () ) , & create_collection_scrolled_window ( collated_grid . get_widget () ) ,
) ; ) ;
@ -52,8 +61,13 @@ impl CollatableSeriesContainer {
pub fn set_series ( & self , series : Vec <Series> ) { pub fn set_series ( & self , series : Vec <Series> ) {
self . collated_grid . set_series ( series , SeriesSortedBy :: Name ) ; self . collated_grid . set_series ( series , SeriesSortedBy :: Name ) ;
} }
}
pub fn get_widget ( & self ) -> & gtk4 :: Box { & self . widget } impl Component <Box> for CollatableFilmsContainer {
fn get_widget ( & self ) -> & Box { & self . widget }
}
impl Component <Box> for CollatableSeriesContainer {
fn get_widget ( & self ) -> & Box { & self . widget }
} }
fn create_collection_scrolled_window ( child : & FlowBox ) -> ScrolledWindow { fn create_collection_scrolled_window ( child : & FlowBox ) -> ScrolledWindow {

View file

@ -6,10 +6,10 @@ use {
gdk :: Texture , gdk :: Texture ,
prelude :: * , prelude :: * ,
} , } ,
std :: { cell :: * , iter :: * , path :: * } , std :: { cell :: * , iter :: * , path :: Path } ,
} ; } ;
use crate :: collection :: * ; use crate :: { collection :: * , ui :: component :: * } ;
@ -66,8 +66,6 @@ impl CollatedFilmsGrid {
self . grid_widget . append (film_widget) ; self . grid_widget . append (film_widget) ;
} }
} }
pub fn get_widget ( & self ) -> & FlowBox { & self . grid_widget }
} }
impl CollatedSeriesGrid { impl CollatedSeriesGrid {
pub fn new ( series : Vec <Series> , sorting : SeriesSortedBy ) -> Self { pub fn new ( series : Vec <Series> , sorting : SeriesSortedBy ) -> Self {
@ -110,8 +108,13 @@ impl CollatedSeriesGrid {
self . grid_widget . append (series_widget) ; self . grid_widget . append (series_widget) ;
} }
} }
}
pub fn get_widget ( & self ) -> & FlowBox { & self . grid_widget } impl Component <FlowBox> for CollatedFilmsGrid {
fn get_widget ( & self ) -> & FlowBox { & self . grid_widget }
}
impl Component <FlowBox> for CollatedSeriesGrid {
fn get_widget ( & self ) -> & FlowBox { & self . grid_widget }
} }
fn sort_film_widget_pairs ( fn sort_film_widget_pairs (

View file

@ -1,6 +1,6 @@
use { use {
gtk4 :: { gtk4 :: {
Image , Label , ListBox , ListBoxRow , Popover , Box , Image , Label , ListBox , ListBoxRow , Popover ,
Align :: * , Align :: * ,
Orientation :: * , Orientation :: * ,
prelude :: * , prelude :: * ,
@ -8,37 +8,51 @@ use {
libadwaita :: * , libadwaita :: * ,
} ; } ;
use crate :: ui :: { collated_grid :: * , utility :: * } ; use crate :: ui :: { collated_grid :: * , component :: * , utility :: * } ;
pub fn create_film_collection_menu < F : Fn (FilmsSortedBy) + 'static > ( on_sort : F ) pub struct FilmCollationMenu { widget : Box }
-> gtk4 :: Box { pub struct SeriesCollationMenu { widget : Box }
let container = gtk4 :: Box :: builder ()
. orientation (Horizontal)
. halign (Center)
. spacing (20)
. css_classes ( ["toolbar"] )
. build () ;
container . append ( & create_sort_button ( & create_films_sort_menu (on_sort) ) ) ; impl FilmCollationMenu {
container . append ( & SplitButton :: builder () . label ("Filter") . build () ) ; pub fn new <F> ( on_sort : F ) -> Self
where F : Fn (FilmsSortedBy) + 'static {
let widget = Box :: builder ()
. orientation (Horizontal)
. halign (Center)
. spacing (20)
. css_classes ( ["toolbar"] )
. build () ;
container widget . append ( & create_sort_button ( & create_films_sort_menu (on_sort) ) ) ;
widget . append ( & SplitButton :: builder () . label ("Filter") . build () ) ;
Self { widget }
}
} }
pub fn create_series_collection_menu < F : Fn (SeriesSortedBy) + 'static > ( on_sort : F ) impl SeriesCollationMenu {
-> gtk4 :: Box { pub fn new <F> ( on_sort : F ) -> Self
let container = gtk4 :: Box :: builder () where F : Fn (SeriesSortedBy) + 'static {
. orientation (Horizontal) let widget = Box :: builder ()
. halign (Center) . orientation (Horizontal)
. spacing (20) . halign (Center)
. css_classes ( ["toolbar"] ) . spacing (20)
. build () ; . css_classes ( ["toolbar"] )
. build () ;
container . append ( & create_sort_button ( & create_series_sort_menu (on_sort) ) ) ; widget . append ( & create_sort_button ( & create_series_sort_menu (on_sort) ) ) ;
container . append ( & SplitButton :: builder () . label ("Filter") . build () ) ; widget . append ( & SplitButton :: builder () . label ("Filter") . build () ) ;
container Self { widget }
}
}
impl Component <Box> for FilmCollationMenu {
fn get_widget ( & self ) -> & Box { & self . widget }
}
impl Component <Box> for SeriesCollationMenu {
fn get_widget ( & self ) -> & Box { & self . widget }
} }
fn create_sort_button ( sort_menu : & Popover ) -> SplitButton { fn create_sort_button ( sort_menu : & Popover ) -> SplitButton {
@ -48,8 +62,8 @@ fn create_sort_button ( sort_menu : & Popover ) -> SplitButton {
. build () . build ()
} }
fn create_films_sort_menu < F : Fn (FilmsSortedBy) + 'static > ( on_sort : F ) fn create_films_sort_menu <F> ( on_sort : F ) -> Popover
-> Popover { where F : Fn (FilmsSortedBy) + 'static {
let container = ListBox :: new () ; let container = ListBox :: new () ;
container . append ( & create_sort_menu_entry ( "Name" , false , true ) ) ; container . append ( & create_sort_menu_entry ( "Name" , false , true ) ) ;
@ -70,8 +84,8 @@ fn create_films_sort_menu < F : Fn (FilmsSortedBy) + 'static > ( on_sort : F )
. css_classes ( ["menu"] ) . css_classes ( ["menu"] )
. build () . build ()
} }
fn create_series_sort_menu < F : Fn (SeriesSortedBy) + 'static > ( on_sort : F ) fn create_series_sort_menu <F> ( on_sort : F ) -> Popover
-> Popover { where F : Fn (SeriesSortedBy) + 'static {
let container = ListBox :: new () ; let container = ListBox :: new () ;
container . append ( & create_sort_menu_entry ( "Name" , false , true ) ) ; container . append ( & create_sort_menu_entry ( "Name" , false , true ) ) ;

View file

@ -0,0 +1,25 @@
use libadwaita :: * ;
use crate :: ui :: { collatable_container :: * , component :: * , utility :: * } ;
pub struct CollectionViewStack { widget : ViewStack }
impl CollectionViewStack {
pub fn new (
films_container : & CollatableFilmsContainer ,
series_container : & CollatableSeriesContainer ,
) -> Self {
let widget = create_view_stack ! (
"Films" , "camera-video-symbolic" , films_container . get_widget () ,
"Series" , "video-display-symbolic" , series_container . get_widget () ,
) ;
Self { widget }
}
}
impl Component <ViewStack> for CollectionViewStack {
fn get_widget ( & self ) -> & ViewStack { & self . widget }
}

7
src/ui/component.rs Normal file
View file

@ -0,0 +1,7 @@
use gtk4 :: { * , prelude :: * } ;
pub trait Component < W : IsA <Widget> > {
fn get_widget ( & self ) -> & W ;
}

View file

@ -1,37 +0,0 @@
use {
gtk4 :: { HeaderBar , Orientation :: * , prelude :: * } ,
libadwaita :: { * , ViewSwitcherPolicy :: * } ,
} ;
pub fn create_window (
application : & Application ,
header_bar : & HeaderBar ,
collection_view_stack : & ViewStack ,
) -> ApplicationWindow {
let content = gtk4 :: Box :: builder () . orientation (Vertical) . build () ;
content . append (header_bar) ;
content . append (collection_view_stack) ;
ApplicationWindow :: builder ()
. application (application)
. content ( & content )
. title ("Zoödex")
. build ()
}
pub fn create_header_bar ( collection_view_stack : & ViewStack ) -> HeaderBar {
HeaderBar :: builder ()
. title_widget (
& create_collection_view_switcher ( collection_view_stack ) ,
)
. build ()
}
pub fn create_collection_view_switcher ( stack : & ViewStack ) -> ViewSwitcher {
ViewSwitcher :: builder ()
. policy (Wide)
. stack (stack)
. build ()
}

View file

@ -1,42 +1,71 @@
mod application_header_bar ;
mod collatable_container ; mod collatable_container ;
mod collated_grid ; mod collated_grid ;
mod collation_menu ; mod collation_menu ;
mod internal ; mod collection_view_stack ;
mod component ;
mod utility ; mod utility ;
use { gtk4 :: prelude :: * , libadwaita :: * } ; use {
gtk4 :: { Orientation :: * , prelude :: * } ,
libadwaita :: * ,
} ;
use crate :: { use crate :: {
collection :: * , collection :: * ,
ui :: { collatable_container :: * , internal :: * , utility :: * } , ui :: {
application_header_bar :: * ,
collatable_container :: * ,
collection_view_stack :: * ,
component :: * ,
} ,
} ; } ;
pub struct UI { pub struct UI {
window : ApplicationWindow , window : ApplicationWindow ,
films_container : CollatableFilmsContainer , films_component : CollatableFilmsContainer ,
series_container : CollatableSeriesContainer , series_component : CollatableSeriesContainer ,
} }
impl UI { impl UI {
pub fn new ( application : & Application ) -> UI { pub fn new ( application : & Application ) -> UI {
let films_container = CollatableFilmsContainer :: new ( vec ! () ) ; let films_component = CollatableFilmsContainer :: new ( vec ! () ) ;
let series_container = CollatableSeriesContainer :: new ( vec ! () ) ; let series_component = CollatableSeriesContainer :: new ( vec ! () ) ;
let collection_view_stack = create_view_stack ! ( let switch_component = CollectionViewStack :: new (
"Films" , "camera-video-symbolic" , films_container . get_widget () , & films_component , & series_component ) ;
"Series" , "video-display-symbolic" , series_container . get_widget () , let header_bar = ApplicationHeaderBar :: new ( & switch_component ) ;
) ;
let header_bar = create_header_bar ( & collection_view_stack ) ;
let window = create_window ( application , & header_bar , & collection_view_stack ) ;
UI { window , films_container , series_container } let window = create_window (
application ,
header_bar . get_widget () ,
switch_component . get_widget () ,
) ;
UI { window , films_component , series_component }
} }
pub fn show_window ( & self ) { self . window . set_visible (true) } pub fn show_window ( & self ) { self . window . set_visible (true) }
pub fn render_collection ( & self , collection : Collection ) { pub fn render_collection ( & self , collection : Collection ) {
self . films_container . set_films ( collection . films ) ; self . films_component . set_films ( collection . films ) ;
self . series_container . set_series ( collection . series ) ; self . series_component . set_series ( collection . series ) ;
} }
} }
fn create_window (
application : & Application ,
header_bar : & HeaderBar ,
collection_view_stack : & ViewStack ,
) -> ApplicationWindow {
let content = gtk4 :: Box :: builder () . orientation (Vertical) . build () ;
content . append (header_bar) ;
content . append (collection_view_stack) ;
ApplicationWindow :: builder ()
. application (application)
. content ( & content )
. title ("Zoödex")
. build ()
}