use crate::prelude::*; /// Tipo de función para determinar si un componente se renderiza o no. /// /// Se usa en la acción [`IsRenderable`] para controlar dinámicamente la visibilidad del componente /// `component` según el contexto `cx`. El componente **no se renderiza** en cuanto una de las /// funciones devuelva `false`. pub type FnIsRenderable = fn(component: &C, cx: &Context) -> bool; /// Con la función [`FnIsRenderable`] se puede decidir si se renderiza o no un componente. pub struct IsRenderable { f: FnIsRenderable, referer_type_id: Option, referer_id: OptionId, weight: Weight, } /// Filtro para despachar [`FnIsRenderable`] para decidir si se renderiza o no un componente `C`. impl ActionDispatcher for IsRenderable { /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. fn referer_type_id(&self) -> Option { self.referer_type_id } /// Devuelve el identificador del componente. fn referer_id(&self) -> Option { self.referer_id.get() } /// Devuelve el peso para definir el orden de ejecución. fn weight(&self) -> Weight { self.weight } } impl IsRenderable { /// Permite [registrar](Extension::actions) una nueva acción [`FnIsRenderable`]. pub fn new(f: FnIsRenderable) -> Self { IsRenderable { f, referer_type_id: Some(UniqueId::of::()), referer_id: OptionId::default(), weight: 0, } } /// Afina el registro para ejecutar la acción [`FnIsRenderable`] sólo para el componente `C` /// con identificador `id`. pub fn filter_by_referer_id(mut self, id: impl AsRef) -> Self { self.referer_id.alter_value(id); self } /// Opcional. Acciones con pesos más bajos se aplican antes. Se pueden usar valores negativos. pub fn with_weight(mut self, value: Weight) -> Self { self.weight = value; self } // Despacha las acciones. Se detiene en cuanto una [`FnIsRenderable`] devuelve `false`. #[inline] pub(crate) fn dispatch(component: &C, cx: &mut Context) -> bool { let mut renderable = true; dispatch_actions( &ActionKey::new( UniqueId::of::(), None, Some(UniqueId::of::()), None, ), |action: &Self| { if renderable && !(action.f)(component, cx) { renderable = false; } }, ); if renderable { if let Some(id) = component.id() { dispatch_actions( &ActionKey::new( UniqueId::of::(), None, Some(UniqueId::of::()), Some(id), ), |action: &Self| { if renderable && !(action.f)(component, cx) { renderable = false; } }, ); } } renderable } }