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
use gtk::prelude::{Cast, GtkWindowExt};
use relm4::{gtk, AppUpdate, Model, RelmApp, RelmComponent, Sender, Widgets};
use relm4_components::open_button::{
    OpenButtonConfig, OpenButtonModel, OpenButtonParent, OpenButtonSettings,
};
use relm4_components::open_dialog::{OpenDialogConfig, OpenDialogSettings};
use relm4_components::ParentWindow;

use std::path::PathBuf;

struct AppModel {}

enum AppMsg {
    Open(PathBuf),
}

impl Model for AppModel {
    type Msg = AppMsg;
    type Widgets = AppWidgets;
    type Components = AppComponents;
}

impl AppUpdate for AppModel {
    fn update(
        &mut self,
        msg: AppMsg,
        _components: &AppComponents,
        _sender: Sender<AppMsg>,
    ) -> bool {
        match msg {
            AppMsg::Open(path) => {
                println!("* Open file at {:?} *", path);
            }
        }

        true
    }
}

struct OpenFileButtonConfig {}

impl OpenDialogConfig for OpenFileButtonConfig {
    type Model = AppModel;

    fn open_dialog_config(_model: &Self::Model) -> OpenDialogSettings {
        OpenDialogSettings {
            accept_label: "Open",
            cancel_label: "Cancel",
            create_folders: true,
            is_modal: true,
            filters: Vec::new(),
        }
    }
}

impl OpenButtonConfig for OpenFileButtonConfig {
    fn open_button_config(_model: &Self::Model) -> OpenButtonSettings {
        OpenButtonSettings {
            text: "Open file",
            recently_opened_files: Some(".recent_files"),
            max_recent_files: 10,
        }
    }
}

impl OpenButtonParent for AppModel {
    fn open_msg(path: PathBuf) -> Self::Msg {
        AppMsg::Open(path)
    }
}

impl ParentWindow for AppWidgets {
    fn parent_window(&self) -> Option<gtk::Window> {
        Some(self.main_window.clone().upcast::<gtk::Window>())
    }
}

#[derive(relm4::Components)]
pub struct AppComponents {
    open_button: RelmComponent<OpenButtonModel<OpenFileButtonConfig>, AppModel>,
}

#[relm4::widget]
impl Widgets<AppModel, ()> for AppWidgets {
    view! {
        main_window = gtk::ApplicationWindow {
            set_default_width: 300,
            set_default_height: 100,
            set_titlebar = Some(&gtk::HeaderBar) {
                pack_start: components.open_button.root_widget(),
            }
        }
    }
}

fn main() {
    let model = AppModel {};
    let app = RelmApp::new(model);
    app.run();
}