use super::mouse_area::MouseArea;
use crate::component::{ChildOf, Desc};
use crate::layout::{Layout, fixed};
use crate::persist::{FnPersist, VectorMap};
use crate::{Component, DRect, Slot, SourceID, layout};
use derive_where::derive_where;
use std::rc::Rc;
use std::sync::Arc;
#[derive_where(Clone)]
pub struct Button<T> {
pub id: Arc<SourceID>,
props: Rc<T>,
marea: MouseArea<DRect>,
children: im::Vector<Option<Box<ChildOf<dyn fixed::Prop>>>>,
}
impl<T: fixed::Prop> Button<T> {
pub fn new(
id: Arc<SourceID>,
props: T,
onclick: Slot,
children: im::Vector<Option<Box<ChildOf<dyn fixed::Prop>>>>,
) -> Self {
Self {
id: id.clone(),
props: props.into(),
marea: MouseArea::new(
id.child(crate::DataID::Named("__marea_internal__")),
crate::FILL_DRECT,
None,
[Some(onclick), None, None, None, None, None],
),
children,
}
}
}
impl<T: fixed::Prop> crate::StateMachineChild for Button<T> {
fn id(&self) -> Arc<SourceID> {
self.id.clone()
}
fn apply_children(
&self,
f: &mut dyn FnMut(&dyn crate::StateMachineChild) -> eyre::Result<()>,
) -> eyre::Result<()> {
self.children
.iter()
.try_for_each(|x| f(x.as_ref().unwrap().as_ref()))?;
f(&self.marea)
}
}
impl<T: fixed::Prop + 'static> Component for Button<T>
where
for<'a> &'a T: Into<&'a (dyn fixed::Prop + 'static)>,
{
type Props = T;
fn layout(
&self,
manager: &mut crate::StateManager,
driver: &crate::graphics::Driver,
window: &Arc<SourceID>,
) -> Box<dyn Layout<T>> {
let mut map = VectorMap::new(crate::persist::Persist::new(
|child: &Option<Box<ChildOf<dyn fixed::Prop>>>| -> Option<Box<dyn Layout<<dyn fixed::Prop as Desc>::Child>>> {
Some(child.as_ref()?.layout(manager, driver, window))
})
);
let (_, mut children) = map.call(Default::default(), &self.children);
children.push_back(Some(Box::new(self.marea.layout(manager, driver, window))));
Box::new(layout::Node::<T, dyn fixed::Prop> {
props: self.props.clone(),
children,
id: Arc::downgrade(&self.id),
renderable: None,
layer: None,
})
}
}