diff --git a/src/main.rs b/src/main.rs index 10f94fe..5ee6cd0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,7 @@ use relm::{Dialog, DialogInput}; use relm4::{ Component, ComponentController, Controller, RelmApp, adw::{self, prelude::*}, - gtk::{self, gio, glib::clone}, + gtk::{self, gio}, prelude::{AsyncComponent, AsyncComponentParts}, tokio, }; @@ -47,11 +47,6 @@ enum Message { Nothing, } -struct Widgets { - file_picker_row: adw::ActionRow, - send_button: gtk::Button, -} - struct Tyrolienne { config: Config, video_path: Option, @@ -68,19 +63,69 @@ impl Tyrolienne { } } +#[relm4::component(async)] impl AsyncComponent for Tyrolienne { type Input = Message; type Output = (); type CommandOutput = (); type Init = Config; - type Root = adw::ApplicationWindow; - type Widgets = Widgets; - fn init_root() -> Self::Root { - adw::ApplicationWindow::builder() - .title("Tyrolienne") - .default_width(500) - .build() + view! { + adw::ApplicationWindow { + set_title: Some("Tyrolienne"), + set_default_width: 500, + + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + set_spacing: 0, + + adw::HeaderBar {}, + + gtk::Box { + set_orientation: gtk::Orientation::Vertical, + set_spacing: 32, + set_margin_top: 32, + set_margin_bottom: 32, + set_margin_start: 32, + set_margin_end: 32, + + gtk::ListBox { + set_selection_mode: gtk::SelectionMode::None, + set_css_classes: &["boxed-list"], + + adw::ActionRow { + set_activatable: true, + set_css_classes: &["property"], + set_title: "Video file", + #[watch] + set_subtitle: &model.display_video_path(), + connect_activated => Message::OpenFilePicker, + }, + + adw::ComboRow { + set_title: "Folder", + set_model: Some(&folder_store), + set_expression: Some(&folder_expression), + connect_activated[sender] => move |r| { + if let Some(item) = r + .selected_item() + .and_then(|i| i.downcast::().ok()) + { + sender.input(Message::SetFolder(item.as_folder())); + } + }, + } + }, + + gtk::Button { + set_label: "Send", + #[watch] + set_sensitive: model.video_path.is_some(), + connect_clicked => Message::StartTheProcess, + } + } + } + } } async fn init( @@ -110,85 +155,22 @@ impl AsyncComponent for Tyrolienne { } }; - let file_picker_row = adw::ActionRow::builder() - .activatable(true) - .title("Video file") - .subtitle(model.display_video_path()) - .css_classes(["property"]) - .build(); - file_picker_row.connect_activated(clone!( - #[strong] - sender, - move |_| sender.input(Message::OpenFilePicker) - )); - let mut gtk_folders = folders .iter() .map(GtkZiplineFolder::from_folder) .collect::>(); gtk_folders.insert(0, GtkZiplineFolder::none()); - let store = gio::ListStore::new::(); - store.extend_from_slice(>k_folders); + let folder_store = gio::ListStore::new::(); + folder_store.extend_from_slice(>k_folders); - let folder_row = adw::ComboRow::builder() - .title("Folder") - .model(&store) - .expression(gtk::PropertyExpression::new( - GtkZiplineFolder::r#type(), - None::<>k::Expression>, - "name", - )) - .build(); - folder_row.connect_activated(clone!( - #[strong] - sender, - move |r| { - if let Some(item) = r - .selected_item() - .and_then(|i| i.downcast::().ok()) - { - sender.input(Message::SetFolder(item.as_folder())); - } - } - )); - - let send_button = gtk::Button::builder() - .label("Send") - .sensitive(false) - .margin_start(32) - .margin_end(32) - .margin_bottom(32) - .build(); - send_button.connect_clicked(clone!( - #[strong] - sender, - move |_| sender.input(Message::StartTheProcess) - )); - - let list = gtk::ListBox::builder() - .margin_top(32) - .margin_end(32) - .margin_bottom(32) - .margin_start(32) - .selection_mode(gtk::SelectionMode::None) - .css_classes(["boxed-list"]) - .build(); - list.append(&file_picker_row); - list.append(&folder_row); - - let root_box = gtk::Box::new(gtk::Orientation::Vertical, 0); - root_box.append(&adw::HeaderBar::new()); - root_box.append(&list); - root_box.append(&send_button); - - root.set_content(Some(&root_box)); - - let widgets = Widgets { - file_picker_row, - send_button, - }; + let folder_expression = gtk::PropertyExpression::new( + GtkZiplineFolder::r#type(), + None::<>k::Expression>, + "name", + ); + let widgets = view_output!(); AsyncComponentParts { model, widgets } } @@ -222,14 +204,6 @@ impl AsyncComponent for Tyrolienne { } } } - - fn update_view(&self, widgets: &mut Self::Widgets, _sender: relm4::AsyncComponentSender) { - widgets - .file_picker_row - .set_subtitle(&self.display_video_path()); - - widgets.send_button.set_sensitive(self.video_path.is_some()); - } } fn main() -> Result<()> {