use gtk::prelude::*; use relm4::{ gtk::{self, glib}, Component, ComponentController, ComponentParts, ComponentSender, Controller, RelmApp, RelmWidgetExt, SimpleComponent, }; use relm4_components::alert::{Alert, AlertMsg, AlertResponse, AlertSettings}; struct App { counter: u8, alert_toggle: bool, dialog: Controller, second_dialog: Controller, } #[derive(Debug)] enum AppMsg { Increment, Decrement, CloseRequest, Save, Close, Ignore, } #[relm4::component] impl SimpleComponent for App { type Init = (); type Input = AppMsg; type Output = (); view! { main_window = gtk::ApplicationWindow { set_title: Some("Alert example"), set_default_size: (300, 100), connect_close_request[sender] => move |_| { sender.input(AppMsg::CloseRequest); glib::Propagation::Proceed }, gtk::Box { set_orientation: gtk::Orientation::Vertical, set_margin_all: 5, set_spacing: 5, append = >k::Button { set_label: "Increment", connect_clicked => AppMsg::Increment, }, append = >k::Button { set_label: "Decrement", connect_clicked => AppMsg::Decrement, }, append = >k::Label { set_margin_all: 5, #[watch] set_label: &format!("Counter: {}", model.counter), }, append = >k::Button { set_label: "Close", connect_clicked => AppMsg::CloseRequest, }, }, } } fn update(&mut self, msg: AppMsg, _sender: ComponentSender) { match msg { AppMsg::Increment => { self.counter = self.counter.wrapping_add(1); } AppMsg::Decrement => { self.counter = self.counter.wrapping_sub(1); } AppMsg::CloseRequest => { if self.counter == 42 { relm4::main_application().quit(); } else { self.alert_toggle = !self.alert_toggle; if self.alert_toggle { self.dialog.emit(AlertMsg::Show); } else { self.second_dialog.emit(AlertMsg::Show); } } } AppMsg::Save => { println!("* Open save dialog here *"); } AppMsg::Close => { relm4::main_application().quit(); } AppMsg::Ignore => (), } } fn init( _: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = App { counter: 0, alert_toggle: false, dialog: Alert::builder() .transient_for(&root) .launch(AlertSettings { text: Some(String::from( "Do you want to quit without saving? (First alert)", )), secondary_text: Some(String::from("Your counter hasn't reached 42 yet")), confirm_label: Some(String::from("Close without saving")), cancel_label: Some(String::from("Cancel")), option_label: Some(String::from("Save")), is_modal: true, destructive_accept: true, extra_child: Some(gtk::Button::with_label("Button in Alert").into()), }) .forward(sender.input_sender(), convert_alert_response), second_dialog: Alert::builder() .transient_for(&root) .launch(AlertSettings { text: Some(String::from( "Do you want to quit without saving? (Second alert)", )), secondary_text: Some(String::from("Your counter hasn't reached 42 yet")), confirm_label: Some(String::from("Close without saving")), cancel_label: Some(String::from("Cancel")), option_label: Some(String::from("Save")), is_modal: true, destructive_accept: true, extra_child: None, }) .forward(sender.input_sender(), convert_alert_response), }; let widgets = view_output!(); ComponentParts { model, widgets } } } fn convert_alert_response(response: AlertResponse) -> AppMsg { match response { AlertResponse::Confirm => AppMsg::Close, AlertResponse::Cancel => AppMsg::Ignore, AlertResponse::Option => AppMsg::Save, } } fn main() { let app = RelmApp::new("relm4.example.alert"); app.run::(()); }