diff --git a/src/elements/button.rs b/src/elements/button.rs index fc6b005..d97228d 100644 --- a/src/elements/button.rs +++ b/src/elements/button.rs @@ -135,9 +135,9 @@ impl ButtonBuilder { }, )?; - let click_executable = Executable::new(); - let select_executable = Executable::new(); - let on_select_executable = Executable::new(); + let click_executable = Executable::new(&gui_handler); + let select_executable = Executable::new(&gui_handler); + let on_select_executable = Executable::new(&gui_handler); #[cfg(feature = "audio")] let click_sound = self diff --git a/src/elements/multi_line_textfield.rs b/src/elements/multi_line_textfield.rs index 88c7f7b..29d552d 100644 --- a/src/elements/multi_line_textfield.rs +++ b/src/elements/multi_line_textfield.rs @@ -82,7 +82,7 @@ impl MultiLineTextFieldBuilder { } let text = Arc::new(SplittedText::new(self.text)); - let text_changed_exec = Executable::new(); + let text_changed_exec = Executable::new(&gui_handler); let writeable = Writeable::new(gui_handler, text.clone(), text_changed_exec.clone())?; let multi_line_text_field = Arc::new(MultiLineTextField { diff --git a/src/elements/textfield.rs b/src/elements/textfield.rs index 07b0e7c..80a1714 100644 --- a/src/elements/textfield.rs +++ b/src/elements/textfield.rs @@ -69,7 +69,7 @@ impl TextFieldBuilder { self.text_color, )?; - let text_changed_executable = Executable::new(); + let text_changed_executable = Executable::new(&gui_handler); let writeable = Writeable::new( gui_handler, diff --git a/src/guihandler/gui/executable.rs b/src/guihandler/gui/executable.rs index dac4add..8da393d 100644 --- a/src/guihandler/gui/executable.rs +++ b/src/guihandler/gui/executable.rs @@ -4,15 +4,19 @@ use anyhow::Result; use std::sync::{Arc, RwLock}; +use crate::prelude::*; + /// `Executable` holds a closure which can be executed -pub struct Executable { - callback: RwLock Result<()> + Send + Sync>>>, +pub struct Executable { + gui_handler: Arc, + callback: RwLock Result<()> + Send + Sync>>>, } -impl Executable { +impl Executable { /// Factory method for `Executable`, returns `Arc` - pub fn new() -> Arc { + pub fn new(gui_handler: &Arc) -> Arc { Arc::new(Executable { + gui_handler: gui_handler.clone(), callback: RwLock::new(None), }) } @@ -29,7 +33,7 @@ impl Executable { let mut function = self.callback.write().unwrap(); match callback.into() { - Some(f) => *function = Some(Box::new(f)), + Some(f) => *function = Some(Arc::new(f)), None => *function = None, } } @@ -37,7 +41,9 @@ impl Executable { /// Execute the callback closure if possible pub fn execute(&self, input: I) -> Result<()> { if let Some(callback) = self.callback.read().unwrap().as_ref() { - (callback)(input)?; + let callback = callback.clone(); + + self.gui_handler.add_callback(move || (callback)(input)); } Ok(()) diff --git a/src/guihandler/guihandler.rs b/src/guihandler/guihandler.rs index 80e99d8..3bcafd5 100644 --- a/src/guihandler/guihandler.rs +++ b/src/guihandler/guihandler.rs @@ -14,12 +14,12 @@ use super::{ use cgmath::{ortho, vec2}; -use std::sync::Weak; use std::sync::{ atomic::{AtomicBool, AtomicU32, Ordering::SeqCst}, Arc, Mutex, RwLock, }; use std::{collections::HashMap, ptr}; +use std::{mem, sync::Weak}; use paste::paste; @@ -257,6 +257,8 @@ pub struct GuiHandler { current_selectable: RwLock>>, text_sample_count: VkSampleCountFlags, + + callback_list: Mutex Result<()> + Send + Sync>>>, } impl GuiHandler { @@ -403,6 +405,8 @@ impl GuiHandler { current_writeable: RwLock::new(None), text_sample_count, + + callback_list: Mutex::default(), })) } @@ -881,6 +885,16 @@ impl GuiHandler { *self.tooltip_ui.write().unwrap() = tooltip; } + pub(crate) fn add_callback Result<()> + Send + Sync + 'static>(&self, f: F) { + self.callback_list.lock().unwrap().push(Box::new(f)); + } + + pub fn process_callbacks(&self) -> Result<()> { + mem::take(&mut *self.callback_list.lock().unwrap()) + .into_iter() + .try_for_each(|callback| callback()) + } + fn render( &self, buffer_recorder: &mut CommandBufferRecorder<'_>,