mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
Implement program editor
This commit is contained in:
parent
fa94d61e1e
commit
8950b04ed2
8 changed files with 590 additions and 81 deletions
181
src/editor/program.rs
Normal file
181
src/editor/program.rs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
use std::{cell::OnceCell, str::FromStr};
|
||||
|
||||
use adw::{prelude::*, subclass::prelude::*};
|
||||
use gtk::{
|
||||
gio,
|
||||
glib::{self, subclass::Signal},
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::{
|
||||
program::{Program, ProgramDesign},
|
||||
slider_row::SliderRow,
|
||||
};
|
||||
|
||||
mod imp {
|
||||
use super::*;
|
||||
|
||||
#[derive(Debug, Default, gtk::CompositeTemplate)]
|
||||
#[template(file = "data/ui/editor/program.blp")]
|
||||
pub struct ProgramEditor {
|
||||
pub navigation: OnceCell<adw::NavigationView>,
|
||||
pub action_group: OnceCell<gio::SimpleActionGroup>,
|
||||
|
||||
#[template_child]
|
||||
pub title_row: TemplateChild<adw::EntryRow>,
|
||||
#[template_child]
|
||||
pub description_row: TemplateChild<adw::EntryRow>,
|
||||
#[template_child]
|
||||
pub prefer_least_recently_played_adjustment: TemplateChild<gtk::Adjustment>,
|
||||
#[template_child]
|
||||
pub prefer_recently_added_adjustment: TemplateChild<gtk::Adjustment>,
|
||||
#[template_child]
|
||||
pub avoid_repeated_composers_adjustment: TemplateChild<gtk::Adjustment>,
|
||||
#[template_child]
|
||||
pub avoid_repeated_instruments_adjustment: TemplateChild<gtk::Adjustment>,
|
||||
#[template_child]
|
||||
pub play_full_recordings_row: TemplateChild<adw::SwitchRow>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
impl ObjectSubclass for ProgramEditor {
|
||||
const NAME: &'static str = "MusicusProgramEditor";
|
||||
type Type = super::ProgramEditor;
|
||||
type ParentType = adw::NavigationPage;
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
SliderRow::static_type();
|
||||
klass.bind_template();
|
||||
klass.bind_template_instance_callbacks();
|
||||
}
|
||||
|
||||
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||
obj.init_template();
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for ProgramEditor {
|
||||
fn signals() -> &'static [Signal] {
|
||||
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
|
||||
vec![Signal::builder("save")
|
||||
.param_types([Program::static_type()])
|
||||
.build()]
|
||||
});
|
||||
|
||||
SIGNALS.as_ref()
|
||||
}
|
||||
|
||||
fn constructed(&self) {
|
||||
self.parent_constructed();
|
||||
|
||||
let set_design_action = gio::ActionEntry::builder("set-design")
|
||||
.parameter_type(Some(&glib::VariantTy::STRING))
|
||||
.state(glib::Variant::from("program-1"))
|
||||
.build();
|
||||
|
||||
let actions = gio::SimpleActionGroup::new();
|
||||
actions.add_action_entries([set_design_action]);
|
||||
self.obj().insert_action_group("program", Some(&actions));
|
||||
self.action_group.set(actions).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for ProgramEditor {}
|
||||
impl NavigationPageImpl for ProgramEditor {}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct ProgramEditor(ObjectSubclass<imp::ProgramEditor>)
|
||||
@extends gtk::Widget, adw::NavigationPage;
|
||||
}
|
||||
|
||||
#[gtk::template_callbacks]
|
||||
impl ProgramEditor {
|
||||
pub fn new(navigation: &adw::NavigationView, program: Option<&Program>) -> Self {
|
||||
let obj: Self = glib::Object::new();
|
||||
|
||||
if let Some(program) = program {
|
||||
if let Some(title) = program.title() {
|
||||
obj.imp().title_row.set_text(&title);
|
||||
}
|
||||
|
||||
if let Some(description) = program.description() {
|
||||
obj.imp().description_row.set_text(&description);
|
||||
}
|
||||
|
||||
if let Err(err) = obj.activate_action(
|
||||
"program.set-design",
|
||||
Some(&glib::Variant::from(&program.design().to_string())),
|
||||
) {
|
||||
log::warn!("Failed to initialize program design buttons: {err:?}");
|
||||
}
|
||||
|
||||
obj.imp()
|
||||
.prefer_least_recently_played_adjustment
|
||||
.set_value(program.prefer_least_recently_played() * 100.0);
|
||||
|
||||
obj.imp()
|
||||
.prefer_recently_added_adjustment
|
||||
.set_value(program.prefer_recently_added() * 100.0);
|
||||
|
||||
obj.imp()
|
||||
.avoid_repeated_composers_adjustment
|
||||
.set_value(program.avoid_repeated_composers() as f64);
|
||||
|
||||
obj.imp()
|
||||
.avoid_repeated_instruments_adjustment
|
||||
.set_value(program.avoid_repeated_instruments() as f64);
|
||||
|
||||
obj.imp()
|
||||
.play_full_recordings_row
|
||||
.set_active(program.play_full_recordings());
|
||||
}
|
||||
|
||||
obj.imp().navigation.set(navigation.to_owned()).unwrap();
|
||||
obj
|
||||
}
|
||||
|
||||
pub fn connect_save<F: Fn(&Self, Program) + 'static>(&self, f: F) -> glib::SignalHandlerId {
|
||||
self.connect_local("save", true, move |values| {
|
||||
let obj = values[0].get::<Self>().unwrap();
|
||||
let program = values[1].get::<Program>().unwrap();
|
||||
f(&obj, program);
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn save(&self) {
|
||||
let program = Program::new(
|
||||
&self.imp().title_row.text(),
|
||||
&self.imp().description_row.text(),
|
||||
ProgramDesign::from_str(
|
||||
&self
|
||||
.imp()
|
||||
.action_group
|
||||
.get()
|
||||
.unwrap()
|
||||
.action_state("set-design")
|
||||
.map(|v| v.get::<String>().unwrap_or_default())
|
||||
.unwrap_or_default(),
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
);
|
||||
|
||||
program.set_prefer_least_recently_played(
|
||||
self.imp().prefer_least_recently_played_adjustment.value() / 100.0,
|
||||
);
|
||||
program
|
||||
.set_prefer_recently_added(self.imp().prefer_recently_added_adjustment.value() / 100.0);
|
||||
program.set_avoid_repeated_composers(
|
||||
self.imp().avoid_repeated_composers_adjustment.value() as i32,
|
||||
);
|
||||
program.set_avoid_repeated_instruments(
|
||||
self.imp().avoid_repeated_instruments_adjustment.value() as i32,
|
||||
);
|
||||
program.set_play_full_recordings(self.imp().play_full_recordings_row.is_active());
|
||||
|
||||
self.emit_by_name::<()>("save", &[&program]);
|
||||
self.imp().navigation.get().unwrap().pop();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue