diff --git a/src/base/action.rs b/src/base/action.rs index 1e4debca..977ae9e2 100644 --- a/src/base/action.rs +++ b/src/base/action.rs @@ -1,5 +1,17 @@ //! Acciones predefinidas para alterar el funcionamiento interno de PageTop. +use crate::prelude::*; + +/// Tipo de función para manipular componentes y su contexto de renderizado. +/// +/// Se usa en acciones definidas en [`component`] y [`theme`] para alterar el comportamiento de los +/// componentes. +/// +/// Recibe referencias mutables (`&mut`) del componente `component` y del contexto `cx`. +pub type FnActionWithComponent = fn(component: &mut C, cx: &mut Context); + pub mod component; +pub mod theme; + pub mod page; diff --git a/src/base/action/component.rs b/src/base/action/component.rs index b25dd3b1..30c7ba4a 100644 --- a/src/base/action/component.rs +++ b/src/base/action/component.rs @@ -1,33 +1,7 @@ //! Acciones que operan sobre componentes. -use pagetop::prelude::*; - -/// Tipo de función para manipular componentes y su contexto de renderizado. -/// -/// Se usa en [`action::component::BeforeRender`] y [`action::component::AfterRender`] para alterar -/// el comportamiento predefinido de los componentes. -/// -/// Recibe referencias mutables (`&mut`) del componente `component` y del contexto `cx`. -pub type FnActionWithComponent = fn(component: &mut C, cx: &mut Context); - -/// Tipo de función para alterar el [`Markup`] generado por un componente. -/// -/// Se usa en [`action::component::TransformMarkup`] para permitir a las extensiones alterar el HTML -/// final producido por el renderizado de un componente. La edición trabaja a nivel de texto: el -/// [`Markup`] recibido expone su contenido como [`String`], lo que permite aplicar búsquedas, -/// sustituciones, concatenaciones y cualquier otra primitiva de trabajo con cadenas. -/// -/// La función recibe una referencia inmutable al componente `component` (el renderizado ya ha -/// concluido, solo se necesita leer su estado), una referencia mutable al contexto `cx`, y toma -/// posesión del `markup` producido hasta ese momento. Devuelve el nuevo [`Markup`] transformado, -/// que se encadena como entrada para la siguiente acción registrada, si la hay. -pub type FnActionTransformMarkup = fn(component: &C, cx: &mut Context, markup: Markup) -> Markup; - mod before_render_component; pub use before_render_component::*; mod after_render_component; pub use after_render_component::*; - -mod transform_markup_component; -pub use transform_markup_component::*; diff --git a/src/base/action/component/after_render_component.rs b/src/base/action/component/after_render_component.rs index 0778e9c8..c4fddffe 100644 --- a/src/base/action/component/after_render_component.rs +++ b/src/base/action/component/after_render_component.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -use super::FnActionWithComponent; +use crate::base::action::FnActionWithComponent; /// Ejecuta [`FnActionWithComponent`] después de renderizar un componente. pub struct AfterRender { @@ -57,14 +57,23 @@ impl AfterRender { 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::(), Some(UniqueId::of::()), None), + &ActionKey::new( + UniqueId::of::(), + None, + Some(UniqueId::of::()), + 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::(), Some(UniqueId::of::()), Some(id)), + &ActionKey::new( + UniqueId::of::(), + None, + Some(UniqueId::of::()), + Some(id), + ), |action: &Self| (action.f)(component, cx), ); } diff --git a/src/base/action/component/before_render_component.rs b/src/base/action/component/before_render_component.rs index 051a3dd6..7f0b5b57 100644 --- a/src/base/action/component/before_render_component.rs +++ b/src/base/action/component/before_render_component.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -use super::FnActionWithComponent; +use crate::base::action::FnActionWithComponent; /// Ejecuta [`FnActionWithComponent`] antes de renderizar el componente. pub struct BeforeRender { @@ -57,14 +57,23 @@ impl BeforeRender { 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::(), Some(UniqueId::of::()), None), + &ActionKey::new( + UniqueId::of::(), + None, + Some(UniqueId::of::()), + 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::(), Some(UniqueId::of::()), Some(id)), + &ActionKey::new( + UniqueId::of::(), + None, + Some(UniqueId::of::()), + Some(id), + ), |action: &Self| (action.f)(component, cx), ); } diff --git a/src/base/action/component/transform_markup_component.rs b/src/base/action/component/transform_markup_component.rs deleted file mode 100644 index 0dfd1f51..00000000 --- a/src/base/action/component/transform_markup_component.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::prelude::*; - -use super::FnActionTransformMarkup; - -/// Ejecuta [`FnActionTransformMarkup`] para alterar el renderizado de componentes. -pub struct TransformMarkup { - f: FnActionTransformMarkup, - referer_type_id: Option, - referer_id: AttrId, - weight: Weight, -} - -/// Filtro para despachar [`FnActionTransformMarkup`] sobre el renderizado de un componente `C`. -impl ActionDispatcher for TransformMarkup { - /// 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 TransformMarkup { - /// Permite [registrar](Extension::actions) una nueva acción [`FnActionTransformMarkup`]. - pub fn new(f: FnActionTransformMarkup) -> Self { - TransformMarkup { - f, - referer_type_id: Some(UniqueId::of::()), - referer_id: AttrId::default(), - weight: 0, - } - } - - /// Afina el registro para ejecutar la acción [`FnActionTransformMarkup`] 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_id(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 encadenando el [`Markup`] entre cada una. - #[inline] - pub(crate) fn dispatch(component: &C, cx: &mut Context, markup: Markup) -> Markup { - let mut output = markup; - - // Primero despacha las acciones para el tipo de componente. - dispatch_actions( - &ActionKey::new(UniqueId::of::(), Some(UniqueId::of::()), None), - |action: &Self| { - let taken = std::mem::replace(&mut output, html! {}); - output = (action.f)(component, cx, taken); - }, - ); - - // 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::(), Some(UniqueId::of::()), Some(id)), - |action: &Self| { - let taken = std::mem::replace(&mut output, html! {}); - output = (action.f)(component, cx, taken); - }, - ); - } - - output - } -} diff --git a/src/base/action/page/after_render_body.rs b/src/base/action/page/after_render_body.rs index 74ee0df1..7ecc353a 100644 --- a/src/base/action/page/after_render_body.rs +++ b/src/base/action/page/after_render_body.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -use super::FnActionWithPage; +use crate::base::action::page::FnActionWithPage; /// Ejecuta [`FnActionWithPage`](crate::base::action::page::FnActionWithPage) después de renderizar /// el cuerpo de la página. @@ -39,7 +39,7 @@ impl AfterRenderBody { #[allow(clippy::inline_always)] pub(crate) fn dispatch(page: &mut Page) { dispatch_actions( - &ActionKey::new(UniqueId::of::(), None, None), + &ActionKey::new(UniqueId::of::(), None, None, None), |action: &Self| (action.f)(page), ); } diff --git a/src/base/action/page/before_render_body.rs b/src/base/action/page/before_render_body.rs index 7a72854f..d4ae64d0 100644 --- a/src/base/action/page/before_render_body.rs +++ b/src/base/action/page/before_render_body.rs @@ -1,6 +1,6 @@ use crate::prelude::*; -use super::FnActionWithPage; +use crate::base::action::page::FnActionWithPage; /// Ejecuta [`FnActionWithPage`](crate::base::action::page::FnActionWithPage) antes de renderizar /// el cuerpo de la página. @@ -39,7 +39,7 @@ impl BeforeRenderBody { #[allow(clippy::inline_always)] pub(crate) fn dispatch(page: &mut Page) { dispatch_actions( - &ActionKey::new(UniqueId::of::(), None, None), + &ActionKey::new(UniqueId::of::(), None, None, None), |action: &Self| (action.f)(page), ); } diff --git a/src/base/action/theme.rs b/src/base/action/theme.rs new file mode 100644 index 00000000..a3db61a0 --- /dev/null +++ b/src/base/action/theme.rs @@ -0,0 +1,7 @@ +//! Acciones lanzadas desde los temas. + +mod before_render_component; +pub use before_render_component::*; + +mod after_render_component; +pub use after_render_component::*; diff --git a/src/base/action/theme/after_render_component.rs b/src/base/action/theme/after_render_component.rs new file mode 100644 index 00000000..a31ad56a --- /dev/null +++ b/src/base/action/theme/after_render_component.rs @@ -0,0 +1,50 @@ +use crate::prelude::*; + +use crate::base::action::FnActionWithComponent; + +/// Ejecuta [`FnActionWithComponent`] después de que un tema renderice el componente. +pub struct AfterRender { + f: FnActionWithComponent, + theme_type_id: Option, + referer_type_id: Option, +} + +/// Filtro para despachar [`FnActionWithComponent`] después de que un tema renderice el componente +/// `C`. +impl ActionDispatcher for AfterRender { + /// Devuelve el identificador de tipo ([`UniqueId`]) del tema. + fn theme_type_id(&self) -> Option { + self.theme_type_id + } + + /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. + fn referer_type_id(&self) -> Option { + self.referer_type_id + } +} + +impl AfterRender { + /// Permite [registrar](Extension::actions) una nueva acción [`FnActionWithComponent`] para un + /// tema dado. + pub fn new(theme: ThemeRef, f: FnActionWithComponent) -> Self { + AfterRender { + f, + theme_type_id: Some(theme.type_id()), + referer_type_id: Some(UniqueId::of::()), + } + } + + /// Despacha las acciones. + #[inline] + pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { + dispatch_actions( + &ActionKey::new( + UniqueId::of::(), + Some(cx.theme().type_id()), + Some(UniqueId::of::()), + None, + ), + |action: &Self| (action.f)(component, cx), + ); + } +} diff --git a/src/base/action/theme/before_render_component.rs b/src/base/action/theme/before_render_component.rs new file mode 100644 index 00000000..c00de8e9 --- /dev/null +++ b/src/base/action/theme/before_render_component.rs @@ -0,0 +1,50 @@ +use crate::prelude::*; + +use crate::base::action::FnActionWithComponent; + +/// Ejecuta [`FnActionWithComponent`] antes de que un tema renderice el componente. +pub struct BeforeRender { + f: FnActionWithComponent, + theme_type_id: Option, + referer_type_id: Option, +} + +/// Filtro para despachar [`FnActionWithComponent`] antes de que un tema renderice el componente +/// `C`. +impl ActionDispatcher for BeforeRender { + /// Devuelve el identificador de tipo ([`UniqueId`]) del tema. + fn theme_type_id(&self) -> Option { + self.theme_type_id + } + + /// Devuelve el identificador de tipo ([`UniqueId`]) del componente `C`. + fn referer_type_id(&self) -> Option { + self.referer_type_id + } +} + +impl BeforeRender { + /// Permite [registrar](Extension::actions) una nueva acción [`FnActionWithComponent`] para un + /// tema dado. + pub fn new(theme: ThemeRef, f: FnActionWithComponent) -> Self { + BeforeRender { + f, + theme_type_id: Some(theme.type_id()), + referer_type_id: Some(UniqueId::of::()), + } + } + + /// Despacha las acciones. + #[inline] + pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { + dispatch_actions( + &ActionKey::new( + UniqueId::of::(), + Some(cx.theme().type_id()), + Some(UniqueId::of::()), + None, + ), + |action: &Self| (action.f)(component, cx), + ); + } +} diff --git a/src/core/action.rs b/src/core/action.rs index ceb5eef4..92b3f1aa 100644 --- a/src/core/action.rs +++ b/src/core/action.rs @@ -14,7 +14,7 @@ mod all; pub(crate) use all::add_action; pub use all::dispatch_actions; -// **< actions! >*********************************************************************************** +// **< actions_boxed! >***************************************************************************** /// Facilita la implementación del método [`actions()`](crate::core::extension::Extension::actions). /// @@ -23,28 +23,23 @@ pub use all::dispatch_actions; /// /// # Ejemplo /// -/// Extensión que ajusta un botón antes de renderizarlo y transforma su HTML final: -/// /// ```rust,ignore -/// impl Extension for MyExtension { +/// impl Extension for MyTheme { /// fn actions(&self) -> Vec { -/// actions![ -/// action::component::BeforeRender::