From 616d7ee20712af761062cb0d48a2b6dc66b0898a Mon Sep 17 00:00:00 2001 From: Manuel Cillero Date: Sat, 16 Jul 2022 21:16:38 +0200 Subject: [PATCH] =?UTF-8?q?A=C3=B1ade=20hook=20previo=20antes=20de=20rende?= =?UTF-8?q?rizar=20componentes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pagetop/Cargo.toml | 1 + pagetop/src/base/component/block.rs | 9 +++ pagetop/src/base/component/container.rs | 9 +++ pagetop/src/base/component/form/form.rs | 9 +++ pagetop/src/base/component/grid/column.rs | 9 +++ pagetop/src/base/component/grid/row.rs | 9 +++ pagetop/src/base/component/menu.rs | 12 +++- pagetop/src/core/component.rs | 6 -- pagetop/src/core/component/definition.rs | 75 ++++++++++++++++++++--- pagetop/src/core/component/hook.rs | 48 --------------- pagetop/src/core/hook.rs | 6 +- pagetop/src/core/hook/all.rs | 2 +- pagetop/src/core/hook/definition.rs | 2 +- pagetop/src/prelude.rs | 11 +++- pagetop/src/response/page/definition.rs | 6 +- pagetop/src/response/page/hook.rs | 6 +- 16 files changed, 145 insertions(+), 75 deletions(-) delete mode 100644 pagetop/src/core/component/hook.rs diff --git a/pagetop/Cargo.toml b/pagetop/Cargo.toml index 1e9ce156..6292a160 100644 --- a/pagetop/Cargo.toml +++ b/pagetop/Cargo.toml @@ -27,6 +27,7 @@ doc-comment = "0.3.3" figlet-rs = "0.1.3" futures = "0.3.21" once_cell = "1.12.0" +paste = "1.0.7" substring = "1.4.5" term_size = "0.3.2" url = "2.2.2" diff --git a/pagetop/src/base/component/block.rs b/pagetop/src/base/component/block.rs index 868751fc..8740d522 100644 --- a/pagetop/src/base/component/block.rs +++ b/pagetop/src/base/component/block.rs @@ -2,6 +2,11 @@ use crate::prelude::*; pub const COMPONENT_BLOCK: &str = "pagetop::component::block"; +hook_before_render_component!( + HOOK_BEFORE_RENDER_BLOCK = "pagetop::action::before_render_block", + Block +); + pub struct Block { weight : isize, renderable: Renderable, @@ -37,6 +42,10 @@ impl ComponentTrait for Block { (self.renderable)(context) } + fn before_render(&mut self, context: &mut InContext) { + before_render_inline(self, context); + } + fn default_render(&self, context: &mut InContext) -> Markup { let id = context.required_id::(self.id()); html! { diff --git a/pagetop/src/base/component/container.rs b/pagetop/src/base/component/container.rs index fe49e224..2f64e762 100644 --- a/pagetop/src/base/component/container.rs +++ b/pagetop/src/base/component/container.rs @@ -2,6 +2,11 @@ use crate::prelude::*; pub const COMPONENT_CONTAINER: &str = "pagetop::component::container"; +hook_before_render_component!( + HOOK_BEFORE_RENDER_CONTAINER = "pagetop::action::before_render_container", + Container +); + pub enum ContainerType { Header, Footer, Main, Section, Wrapper } pub struct Container { @@ -41,6 +46,10 @@ impl ComponentTrait for Container { (self.renderable)(context) } + fn before_render(&mut self, context: &mut InContext) { + before_render_inline(self, context); + } + fn default_render(&self, context: &mut InContext) -> Markup { match self.container_type() { ContainerType::Header => html! { diff --git a/pagetop/src/base/component/form/form.rs b/pagetop/src/base/component/form/form.rs index f331700d..cfe973ba 100644 --- a/pagetop/src/base/component/form/form.rs +++ b/pagetop/src/base/component/form/form.rs @@ -2,6 +2,11 @@ use crate::prelude::*; pub const COMPONENT_FORM: &str = "pagetop::component::form"; +hook_before_render_component!( + HOOK_BEFORE_RENDER_FORM = "pagetop::action::before_render_form", + Form +); + pub enum FormMethod {Get, Post} pub struct Form { @@ -43,6 +48,10 @@ impl ComponentTrait for Form { (self.renderable)(context) } + fn before_render(&mut self, context: &mut InContext) { + before_render_inline(self, context); + } + fn default_render(&self, context: &mut InContext) -> Markup { let method = match self.method() { FormMethod::Get => None, diff --git a/pagetop/src/base/component/grid/column.rs b/pagetop/src/base/component/grid/column.rs index 80d70fd0..0a988599 100644 --- a/pagetop/src/base/component/grid/column.rs +++ b/pagetop/src/base/component/grid/column.rs @@ -2,6 +2,11 @@ use crate::prelude::*; pub const COMPONENT_COLUMN: &str = "pagetop::component::grid::column"; +hook_before_render_component!( + HOOK_BEFORE_RENDER_COLUMN = "pagetop::action::before_render_column", + Column +); + const SIZE_DEFAULT: &str = "col-md"; const SIZE_1_OF_12: &str = "col-md-1"; const SIZE_2_OF_12: &str = "col-md-2"; @@ -66,6 +71,10 @@ impl ComponentTrait for Column { (self.renderable)(context) } + fn before_render(&mut self, context: &mut InContext) { + before_render_inline(self, context); + } + fn default_render(&self, context: &mut InContext) -> Markup { html! { div id=[self.id().get()] class=[self.classes().get()] { diff --git a/pagetop/src/base/component/grid/row.rs b/pagetop/src/base/component/grid/row.rs index 5bfa8ad2..0cf59b90 100644 --- a/pagetop/src/base/component/grid/row.rs +++ b/pagetop/src/base/component/grid/row.rs @@ -2,6 +2,11 @@ use crate::prelude::*; pub const COMPONENT_ROW: &str = "pagetop::component::grid::row"; +hook_before_render_component!( + HOOK_BEFORE_RENDER_ROW = "pagetop::action::before_render_row", + Row +); + pub struct Row { weight : isize, renderable: Renderable, @@ -35,6 +40,10 @@ impl ComponentTrait for Row { (self.renderable)(context) } + fn before_render(&mut self, context: &mut InContext) { + before_render_inline(self, context); + } + fn default_render(&self, context: &mut InContext) -> Markup { html! { div id=[self.id().get()] class=[self.classes().get()] { diff --git a/pagetop/src/base/component/menu.rs b/pagetop/src/base/component/menu.rs index 95fd16a6..2c0e94e5 100644 --- a/pagetop/src/base/component/menu.rs +++ b/pagetop/src/base/component/menu.rs @@ -1,6 +1,5 @@ use crate::prelude::*; -pub const COMPONENT_MENU: &str = "pagetop::component::menu"; pub const COMPONENT_MENUITEM: &str = "pagetop::component::menu_item"; pub enum MenuItemType { @@ -173,6 +172,13 @@ impl MenuItem { // Menu. +pub const COMPONENT_MENU: &str = "pagetop::component::menu"; + +hook_before_render_component!( + HOOK_BEFORE_RENDER_MENU = "pagetop::action::before_render_menu", + Menu +); + pub struct Menu { weight : isize, renderable: Renderable, @@ -206,6 +212,10 @@ impl ComponentTrait for Menu { (self.renderable)(context) } + fn before_render(&mut self, context: &mut InContext) { + before_render_inline(self, context); + } + fn default_render(&self, context: &mut InContext) -> Markup { context .alter(InContextOp::StyleSheet(AssetsOp::Add( diff --git a/pagetop/src/core/component.rs b/pagetop/src/core/component.rs index a6d91d21..20ec2b42 100644 --- a/pagetop/src/core/component.rs +++ b/pagetop/src/core/component.rs @@ -1,9 +1,3 @@ -mod hook; -pub use hook::{ - HOOK_BEFORE_RENDER_COMPONENT, - BeforeRenderComponentHook, -}; - mod context; pub use context::{InContext, InContextOp}; diff --git a/pagetop/src/core/component/definition.rs b/pagetop/src/core/component/definition.rs index d8eb920e..b437fa0b 100644 --- a/pagetop/src/core/component/definition.rs +++ b/pagetop/src/core/component/definition.rs @@ -1,7 +1,6 @@ use crate::util; use crate::html::{Markup, html}; -use crate::core::hook::{hook_ref, run_hooks}; -use super::{HOOK_BEFORE_RENDER_COMPONENT, BeforeRenderComponentHook, InContext}; +use super::InContext; pub use std::any::Any as AnyComponent; @@ -50,11 +49,8 @@ pub fn component_mut(component: &mut dyn ComponentTrait) -> &mut C { } pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InContext) -> Markup { - // Acciones de los módulos antes de renderizar el componente. - run_hooks( - HOOK_BEFORE_RENDER_COMPONENT, - |hook| hook_ref::(&**hook).run(component, context) - ); + // Acciones del componente antes de renderizar. + component.before_render(context); // Acciones del tema antes de renderizar el componente. context.theme().before_render_component(component, context); @@ -67,3 +63,68 @@ pub fn render_component(component: &mut dyn ComponentTrait, context: &mut InCont false => html! {} } } + +#[macro_export] +macro_rules! hook_before_render_component { + ( $ACTION_HANDLER:ident = $handler:literal, $Component:ty ) => { + paste::paste! { + const $ACTION_HANDLER: &str = $handler; + + type Action = fn(&$Component, &mut InContext); + + pub struct [< BeforeRender $Component >] { + action: Option, + weight: isize, + } + + impl HookTrait for [< BeforeRender $Component >] { + fn new() -> Self { + [< BeforeRender $Component >] { + action: None, + weight: 0, + } + } + + fn handler(&self) -> &'static str { + $ACTION_HANDLER + } + + fn weight(&self) -> isize { + self.weight + } + + fn as_ref_any(&self) -> &dyn AnyHook { + self + } + } + + impl [< BeforeRender $Component >] { + #[allow(dead_code)] + pub fn with_hook(mut self, action: Action) -> Self { + self.action = Some(action); + self + } + + #[allow(dead_code)] + pub fn with_weight(mut self, weight: isize) -> Self { + self.weight = weight; + self + } + + pub fn run(&self, component: &mut $Component, context: &mut InContext) { + if let Some(action) = self.action { + action(component, context) + } + } + } + + #[inline(always)] + fn before_render_inline(component: &mut $Component, context: &mut InContext) { + run_actions( + $ACTION_HANDLER, + |action| action_ref::<[< BeforeRender $Component >]>(&**action).run(component, context) + ); + } + } + }; +} diff --git a/pagetop/src/core/component/hook.rs b/pagetop/src/core/component/hook.rs deleted file mode 100644 index d95d1cdf..00000000 --- a/pagetop/src/core/component/hook.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::core::hook::{HookTrait, AnyHook}; -use super::{ComponentTrait, InContext}; - -pub const HOOK_BEFORE_RENDER_COMPONENT: &str = "pagetop::hook::before_render_component"; - -pub struct BeforeRenderComponentHook { - hook: Option, - weight: isize, -} - -impl HookTrait for BeforeRenderComponentHook { - fn new() -> Self { - BeforeRenderComponentHook { - hook: None, - weight: 0, - } - } - - fn handler(&self) -> &'static str { - HOOK_BEFORE_RENDER_COMPONENT - } - - fn weight(&self) -> isize { - self.weight - } - - fn as_ref_any(&self) -> &dyn AnyHook { - self - } -} - -impl BeforeRenderComponentHook { - pub fn with_hook(mut self, hook: fn(&mut dyn ComponentTrait, &mut InContext)) -> Self { - self.hook = Some(hook); - self - } - - pub fn with_weight(mut self, weight: isize) -> Self { - self.weight = weight; - self - } - - pub fn run(&self, component: &mut dyn ComponentTrait, context: &mut InContext) { - if let Some(hook) = self.hook { - hook(component, context) - } - } -} diff --git a/pagetop/src/core/hook.rs b/pagetop/src/core/hook.rs index 00b6d4ea..c90dd436 100644 --- a/pagetop/src/core/hook.rs +++ b/pagetop/src/core/hook.rs @@ -1,8 +1,8 @@ mod definition; pub use definition::{ - HookTrait, AnyHook, - hook_ref, + HookTrait, + action_ref, }; mod holder; @@ -10,5 +10,5 @@ pub use holder::HookAction; use holder::HooksHolder; mod all; -pub use all::run_hooks; +pub use all::run_actions; pub(crate) use all::add_hook; diff --git a/pagetop/src/core/hook/all.rs b/pagetop/src/core/hook/all.rs index 6321dfbc..0d0d3e08 100644 --- a/pagetop/src/core/hook/all.rs +++ b/pagetop/src/core/hook/all.rs @@ -19,7 +19,7 @@ pub fn add_hook(hook: HookAction) { } } -pub fn run_hooks(action_handler: &str, f: F) where F: FnMut(&HookAction) -> B { +pub fn run_actions(action_handler: &str, f: F) where F: FnMut(&HookAction) -> B { if let Some(actions) = ACTIONS.read().unwrap().get(action_handler) { actions.iter_map(f) } diff --git a/pagetop/src/core/hook/definition.rs b/pagetop/src/core/hook/definition.rs index e21ea10f..b3611f08 100644 --- a/pagetop/src/core/hook/definition.rs +++ b/pagetop/src/core/hook/definition.rs @@ -12,6 +12,6 @@ pub trait HookTrait: AnyHook + Send + Sync { fn as_ref_any(&self) -> &dyn AnyHook; } -pub fn hook_ref(hook: &dyn HookTrait) -> &A { +pub fn action_ref(hook: &dyn HookTrait) -> &A { hook.as_ref_any().downcast_ref::().unwrap() } diff --git a/pagetop/src/prelude.rs b/pagetop/src/prelude.rs index 9c0f552a..c91a9678 100644 --- a/pagetop/src/prelude.rs +++ b/pagetop/src/prelude.rs @@ -1,6 +1,6 @@ //! Re-exporta recursos comunes. -// Macros, globals and helpers. +// Global macros and helpers. pub use crate::{ args, concat_string, @@ -25,12 +25,17 @@ pub use crate::app; pub use crate::app::AppTrait; pub use crate::app::application::Application; -pub use crate::{hook_action, core::{ +pub use crate::core::{ component::*, hook::*, module::*, theme::*, -}}; +}; +pub use crate::{ + hook_action, + hook_before_render_component, +}; + pub use crate::response::page::*; diff --git a/pagetop/src/response/page/definition.rs b/pagetop/src/response/page/definition.rs index 322c6e77..cf05e8f8 100644 --- a/pagetop/src/response/page/definition.rs +++ b/pagetop/src/response/page/definition.rs @@ -1,7 +1,7 @@ use crate::{Lazy, app, trace}; use crate::config::SETTINGS; use crate::html::*; -use crate::core::hook::{hook_ref, run_hooks}; +use crate::core::hook::{action_ref, run_actions}; use crate::core::component::*; use super::{HOOK_BEFORE_RENDER_PAGE, BeforeRenderPageHook}; @@ -193,9 +193,9 @@ impl Page { pub fn render(&mut self) -> app::Result { // Acciones de los módulos antes de renderizar la página. - run_hooks( + run_actions( HOOK_BEFORE_RENDER_PAGE, - |hook| hook_ref::(&**hook).run(self) + |hook| action_ref::(&**hook).run(self) ); // Acciones del tema antes de renderizar la página. diff --git a/pagetop/src/response/page/hook.rs b/pagetop/src/response/page/hook.rs index e094c9ca..75b330d8 100644 --- a/pagetop/src/response/page/hook.rs +++ b/pagetop/src/response/page/hook.rs @@ -3,8 +3,10 @@ use super::Page; pub const HOOK_BEFORE_RENDER_PAGE: &str = "pagetop::hook::before_render_page"; +type Hook = fn(&mut Page); + pub struct BeforeRenderPageHook { - hook: Option, + hook: Option, weight: isize, } @@ -30,7 +32,7 @@ impl HookTrait for BeforeRenderPageHook { } impl BeforeRenderPageHook { - pub fn with_hook(mut self, hook: fn(&mut Page)) -> Self { + pub fn with_hook(mut self, hook: Hook) -> Self { self.hook = Some(hook); self }