grx 0.3.2

Abstraction layer for UI development
Documentation
// SPDX-License-Identifier: GPL-3.0-or-later

//! A container that allows to switch between views.

use std::rc::Rc;

use glib::prelude::Cast;
use grx_macros::gtk_component;
use gtk::glib;
use gtk::prelude::WidgetExt;

use crate::props;

use super::gtk_props::apply;

#[props]
#[derive(Default, Debug)]
pub struct Props {}

#[gtk_component(libadwaita::ViewStack)]
#[derive(Debug)]
pub struct ViewStack {}

pub fn view_stack(mut props: Props) -> Rc<ViewStack> {
    let stack = libadwaita::ViewStack::builder().build();
    let children: &Vec<crate::grx::Component> = &props.children;
    for c in children {
        let annotations = c.annotations();
        if let Some(name) = annotations.get("name").and_then(|n| n.as_str()) {
            let widget: std::rc::Rc<gtk::Widget> = c.clone().inner().downcast().unwrap();
            let widget = widget.as_ref();
            widget.set_widget_name(name);
            let icon = annotations.get("icon").and_then(|i| i.as_str());

            if let Some(title) = annotations.get("title").and_then(|n| n.as_str()) {
                let page = stack.add_titled(widget, Some(name), title);
                page.set_icon_name(icon);
            } else {
                let page = stack.add_named(widget, Some(name));
                page.set_icon_name(icon);
            }

            if stack.visible_child_name().is_none() {
                stack.set_visible_child_name(name);
            }
        }
    }
    let component = crate::new_gc!(ViewStack { stack, props });
    apply(component.clone());
    component
}

impl ViewStack {
    pub fn set_visible_child_name(self: &Rc<Self>, name: &str) {
        self.widget.set_visible_child_name(name);
    }
    pub fn on_change_view(self: &Rc<Self>, handler: impl Fn(String) + 'static) {
        self.widget.connect_visible_child_notify(move |s| {
            if let Some(name) = s.visible_child_name() {
                handler(name.to_string())
            }
        });
    }
}