Skip to main content

mimick/library/
bottom_nav.rs

1use std::rc::Rc;
2
3use gtk::prelude::*;
4
5use super::LibraryWindowUi;
6
7const ITEMS: [(&str, &str, &str); 4] = [
8    ("photos", "Photos", "image-x-generic-symbolic"),
9    ("explore", "Explore", "view-grid-symbolic"),
10    ("albums", "Albums", "folder-pictures-symbolic"),
11    ("people", "People", "avatar-default-symbolic"),
12];
13
14pub(super) struct BottomNav {
15    pub root: gtk::Box,
16    pub revealer: gtk::Revealer,
17    buttons: Vec<(String, gtk::ToggleButton)>,
18}
19
20pub(super) fn build_bottom_nav() -> BottomNav {
21    let row = gtk::Box::builder()
22        .homogeneous(true)
23        .spacing(4)
24        .margin_top(4)
25        .margin_bottom(4)
26        .margin_start(8)
27        .margin_end(8)
28        .build();
29    let buttons: Vec<(String, gtk::ToggleButton)> = ITEMS
30        .iter()
31        .map(|(key, label, icon)| (key.to_string(), nav_button(label, icon)))
32        .collect();
33    for (_, button) in &buttons {
34        row.append(button);
35    }
36    let revealer = gtk::Revealer::builder()
37        .transition_type(gtk::RevealerTransitionType::SlideUp)
38        .reveal_child(true)
39        .child(&row)
40        .build();
41    let root = gtk::Box::builder()
42        .orientation(gtk::Orientation::Vertical)
43        .visible(false)
44        .css_classes(["mimick-bottom-nav"])
45        .build();
46    root.append(&gtk::Separator::new(gtk::Orientation::Horizontal));
47    root.append(&revealer);
48    BottomNav {
49        root,
50        revealer,
51        buttons,
52    }
53}
54
55fn nav_button(label: &str, icon: &str) -> gtk::ToggleButton {
56    let content = gtk::Box::builder()
57        .orientation(gtk::Orientation::Vertical)
58        .spacing(2)
59        .build();
60    content.append(&gtk::Image::from_icon_name(icon));
61    content.append(
62        &gtk::Label::builder()
63            .label(label)
64            .ellipsize(gtk::pango::EllipsizeMode::End)
65            .css_classes(["caption"])
66            .build(),
67    );
68    gtk::ToggleButton::builder()
69        .child(&content)
70        .tooltip_text(label)
71        .css_classes(["flat"])
72        .build()
73}
74
75pub(super) fn connect_bottom_nav(ui: &Rc<LibraryWindowUi>) {
76    ui.bulk_bar
77        .bind_property("reveal-child", &ui.bottom_nav.revealer, "reveal-child")
78        .invert_boolean()
79        .sync_create()
80        .build();
81    for (key, button) in &ui.bottom_nav.buttons {
82        let (ui, key) = (ui.clone(), key.clone());
83        button.connect_clicked(move |_| {
84            if let Some(location) = super::navigation::location_for_key(&key) {
85                super::navigation::navigate(&ui, location);
86            }
87        });
88    }
89}
90
91pub(super) fn set_button_visible(nav: &BottomNav, key: &str, visible: bool) {
92    for (button_key, button) in &nav.buttons {
93        if button_key == key {
94            button.set_visible(visible);
95        }
96    }
97}
98
99pub(super) fn sync(nav: &BottomNav, active_key: &str) {
100    for (key, button) in &nav.buttons {
101        button.set_active(key == active_key);
102    }
103}