Reimplement collation menu as component
This commit is contained in:
parent
ebc8bc0d2f
commit
04755fabb7
4 changed files with 133 additions and 45 deletions
|
@ -3,8 +3,7 @@ mod sort_button ;
|
||||||
use {
|
use {
|
||||||
gtk4 :: {
|
gtk4 :: {
|
||||||
Box , Image , Label , ListBox , ListBoxRow , Popover ,
|
Box , Image , Label , ListBox , ListBoxRow , Popover ,
|
||||||
Align :: * ,
|
Align :: * , Orientation :: * ,
|
||||||
Orientation :: * ,
|
|
||||||
prelude :: * ,
|
prelude :: * ,
|
||||||
} ,
|
} ,
|
||||||
libadwaita :: * ,
|
libadwaita :: * ,
|
||||||
|
@ -12,33 +11,31 @@ use {
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
use crate :: {
|
use crate :: {
|
||||||
ui :: { collatable_container :: * , component :: * , utility :: * } ,
|
ui :: {
|
||||||
|
component :: * , utility :: * ,
|
||||||
|
collatable_container :: { * , collation_menu :: sort_button :: * } } ,
|
||||||
utility :: * ,
|
utility :: * ,
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pub struct FilmCollationMenu {
|
pub struct FilmCollationMenu { widget : Box }
|
||||||
widget : Box ,
|
|
||||||
sorting : & 'static RefCell < ( FilmsSortedBy , SortingDirection ) > ,
|
|
||||||
}
|
|
||||||
pub struct SeriesCollationMenu { widget : Box }
|
pub struct SeriesCollationMenu { widget : Box }
|
||||||
|
|
||||||
impl FilmCollationMenu {
|
impl FilmCollationMenu {
|
||||||
pub fn new < F : Fn ( FilmsSortedBy , SortingDirection ) + 'static > ( on_sort : F ) -> Self {
|
pub fn new < F : Fn ( FilmsSortedBy , SortingDirection ) + 'static > ( on_sort : F ) -> Self {
|
||||||
let widget = Box :: builder ()
|
let film_sort_button = FilmSortButton :: new (on_sort) ;
|
||||||
. orientation (Horizontal)
|
|
||||||
. halign (Center)
|
|
||||||
. spacing (20)
|
|
||||||
. name ("film-collation-menu")
|
|
||||||
. css_classes ( ["toolbar"] )
|
|
||||||
. build () ;
|
|
||||||
let sorting = leak ( RefCell :: new ( ( FilmsSortedBy :: Name , SortingDirection :: Ascending ) ) ) ;
|
|
||||||
|
|
||||||
widget . append ( & create_sort_button ( & create_films_sort_menu ( sorting , on_sort ) ) ) ;
|
let widget = g_box ! (
|
||||||
widget . append ( & create_filter_button () ) ;
|
@ 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 {
|
impl SeriesCollationMenu {
|
||||||
|
@ -126,12 +123,12 @@ fn create_sort_menu_entry ( label : & str , reverse : bool ) -> ListBoxRow {
|
||||||
|
|
||||||
let container = g_box ! (
|
let container = g_box ! (
|
||||||
@ orientation : Horizontal ,
|
@ orientation : Horizontal ,
|
||||||
& Label :: builder ()
|
Label :: builder ()
|
||||||
. label (label)
|
. label (label)
|
||||||
. hexpand (true)
|
. hexpand (true)
|
||||||
. halign (Start)
|
. halign (Start)
|
||||||
. build () ,
|
. build () ,
|
||||||
& icon ,
|
icon ,
|
||||||
) ;
|
) ;
|
||||||
container . set_spacing (20) ;
|
container . set_spacing (20) ;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
impl FilmSortButton {
|
||||||
pub fn new () -> Self {
|
pub fn new < F : Fn ( FilmsSortedBy , SortingDirection ) + 'static > ( on_sort : F ) -> Self {
|
||||||
let widget = SplitButton :: builder ()
|
let list_box = list_box ! (
|
||||||
. child ( & label ! ("Sort") )
|
g_box ! (
|
||||||
. build () ;
|
@ 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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,18 +6,19 @@ use gtk4 :: { * , Orientation :: * , prelude :: * } ;
|
||||||
use crate :: {
|
use crate :: {
|
||||||
collection :: * ,
|
collection :: * ,
|
||||||
ui :: {
|
ui :: {
|
||||||
|
component :: * , utility :: * ,
|
||||||
collatable_container :: { collated_grid :: * , collation_menu :: * } ,
|
collatable_container :: { collated_grid :: * , collation_menu :: * } ,
|
||||||
component :: * ,
|
|
||||||
utility :: * ,
|
|
||||||
} ,
|
} ,
|
||||||
utility :: * ,
|
utility :: * ,
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [ derive (PartialEq) ] pub enum FilmsSortedBy { Name , ReleaseDate , Runtime }
|
# [ derive ( Clone , Copy , PartialEq ) ] pub enum FilmsSortedBy { Name , ReleaseDate , Runtime }
|
||||||
# [ derive (PartialEq) ] pub enum SeriesSortedBy { Name , FirstReleaseDate }
|
# [ derive ( Clone , Copy , PartialEq ) ] pub enum SeriesSortedBy { Name , FirstReleaseDate }
|
||||||
# [ derive (PartialEq) ] pub enum SortingDirection { Ascending , Descending }
|
# [ derive ( Clone , Copy , PartialEq ) ] pub enum SortingDirection { Ascending , Descending }
|
||||||
|
|
||||||
|
pub struct FilmSorting { property : FilmsSortedBy , direction : SortingDirection }
|
||||||
|
|
||||||
pub struct CollatableFilmsContainer {
|
pub struct CollatableFilmsContainer {
|
||||||
collated_grid : & 'static CollatedFilmsGrid ,
|
collated_grid : & 'static CollatedFilmsGrid ,
|
||||||
|
@ -37,8 +38,8 @@ impl CollatableFilmsContainer {
|
||||||
|
|
||||||
let widget = g_box ! (
|
let widget = g_box ! (
|
||||||
@ orientation : Vertical ,
|
@ orientation : Vertical ,
|
||||||
film_collation_menu . get_widget () ,
|
* film_collation_menu . get_widget () ,
|
||||||
& create_collection_scrolled_window ( collated_grid . get_widget () ) ,
|
create_collection_scrolled_window ( collated_grid . get_widget () ) ,
|
||||||
) ;
|
) ;
|
||||||
|
|
||||||
Self { collated_grid , widget }
|
Self { collated_grid , widget }
|
||||||
|
@ -58,8 +59,8 @@ impl CollatableSeriesContainer {
|
||||||
|
|
||||||
let widget = g_box ! (
|
let widget = g_box ! (
|
||||||
@ orientation : Vertical ,
|
@ orientation : Vertical ,
|
||||||
series_collation_menu . get_widget () ,
|
* series_collation_menu . get_widget () ,
|
||||||
& create_collection_scrolled_window ( collated_grid . get_widget () ) ,
|
create_collection_scrolled_window ( collated_grid . get_widget () ) ,
|
||||||
) ;
|
) ;
|
||||||
|
|
||||||
Self { collated_grid , widget }
|
Self { collated_grid , widget }
|
||||||
|
@ -79,7 +80,7 @@ impl Component <Box> for CollatableSeriesContainer {
|
||||||
|
|
||||||
fn create_collection_scrolled_window ( child : & FlowBox ) -> ScrolledWindow {
|
fn create_collection_scrolled_window ( child : & FlowBox ) -> ScrolledWindow {
|
||||||
ScrolledWindow :: builder ()
|
ScrolledWindow :: builder ()
|
||||||
. child ( & vertically_filling ! (child) )
|
. child ( & vertically_filling ! ( * child ) )
|
||||||
. propagate_natural_height (true)
|
. propagate_natural_height (true)
|
||||||
. build ()
|
. build ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,24 +3,34 @@ macro_rules ! label { (
|
||||||
$ ( @ vexpand : $ vexpand : expr , ) ?
|
$ ( @ vexpand : $ vexpand : expr , ) ?
|
||||||
$ ( @ halign : $ halign : expr , ) ?
|
$ ( @ halign : $ halign : expr , ) ?
|
||||||
$ ( @ valign : $ valign : expr , ) ?
|
$ ( @ valign : $ valign : expr , ) ?
|
||||||
$ ( $ label : expr ) ? $ (,) ?
|
$ label : expr $ (,) ?
|
||||||
) => { {
|
) => { {
|
||||||
let label = gtk4 :: Label :: builder () . build () ;
|
let label = gtk4 :: Label :: builder () . build () ;
|
||||||
$ ( label . set_hexpand ( $ hexpand ) ; ) ?
|
$ ( label . set_hexpand ( $ hexpand ) ; ) ?
|
||||||
$ ( label . set_vexpand ( $ vexpand ) ; ) ?
|
$ ( label . set_vexpand ( $ vexpand ) ; ) ?
|
||||||
$ ( label . set_halign ( $ halign ) ; ) ?
|
$ ( label . set_halign ( $ halign ) ; ) ?
|
||||||
$ ( label . set_valign ( $ valign ) ; ) ?
|
$ ( label . set_valign ( $ valign ) ; ) ?
|
||||||
$ ( label . set_label ( $ label ) ; ) ?
|
label . set_label ( $ label ) ;
|
||||||
label
|
label
|
||||||
} } }
|
} } }
|
||||||
|
|
||||||
macro_rules ! g_box { (
|
macro_rules ! g_box { (
|
||||||
$ ( @ orientation : $ orientation : expr , ) ?
|
$ ( @ 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 () ;
|
let container = gtk4 :: Box :: builder () . build () ;
|
||||||
$ ( container . set_orientation ( $ orientation ) ; ) ?
|
$ ( 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
|
container
|
||||||
} } }
|
} } }
|
||||||
|
|
||||||
|
@ -32,17 +42,41 @@ macro_rules ! view_stack { (
|
||||||
container
|
container
|
||||||
} } }
|
} } }
|
||||||
|
|
||||||
macro_rules ! list_box { ( $ ( $ child : expr , ) * ) => { {
|
macro_rules ! list_box { ( $ ( $ child : expr ) , * $ (,) ? ) => { {
|
||||||
let container = gtk4 :: ListBox :: new () ;
|
let container = gtk4 :: ListBox :: new () ;
|
||||||
$ ( container . append ( $ child ) ; ) *
|
$ ( container . append ( & $ child ) ; ) *
|
||||||
container
|
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 ) => {
|
macro_rules ! vertically_filling { ( $ child : expr ) => {
|
||||||
g_box ! (
|
g_box ! (
|
||||||
@ orientation : gtk4 :: Orientation :: Vertical ,
|
@ orientation : gtk4 :: Orientation :: Vertical ,
|
||||||
$ child ,
|
$ child ,
|
||||||
& libadwaita :: Bin :: builder ()
|
libadwaita :: Bin :: builder ()
|
||||||
. css_name ("filler")
|
. css_name ("filler")
|
||||||
. vexpand (true)
|
. vexpand (true)
|
||||||
. build () ,
|
. build () ,
|
||||||
|
@ -56,5 +90,8 @@ pub (crate) use {
|
||||||
g_box ,
|
g_box ,
|
||||||
view_stack ,
|
view_stack ,
|
||||||
list_box ,
|
list_box ,
|
||||||
|
split_button ,
|
||||||
|
popover ,
|
||||||
|
icon ,
|
||||||
vertically_filling ,
|
vertically_filling ,
|
||||||
} ;
|
} ;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue