//! `Writeable` is a property to change text of an item use crate::prelude::*; use anyhow::Result; use std::sync::{ Arc, RwLock, atomic::{AtomicI32, Ordering::SeqCst}, }; pub trait ModifyText: Send + Sync { fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()>; fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result; fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result>; } /// `Writeable` gives the ability to modify the text inside an `Textable` pub struct Writeable { modifyable: Arc, text_change_executable: Arc>>, activation_changed_executable: RwLock, bool) -> Result<()> + Send + Sync>>>, ui_layer: AtomicI32, } impl Writeable { /// Factory method for `Writeable`, returns `Arc`. pub fn new( modifyable: Arc, text_change_executable: Arc>>, ) -> Result> { Ok(Arc::new(Writeable { modifyable, text_change_executable, activation_changed_executable: RwLock::new(None), ui_layer: AtomicI32::new(0), })) } pub fn set_active(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { if gui_handler.set_active_writeable(self.clone())? { if let Some(exec) = &*self.activation_changed_executable.read().unwrap() { exec(true)?; } } Ok(()) } pub(crate) fn inactivation_event(&self) -> Result<()> { if let Some(exec) = &*self.activation_changed_executable.read().unwrap() { exec(false)?; } Ok(()) } pub fn set_activation_changed(&self, f: F) where F: Fn(&mut GuiHandler<'_>, bool) -> Result<()> + Send + Sync + 'static, { *self.activation_changed_executable.write().unwrap() = Some(Box::new(f)); } /// Add method /// /// # Arguments /// /// * `writeable` is a `&Arc` instance that is going to be added pub fn add(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { gui_handler.add_writeable(self.ui_layer.load(SeqCst), self.clone()) } /// Delete method, has to be explicitly called, otherwise it will remain in memory. /// /// # Arguments /// /// * `writeable` is a `&Arc` instance that is going to be deleted pub fn delete(self: &Arc, gui_handler: &mut GuiHandler<'_>) -> Result<()> { gui_handler.delete_writeable(self.ui_layer.load(SeqCst), self) } pub fn set_ui_layer(&self, ui_layer: i32) { self.ui_layer.store(ui_layer, SeqCst); } /// Replaces the text of `Textable` /// /// # Arguments /// /// * `text` that replaces the current text pub fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()> { self.modifyable.set_text(gui_handler, text.clone())?; self.text_change_executable .execute(gui_handler, if text.is_empty() { None } else { Some(text) })?; Ok(()) } /// Adds the letter to Text /// /// # Arguments /// /// * `letter` the letter thats going to be added pub fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result<()> { self.text_change_executable.execute( gui_handler, Some(self.modifyable.add_letter(gui_handler, letter)?), )?; Ok(()) } /// Removes the last letter pub fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> { self.text_change_executable .execute(gui_handler, self.modifyable.remove_last(gui_handler)?)?; Ok(()) } }