musicus/src/program_tile.rs

132 lines
3.9 KiB
Rust
Raw Normal View History

2025-03-22 18:55:29 +01:00
use std::cell::{OnceCell, RefCell};
2024-04-01 18:43:00 +02:00
2024-06-09 16:26:37 +02:00
use gtk::{
2025-03-22 18:55:29 +01:00
gio,
glib::{self, clone, Properties},
2024-06-09 16:26:37 +02:00
prelude::*,
subclass::prelude::*,
};
2025-03-22 18:55:29 +01:00
use crate::{config, editor::program::ProgramEditor, program::Program};
2024-06-09 16:26:37 +02:00
2024-04-01 18:43:00 +02:00
mod imp {
use super::*;
2024-06-09 16:26:37 +02:00
#[derive(Properties, Debug, Default, gtk::CompositeTemplate)]
2025-03-01 09:57:01 +01:00
#[properties(wrapper_type = super::ProgramTile)]
2024-04-01 18:43:00 +02:00
#[template(file = "data/ui/program_tile.blp")]
2025-03-01 09:57:01 +01:00
pub struct ProgramTile {
2024-06-09 16:26:37 +02:00
#[property(get, construct_only)]
2025-03-22 18:55:29 +01:00
pub navigation: OnceCell<adw::NavigationView>,
#[property(get, construct_only)]
pub key: OnceCell<String>,
#[property(get, set = Self::set_program)]
pub program: RefCell<Program>,
2024-06-09 16:26:37 +02:00
2024-04-01 18:43:00 +02:00
#[template_child]
pub edit_button: TemplateChild<gtk::Button>,
#[template_child]
pub title_label: TemplateChild<gtk::Label>,
#[template_child]
pub description_label: TemplateChild<gtk::Label>,
}
#[glib::object_subclass]
2025-03-01 09:57:01 +01:00
impl ObjectSubclass for ProgramTile {
2024-04-01 18:43:00 +02:00
const NAME: &'static str = "MusicusProgramTile";
2025-03-01 09:57:01 +01:00
type Type = super::ProgramTile;
2024-04-01 18:43:00 +02:00
type ParentType = gtk::FlowBoxChild;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
2025-03-22 18:55:29 +01:00
klass.bind_template_instance_callbacks();
2024-04-01 18:43:00 +02:00
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
2024-06-09 16:26:37 +02:00
#[glib::derived_properties]
2025-03-22 18:55:29 +01:00
impl ObjectImpl for ProgramTile {
fn constructed(&self) {
self.parent_constructed();
let settings = gio::Settings::new(config::APP_ID);
self.set_program_from_settings(&settings);
let obj = self.obj().to_owned();
settings.connect_changed(Some(&self.key.get().unwrap()), move |settings, _| {
obj.imp().set_program_from_settings(settings);
});
}
}
2024-06-09 16:26:37 +02:00
2025-03-01 09:57:01 +01:00
impl WidgetImpl for ProgramTile {}
impl FlowBoxChildImpl for ProgramTile {}
2025-03-22 18:55:29 +01:00
impl ProgramTile {
fn set_program_from_settings(&self, settings: &gio::Settings) {
match Program::deserialize(&settings.string(self.key.get().unwrap())) {
Ok(program) => self.set_program(&program),
Err(err) => log::error!("Failed to deserialize program from settings: {err:?}"),
}
}
fn set_program(&self, program: &Program) {
2025-03-23 08:44:46 +01:00
self.obj().set_css_classes(&[
"program-tile",
"card",
"activatable",
&program.design().css_class(),
]);
2025-03-22 18:55:29 +01:00
if let Some(title) = program.title() {
self.title_label.set_label(&title);
}
if let Some(description) = program.description() {
self.description_label.set_label(&description);
}
self.program.replace(program.to_owned());
}
}
2024-04-01 18:43:00 +02:00
}
glib::wrapper! {
2025-03-01 09:57:01 +01:00
pub struct ProgramTile(ObjectSubclass<imp::ProgramTile>)
2024-04-01 18:43:00 +02:00
@extends gtk::Widget, gtk::FlowBoxChild;
}
2025-03-22 18:55:29 +01:00
#[gtk::template_callbacks]
2025-03-01 09:57:01 +01:00
impl ProgramTile {
2025-03-22 18:55:29 +01:00
pub fn new_for_setting(navigation: &adw::NavigationView, key: &str) -> Self {
2024-06-09 16:26:37 +02:00
let obj: Self = glib::Object::builder()
2025-03-22 18:55:29 +01:00
.property("navigation", navigation)
.property("key", key)
2024-06-09 16:26:37 +02:00
.build();
obj
}
2025-03-22 18:55:29 +01:00
#[template_callback]
fn edit_button_clicked(&self) {
let editor = ProgramEditor::new(&self.navigation(), Some(&self.program()));
editor.connect_save(clone!(
#[weak(rename_to = obj)]
self,
move |_, program| {
let settings = gio::Settings::new(config::APP_ID);
if let Err(err) = settings.set_string(&obj.key(), &program.serialize()) {
log::error!("Failed to save program to settings: {err:?}");
};
obj.set_program(&program);
}
));
self.navigation().push(&editor);
}
2024-04-01 18:43:00 +02:00
}