Documenta el nuevo comportamiento y aprovecha para pulir varios comentarios y restringir visibilidad de símbolos internos.
107 lines
3.3 KiB
Rust
107 lines
3.3 KiB
Rust
use crate::core::action::{ActionBox, ActionDispatcher, ActionKey, ActionsList};
|
|
|
|
use parking_lot::RwLock;
|
|
|
|
use std::collections::HashMap;
|
|
use std::sync::LazyLock;
|
|
|
|
// **< ACCIONES >***********************************************************************************
|
|
|
|
static ACTIONS: LazyLock<RwLock<HashMap<ActionKey, ActionsList>>> =
|
|
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::<Self>(),
|
|
/// Some(UniqueId::of::<C>()),
|
|
/// None,
|
|
/// ),
|
|
/// |action: &Self| (action.f)(component, cx),
|
|
/// );
|
|
/// }
|
|
/// ```
|
|
pub fn dispatch_actions<A, F>(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::<Self>(), 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<A, F>(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);
|
|
}
|
|
}
|