mxl_player_components/ui/message_dialog/
widget.rs

1use super::{
2    messages::{MessageDialogInput, MessageDialogOutput, MessageDialogType, internal::PrivateMsg},
3    model::MessageDialog,
4};
5use crate::localization::helper::fl;
6use mxl_relm4_components::relm4::{self, adw::gtk::prelude::*, css as adw_css, prelude::*};
7
8#[relm4::component(pub)]
9impl Component for MessageDialog {
10    type Init = ();
11    type Input = MessageDialogInput;
12    type Output = MessageDialogOutput;
13    type CommandOutput = ();
14
15    view! {
16        #[name(dialog)]
17        adw::Window {
18            #[watch]
19            set_title: Some(model.title.as_str()),
20            set_modal: true,
21            set_hide_on_close: true,
22            set_destroy_with_parent: true,
23            set_height_request: 500,
24            set_width_request: 800,
25            #[watch]
26            set_visible: !model.hidden,
27
28            gtk::Box {
29                set_orientation: gtk::Orientation::Vertical,
30
31                adw::HeaderBar {
32                    set_show_end_title_buttons: false,
33                },
34
35                gtk::Box {
36                    set_orientation: gtk::Orientation::Vertical,
37                    set_margin_all: 8,
38                    set_spacing: 8,
39
40                    gtk::ScrolledWindow {
41                        set_vexpand: true,
42                        set_hexpand: true,
43                        set_vscrollbar_policy: gtk::PolicyType::Always,
44
45                        gtk::TextView {
46                            set_buffer: Some(&model.text_buffer),
47                            set_vexpand: true,
48                            set_hexpand: true,
49                            set_editable: false,
50                            set_wrap_mode: gtk::WrapMode::Word,
51                            set_cursor_visible: false,
52                        },
53                    },
54
55                    gtk::Box {
56                        set_hexpand: true,
57                        set_homogeneous: true,
58                        set_spacing: 8,
59
60                        gtk::Button {
61                            #[watch]
62                            set_label: &fl!("create-report"),
63                            set_hexpand: true,
64                            connect_clicked => MessageDialogInput::PrivateMessage(PrivateMsg::CreateReportButtonPressed),
65                        },
66
67                        gtk::Button {
68                            #[watch]
69                            set_label: match model.dialog_type {
70                                MessageDialogType::Fatal => fl!("quit").to_owned(),
71                                _ =>  fl!("close").to_owned(),
72                            }.as_ref(),
73                            add_css_class: adw_css::ERROR,
74                            set_hexpand: true,
75                            connect_clicked => MessageDialogInput::PrivateMessage(PrivateMsg::CloseButtonPressed),
76                       },
77                    },
78                },
79            },
80        }
81    }
82
83    fn init(_init: (), root: Self::Root, sender: ComponentSender<Self>) -> ComponentParts<Self> {
84        let model = MessageDialog {
85            hidden: true,
86            dialog_type: MessageDialogType::Error,
87            title: "".to_owned(),
88            text_buffer: gtk::TextBuffer::new(None),
89        };
90        let widgets = view_output!();
91
92        {
93            let controller = gtk::EventControllerKey::new();
94            controller.connect_key_pressed(move |_, key, _keycode, _modifiers| {
95                if key == gtk::gdk::Key::Escape {
96                    sender.input(MessageDialogInput::PrivateMessage(PrivateMsg::CloseButtonPressed));
97                    return gtk::glib::Propagation::Stop;
98                }
99                gtk::glib::Propagation::Proceed
100            });
101            root.add_controller(controller);
102        }
103
104        ComponentParts { model, widgets }
105    }
106
107    fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>, root: &Self::Root) {
108        match msg {
109            MessageDialogInput::PrivateMessage(msg) => match msg {
110                PrivateMsg::CreateReportButtonPressed => {
111                    sender.output_sender().emit(MessageDialogOutput::CreateReport);
112                }
113                PrivateMsg::CloseButtonPressed => {
114                    self.hidden = true;
115                    root.close();
116                    if self.dialog_type == MessageDialogType::Fatal {
117                        sender.output_sender().emit(MessageDialogOutput::Quit);
118                    }
119                }
120            },
121            MessageDialogInput::Message(message_type, title, text) => {
122                self.title = {
123                    if let Some(title) = title {
124                        title
125                    } else {
126                        match message_type {
127                            MessageDialogType::Fatal => fl!("fatal-error-title").to_owned(),
128                            MessageDialogType::Error => fl!("error-title").to_owned(),
129                            MessageDialogType::Warning => fl!("warning-title").to_owned(),
130                        }
131                    }
132                };
133                self.dialog_type = message_type;
134                self.text_buffer.set_text(text.as_str());
135                self.hidden = false;
136            }
137        }
138    }
139}