nrelm 0.1.0

An idiomatic GUI library inspired by Elm and based on gtk3-rs
use super::ContainerChild;
use gtk::prelude::*;

/// Extension trait that emulates GTK4's `set_child` API for widgets that
/// contain a single child.
pub trait RelmSetChildExt: ContainerChild {
    /// Replaces the child of the container. All existing children are removed
    /// first.
    fn container_set_child(&self, widget: Option<&impl AsRef<Self::Child>>);

    /// Returns the first child of the container, if it can be downcast to
    /// [`Self::Child`].
    fn container_get_child(&self) -> Option<Self::Child>;
}

macro_rules! set_child_impl {
    ($($type:ty), +) => {
        $(
            impl RelmSetChildExt for $type {
                fn container_set_child(&self, widget: Option<&impl AsRef<Self::Child>>) {
                    let self_ref: &gtk::Container = self.upcast_ref();
                    for child in self_ref.children() {
                        self_ref.remove(&child);
                    }
                    if let Some(widget) = widget {
                        self_ref.add(widget.as_ref());
                    }
                }

                fn container_get_child(&self) -> Option<Self::Child> {
                    let self_ref: &gtk::Container = self.upcast_ref();
                    self_ref.children().first().and_then(|child| child.clone().downcast::<Self::Child>().ok())
                }
            }
        )+
    }
}

set_child_impl!(
    gtk::Button,
    gtk::LinkButton,
    gtk::ToggleButton,
    gtk::FlowBoxChild,
    gtk::Frame,
    gtk::ListBoxRow,
    gtk::Popover,
    gtk::Window,
    gtk::ScrolledWindow,
    gtk::ApplicationWindow,
    gtk::Overlay,
    gtk::Revealer,
    gtk::Expander,
    gtk::AspectFrame,
    gtk::SearchBar,
    gtk::Viewport,
    gtk::MenuButton
);