feather_ui/component/
button.rs1use super::mouse_area::MouseArea;
5
6use crate::component::{ChildOf, Desc};
7use crate::layout::{Layout, fixed};
8use crate::persist::{FnPersist, VectorMap};
9use crate::{Component, DRect, Slot, SourceID, layout};
10use derive_where::derive_where;
11use std::rc::Rc;
12use std::sync::Arc;
13
14#[derive_where(Clone)]
16pub struct Button<T> {
17 pub id: Arc<SourceID>,
18 props: Rc<T>,
19 marea: MouseArea<DRect>,
20 children: im::Vector<Option<Box<ChildOf<dyn fixed::Prop>>>>,
21}
22
23impl<T: fixed::Prop + 'static> Button<T> {
24 pub fn new(
25 id: Arc<SourceID>,
26 props: T,
27 onclick: Slot,
28 children: im::Vector<Option<Box<ChildOf<dyn fixed::Prop>>>>,
29 ) -> Self {
30 Self {
31 id: id.clone(),
32 props: props.into(),
33 marea: MouseArea::new(
34 id.child(crate::DataID::Named("__marea_internal__")),
35 crate::FILL_DRECT,
36 None,
37 [Some(onclick), None, None, None, None, None],
38 ),
39 children,
40 }
41 }
42}
43
44impl<T: fixed::Prop + 'static> crate::StateMachineChild for Button<T> {
45 fn id(&self) -> Arc<SourceID> {
46 self.id.clone()
47 }
48
49 fn apply_children(
50 &self,
51 f: &mut dyn FnMut(&dyn crate::StateMachineChild) -> eyre::Result<()>,
52 ) -> eyre::Result<()> {
53 self.children
54 .iter()
55 .try_for_each(|x| f(x.as_ref().unwrap().as_ref()))?;
56 f(&self.marea)
57 }
58}
59
60impl<T: fixed::Prop + 'static> Component for Button<T>
61where
62 for<'a> &'a T: Into<&'a (dyn fixed::Prop + 'static)>,
63{
64 type Props = T;
65
66 fn layout(
67 &self,
68 manager: &mut crate::StateManager,
69 driver: &crate::graphics::Driver,
70 window: &Arc<SourceID>,
71 ) -> Box<dyn Layout<T>> {
72 let mut map = VectorMap::new(crate::persist::Persist::new(
73 |child: &Option<Box<ChildOf<dyn fixed::Prop>>>| -> Option<Box<dyn Layout<<dyn fixed::Prop as Desc>::Child>>> {
74 Some(child.as_ref()?.layout(manager, driver, window))
75 })
76 );
77
78 let (_, mut children) = map.call(Default::default(), &self.children);
79 children.push_back(Some(Box::new(self.marea.layout(manager, driver, window))));
80
81 Box::new(layout::Node::<T, dyn fixed::Prop> {
82 props: self.props.clone(),
83 children,
84 id: Arc::downgrade(&self.id),
85 renderable: None,
86 layer: None,
87 })
88 }
89}