Reimplement collation menu as component

This commit is contained in:
Reinout Meliesie 2025-01-31 15:34:09 +01:00
parent ebc8bc0d2f
commit 04755fabb7
Signed by: zedfrigg
GPG key ID: 3AFCC06481308BC6
4 changed files with 133 additions and 45 deletions

View file

@ -3,8 +3,7 @@ mod sort_button ;
use {
gtk4 :: {
Box , Image , Label , ListBox , ListBoxRow , Popover ,
Align :: * ,
Orientation :: * ,
Align :: * , Orientation :: * ,
prelude :: * ,
} ,
libadwaita :: * ,
@ -12,33 +11,31 @@ use {
} ;
use crate :: {
ui :: { collatable_container :: * , component :: * , utility :: * } ,
ui :: {
component :: * , utility :: * ,
collatable_container :: { * , collation_menu :: sort_button :: * } } ,
utility :: * ,
} ;
pub struct FilmCollationMenu {
widget : Box ,
sorting : & 'static RefCell < ( FilmsSortedBy , SortingDirection ) > ,
}
pub struct FilmCollationMenu { widget : Box }
pub struct SeriesCollationMenu { widget : Box }
impl FilmCollationMenu {
pub fn new < F : Fn ( FilmsSortedBy , SortingDirection ) + 'static > ( on_sort : F ) -> Self {
let widget = Box :: builder ()
. orientation (Horizontal)
. halign (Center)
. spacing (20)
. name ("film-collation-menu")
. css_classes ( ["toolbar"] )
. build () ;
let sorting = leak ( RefCell :: new ( ( FilmsSortedBy :: Name , SortingDirection :: Ascending ) ) ) ;
let film_sort_button = FilmSortButton :: new (on_sort) ;
widget . append ( & create_sort_button ( & create_films_sort_menu ( sorting , on_sort ) ) ) ;
widget . append ( & create_filter_button () ) ;
let widget = g_box ! (
@ orientation : Horizontal ,
@ halign : Center ,
@ spacing : 20 ,
@ widget_name : "film-collation-menu" ,
@ css_classes : [ "toolbar" ] ,
* film_sort_button . get_widget ()
) ;
Self { widget , sorting }
Self { widget }
}
}
impl SeriesCollationMenu {
@ -126,12 +123,12 @@ fn create_sort_menu_entry ( label : & str , reverse : bool ) -> ListBoxRow {
let container = g_box ! (
@ orientation : Horizontal ,
& Label :: builder ()
Label :: builder ()
. label (label)
. hexpand (true)
. halign (Start)
. build () ,
& icon ,
icon ,
) ;
container . set_spacing (20) ;

View file

@ -1,18 +1,71 @@
use libadwaita :: * ;
use { gtk4 :: Align :: * , libadwaita :: * , std :: cell :: * } ;
use crate :: ui :: { * , utility :: * } ;
use crate :: { utility :: * , ui :: { * , utility :: * } } ;
pub struct FilmSortButton { widget : SplitButton }
pub struct FilmSortButton {
widget : SplitButton ,
previous_sorting : & 'static RefCell < ( FilmsSortedBy , SortingDirection ) > ,
}
impl FilmSortButton {
pub fn new () -> Self {
let widget = SplitButton :: builder ()
. child ( & label ! ("Sort") )
. build () ;
pub fn new < F : Fn ( FilmsSortedBy , SortingDirection ) + 'static > ( on_sort : F ) -> Self {
let list_box = list_box ! (
g_box ! (
@ orientation : Horizontal , @ spacing : 20 ,
label ! ( @ hexpand : true , @ halign : Start , "Name" ) ,
icon ! ("view-sort-ascending-symbolic") ,
) ,
g_box ! (
@ orientation : Horizontal , @ spacing : 20 ,
label ! ( @ hexpand : true , @ halign : Start , "Release date" ) ,
icon ! ("view-sort-ascending-symbolic") ,
) ,
g_box ! (
@ orientation : Horizontal , @ spacing : 20 ,
label ! ( @ hexpand : true , @ halign : Start , "Runtime" ) ,
icon ! ("view-sort-ascending-symbolic") ,
) ,
) ;
Self { widget }
let widget = split_button ! (
@ popover : popover ! ( @ css_classes : [ "menu" ] , list_box ) ,
label ! ("Sort") ,
) ;
let previous_sorting = leak ( RefCell :: new (
( FilmsSortedBy :: Name , SortingDirection :: Ascending )
) ) ;
list_box . connect_row_activated ( move | _ , row | {
let sorting_property = match row . index () {
0 => FilmsSortedBy :: Name ,
1 => FilmsSortedBy :: ReleaseDate ,
2 => FilmsSortedBy :: Runtime ,
_ => panic ! () ,
} ;
let previous_sorting_property = previous_sorting . borrow () . 0 ;
if sorting_property == previous_sorting_property {
let previous_sorting_direction = previous_sorting . borrow () . 1 ;
match previous_sorting_direction {
SortingDirection :: Ascending => {
previous_sorting . replace ( ( sorting_property , SortingDirection :: Descending ) ) ;
on_sort ( sorting_property , SortingDirection :: Descending ) ;
} ,
SortingDirection :: Descending => {
previous_sorting . replace ( ( sorting_property , SortingDirection :: Ascending ) ) ;
on_sort ( sorting_property , SortingDirection :: Ascending ) ;
} ,
}
} else {
previous_sorting . replace ( ( sorting_property , SortingDirection :: Ascending ) ) ;
on_sort ( sorting_property , SortingDirection :: Ascending ) ;
}
} ) ;
Self { widget , previous_sorting }
}
}

View file

@ -6,18 +6,19 @@ use gtk4 :: { * , Orientation :: * , prelude :: * } ;
use crate :: {
collection :: * ,
ui :: {
component :: * , utility :: * ,
collatable_container :: { collated_grid :: * , collation_menu :: * } ,
component :: * ,
utility :: * ,
} ,
utility :: * ,
} ;
# [ derive (PartialEq) ] pub enum FilmsSortedBy { Name , ReleaseDate , Runtime }
# [ derive (PartialEq) ] pub enum SeriesSortedBy { Name , FirstReleaseDate }
# [ derive (PartialEq) ] pub enum SortingDirection { Ascending , Descending }
# [ derive ( Clone , Copy , PartialEq ) ] pub enum FilmsSortedBy { Name , ReleaseDate , Runtime }
# [ derive ( Clone , Copy , PartialEq ) ] pub enum SeriesSortedBy { Name , FirstReleaseDate }
# [ derive ( Clone , Copy , PartialEq ) ] pub enum SortingDirection { Ascending , Descending }
pub struct FilmSorting { property : FilmsSortedBy , direction : SortingDirection }
pub struct CollatableFilmsContainer {
collated_grid : & 'static CollatedFilmsGrid ,
@ -37,8 +38,8 @@ impl CollatableFilmsContainer {
let widget = g_box ! (
@ orientation : Vertical ,
film_collation_menu . get_widget () ,
& create_collection_scrolled_window ( collated_grid . get_widget () ) ,
* film_collation_menu . get_widget () ,
create_collection_scrolled_window ( collated_grid . get_widget () ) ,
) ;
Self { collated_grid , widget }
@ -58,8 +59,8 @@ impl CollatableSeriesContainer {
let widget = g_box ! (
@ orientation : Vertical ,
series_collation_menu . get_widget () ,
& create_collection_scrolled_window ( collated_grid . get_widget () ) ,
* series_collation_menu . get_widget () ,
create_collection_scrolled_window ( collated_grid . get_widget () ) ,
) ;
Self { collated_grid , widget }
@ -79,7 +80,7 @@ impl Component <Box> for CollatableSeriesContainer {
fn create_collection_scrolled_window ( child : & FlowBox ) -> ScrolledWindow {
ScrolledWindow :: builder ()
. child ( & vertically_filling ! (child) )
. child ( & vertically_filling ! ( * child ) )
. propagate_natural_height (true)
. build ()
}

View file

@ -3,24 +3,34 @@ macro_rules ! label { (
$ ( @ vexpand : $ vexpand : expr , ) ?
$ ( @ halign : $ halign : expr , ) ?
$ ( @ valign : $ valign : expr , ) ?
$ ( $ label : expr ) ? $ (,) ?
$ label : expr $ (,) ?
) => { {
let label = gtk4 :: Label :: builder () . build () ;
$ ( label . set_hexpand ( $ hexpand ) ; ) ?
$ ( label . set_vexpand ( $ vexpand ) ; ) ?
$ ( label . set_halign ( $ halign ) ; ) ?
$ ( label . set_valign ( $ valign ) ; ) ?
$ ( label . set_label ( $ label ) ; ) ?
label . set_label ( $ label ) ;
label
} } }
macro_rules ! g_box { (
$ ( @ orientation : $ orientation : expr , ) ?
$ ( $ child : expr ) , * $ (,) ?
$ ( @ halign : $ halign : expr , ) ?
$ ( @ valign : $ valign : expr , ) ?
$ ( @ spacing : $ spacing : expr , ) ?
$ ( @ widget_name : $ widget_name : expr , ) ?
$ ( @ css_classes : $ css_classes : expr , ) ?
$ ( $ child : expr ) , + $ (,) ?
) => { {
let container = gtk4 :: Box :: builder () . build () ;
$ ( container . set_orientation ( $ orientation ) ; ) ?
$ ( container . append ( $ child ) ; ) *
$ ( container . set_halign ( $ halign ) ; ) ?
$ ( container . set_valign ( $ valign ) ; ) ?
$ ( container . set_spacing ( $ spacing ) ; ) ?
$ ( container . set_widget_name ( & $ widget_name ) ; ) ?
$ ( container . set_css_classes ( & $ css_classes ) ; ) ?
$ ( container . append ( & $ child ) ; ) *
container
} } }
@ -32,17 +42,41 @@ macro_rules ! view_stack { (
container
} } }
macro_rules ! list_box { ( $ ( $ child : expr , ) * ) => { {
macro_rules ! list_box { ( $ ( $ child : expr ) , * $ (,) ? ) => { {
let container = gtk4 :: ListBox :: new () ;
$ ( container . append ( $ child ) ; ) *
$ ( container . append ( & $ child ) ; ) *
container
} } }
macro_rules ! split_button { (
$ ( @ popover : $ popover : expr , ) ?
$ child : expr $ (,) ?
) => { {
let widget = libadwaita :: SplitButton :: new () ;
$ ( widget . set_popover ( Some ( & $ popover ) ) ; ) ?
widget . set_child ( Some ( & $ child ) ) ;
widget
} } }
macro_rules ! popover { (
$ ( @ css_classes : $ css_classes : expr , ) ?
$ child : expr $ (,) ?
) => { {
let widget = gtk4 :: Popover :: new () ;
$ ( widget . set_css_classes ( & $ css_classes ) ; ) ?
widget . set_child ( Some ( & $ child ) ) ;
widget
} } }
macro_rules ! icon { ( $ icon_name : expr ) => {
gtk4 :: Image :: from_icon_name ( $ icon_name )
} }
macro_rules ! vertically_filling { ( $ child : expr ) => {
g_box ! (
@ orientation : gtk4 :: Orientation :: Vertical ,
$ child ,
& libadwaita :: Bin :: builder ()
libadwaita :: Bin :: builder ()
. css_name ("filler")
. vexpand (true)
. build () ,
@ -56,5 +90,8 @@ pub (crate) use {
g_box ,
view_stack ,
list_box ,
split_button ,
popover ,
icon ,
vertically_filling ,
} ;