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 = >k::Button {
48 set_label: "Increment",
49 connect_clicked => AppMsg::Increment,
50 },
51 append = >k::Button {
52 set_label: "Decrement",
53 connect_clicked => AppMsg::Decrement,
54 },
55 append = >k::Label {
56 set_margin_all: 5,
57 #[watch]
58 set_label: &format!("Counter: {}", model.counter),
59 },
60 append = >k::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}