macro_rules! ferro_class {
(@class_members $name:ident) => { ... };
(@register_class $name:ident : $base:ident) => { ... };
(@common $name:ident : $base:ident) => { ... };
($name:ident : $base:ident) => { ... };
(
$name:ident : $base:ident, virtuals $impl_trait:ident : $parent_impl:path {
$(
$(#[$meta:meta])*
fn $method:ident(this $(, $arg:ident : $arg_ty:ty)* $(,)?) $(-> $ret:ty)?;
)*
}
) => { ... };
}Expand description
Declares a class.
ⓘ
#[repr(C)]
pub struct Decorator { base: Control, /* fields */ }
// A class without new virtual members:
ferro_class!(Decorator: Control);
// A class that introduces virtual members:
ferro_class! {
Layoutable: Visual, virtuals LayoutableImpl: VisualImpl {
/// Measures the control.
fn measure_override(this, available_size: Size) -> Size;
fn arrange_override(this, final_size: Size) -> Size;
}
}Both forms generate Deref<Target = Base>, Upcast to every ancestor,
the TYPE runtime type and ObjectType, including the static
initialisation of the class (ObjectType::register_class). What the
initialisation does is taken from the other declarations of the class,
each optional and found by the macro without being named here:
ferro_properties! { impl Decorator { .. } }, the property definitions;fn static_constructor(), an inherent function declared in the same module (ClassDefaults::static_constructor);ferro_class_info!(Decorator { new: Decorator::new, interfaces: [..] }), the default constructor and the interface handles the class converts to.
The second form also generates:
LayoutableVTable, the table of the new members;trait LayoutableImpl, with one associated function per member takingthis: &Self. Every class deriving fromLayoutableimplements it (impl LayoutableImpl for Border {}) and overrides what it needs ([ferro_impl_classes!] and [ferro_overrides!] write the same implementation and state what it overrides, which shortens the calls);LayoutableImplExt::parent_<member>, to call the base implementation from an override;Layoutable::<member>(&self, ..), which performs the virtual call.
The declaring class must implement every member itself; these are the base implementations.