194 lines
6.6 KiB
Rust
194 lines
6.6 KiB
Rust
use diesel::prelude::*;
|
|
use gtk::gdk::Display;
|
|
use gtk::glib::BoxedAnyObject;
|
|
use gtk::prelude::*;
|
|
use relm4::{factory::FactoryVecDeque, prelude::*};
|
|
use std::cell::Ref;
|
|
|
|
mod library_list;
|
|
use library_list::LibraryListItem;
|
|
mod app_msg;
|
|
use app_msg::AppMsg;
|
|
use sample_amp::establish_connection;
|
|
use sample_amp::models::Library;
|
|
use sample_amp::schema::libraries;
|
|
|
|
struct AppModel {
|
|
samples: gtk::MultiSelection,
|
|
libraries: FactoryVecDeque<LibraryListItem>,
|
|
connection: SqliteConnection,
|
|
}
|
|
|
|
struct Sample {
|
|
name: String,
|
|
bpm: f32,
|
|
key: String, // todo: key struct?
|
|
}
|
|
|
|
#[relm4::component]
|
|
impl SimpleComponent for AppModel {
|
|
type Init = ();
|
|
|
|
type Input = AppMsg;
|
|
type Output = ();
|
|
|
|
view! {
|
|
gtk::Window {
|
|
set_title: Some("SampleAmp"),
|
|
set_default_width: 1000,
|
|
set_default_height: 600,
|
|
|
|
connect_close_request[sender] => move |_| {
|
|
sender.input(AppMsg::Close);
|
|
gtk::Inhibit(true)
|
|
},
|
|
|
|
gtk::Box {
|
|
gtk::ScrolledWindow {
|
|
set_css_classes: &["sidebar"],
|
|
set_hscrollbar_policy: gtk::PolicyType::Never,
|
|
#[local_ref]
|
|
library_view -> gtk::ListBox{
|
|
set_css_classes: &["navigation-sidebar"]
|
|
}
|
|
},
|
|
gtk::Box {
|
|
set_orientation: gtk::Orientation::Vertical,
|
|
set_hexpand: true,
|
|
|
|
gtk::ScrolledWindow {
|
|
set_vexpand: true,
|
|
set_css_classes: &["sample-list-view"],
|
|
gtk::ColumnView {
|
|
set_model: Some(&model.samples),
|
|
append_column = >k::ColumnViewColumn {
|
|
set_title: Some("Name"),
|
|
set_resizable: true,
|
|
set_expand: true,
|
|
set_factory: Some(&factory_name)
|
|
},
|
|
append_column = >k::ColumnViewColumn {
|
|
set_title: Some("BPM"),
|
|
set_factory: Some(&factory_bpm)
|
|
},
|
|
append_column = >k::ColumnViewColumn {
|
|
set_title: Some("Key"),
|
|
set_factory: Some(&factory_key)
|
|
},
|
|
append_column = >k::ColumnViewColumn {
|
|
set_title: Some("Tags"),
|
|
set_resizable: true,
|
|
}
|
|
}
|
|
},
|
|
|
|
gtk::Box {
|
|
set_height_request: 100,
|
|
set_margin_all: 5,
|
|
gtk::Label {
|
|
#[watch]
|
|
set_label: "Sample playback",
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn init(
|
|
_: Self::Init,
|
|
window: &Self::Root,
|
|
sender: ComponentSender<Self>,
|
|
) -> relm4::ComponentParts<Self> {
|
|
let factory_name = gtk::SignalListItemFactory::new();
|
|
factory_name.connect_bind(move |_factory, item| {
|
|
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
|
let obj = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
|
let sample: Ref<Sample> = obj.borrow();
|
|
let cell = gtk::Label::new(Some(&sample.name.to_string()));
|
|
cell.set_halign(gtk::Align::Start);
|
|
item.set_child(Some(&cell))
|
|
});
|
|
|
|
let factory_bpm = gtk::SignalListItemFactory::new();
|
|
factory_bpm.connect_bind(move |_factory, item| {
|
|
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
|
let obj = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
|
let sample: Ref<Sample> = obj.borrow();
|
|
let cell = gtk::Label::new(Some(&sample.bpm.to_string()));
|
|
cell.set_halign(gtk::Align::End);
|
|
item.set_child(Some(&cell))
|
|
});
|
|
|
|
let factory_key = gtk::SignalListItemFactory::new();
|
|
factory_key.connect_bind(move |_factory, item| {
|
|
let item = item.downcast_ref::<gtk::ListItem>().unwrap();
|
|
let obj = item.item().and_downcast::<BoxedAnyObject>().unwrap();
|
|
let sample: Ref<Sample> = obj.borrow();
|
|
let cell = gtk::Label::new(Some(&sample.key.to_string()));
|
|
cell.set_halign(gtk::Align::Start);
|
|
item.set_child(Some(&cell))
|
|
});
|
|
|
|
let samples = gtk::gio::ListStore::new(gtk::glib::types::Type::OBJECT);
|
|
let sample_a = BoxedAnyObject::new(Sample {
|
|
name: "01 MOOLOO-108 bpm a.wav".to_string(),
|
|
bpm: 108.0,
|
|
key: "A".to_string(),
|
|
});
|
|
samples.append(&sample_a);
|
|
let sample_b = BoxedAnyObject::new(Sample {
|
|
name: "03 FAST AND FURIOUS-144.3 bpm a.wav".to_string(),
|
|
bpm: 144.3,
|
|
key: "A".to_string(),
|
|
});
|
|
samples.append(&sample_b);
|
|
|
|
let samples = gtk::MultiSelection::new(Some(samples));
|
|
|
|
let mut model = AppModel {
|
|
samples,
|
|
connection: establish_connection(),
|
|
libraries: FactoryVecDeque::new(gtk::ListBox::default(), sender.input_sender()),
|
|
};
|
|
|
|
// todo: cleaner
|
|
|
|
let library_results = libraries::dsl::libraries
|
|
.select(Library::as_select())
|
|
.load(&mut model.connection)
|
|
.expect("Error loading libraries");
|
|
|
|
model.libraries.guard().push_back("All".to_string());
|
|
for lib in library_results {
|
|
model.libraries.guard().push_back(lib.name);
|
|
}
|
|
|
|
let library_view = model.libraries.widget();
|
|
let widgets = view_output!();
|
|
|
|
ComponentParts { model, widgets }
|
|
}
|
|
|
|
fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
|
|
match message {
|
|
AppMsg::Close => {
|
|
relm4::main_application().quit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn load_css() {
|
|
let provider = gtk::CssProvider::new();
|
|
provider.load_from_data(include_str!("../css/style.css"));
|
|
gtk::style_context_add_provider_for_display(&Display::default().expect("Could not connect to a display."), &provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);
|
|
}
|
|
|
|
fn main() {
|
|
let app = RelmApp::new("relm.test.simple_manual");
|
|
relm4::main_application().connect_startup(|_| load_css());
|
|
relm4_icons::initialize_icons();
|
|
app.run::<AppModel>(());
|
|
}
|