use glib::{Cast, IsA, Object};
use gtk::{prelude::ContainerExt, prelude::WidgetExt};
use crate::state::EventStream;
use super::{Component, DisplayVariant, StreamHandle, create_widget, init_component};
use crate::widget::Widget;
pub struct ContainerComponent<WIDGET: Container + Widget> {
component: Component<WIDGET>,
pub container: WIDGET::Container,
pub containers: WIDGET::Containers,
}
impl<WIDGET: Container + Widget> ContainerComponent<WIDGET> {
#[doc(hidden)]
pub fn new(component: Component<WIDGET>, container: WIDGET::Container, containers: WIDGET::Containers) -> Self {
ContainerComponent {
component,
container,
containers,
}
}
pub fn add<CHILDWIDGET: IsA<gtk::Widget>>(&self, widget: &CHILDWIDGET) {
self.container.add(widget);
}
pub fn add_widget<CHILDWIDGET>(&self, model_param: CHILDWIDGET::ModelParam)
-> Component<CHILDWIDGET>
where CHILDWIDGET: Widget + 'static,
WIDGET::Container: ContainerExt + IsA<gtk::Widget> + IsA<Object>,
{
let (component, widget, child_relm) = create_widget::<CHILDWIDGET>(model_param);
let container = WIDGET::add_widget(self, &component);
widget.on_add(container);
init_component::<CHILDWIDGET>(component.owned_stream(), widget, &child_relm);
component
}
pub fn emit(&self, msg: WIDGET::Msg) {
self.owned_stream().emit(msg);
}
pub fn owned_stream(&self) -> &EventStream<WIDGET::Msg> {
self.component.owned_stream()
}
pub fn stream(&self) -> StreamHandle<WIDGET::Msg> {
self.component.stream()
}
pub fn widget(&self) -> &WIDGET::Root {
self.component.widget()
}
}
pub trait Container: Widget {
type Container: Clone + IsA<gtk::Container> + IsA<Object> + IsA<gtk::Widget>;
type Containers: Clone;
fn add_widget<WIDGET: Widget>(container: &ContainerComponent<Self>, component: &Component<WIDGET>)
-> gtk::Container
{
container.container.add(component.widget());
container.container.clone().upcast()
}
fn container(&self) -> &Self::Container;
fn other_containers(&self) -> Self::Containers;
}
pub trait ContainerWidget {
fn add_container<CHILDWIDGET>(&self, model_param: CHILDWIDGET::ModelParam)
-> ContainerComponent<CHILDWIDGET>
where CHILDWIDGET: Container + Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt;
fn add_widget<CHILDWIDGET>(&self, model_param: CHILDWIDGET::ModelParam)
-> Component<CHILDWIDGET>
where CHILDWIDGET: Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt;
fn remove_widget<CHILDWIDGET>(&self, component: Component<CHILDWIDGET>)
where CHILDWIDGET: Widget,
CHILDWIDGET::Root: IsA<gtk::Widget>;
}
impl<W: Clone + ContainerExt + IsA<gtk::Widget> + IsA<Object>> ContainerWidget for W {
fn add_container<CHILDWIDGET>(&self, model_param: CHILDWIDGET::ModelParam)
-> ContainerComponent<CHILDWIDGET>
where CHILDWIDGET: Container + Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt,
{
let (component, widget, child_relm) = create_widget::<CHILDWIDGET>(model_param);
let container = widget.container().clone();
let containers = widget.other_containers();
let root = widget.root();
self.add(&root);
widget.on_add(self.clone());
init_component::<CHILDWIDGET>(component.owned_stream(), widget, &child_relm);
ContainerComponent::new(component, container, containers)
}
fn add_widget<CHILDWIDGET>(&self, model_param: CHILDWIDGET::ModelParam)
-> Component<CHILDWIDGET>
where CHILDWIDGET: Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt,
{
let (component, widget, child_relm) = create_widget::<CHILDWIDGET>(model_param);
self.add(component.widget());
widget.on_add(self.clone());
init_component::<CHILDWIDGET>(component.owned_stream(), widget, &child_relm);
component
}
fn remove_widget<WIDGET>(&self, component: Component<WIDGET>)
where WIDGET: Widget,
WIDGET::Root: IsA<gtk::Widget>,
{
self.remove(component.widget());
}
}