//! `Executable` is a property to execute a closure use anyhow::Result; use std::sync::{Arc, RwLock}; use crate::prelude::*; /// `Executable` holds a closure which can be executed pub struct Executable<I: Send + Sync + 'static> { callback: RwLock<Option<Arc<dyn Fn(I) -> Result<()> + Send + Sync>>>, } impl<I: Send + Sync + 'static> Executable<I> { /// Factory method for `Executable`, returns `Arc<Executable>` pub fn new() -> Arc<Self> { Arc::new(Executable { callback: RwLock::new(None), }) } /// Set callback closure /// /// # Arguments /// /// * `callback` is a `Option<Callback>` closure pub fn set_callback<F>(&self, callback: impl Into<Option<F>>) where F: Fn(I) -> Result<()> + Send + Sync + 'static, { let mut function = self.callback.write().unwrap(); match callback.into() { Some(f) => *function = Some(Arc::new(f)), None => *function = None, } } /// Execute the callback closure if possible pub fn execute(&self, gui_handler: &mut GuiHandler<'_>, input: I) -> Result<()> { if let Some(callback) = self.callback.read().unwrap().as_ref() { let callback = callback.clone(); gui_handler.add_callback(move || (callback)(input)); } Ok(()) } }