diff --git a/resources/album_carousel.blp b/resources/album_carousel.blp new file mode 100644 index 0000000..eaaa1f5 --- /dev/null +++ b/resources/album_carousel.blp @@ -0,0 +1,110 @@ +using Gtk 4.0; +using Adw 1; + +template $AudreyUiAlbumCarousel: Adw.Bin { + styles [ "album-carousel" ] + + child: Box { + orientation: vertical; + + Box { + margin-start: 12; + spacing: 6; + height-request: 42; + + Label { + label: bind template.title; + styles [ "title-2" ] + } + + Button { + valign: center; + icon-name: "view-refresh-symbolic"; + styles [ "circular", "flat" ] + } + + Box { + halign: end; + hexpand: true; + valign: center; + + Button { + icon-name: "go-previous-symbolic"; + styles [ "flat" ] + } + + Button { + icon-name: "go-next-symbolic"; + styles [ "flat" ] + } + } + } + + Separator { styles [ "spacer" ] } + + ScrolledWindow { + hexpand: true; + vscrollbar-policy: never; + hscrollbar-policy: external; + + child: ListView { + orientation: horizontal; + + styles [ + "albums" + ] + + single-click-activate: true; + + model: NoSelection { + model: bind template.model; + }; + + factory: BuilderListItemFactory { + template ListItem { + child: Box { + orientation: vertical; + margin-bottom: 6; + spacing: 6; + + Image { + icon-name: "media-optical-cd"; + pixel-size: 160; + halign: center; + hexpand: false; + } + + Box { + styles [ "labels" ] + orientation: vertical; + homogeneous: true; + + Label { + label: bind template.item as .string; + ellipsize: end; + xalign: 0; + margin-start: 6; + + styles [ + "heading" + ] + } + + Label { + label: bind template.item as .string; + ellipsize: end; + xalign: 0; + margin-start: 6; + + styles [ + "caption" + ] + } + } + }; + } + }; + }; + } + }; +} diff --git a/resources/audrey.gresource.xml b/resources/audrey.gresource.xml index 911af81..99d581c 100644 --- a/resources/audrey.gresource.xml +++ b/resources/audrey.gresource.xml @@ -7,6 +7,7 @@ style.css gtk/help-overlay.ui + album_carousel.ui play_queue.ui play_queue_song.ui playbar.ui diff --git a/resources/meson.build b/resources/meson.build index 57c1863..763eb97 100644 --- a/resources/meson.build +++ b/resources/meson.build @@ -1,6 +1,7 @@ blueprints = custom_target( 'blueprints', input: files( + 'album_carousel.blp', 'play_queue.blp', 'play_queue_song.blp', 'playbar.blp', @@ -8,6 +9,7 @@ blueprints = custom_target( 'window.blp', ), output: [ + 'album_carousel.ui', 'play_queue.ui', 'play_queue_song.ui', 'playbar.ui', diff --git a/resources/style.css b/resources/style.css index 3a092fb..d492c9f 100644 --- a/resources/style.css +++ b/resources/style.css @@ -77,3 +77,28 @@ gridview.albums child image { border-radius: 10px; box-shadow: rgba(0, 0, 0, 0.6) 0px 0px 7px; } + +/* album carousel */ +.album-carousel listview { + background-color: rgba(0,0,0,0); +} + +.album-carousel listview row { + padding-left: 10px; + padding-right: 10px; +} + +.album-carousel listview row image { + border-radius: 3px; + background-color: #000; +} + +.album-carousel .labels { + border-radius: 3px; + background: + linear-gradient( + 150deg, + color-mix(in srgb, var(--background-color-1) 16%, transparent), + color-mix(in srgb, var(--background-color-2) 16%, transparent) 50%); + box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 3px; +} diff --git a/resources/window.blp b/resources/window.blp index c54e16f..b5022b3 100644 --- a/resources/window.blp +++ b/resources/window.blp @@ -37,101 +37,30 @@ template $AudreyUiWindow: Adw.ApplicationWindow { icon-name: "folder-music-symbolic"; title: _("Browse"); - child: Adw.NavigationView { - Adw.NavigationPage { - title: _("Browse"); - vexpand: true; + child: ScrolledWindow { + child: Box { + orientation: vertical; - child: Adw.ToolbarView { - [top] - CenterBox { - styles [ - "toolbar" - ] + $AudreyUiAlbumCarousel { + title: _("Most played"); + model: StringList { strings [ "a", "b", "c", "d", "e", "f" ] }; + } - [start] - DropDown { - selected: 0; + $AudreyUiAlbumCarousel { + title: _("Explore from your library"); + model: StringList { strings [ "a", "b", "c", "d", "e", "f" ] }; + } - model: StringList { - strings [ - _("Random"), - _("Recently added"), - _("Most played"), - _("Recently played"), - _("Starred"), - _("Name"), - _("Artist"), - ] - }; - } + $AudreyUiAlbumCarousel { + title: _("Newly added releases"); + model: StringList { strings [ "a", "b", "c", "d", "e", "f" ] }; + } - [center] - SearchEntry { - placeholder-text: _("Search..."); - } - - [end] - Box { - Button { - sensitive: bind template.refreshing-albums inverted; - icon-name: "view-refresh"; - clicked => $on_refresh_albums_clicked() swapped; - } - } - } - - ScrolledWindow { - vexpand: true; - - GridView { - styles [ - "albums" - ] - - single-click-activate: true; - - model: NoSelection { - model: bind template.albums-model; - }; - - factory: BuilderListItemFactory { - template ListItem { - child: Box { - orientation: vertical; - margin-bottom: 6; - - Image { - icon-name: "media-optical-cd"; - pixel-size: 160; - halign: center; - hexpand: false; - } - - Label { - label: bind template.item as <$AudreyModelAlbum>.name; - ellipsize: end; - - styles [ - "heading" - ] - } - - Label { - label: bind template.item as <$AudreyModelAlbum>.artist; - ellipsize: end; - - styles [ - "caption" - ] - } - }; - } - }; - } - } - }; - } + $AudreyUiAlbumCarousel { + title: _("Recently played"); + model: StringList { strings [ "a", "b", "c", "d", "e", "f" ] }; + } + }; }; } diff --git a/src/ui.rs b/src/ui.rs index ca23d3a..567b4c1 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -9,3 +9,6 @@ pub use setup::Setup; pub mod play_queue; pub use play_queue::PlayQueue; + +pub mod album_carousel; +pub use album_carousel::AlbumCarousel; diff --git a/src/ui/album_carousel.rs b/src/ui/album_carousel.rs new file mode 100644 index 0000000..ac76463 --- /dev/null +++ b/src/ui/album_carousel.rs @@ -0,0 +1,52 @@ +use adw::prelude::*; +use adw::subclass::prelude::*; +use adw::{gio, glib}; +use glib::subclass::InitializingObject; +use std::cell::RefCell; + +mod imp { + use super::*; + + #[derive(glib::Properties, gtk::CompositeTemplate, Default)] + #[properties(wrapper_type = super::AlbumCarousel)] + #[template(resource = "/eu/callcc/audrey/album_carousel.ui")] + pub struct AlbumCarousel { + #[property(get, set)] + title: RefCell, + + #[property(get, set)] + model: RefCell>, + } + + #[glib::object_subclass] + impl ObjectSubclass for AlbumCarousel { + const NAME: &'static str = "AudreyUiAlbumCarousel"; + type Type = super::AlbumCarousel; + type ParentType = adw::Bin; + + fn class_init(klass: &mut Self::Class) { + klass.bind_template(); + klass.bind_template_callbacks(); + } + + fn instance_init(obj: &InitializingObject) { + obj.init_template(); + } + } + + #[glib::derived_properties] + impl ObjectImpl for AlbumCarousel {} + + impl WidgetImpl for AlbumCarousel {} + + impl BinImpl for AlbumCarousel {} + + #[gtk::template_callbacks] + impl AlbumCarousel {} +} + +glib::wrapper! { + pub struct AlbumCarousel(ObjectSubclass) + @extends adw::Bin, gtk::Widget, + @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget; +} diff --git a/src/ui/window.rs b/src/ui/window.rs index 77bae49..73660de 100644 --- a/src/ui/window.rs +++ b/src/ui/window.rs @@ -163,6 +163,8 @@ mod imp { type ParentType = adw::ApplicationWindow; fn class_init(klass: &mut Self::Class) { + crate::ui::AlbumCarousel::ensure_type(); + klass.bind_template(); klass.bind_template_callbacks(); }