1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
use crate::virtual_dom::VNode;
use std::any::Any;
use std::hash::Hash;
use self::behavior::{AnyComponentBehavior, Behavior};
pub mod behavior;
pub mod callback;
pub(crate) mod node;
pub(crate) mod scheduler;
/// Trait for defining custom component.
///
/// It adapts a MVC pattern.
/// Model is the fields and state of the component. It is initialized by [new](#tymethod.new) function using [Properties](#associatedtype.Properties).
/// View is the function [view](#tymethod.view) that returns a view of an application.
/// Controller is the function [update](#tymethod.update) that updates the model based on the [Message](#associatedtype.Message).
pub trait Component: Sized {
/// Type to describe the message that can be sent to the component.
/// It is used to update the model of the component.
type Message: 'static;
/// Type to describe the properties that can be passed to the component.
/// It is used to initialize the model of the component.
type Properties: Hash + 'static;
/// Function that creates a new instance of the component therefore initialize a model using [Properties](#associatedtype.Properties).
fn new(props: Self::Properties) -> Self;
/// Function that returns a view of the component.
/// It uses [Behavior](behavior::Behavior) to create [Callbacks](callback::Callback) that are responsible to send [Messages](#associatedtype.Message) to the component.
/// Defining the views is done using [rsx](../../wal_rsx/macro.rsx.html) macro.
/// Using the macro is not mandatory but it is recommended and makes in unnecessary to know the complex structure of [VNode].
fn view(&self, behavior: &mut impl Behavior<Self>) -> VNode;
/// Function that updates the model of the component based on the [Message](#associatedtype.Message).
/// It returns a boolean that indicates if the rerender of the component is necessary.
/// Meaning whether the view of the component should be updated or not.
fn update(&mut self, message: Self::Message) -> bool;
}
pub(crate) trait AnyComponent {
fn new(props: Box<dyn Any>) -> Self
where
Self: Sized;
fn view(&self, behavior: &mut AnyComponentBehavior) -> VNode;
fn update(&mut self, message: Box<dyn Any>) -> bool;
}
impl<C: Component> AnyComponent for C {
fn new(props: Box<dyn Any>) -> Self {
let props = *props.downcast::<C::Properties>().expect(
"Failed to downcast properties in any component to properties of a real component",
);
C::new(props)
}
fn view(&self, any_component_behavior: &mut AnyComponentBehavior) -> VNode {
self.view(any_component_behavior)
}
fn update(&mut self, message: Box<dyn Any>) -> bool {
let msg = *message
.downcast::<C::Message>()
.expect("Failed to downcast message in any component to message of a real component");
self.update(msg)
}
}