✨ Añade acciones base y renderizado de componentes
- Añade acciones BeforeRender y AfterRender para ejecutar código personalizado antes y después de renderizar un componente. - Introduce la acción PrepareRender para personalizar totalmente el renderizado de un componente. - Se actualizan las definiciones de acciones para utilizar el nuevo "trait" ActionDispatcher. - Se crea un nuevo trait ComponentTrait para definir componentes renderizables. - Se implementan las estructuras Children y Child para gestionar componentes hijos dentro de un componente padre. - Se añade OptionComponent para encapsular de forma segura componentes opcionales y poder usarlos en otros componentes.
This commit is contained in:
parent
f76a208520
commit
37df2ada75
28 changed files with 1102 additions and 147 deletions
81
src/base/action/component/after_render_component.rs
Normal file
81
src/base/action/component/after_render_component.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
use crate::base::action::FnActionWithComponent;
|
||||
|
||||
/// Ejecuta [`FnActionWithComponent`] después de renderizar un componente.
|
||||
pub struct AfterRender<C: ComponentTrait> {
|
||||
f: FnActionWithComponent<C>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
referer_id: OptionId,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
/// Filtro para despachar [`FnActionWithComponent`] después de renderizar un componente `C`.
|
||||
impl<C: ComponentTrait> ActionDispatcher for AfterRender<C> {
|
||||
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
|
||||
fn referer_type_id(&self) -> Option<UniqueId> {
|
||||
self.referer_type_id
|
||||
}
|
||||
|
||||
/// Devuelve el identificador del componente.
|
||||
fn referer_id(&self) -> Option<String> {
|
||||
self.referer_id.get()
|
||||
}
|
||||
|
||||
/// Devuelve el peso para definir el orden de aplicación.
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> AfterRender<C> {
|
||||
/// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`].
|
||||
pub fn new(f: FnActionWithComponent<C>) -> Self {
|
||||
AfterRender {
|
||||
f,
|
||||
referer_type_id: Some(UniqueId::of::<C>()),
|
||||
referer_id: OptionId::default(),
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Afina el registro para ejecutar la acción [`FnActionWithComponent`] sólo para el componente
|
||||
/// `C` con identificador `id`.
|
||||
pub fn filter_by_referer_id(mut self, id: impl AsRef<str>) -> 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.
|
||||
#[inline]
|
||||
pub(crate) fn dispatch(component: &mut C, cx: &mut Context) {
|
||||
// Primero despacha las acciones para el tipo de componente.
|
||||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
None,
|
||||
Some(UniqueId::of::<C>()),
|
||||
None,
|
||||
),
|
||||
|action: &Self| (action.f)(component, cx),
|
||||
);
|
||||
// Y luego despacha las acciones para el tipo de componente con un identificador dado.
|
||||
if let Some(id) = component.id() {
|
||||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
None,
|
||||
Some(UniqueId::of::<C>()),
|
||||
Some(id),
|
||||
),
|
||||
|action: &Self| (action.f)(component, cx),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
81
src/base/action/component/before_render_component.rs
Normal file
81
src/base/action/component/before_render_component.rs
Normal file
|
@ -0,0 +1,81 @@
|
|||
use crate::prelude::*;
|
||||
|
||||
use crate::base::action::FnActionWithComponent;
|
||||
|
||||
/// Ejecuta [`FnActionWithComponent`] antes de renderizar el componente.
|
||||
pub struct BeforeRender<C: ComponentTrait> {
|
||||
f: FnActionWithComponent<C>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
referer_id: OptionId,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
/// Filtro para despachar [`FnActionWithComponent`] antes de renderizar un componente `C`.
|
||||
impl<C: ComponentTrait> ActionDispatcher for BeforeRender<C> {
|
||||
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
|
||||
fn referer_type_id(&self) -> Option<UniqueId> {
|
||||
self.referer_type_id
|
||||
}
|
||||
|
||||
/// Devuelve el identificador del componente.
|
||||
fn referer_id(&self) -> Option<String> {
|
||||
self.referer_id.get()
|
||||
}
|
||||
|
||||
/// Devuelve el peso para definir el orden de aplicación.
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> BeforeRender<C> {
|
||||
/// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnActionWithComponent`].
|
||||
pub fn new(f: FnActionWithComponent<C>) -> Self {
|
||||
BeforeRender {
|
||||
f,
|
||||
referer_type_id: Some(UniqueId::of::<C>()),
|
||||
referer_id: OptionId::default(),
|
||||
weight: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Afina el registro para ejecutar la acción [`FnActionWithComponent`] sólo para el componente
|
||||
/// `C` con identificador `id`.
|
||||
pub fn filter_by_referer_id(mut self, id: impl AsRef<str>) -> 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.
|
||||
#[inline]
|
||||
pub(crate) fn dispatch(component: &mut C, cx: &mut Context) {
|
||||
// Primero despacha las acciones para el tipo de componente.
|
||||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
None,
|
||||
Some(UniqueId::of::<C>()),
|
||||
None,
|
||||
),
|
||||
|action: &Self| (action.f)(component, cx),
|
||||
);
|
||||
// Y luego despacha las aciones para el tipo de componente con un identificador dado.
|
||||
if let Some(id) = component.id() {
|
||||
dispatch_actions(
|
||||
&ActionKey::new(
|
||||
UniqueId::of::<Self>(),
|
||||
None,
|
||||
Some(UniqueId::of::<C>()),
|
||||
Some(id),
|
||||
),
|
||||
|action: &Self| (action.f)(component, cx),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
96
src/base/action/component/is_renderable.rs
Normal file
96
src/base/action/component/is_renderable.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
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<C> = fn(component: &C, cx: &Context) -> bool;
|
||||
|
||||
/// Con la función [`FnIsRenderable`] se puede decidir si se renderiza o no un componente.
|
||||
pub struct IsRenderable<C: ComponentTrait> {
|
||||
f: FnIsRenderable<C>,
|
||||
referer_type_id: Option<UniqueId>,
|
||||
referer_id: OptionId,
|
||||
weight: Weight,
|
||||
}
|
||||
|
||||
/// Filtro para despachar [`FnIsRenderable`] para decidir si se renderiza o no un componente `C`.
|
||||
impl<C: ComponentTrait> ActionDispatcher for IsRenderable<C> {
|
||||
/// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`.
|
||||
fn referer_type_id(&self) -> Option<UniqueId> {
|
||||
self.referer_type_id
|
||||
}
|
||||
|
||||
/// Devuelve el identificador del componente.
|
||||
fn referer_id(&self) -> Option<String> {
|
||||
self.referer_id.get()
|
||||
}
|
||||
|
||||
/// Devuelve el peso para definir el orden de aplicación.
|
||||
fn weight(&self) -> Weight {
|
||||
self.weight
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: ComponentTrait> IsRenderable<C> {
|
||||
/// Permite [registrar](ExtensionTrait::actions) una nueva acción [`FnIsRenderable`].
|
||||
pub fn new(f: FnIsRenderable<C>) -> Self {
|
||||
IsRenderable {
|
||||
f,
|
||||
referer_type_id: Some(UniqueId::of::<C>()),
|
||||
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<str>) -> 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::<Self>(),
|
||||
None,
|
||||
Some(UniqueId::of::<C>()),
|
||||
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::<Self>(),
|
||||
None,
|
||||
Some(UniqueId::of::<C>()),
|
||||
Some(id),
|
||||
),
|
||||
|action: &Self| {
|
||||
if renderable && !(action.f)(component, cx) {
|
||||
renderable = false;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
renderable
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue