2023-01-16 09:53:52 +00:00
|
|
|
//! `Writeable` is a property to change text of an item
|
|
|
|
|
|
|
|
use crate::prelude::*;
|
|
|
|
use anyhow::Result;
|
|
|
|
|
|
|
|
use std::sync::{
|
|
|
|
Arc, RwLock,
|
2025-03-04 08:11:05 +00:00
|
|
|
atomic::{AtomicI32, Ordering::SeqCst},
|
2023-01-16 09:53:52 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
pub trait ModifyText: Send + Sync {
|
2025-03-04 08:11:05 +00:00
|
|
|
fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()>;
|
|
|
|
fn add_letter(&self, gui_handler: &mut GuiHandler<'_>, letter: char) -> Result<String>;
|
|
|
|
fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<Option<String>>;
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// `Writeable` gives the ability to modify the text inside an `Textable`
|
|
|
|
pub struct Writeable {
|
|
|
|
modifyable: Arc<dyn ModifyText>,
|
|
|
|
text_change_executable: Arc<Executable<Option<String>>>,
|
|
|
|
|
2025-03-04 10:37:45 +00:00
|
|
|
activation_changed_executable:
|
|
|
|
RwLock<Option<Box<dyn Fn(&mut GuiHandler<'_>, bool) -> Result<()> + Send + Sync>>>,
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
ui_layer: AtomicI32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Writeable {
|
|
|
|
/// Factory method for `Writeable`, returns `Arc<Writeable>`.
|
|
|
|
pub fn new(
|
|
|
|
modifyable: Arc<dyn ModifyText>,
|
|
|
|
text_change_executable: Arc<Executable<Option<String>>>,
|
|
|
|
) -> Result<Arc<Self>> {
|
|
|
|
Ok(Arc::new(Writeable {
|
|
|
|
modifyable,
|
|
|
|
text_change_executable,
|
|
|
|
|
|
|
|
activation_changed_executable: RwLock::new(None),
|
|
|
|
|
|
|
|
ui_layer: AtomicI32::new(0),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
|
2025-03-04 08:11:05 +00:00
|
|
|
pub fn set_active(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
|
|
|
|
if gui_handler.set_active_writeable(self.clone())? {
|
2023-01-16 09:53:52 +00:00
|
|
|
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<F>(&self, f: F)
|
|
|
|
where
|
2025-03-04 10:37:45 +00:00
|
|
|
F: Fn(&mut GuiHandler<'_>, bool) -> Result<()> + Send + Sync + 'static,
|
2023-01-16 09:53:52 +00:00
|
|
|
{
|
|
|
|
*self.activation_changed_executable.write().unwrap() = Some(Box::new(f));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add method
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `writeable` is a `&Arc<Writeable>` instance that is going to be added
|
2025-03-04 08:11:05 +00:00
|
|
|
pub fn add(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
|
|
|
|
gui_handler.add_writeable(self.ui_layer.load(SeqCst), self.clone())
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Delete method, has to be explicitly called, otherwise it will remain in memory.
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `writeable` is a `&Arc<Writeable>` instance that is going to be deleted
|
2025-03-04 08:11:05 +00:00
|
|
|
pub fn delete(self: &Arc<Self>, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
|
|
|
|
gui_handler.delete_writeable(self.ui_layer.load(SeqCst), self)
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2025-03-04 08:11:05 +00:00
|
|
|
pub fn set_text(&self, gui_handler: &mut GuiHandler<'_>, text: String) -> Result<()> {
|
|
|
|
self.modifyable.set_text(gui_handler, text.clone())?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
self.text_change_executable
|
2025-03-04 08:11:05 +00:00
|
|
|
.execute(gui_handler, if text.is_empty() { None } else { Some(text) })?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Adds the letter to Text
|
|
|
|
///
|
|
|
|
/// # Arguments
|
|
|
|
///
|
|
|
|
/// * `letter` the letter thats going to be added
|
2025-03-04 08:11:05 +00:00
|
|
|
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)?),
|
|
|
|
)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Removes the last letter
|
2025-03-04 08:11:05 +00:00
|
|
|
pub fn remove_last(&self, gui_handler: &mut GuiHandler<'_>) -> Result<()> {
|
2023-01-16 09:53:52 +00:00
|
|
|
self.text_change_executable
|
2025-03-04 08:11:05 +00:00
|
|
|
.execute(gui_handler, self.modifyable.remove_last(gui_handler)?)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|