leaflet_sidebar/
leaflet_sidebar.rs

1// This example should be updated soon...
2#![allow(deprecated)]
3
4/// Responsive sidebar layout inspired by the example code in the [libadwaita documentation].
5///
6/// Shrink the window small enough to see the sidebar and content pages become folded.
7///
8/// [libadwaita documentation]: https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/adaptive-layouts.html#leaflet
9use adw::prelude::*;
10use gtk::glib;
11use relm4::prelude::*;
12
13struct App {
14    current_section: u32,
15}
16
17#[relm4::component]
18impl SimpleComponent for App {
19    type Input = u32;
20    type Output = ();
21    type Init = ();
22
23    view! {
24        adw::Window {
25            #[name = "leaflet"]
26            adw::Leaflet {
27                set_can_navigate_back: true,
28
29                gtk::Box {
30                    set_orientation: gtk::Orientation::Vertical,
31
32                    #[name = "sidebar_header"]
33                    adw::HeaderBar {
34                        #[wrap(Some)]
35                        set_title_widget = &adw::WindowTitle {
36                            set_title: "Sidebar",
37                        }
38                    },
39
40                    gtk::ListBox {
41                        set_selection_mode: gtk::SelectionMode::Single,
42                        add_css_class: relm4::css::NAVIGATION_SIDEBAR,
43
44                        adw::ActionRow {
45                            set_title: "Section 1",
46                        },
47
48                        adw::ActionRow {
49                            set_title: "Section 2",
50                        },
51
52                        adw::ActionRow {
53                            set_title: "Section 3",
54                        },
55
56                        connect_row_selected[sender] => move |_, row| {
57                            if let Some(row) = row {
58                                sender.input((row.index() + 1) as u32);
59                            }
60                        }
61                    }
62                },
63
64                append = &gtk::Separator {
65                    set_orientation: gtk::Orientation::Vertical,
66                } -> {
67                    set_navigatable: false,
68                },
69
70                gtk::Box {
71                    set_orientation: gtk::Orientation::Vertical,
72                    set_hexpand: true,
73
74                    #[name = "content_header"]
75                    adw::HeaderBar {
76                        #[name = "back_button"]
77                        pack_start = &gtk::Button {
78                            set_icon_name: "go-previous-symbolic",
79                            connect_clicked[leaflet] => move |_| {
80                                leaflet.navigate(adw::NavigationDirection::Back);
81                            }
82                        },
83
84                        #[wrap(Some)]
85                        set_title_widget = &adw::WindowTitle {
86                            set_title: "Content",
87                        }
88                    },
89
90                    gtk::Label {
91                        add_css_class: relm4::css::TITLE_1,
92                        set_vexpand: true,
93
94                        #[watch]
95                        set_text: &format!("Page {}", model.current_section),
96                    }
97                },
98            }
99        }
100    }
101
102    fn update(&mut self, msg: u32, _: ComponentSender<Self>) {
103        self.current_section = msg;
104    }
105
106    fn init(_: (), root: Self::Root, sender: ComponentSender<Self>) -> ComponentParts<Self> {
107        let model = App { current_section: 1 };
108
109        let widgets = view_output!();
110
111        widgets
112            .leaflet
113            .bind_property("folded", &widgets.sidebar_header, "show-end-title-buttons")
114            .flags(glib::BindingFlags::SYNC_CREATE)
115            .build();
116        widgets
117            .leaflet
118            .bind_property(
119                "folded",
120                &widgets.content_header,
121                "show-start-title-buttons",
122            )
123            .flags(glib::BindingFlags::SYNC_CREATE)
124            .build();
125        widgets
126            .leaflet
127            .bind_property("folded", &widgets.back_button, "visible")
128            .flags(glib::BindingFlags::SYNC_CREATE)
129            .build();
130
131        ComponentParts { model, widgets }
132    }
133
134    fn pre_view() {
135        widgets.leaflet.navigate(adw::NavigationDirection::Forward);
136    }
137}
138
139fn main() {
140    let app = RelmApp::new("relm4.example.leafletSidebar");
141    app.run::<App>(());
142}