pub trait Component: StateMachineChild + DynClone {
type Props: 'static;
// Required method
fn layout(
&self,
state: &mut StateManager,
driver: &Driver,
window: &Arc<SourceID>,
) -> Box<dyn Layout<Self::Props> + 'static>;
}
Expand description
The trait representing an arbitrary UI component. The Props associated type must be used to expose the concrete property type that was used to instantiate the component. This is expect to be different, so it is assumed that almost all components are generic over the property type, so long as the property type satisfies the requirements of the chosen layout.
All components must implement StateMachineChild
even if they are stateless,
a derive macro is provided to implement an empty version of the trait for you.
In addition, the component must enforce some rather specific constraints due to
limitations of the rust type system to properly capture them. See the example
for what the simplest possible component looks like.
§Examples
use feather_ui::component::{Component};
use feather_ui::layout::base;
use feather_ui::{ StateMachineChild, SourceID, layout, graphics, StateManager };
use std::sync::Arc;
use std::rc::Rc;
// #[derive(feather_macro::StateMachineChild)]
// This derive macro simply implements the following. The implementation would be
// more complex if our component had children, which the derive macro also handles.
impl<T> StateMachineChild for MyComponent<T> {
fn id(&self) -> Arc<SourceID> {
self.id.clone()
}
}
#[derive_where::derive_where(Clone)]
pub struct MyComponent<T> {
pub id: Arc<SourceID>,
pub props: Rc<T>,
}
impl<T: base::Empty + 'static> Component for MyComponent<T>
where
for<'a> &'a T: Into<&'a (dyn base::Empty + 'static)>,
{
type Props = T;
fn layout(
&self,
_: &mut StateManager,
_: &graphics::Driver,
_: &Arc<SourceID>,
) -> Box<dyn layout::Layout<T>> {
Box::new(layout::Node::<T, dyn base::Empty> {
props: self.props.clone(),
children: Default::default(),
id: Arc::downgrade(&self.id),
renderable: None,
layer: None,
})
}
}