mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
player screen: Improve playlist visuals
This commit is contained in:
parent
ee8399e93d
commit
b050a7f0ea
5 changed files with 150 additions and 55 deletions
|
|
@ -17,6 +17,7 @@
|
|||
<file preprocess="xml-stripblanks">ui/selector.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/source_selector.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/track_editor.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/track_row.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/track_selector.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/track_set_editor.ui</file>
|
||||
<file preprocess="xml-stripblanks">ui/work_editor.ui</file>
|
||||
|
|
|
|||
65
musicus/res/ui/track_row.ui
Normal file
65
musicus/res/ui/track_row.ui
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<interface>
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="GtkListBoxRow" id="widget">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="margin-top">12</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<child>
|
||||
<object class="GtkRevealer" id="playing_revealer">
|
||||
<child>
|
||||
<object class="GtkImage" id="playing_image">
|
||||
<property name="icon-name">media-playback-start-symbolic</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-start">12</property>
|
||||
<property name="margin-end">18</property>
|
||||
<property name="valign">start</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="hexpand">true</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="header_box">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="visible">false</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
<child>
|
||||
<object class="GtkLabel" id="work_title_label">
|
||||
<property name="wrap">true</property>
|
||||
<property name="xalign">0.0</property>
|
||||
<attributes>
|
||||
<attribute name="weight" value="bold"/>
|
||||
</attributes>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="performances_label">
|
||||
<property name="wrap">true</property>
|
||||
<property name="xalign">0.0</property>
|
||||
<style>
|
||||
<class name="subtitle"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="track_title_label">
|
||||
<property name="wrap">true</property>
|
||||
<property name="xalign">0.0</property>
|
||||
<property name="margin-bottom">12</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::navigator::{NavigationHandle, Screen};
|
||||
use crate::widgets::{List, Widget};
|
||||
use crate::widgets::{List, TrackRow, Widget};
|
||||
use adw::prelude::*;
|
||||
use gettextrs::gettext;
|
||||
use glib::clone;
|
||||
use gtk_macros::get_widget;
|
||||
use musicus_backend::db::Track;
|
||||
|
|
@ -9,6 +8,7 @@ use std::cell::{Cell, RefCell};
|
|||
use std::rc::Rc;
|
||||
|
||||
/// Elements for visually representing the playlist.
|
||||
#[derive(Clone)]
|
||||
enum ListItem {
|
||||
/// A playable track.
|
||||
Track {
|
||||
|
|
@ -207,64 +207,36 @@ impl Screen<(), ()> for PlayerScreen {
|
|||
}
|
||||
}));
|
||||
|
||||
this.list.set_make_widget_cb(clone!(@weak this => @default-panic, move |index| {
|
||||
this.list
|
||||
.set_make_widget_cb(clone!(@weak this => @default-panic, move |index| {
|
||||
let widget = match this.items.borrow()[index] {
|
||||
ListItem::Track {index, first, playing} => {
|
||||
let track = &this.playlist.borrow()[index];
|
||||
|
||||
let mut parts = Vec::<String>::new();
|
||||
for part in &track.work_parts {
|
||||
parts.push(track.recording.work.parts[*part].title.clone());
|
||||
}
|
||||
|
||||
let title = if first {
|
||||
track.recording.work.get_title()
|
||||
} else if parts.is_empty() {
|
||||
gettext("Unknown")
|
||||
} else {
|
||||
parts.join(", ")
|
||||
};
|
||||
|
||||
let row = adw::ActionRowBuilder::new()
|
||||
.selectable(false)
|
||||
.activatable(true)
|
||||
.title(&title)
|
||||
.build();
|
||||
|
||||
if first {
|
||||
let subtitle = if !parts.is_empty() {
|
||||
format!("{}\n{}", track.recording.get_performers(), parts.join(", "))
|
||||
} else {
|
||||
track.recording.get_performers()
|
||||
};
|
||||
|
||||
row.set_subtitle(&subtitle);
|
||||
}
|
||||
|
||||
row.connect_activated(clone!(@weak this => move |_| {
|
||||
this.handle.backend.pl().set_track(index).unwrap();
|
||||
}));
|
||||
|
||||
let icon = if playing {
|
||||
Some("media-playback-start-symbolic")
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let image = gtk::Image::from_icon_name(icon);
|
||||
row.add_prefix(&image);
|
||||
|
||||
row.upcast()
|
||||
TrackRow::new(track, first, playing).get_widget()
|
||||
}
|
||||
ListItem::Separator => {
|
||||
let separator = gtk::Separator::new(gtk::Orientation::Horizontal);
|
||||
separator.upcast()
|
||||
gtk::ListBoxRowBuilder::new()
|
||||
.selectable(false)
|
||||
.activatable(false)
|
||||
.child(>k::Separator::new(gtk::Orientation::Horizontal))
|
||||
.build()
|
||||
.upcast()
|
||||
}
|
||||
};
|
||||
|
||||
widget
|
||||
}));
|
||||
|
||||
this.list
|
||||
.widget
|
||||
.connect_row_activated(clone!(@weak this => move |_, row| {
|
||||
let list_index = row.index();
|
||||
let list_item = this.items.borrow()[list_index as usize].clone();
|
||||
if let ListItem::Track {index, ..} = list_item {
|
||||
this.handle.backend.pl().set_track(index).unwrap();
|
||||
};
|
||||
}));
|
||||
|
||||
player.send_data();
|
||||
|
||||
this
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ pub use screen::*;
|
|||
pub mod section;
|
||||
pub use section::*;
|
||||
|
||||
pub mod track_row;
|
||||
pub use track_row::TrackRow;
|
||||
|
||||
mod indexed_list_model;
|
||||
|
||||
/// Something that can be represented as a GTK widget.
|
||||
|
|
|
|||
54
musicus/src/widgets/track_row.rs
Normal file
54
musicus/src/widgets/track_row.rs
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
use super::Widget;
|
||||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
use musicus_backend::db::Track;
|
||||
|
||||
/// A widget for showing a single track in a list.
|
||||
pub struct TrackRow {
|
||||
/// The actual GTK widget.
|
||||
pub widget: gtk::ListBoxRow,
|
||||
}
|
||||
|
||||
impl TrackRow {
|
||||
/// Create a new track row.
|
||||
pub fn new(track: &Track, show_header: bool, playing: bool) -> Self {
|
||||
let builder = gtk::Builder::from_resource("/de/johrpan/musicus/ui/track_row.ui");
|
||||
|
||||
get_widget!(builder, gtk::ListBoxRow, widget);
|
||||
get_widget!(builder, gtk::Revealer, playing_revealer);
|
||||
get_widget!(builder, gtk::Image, playing_image);
|
||||
get_widget!(builder, gtk::Box, header_box);
|
||||
get_widget!(builder, gtk::Label, work_title_label);
|
||||
get_widget!(builder, gtk::Label, performances_label);
|
||||
get_widget!(builder, gtk::Label, track_title_label);
|
||||
|
||||
playing_revealer.set_reveal_child(playing);
|
||||
|
||||
let mut parts = Vec::<&str>::new();
|
||||
for part in &track.work_parts {
|
||||
parts.push(&track.recording.work.parts[*part].title);
|
||||
}
|
||||
|
||||
if parts.is_empty() || show_header {
|
||||
work_title_label.set_text(&track.recording.work.get_title());
|
||||
performances_label.set_text(&track.recording.get_performers());
|
||||
header_box.show();
|
||||
} else {
|
||||
playing_image.set_margin_top(0);
|
||||
}
|
||||
|
||||
if !parts.is_empty() {
|
||||
track_title_label.set_text(&parts.join(", "));
|
||||
} else {
|
||||
track_title_label.hide();
|
||||
}
|
||||
|
||||
Self { widget }
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for TrackRow {
|
||||
fn get_widget(&self) -> gtk::Widget {
|
||||
self.widget.clone().upcast()
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue