use crate::core::action::{ActionBox, ActionDispatcher}; use crate::core::AnyCast; use crate::trace; use crate::AutoDefault; use parking_lot::RwLock; #[derive(AutoDefault)] pub struct ActionsList(RwLock>); impl ActionsList { pub fn new() -> Self { Self::default() } pub fn add(&mut self, action: ActionBox) { let mut list = self.0.write(); list.push(action); list.sort_by_key(|a| a.weight()); } pub fn iter_map(&self, mut f: F) where Self: Sized, A: ActionDispatcher, F: FnMut(&A) -> B, { let _: Vec<_> = self .0 .read() .iter() .rev() .map(|a| { if let Some(action) = (**a).downcast_ref::() { f(action); } else { trace::error!("Failed to downcast action of type {}", (**a).type_name()); } }) .collect(); } pub fn iter_try_map(&self, mut f: F) where A: ActionDispatcher, F: FnMut(&A) -> std::ops::ControlFlow<()>, { let list = self.0.read(); for a in list.iter().rev() { if let Some(action) = (**a).downcast_ref::() { if f(action).is_break() { break; } } else { trace::error!("Failed to downcast action of type {}", (**a).type_name()); } } } }