alert/
alert.rs

1use gtk::prelude::*;
2use relm4::{
3    Component, ComponentController, ComponentParts, ComponentSender, Controller, RelmApp,
4    RelmWidgetExt, SimpleComponent,
5    gtk::{self, glib},
6};
7use relm4_components::alert::{Alert, AlertMsg, AlertResponse, AlertSettings};
8
9struct App {
10    counter: u8,
11    alert_toggle: bool,
12    dialog: Controller<Alert>,
13    second_dialog: Controller<Alert>,
14}
15
16#[derive(Debug)]
17enum AppMsg {
18    Increment,
19    Decrement,
20    CloseRequest,
21    Save,
22    Close,
23    Ignore,
24}
25
26#[relm4::component]
27impl SimpleComponent for App {
28    type Init = ();
29    type Input = AppMsg;
30    type Output = ();
31
32    view! {
33        main_window = gtk::ApplicationWindow {
34            set_title: Some("Alert example"),
35            set_default_size: (300, 100),
36
37            connect_close_request[sender] => move |_| {
38                sender.input(AppMsg::CloseRequest);
39                glib::Propagation::Proceed
40            },
41
42            gtk::Box {
43                set_orientation: gtk::Orientation::Vertical,
44                set_margin_all: 5,
45                set_spacing: 5,
46
47                append = &gtk::Button {
48                    set_label: "Increment",
49                    connect_clicked => AppMsg::Increment,
50                },
51                append = &gtk::Button {
52                    set_label: "Decrement",
53                    connect_clicked => AppMsg::Decrement,
54                },
55                append = &gtk::Label {
56                    set_margin_all: 5,
57                    #[watch]
58                    set_label: &format!("Counter: {}", model.counter),
59                },
60                append = &gtk::Button {
61                    set_label: "Close",
62                    connect_clicked => AppMsg::CloseRequest,
63                },
64            },
65        }
66    }
67
68    fn update(&mut self, msg: AppMsg, _sender: ComponentSender<Self>) {
69        match msg {
70            AppMsg::Increment => {
71                self.counter = self.counter.wrapping_add(1);
72            }
73            AppMsg::Decrement => {
74                self.counter = self.counter.wrapping_sub(1);
75            }
76            AppMsg::CloseRequest => {
77                if self.counter == 42 {
78                    relm4::main_application().quit();
79                } else {
80                    self.alert_toggle = !self.alert_toggle;
81                    if self.alert_toggle {
82                        self.dialog.emit(AlertMsg::Show);
83                    } else {
84                        self.second_dialog.emit(AlertMsg::Show);
85                    }
86                }
87            }
88            AppMsg::Save => {
89                println!("* Open save dialog here *");
90            }
91            AppMsg::Close => {
92                relm4::main_application().quit();
93            }
94            AppMsg::Ignore => (),
95        }
96    }
97
98    fn init(
99        _: Self::Init,
100        root: Self::Root,
101        sender: ComponentSender<Self>,
102    ) -> ComponentParts<Self> {
103        let model = App {
104            counter: 0,
105            alert_toggle: false,
106            dialog: Alert::builder()
107                .transient_for(&root)
108                .launch(AlertSettings {
109                    text: Some(String::from(
110                        "Do you want to quit without saving? (First alert)",
111                    )),
112                    secondary_text: Some(String::from("Your counter hasn't reached 42 yet")),
113                    confirm_label: Some(String::from("Close without saving")),
114                    cancel_label: Some(String::from("Cancel")),
115                    option_label: Some(String::from("Save")),
116                    is_modal: true,
117                    destructive_accept: true,
118                    extra_child: Some(gtk::Button::with_label("Button in Alert").into()),
119                })
120                .forward(sender.input_sender(), convert_alert_response),
121            second_dialog: Alert::builder()
122                .transient_for(&root)
123                .launch(AlertSettings {
124                    text: Some(String::from(
125                        "Do you want to quit without saving? (Second alert)",
126                    )),
127                    secondary_text: Some(String::from("Your counter hasn't reached 42 yet")),
128                    confirm_label: Some(String::from("Close without saving")),
129                    cancel_label: Some(String::from("Cancel")),
130                    option_label: Some(String::from("Save")),
131                    is_modal: true,
132                    destructive_accept: true,
133                    extra_child: None,
134                })
135                .forward(sender.input_sender(), convert_alert_response),
136        };
137
138        let widgets = view_output!();
139
140        ComponentParts { model, widgets }
141    }
142}
143
144fn convert_alert_response(response: AlertResponse) -> AppMsg {
145    match response {
146        AlertResponse::Confirm => AppMsg::Close,
147        AlertResponse::Cancel => AppMsg::Ignore,
148        AlertResponse::Option => AppMsg::Save,
149    }
150}
151
152fn main() {
153    let app = RelmApp::new("relm4.example.alert");
154    app.run::<App>(());
155}