mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 03:47:23 +01:00
Handle current item on playlist page
This commit is contained in:
parent
7d21617e9a
commit
7110401f61
8 changed files with 83 additions and 32 deletions
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
adw = { package = "libadwaita", version = "0.5", features = ["v1_4"] }
|
||||
chrono = "0.4"
|
||||
gettext-rs = { version = "0.7", features = ["gettext-system"] }
|
||||
gtk = { package = "gtk4", version = "0.7", features = ["v4_10", "blueprint"] }
|
||||
gtk = { package = "gtk4", version = "0.7", features = ["v4_12", "blueprint"] }
|
||||
log = "0.4"
|
||||
once_cell = "1"
|
||||
rand = "0.8"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ template $MusicusPlaylistPage : Adw.Bin {
|
|||
Gtk.ScrolledWindow {
|
||||
hscrollbar-policy: never;
|
||||
|
||||
Adw.Clamp {
|
||||
Adw.ClampScrollable {
|
||||
maximum-size: 1000;
|
||||
tightening-threshold: 600;
|
||||
|
||||
|
|
@ -30,6 +30,7 @@ template $MusicusPlaylistPage : Adw.Bin {
|
|||
margin-start: 12;
|
||||
margin-end: 12;
|
||||
single-click-activate: true;
|
||||
activate => $select_item() swapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ template $MusicusPlaylistTile : Gtk.Box {
|
|||
styles ["playlisttile"]
|
||||
|
||||
Adw.Bin {
|
||||
valign: end;
|
||||
margin-bottom: 12;
|
||||
width-request: 48;
|
||||
|
||||
Gtk.Image playing_icon {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,26 @@ mod imp {
|
|||
pub playing: Cell<bool>,
|
||||
#[property(get, construct_only)]
|
||||
pub playlist: OnceCell<gio::ListStore>,
|
||||
#[property(get, set)]
|
||||
#[property(get, set = Self::set_current_index)]
|
||||
pub current_index: Cell<u32>,
|
||||
}
|
||||
|
||||
impl MusicusPlayer {
|
||||
pub fn set_current_index(&self, index: u32) {
|
||||
let playlist = self.playlist.get().unwrap();
|
||||
|
||||
if let Some(item) = playlist.item(self.current_index.get()) {
|
||||
item.downcast::<PlaylistItem>().unwrap().set_is_playing(false);
|
||||
}
|
||||
|
||||
self.current_index.set(index);
|
||||
|
||||
if let Some(item) = playlist.item(index) {
|
||||
item.downcast::<PlaylistItem>().unwrap().set_is_playing(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for MusicusPlayer {
|
||||
const NAME: &'static str = "MusicusPlayer";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use gtk::{glib, glib::Properties, prelude::*, subclass::prelude::*};
|
||||
use std::{
|
||||
cell::OnceCell,
|
||||
cell::{Cell, OnceCell},
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
|
|
@ -10,6 +10,9 @@ mod imp {
|
|||
#[derive(Properties, Default)]
|
||||
#[properties(wrapper_type = super::PlaylistItem)]
|
||||
pub struct PlaylistItem {
|
||||
#[property(get, set)]
|
||||
pub is_playing: Cell<bool>,
|
||||
|
||||
#[property(get, construct_only)]
|
||||
pub is_title: OnceCell<bool>,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{player::MusicusPlayer, playlist_tile::PlaylistTile};
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{glib, glib::subclass::Signal, glib::Properties, prelude::*};
|
||||
use gtk::{glib, glib::subclass::Signal, glib::Properties, prelude::*, ListScrollFlags};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::cell::OnceCell;
|
||||
|
||||
|
|
@ -10,7 +10,7 @@ mod imp {
|
|||
use super::*;
|
||||
|
||||
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
|
||||
#[properties(wrapper_type = super::MusicusPlayer)]
|
||||
#[properties(wrapper_type = super::MusicusPlaylistPage)]
|
||||
#[template(file = "data/ui/playlist_page.blp")]
|
||||
pub struct MusicusPlaylistPage {
|
||||
#[property(get, construct_only)]
|
||||
|
|
@ -63,7 +63,13 @@ mod imp {
|
|||
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||
let tile = item.child().and_downcast::<PlaylistTile>().unwrap();
|
||||
let playlist_item = item.item().and_downcast::<PlaylistItem>().unwrap();
|
||||
tile.set_item(&playlist_item);
|
||||
tile.set_item(Some(&playlist_item));
|
||||
});
|
||||
|
||||
factory.connect_unbind(|_, item| {
|
||||
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
||||
let tile = item.child().and_downcast::<PlaylistTile>().unwrap();
|
||||
tile.set_item(None);
|
||||
});
|
||||
|
||||
self.playlist.set_factory(Some(&factory));
|
||||
|
|
@ -93,6 +99,15 @@ impl MusicusPlaylistPage {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn scroll_to_current(&self) {
|
||||
self.imp().playlist.scroll_to(self.player().current_index(), ListScrollFlags::NONE, None);
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn select_item(&self, index: u32, _: >k::ListView) {
|
||||
self.player().set_current_index(index);
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn close(&self, _: >k::Button) {
|
||||
self.emit_by_name::<()>("close", &[]);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::playlist_item::PlaylistItem;
|
||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
||||
use std::cell::RefCell;
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
|
@ -15,6 +16,8 @@ mod imp {
|
|||
pub performances_label: TemplateChild<gtk::Label>,
|
||||
#[template_child]
|
||||
pub part_title_label: TemplateChild<gtk::Label>,
|
||||
|
||||
pub binding: RefCell<Option<glib::Binding>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
|
@ -47,28 +50,36 @@ impl PlaylistTile {
|
|||
glib::Object::new()
|
||||
}
|
||||
|
||||
pub fn set_item(&self, item: &PlaylistItem) {
|
||||
pub fn set_item(&self, item: Option<&PlaylistItem>) {
|
||||
let imp = self.imp();
|
||||
|
||||
if let Some(title) = item.title() {
|
||||
imp.title_label.set_label(&title);
|
||||
imp.title_label.set_visible(true);
|
||||
if let Some(binding) = &*imp.binding.borrow() {
|
||||
binding.unbind();
|
||||
}
|
||||
|
||||
if let Some(performances) = item.performers() {
|
||||
imp.performances_label.set_label(&performances);
|
||||
imp.performances_label.set_visible(true);
|
||||
}
|
||||
if let Some(item) = item {
|
||||
if let Some(title) = item.title() {
|
||||
imp.title_label.set_label(&title);
|
||||
imp.title_label.set_visible(true);
|
||||
}
|
||||
|
||||
if let Some(part_title) = item.part_title() {
|
||||
imp.part_title_label.set_label(&part_title);
|
||||
imp.part_title_label.set_visible(true);
|
||||
} else {
|
||||
imp.obj().set_margin_bottom(24);
|
||||
}
|
||||
}
|
||||
if let Some(performances) = item.performers() {
|
||||
imp.performances_label.set_label(&performances);
|
||||
imp.performances_label.set_visible(true);
|
||||
}
|
||||
|
||||
pub fn set_playing(&self, playing: bool) {
|
||||
self.imp().playing_icon.set_visible(playing);
|
||||
if let Some(part_title) = item.part_title() {
|
||||
imp.part_title_label.set_label(&part_title);
|
||||
imp.part_title_label.set_visible(true);
|
||||
} else {
|
||||
imp.obj().set_margin_bottom(24);
|
||||
}
|
||||
|
||||
imp.binding.replace(Some(
|
||||
item.bind_property("is-playing", &imp.playing_icon.get(), "visible")
|
||||
.sync_create()
|
||||
.build(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ use crate::{
|
|||
home_page::MusicusHomePage, library::MusicusLibrary, player::MusicusPlayer,
|
||||
playlist_page::MusicusPlaylistPage, welcome_page::MusicusWelcomePage,
|
||||
};
|
||||
|
||||
use adw::subclass::prelude::*;
|
||||
use gtk::{gio, glib, glib::clone, prelude::*};
|
||||
use std::cell::OnceCell;
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
|
@ -13,6 +13,7 @@ mod imp {
|
|||
#[template(file = "data/ui/window.blp")]
|
||||
pub struct MusicusWindow {
|
||||
pub player: MusicusPlayer,
|
||||
pub playlist_page: OnceCell<MusicusPlaylistPage>,
|
||||
|
||||
#[template_child]
|
||||
pub stack: TemplateChild<gtk::Stack>,
|
||||
|
|
@ -79,6 +80,7 @@ mod imp {
|
|||
});
|
||||
|
||||
self.stack.add_named(&playlist_page, Some("playlist"));
|
||||
self.playlist_page.set(playlist_page).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,12 +142,13 @@ impl MusicusWindow {
|
|||
|
||||
#[template_callback]
|
||||
fn show_playlist(&self, button: >k::ToggleButton) {
|
||||
self.imp()
|
||||
.stack
|
||||
.set_visible_child_name(if button.is_active() {
|
||||
"playlist"
|
||||
} else {
|
||||
"navigation"
|
||||
});
|
||||
let imp = self.imp();
|
||||
|
||||
if button.is_active() {
|
||||
imp.playlist_page.get().unwrap().scroll_to_current();
|
||||
imp.stack.set_visible_child_name("playlist");
|
||||
} else {
|
||||
imp.stack.set_visible_child_name("navigation");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue