mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-27 04:07:25 +01:00
Modularize main window
This commit is contained in:
parent
56c4268e4d
commit
cefd7dad95
30 changed files with 1905 additions and 1526 deletions
|
|
@ -1,7 +1,7 @@
|
|||
use super::selector_row::SelectorRow;
|
||||
use super::EnsembleEditor;
|
||||
use crate::backend::Backend;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use gio::prelude::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::selector_row::SelectorRow;
|
||||
use super::InstrumentEditor;
|
||||
use crate::backend::Backend;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use gio::prelude::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
|
|
|
|||
|
|
@ -28,9 +28,6 @@ pub use recording_editor::*;
|
|||
pub mod section_editor;
|
||||
pub use section_editor::*;
|
||||
|
||||
pub mod selector_row;
|
||||
pub use selector_row::*;
|
||||
|
||||
pub mod work_editor;
|
||||
pub use work_editor::*;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::selector_row::SelectorRow;
|
||||
use super::{InstrumentSelector, PersonSelector};
|
||||
use crate::backend::*;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
|
|
|
|||
|
|
@ -1,104 +1,58 @@
|
|||
use super::selector_row::SelectorRow;
|
||||
use super::PersonEditor;
|
||||
use crate::backend::Backend;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use gio::prelude::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
use std::convert::TryInto;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct PersonSelector<F>
|
||||
where
|
||||
F: Fn(Person) -> () + 'static,
|
||||
{
|
||||
backend: Rc<Backend>,
|
||||
pub struct PersonSelector {
|
||||
window: gtk::Window,
|
||||
callback: F,
|
||||
list: gtk::ListBox,
|
||||
search_entry: gtk::SearchEntry,
|
||||
}
|
||||
|
||||
impl<F> PersonSelector<F>
|
||||
where
|
||||
F: Fn(Person) -> () + 'static,
|
||||
{
|
||||
pub fn new<P: IsA<gtk::Window>>(backend: Rc<Backend>, parent: &P, callback: F) -> Rc<Self> {
|
||||
impl PersonSelector {
|
||||
pub fn new<P, F>(backend: Rc<Backend>, parent: &P, callback: F) -> Self
|
||||
where
|
||||
P: IsA<gtk::Window>,
|
||||
F: Fn(Person) -> () + 'static,
|
||||
{
|
||||
let builder =
|
||||
gtk::Builder::from_resource("/de/johrpan/musicus_editor/ui/person_selector.ui");
|
||||
|
||||
get_widget!(builder, gtk::Window, window);
|
||||
get_widget!(builder, gtk::Button, add_button);
|
||||
get_widget!(builder, gtk::SearchEntry, search_entry);
|
||||
get_widget!(builder, gtk::ListBox, list);
|
||||
|
||||
let result = Rc::new(PersonSelector {
|
||||
backend: backend,
|
||||
window: window,
|
||||
callback: callback,
|
||||
search_entry: search_entry,
|
||||
list: list,
|
||||
});
|
||||
let callback = Rc::new(callback);
|
||||
|
||||
let c = glib::MainContext::default();
|
||||
let clone = result.clone();
|
||||
c.spawn_local(async move {
|
||||
let persons = clone.backend.get_persons().await.unwrap();
|
||||
let list = PersonList::new(backend.clone());
|
||||
|
||||
for (index, person) in persons.iter().enumerate() {
|
||||
let label = gtk::Label::new(Some(&person.name_lf()));
|
||||
label.set_halign(gtk::Align::Start);
|
||||
let row = SelectorRow::new(index.try_into().unwrap(), &label);
|
||||
row.show_all();
|
||||
clone.list.insert(&row, -1);
|
||||
}
|
||||
|
||||
clone.list.connect_row_activated(
|
||||
clone!(@strong clone, @strong persons => move |_, row| {
|
||||
clone.window.close();
|
||||
let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap();
|
||||
let index: usize = row.get_index().try_into().unwrap();
|
||||
(clone.callback)(persons[index].clone());
|
||||
}),
|
||||
);
|
||||
|
||||
clone
|
||||
.list
|
||||
.set_filter_func(Some(Box::new(clone!(@strong clone => move |row| {
|
||||
let row = row.get_child().unwrap().downcast::<SelectorRow>().unwrap();
|
||||
let index: usize = row.get_index().try_into().unwrap();
|
||||
let search = clone.search_entry.get_text().to_string().to_lowercase();
|
||||
search.is_empty() || persons[index]
|
||||
.name_lf()
|
||||
.to_lowercase()
|
||||
.contains(&search)
|
||||
}))));
|
||||
});
|
||||
|
||||
result
|
||||
.search_entry
|
||||
.connect_search_changed(clone!(@strong result => move |_| {
|
||||
result.list.invalidate_filter();
|
||||
}));
|
||||
|
||||
add_button.connect_clicked(clone!(@strong result => move |_| {
|
||||
let editor = PersonEditor::new(
|
||||
result.backend.clone(),
|
||||
&result.window,
|
||||
None,
|
||||
clone!(@strong result => move |person| {
|
||||
result.window.close();
|
||||
(result.callback)(person);
|
||||
}),
|
||||
);
|
||||
|
||||
editor.show();
|
||||
list.set_selected(clone!(@strong window, @strong callback => move |person| {
|
||||
window.close();
|
||||
callback(person.clone());
|
||||
}));
|
||||
|
||||
result.window.set_transient_for(Some(parent));
|
||||
window.set_transient_for(Some(parent));
|
||||
window.add(&list.widget);
|
||||
|
||||
result
|
||||
add_button.connect_clicked(
|
||||
clone!(@strong backend, @strong window, @strong callback => move |_| {
|
||||
let editor = PersonEditor::new(
|
||||
backend.clone(),
|
||||
&window,
|
||||
None,
|
||||
clone!(@strong window, @strong callback => move |person| {
|
||||
window.close();
|
||||
callback(person);
|
||||
}),
|
||||
);
|
||||
|
||||
editor.show();
|
||||
}),
|
||||
);
|
||||
|
||||
Self { window }
|
||||
}
|
||||
|
||||
pub fn show(&self) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use super::*;
|
||||
use crate::backend::Backend;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
|
|
|
|||
|
|
@ -1,150 +0,0 @@
|
|||
use glib::prelude::*;
|
||||
use glib::subclass;
|
||||
use glib::subclass::prelude::*;
|
||||
use glib::translate::*;
|
||||
use glib::{glib_object_impl, glib_object_subclass, glib_wrapper};
|
||||
use gtk::prelude::*;
|
||||
use gtk::subclass::prelude::*;
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
glib_wrapper! {
|
||||
pub struct SelectorRow(
|
||||
Object<subclass::simple::InstanceStruct<SelectorRowPriv>,
|
||||
subclass::simple::ClassStruct<SelectorRowPriv>,
|
||||
SelectorRowClass>
|
||||
) @extends gtk::Bin, gtk::Container, gtk::Widget;
|
||||
|
||||
match fn {
|
||||
get_type => || SelectorRowPriv::get_type().to_glib(),
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectorRow {
|
||||
pub fn new<T: IsA<gtk::Widget>>(index: u64, child: &T) -> Self {
|
||||
glib::Object::new(
|
||||
Self::static_type(),
|
||||
&[("index", &index), ("child", child.upcast_ref())],
|
||||
)
|
||||
.expect("Failed to create SelectorRow GObject!")
|
||||
.downcast()
|
||||
.expect("SelectorRow GObject is of the wrong type!")
|
||||
}
|
||||
|
||||
pub fn get_index(&self) -> u64 {
|
||||
self.get_property("index").unwrap().get().unwrap().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SelectorRowPriv {
|
||||
index: Cell<u64>,
|
||||
child: RefCell<Option<gtk::Widget>>,
|
||||
}
|
||||
|
||||
static PROPERTIES: [subclass::Property; 2] = [
|
||||
subclass::Property("index", |name| {
|
||||
glib::ParamSpec::uint64(
|
||||
name,
|
||||
"Index",
|
||||
"Index",
|
||||
0,
|
||||
u64::MAX,
|
||||
0,
|
||||
glib::ParamFlags::READWRITE,
|
||||
)
|
||||
}),
|
||||
subclass::Property("child", |name| {
|
||||
glib::ParamSpec::object(
|
||||
name,
|
||||
"Child",
|
||||
"Child",
|
||||
gtk::Widget::static_type(),
|
||||
glib::ParamFlags::READWRITE,
|
||||
)
|
||||
}),
|
||||
];
|
||||
|
||||
impl ObjectSubclass for SelectorRowPriv {
|
||||
const NAME: &'static str = "SelectorRow";
|
||||
type ParentType = gtk::Bin;
|
||||
type Instance = subclass::simple::InstanceStruct<Self>;
|
||||
type Class = subclass::simple::ClassStruct<Self>;
|
||||
|
||||
glib_object_subclass!();
|
||||
|
||||
fn class_init(klass: &mut Self::Class) {
|
||||
klass.install_properties(&PROPERTIES);
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
index: Cell::new(0),
|
||||
child: RefCell::new(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ObjectImpl for SelectorRowPriv {
|
||||
glib_object_impl!();
|
||||
|
||||
fn constructed(&self, object: &glib::Object) {
|
||||
self.parent_constructed(object);
|
||||
|
||||
let row = object.downcast_ref::<SelectorRow>().unwrap();
|
||||
row.set_border_width(6);
|
||||
|
||||
let child = self.child.borrow();
|
||||
match child.as_ref() {
|
||||
Some(child) => row.add(child),
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_property(&self, object: &glib::Object, id: usize, value: &glib::Value) {
|
||||
let prop = &PROPERTIES[id];
|
||||
|
||||
match *prop {
|
||||
subclass::Property("index", ..) => {
|
||||
let index = value
|
||||
.get_some()
|
||||
.expect("Wrong type for SelectorRow GObject index property!");
|
||||
self.index.set(index);
|
||||
}
|
||||
subclass::Property("child", ..) => {
|
||||
let child = value
|
||||
.get()
|
||||
.expect("Wrong type for SelectorRow GObject child property!");
|
||||
|
||||
let row = object.downcast_ref::<SelectorRow>().unwrap();
|
||||
|
||||
{
|
||||
let old = self.child.borrow();
|
||||
match old.as_ref() {
|
||||
Some(old) => row.remove(old),
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
|
||||
self.child.replace(child.clone());
|
||||
match child {
|
||||
Some(child) => row.add(&child),
|
||||
None => (),
|
||||
}
|
||||
}
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_property(&self, _obj: &glib::Object, id: usize) -> Result<glib::Value, ()> {
|
||||
let prop = &PROPERTIES[id];
|
||||
|
||||
match *prop {
|
||||
subclass::Property("index", ..) => Ok(self.index.get().to_value()),
|
||||
subclass::Property("child", ..) => Ok(self.child.borrow().to_value()),
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WidgetImpl for SelectorRowPriv {}
|
||||
impl ContainerImpl for SelectorRowPriv {}
|
||||
impl BinImpl for SelectorRowPriv {}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
use super::selector_row::SelectorRow;
|
||||
use super::{InstrumentSelector, PersonSelector, PartEditor, SectionEditor};
|
||||
use crate::backend::*;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
use gtk_macros::get_widget;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use super::*;
|
||||
use crate::backend::Backend;
|
||||
use crate::database::*;
|
||||
use crate::widgets::*;
|
||||
use gio::prelude::*;
|
||||
use glib::clone;
|
||||
use gtk::prelude::*;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue