use glib::Cast;
use gtk;
use gtk::{ContainerExt, IsA, Object, WidgetExt};
use relm_state::EventStream;
use super::{Component, DisplayVariant, Relm, create_widget, init_component};
use 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, PARENTWIDGET>(&self, relm: &Relm<PARENTWIDGET>, model_param: CHILDWIDGET::ModelParam)
-> Component<CHILDWIDGET>
where CHILDWIDGET: Widget + 'static,
PARENTWIDGET: Widget,
WIDGET::Container: ContainerExt + IsA<gtk::Widget> + IsA<Object>,
{
let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(relm.executor(), model_param);
let container = WIDGET::add_widget(self, &widget);
component.on_add(container);
init_component::<CHILDWIDGET>(widget.stream(), component, relm.executor(), &child_relm);
widget
}
pub fn emit(&self, msg: WIDGET::Msg) {
self.stream().emit(msg);
}
pub fn stream(&self) -> &EventStream<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;
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, WIDGET>(&self, relm: &Relm<WIDGET>, model_param: CHILDWIDGET::ModelParam)
-> ContainerComponent<CHILDWIDGET>
where CHILDWIDGET: Container + Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt,
WIDGET: Widget;
fn add_widget<CHILDWIDGET, WIDGET>(&self, relm: &Relm<WIDGET>, model_param: CHILDWIDGET::ModelParam)
-> Component<CHILDWIDGET>
where CHILDWIDGET: Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt,
WIDGET: Widget;
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, WIDGET>(&self, relm: &Relm<WIDGET>, model_param: CHILDWIDGET::ModelParam)
-> ContainerComponent<CHILDWIDGET>
where CHILDWIDGET: Container + Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt,
WIDGET: Widget,
{
let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(relm.executor(), model_param);
let container = component.container().clone();
let containers = component.other_containers();
let root = component.root().clone();
self.add(&root);
component.on_add(self.clone());
init_component::<CHILDWIDGET>(widget.stream(), component, relm.executor(), &child_relm);
ContainerComponent::new(widget, container, containers)
}
fn add_widget<CHILDWIDGET, WIDGET>(&self, relm: &Relm<WIDGET>, model_param: CHILDWIDGET::ModelParam)
-> Component<CHILDWIDGET>
where CHILDWIDGET: Widget + 'static,
CHILDWIDGET::Msg: DisplayVariant + 'static,
CHILDWIDGET::Root: IsA<gtk::Widget> + IsA<Object> + WidgetExt,
WIDGET: Widget,
{
let (widget, component, child_relm) = create_widget::<CHILDWIDGET>(relm.executor(), model_param);
self.add(widget.widget());
component.on_add(self.clone());
init_component::<CHILDWIDGET>(widget.stream(), component, relm.executor(), &child_relm);
widget
}
fn remove_widget<WIDGET>(&self, component: Component<WIDGET>)
where WIDGET: Widget,
WIDGET::Root: IsA<gtk::Widget>,
{
self.remove(component.widget());
}
}