1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
use gtk::prelude::*;
use relm4::{abstractions::Toaster, prelude::*};

struct App {
    activated: &'static str,
    toaster: Toaster,
}

#[derive(Debug)]
enum Msg {
    Activate,
    Cancel,
}

#[relm4::component]
impl SimpleComponent for App {
    type Init = ();
    type Input = Msg;
    type Output = ();

    view! {
        adw::Window {
            set_title: Some("Simple app"),
            set_default_size: (300, 200),

            gtk::Box {
                set_orientation: gtk::Orientation::Vertical,

                adw::HeaderBar {
                    #[wrap(Some)]
                    set_title_widget = &adw::WindowTitle {
                        set_title: "Toast",
                    }
                },

                #[local_ref]
                toast_overlay -> adw::ToastOverlay {
                    set_vexpand: true,
                    gtk::Box {
                        set_orientation: gtk::Orientation::Vertical,
                        set_spacing: 5,
                        set_margin_all: 5,
                        set_valign: gtk::Align::Center,

                        gtk::Button {
                            set_hexpand: false,
                            set_vexpand: false,
                            set_label: "Activate",
                            connect_clicked => Msg::Activate,
                        },
                        gtk::Button {
                            set_hexpand: false,
                            set_vexpand: false,
                            set_label: "Cancel",
                            connect_clicked => Msg::Cancel,
                        },
                        gtk::Text {
                            #[watch]
                            set_text: model.activated,
                        },
                    },
                }
            }

        }
    }

    // Initialize the component.
    fn init(
        _: Self::Init,
        root: Self::Root,
        sender: ComponentSender<Self>,
    ) -> ComponentParts<Self> {
        let model = App {
            activated: "Idle",
            toaster: Toaster::default(),
        };

        let toast_overlay = model.toaster.overlay_widget();

        // Insert the code generation of the view! macro here
        let widgets = view_output!();

        ComponentParts { model, widgets }
    }

    fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
        match msg {
            Msg::Activate => {
                self.activated = "Active";
                let toast = adw::Toast::builder()
                    .title("Activated")
                    .button_label("Cancel")
                    .timeout(0)
                    .build();
                toast.connect_button_clicked(move |this| {
                    this.dismiss();
                    sender.input(Msg::Cancel);
                });
                self.toaster.add_toast(toast);
            }
            Msg::Cancel => self.activated = "Idle",
        }
    }
}

fn main() {
    let app = RelmApp::new("relm4.example.toast");
    app.run::<App>(());
}