use crate::core::action::{ActionBox, ActionDispatcher, ActionKey, ActionsList}; use parking_lot::RwLock; use std::collections::HashMap; use std::sync::LazyLock; // **< ACCIONES >*********************************************************************************** static ACTIONS: LazyLock>> = LazyLock::new(|| RwLock::new(HashMap::new())); // **< AÑADIR ACCIONES >**************************************************************************** /// Registra una nueva acción en el sistema. /// /// Si ya existen acciones con la misma `ActionKey`, la acción se añade a la misma lista. Si no, se /// crea una nueva lista. /// /// Las extensiones llamarán a esta función durante su inicialización para instalar acciones /// personalizadas que modifiquen el comportamiento del *core* o de otros componentes. pub(crate) fn add_action(action: ActionBox) { let key = ActionKey::new( action.type_id(), action.referer_type_id(), action.referer_id(), ); let mut actions = ACTIONS.write(); if let Some(list) = actions.get_mut(&key) { list.add(action); } else { let mut list = ActionsList::new(); list.add(action); actions.insert(key, list); } } // **< DESPLEGAR ACCIONES >************************************************************************* /// Despacha y ejecuta las funciones asociadas a una [`ActionKey`]. /// /// Permite recorrer de forma segura y ordenada (por peso) la lista de funciones asociadas a una /// acción específica. /// /// # Parámetros genéricos /// /// - `A`: Tipo de acción que esperamos procesar. Debe implementar [`ActionDispatcher`]. /// - `F`: Función que se aplica para una acción dada. /// /// # Ejemplo /// /// ```rust,ignore /// pub(crate) fn dispatch(component: &mut C, cx: &mut Context) { /// dispatch_actions( /// &ActionKey::new( /// UniqueId::of::(), /// Some(UniqueId::of::()), /// None, /// ), /// |action: &Self| (action.f)(component, cx), /// ); /// } /// ``` pub fn dispatch_actions(key: &ActionKey, f: F) where A: ActionDispatcher, F: FnMut(&A), { if let Some(list) = ACTIONS.read().get(key) { list.for_each(f); } } /// Despacha las funciones asociadas a una [`ActionKey`] con posible salida anticipada. /// /// Funciona igual que [`dispatch_actions`], pero el closure puede devolver /// [`std::ops::ControlFlow::Continue`] para continuar ejecutando la siguiente acción; o /// [`std::ops::ControlFlow::Break`] para detener la iteración inmediatamente. /// /// # Ejemplo /// /// ```rust,ignore /// pub(crate) fn check(cx: &Context, key: &str) -> bool { /// let mut granted = false; /// try_dispatch_actions( /// &ActionKey::new(UniqueId::of::(), None, None), /// |action: &Self| { /// (action.f)(cx, key, &mut granted); /// if granted { /// std::ops::ControlFlow::Break(()) /// } else { /// std::ops::ControlFlow::Continue(()) /// } /// }, /// ); /// granted /// } /// ``` pub fn try_dispatch_actions(key: &ActionKey, f: F) where A: ActionDispatcher, F: FnMut(&A) -> std::ops::ControlFlow<()>, { if let Some(list) = ACTIONS.read().get(key) { list.try_for_each(f); } }