use crate::{ gui_handler::gui::iconizable::{IconBuilderType, IconizablePositioning}, prelude::*, }; use anyhow::Result; use std::sync::{ atomic::{AtomicU32, Ordering::SeqCst}, Arc, Mutex, }; use utilities::prelude::*; use vulkan_rs::prelude::*; pub(crate) struct TextableWrapper { framable: Arc, textable: Mutex>>, color: Mutex, ratio: Mutex, alignment: Mutex, } impl TextableWrapper { pub(crate) fn new( framable: Arc, color: Color, ratio: f32, alignment: TextAlignment, ) -> Self { TextableWrapper { framable, textable: Mutex::new(None), color: Mutex::new(color), ratio: Mutex::new(ratio), alignment: Mutex::new(alignment), } } pub(crate) fn set_ui_layer(&self, layer: i32) -> Result<()> { self.framable.set_ui_layer(layer); if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.set_ui_layer(layer); } Ok(()) } pub(crate) fn set_text_color(&self, text_color: Color) -> Result<()> { *self.color.lock().unwrap() = text_color; if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.set_text_color(text_color)?; } Ok(()) } pub(crate) fn set_text(&self, text: impl ToString, is_visible: bool) -> Result<()> { let text = text.to_string(); let mut textable = self.textable.lock().unwrap(); match textable.as_ref() { Some(current_textable) => { if text.is_empty() { current_textable.clear_callback(); if is_visible { current_textable.delete()?; } *textable = None; } else { current_textable.set_text(text)?; } } None => { if !text.is_empty() { let new_textable = Textable::new( self.framable.clone(), text, *self.ratio.lock().unwrap(), *self.alignment.lock().unwrap(), *self.color.lock().unwrap(), )?; if self.framable.is_framed() { new_textable.update_text()?; } new_textable.set_ui_layer(self.framable.ui_layer()); if is_visible { new_textable.add()?; } *textable = Some(new_textable); } } } Ok(()) } pub(crate) fn text(&self) -> Result> { Ok(self .textable .lock() .unwrap() .as_ref() .map(|textable| textable.text())) } pub(crate) fn set_height_ratio(&self, height_ratio: f32) -> Result<()> { *self.ratio.lock().unwrap() = height_ratio; if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.set_size(height_ratio)?; } Ok(()) } pub(crate) fn height_ratio(&self) -> f32 { *self.ratio.lock().unwrap() } pub(crate) fn set_alignment(&self, alignment: TextAlignment) -> Result<()> { *self.alignment.lock().unwrap() = alignment; if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.set_text_alignment(alignment)?; } Ok(()) } pub(crate) fn update(&self) -> Result<()> { if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.update_text()?; } Ok(()) } pub(crate) fn enable(&self) -> Result<()> { if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.add()?; } Ok(()) } pub(crate) fn disable(&self) -> Result<()> { if let Some(textable) = self.textable.lock().unwrap().as_ref() { textable.delete()?; } Ok(()) } } impl Drop for TextableWrapper { fn drop(&mut self) { if let Some(current_textable) = self.textable.lock().unwrap().as_ref() { current_textable.clear_callback(); } } } pub(crate) struct IconizableWrapper { framable: Arc, iconizable: Mutex>>, positioning: Option, margin: AtomicU32, } impl IconizableWrapper { pub(crate) fn new( framable: Arc, builder: Option, positioning: Option, margin: u32, ) -> Result { let iconizable: Option>> = builder.map(|content| { let iconizable = Iconizable::new(framable.clone(), content, positioning.clone())?; iconizable.set_margin(margin)?; Ok(iconizable) }); let iconizable = iconizable.transpose()?; Ok(Self { framable, iconizable: Mutex::new(iconizable), positioning, margin: AtomicU32::new(margin), }) } pub(crate) fn set_ui_layer(&self, layer: i32) -> Result<()> { self.framable.set_ui_layer(layer); if let Some(iconizable) = self.iconizable.lock().unwrap().as_ref() { iconizable.set_ui_layer(layer); } Ok(()) } pub(crate) fn clear_icon(&self, is_visible: bool) -> Result<()> { let mut iconizable = self.iconizable.lock().unwrap(); if let Some(iconizable) = iconizable.as_ref() { if is_visible { iconizable.delete()?; } iconizable.clear_callback(); } *iconizable = None; Ok(()) } pub(crate) fn set_icon( &self, icon_builder: impl Into, is_visible: bool, ) -> Result<()> { let mut iconizable = self.iconizable.lock().unwrap(); match iconizable.as_ref() { Some(iconizable) => iconizable.set_icon(icon_builder)?, None => { let new_iconizable = Iconizable::new( self.framable.clone(), icon_builder, self.positioning.clone(), )?; new_iconizable.set_margin(self.margin.load(SeqCst))?; if self.framable.is_framed() { new_iconizable.update_frame()?; } new_iconizable.set_ui_layer(self.framable.ui_layer()); if is_visible { new_iconizable.add()?; } *iconizable = Some(new_iconizable); } } Ok(()) } pub(crate) fn set_margin(&self, margin: u32) -> Result<()> { if self.framable.is_framed() { if let Some(iconizable) = self.iconizable.lock().unwrap().as_ref() { iconizable.set_margin(margin)?; iconizable.update_frame()?; } } self.margin.store(margin, SeqCst); Ok(()) } pub(crate) fn icon(&self) -> Result>> { match self.iconizable.lock().unwrap().as_ref() { Some(iconizable) => Ok(Some(iconizable.icon())), None => Ok(None), } } pub(crate) fn enable(&self) -> Result<()> { if let Some(iconizable) = self.iconizable.lock().unwrap().as_ref() { iconizable.add()?; } Ok(()) } pub(crate) fn disable(&self) -> Result<()> { if let Some(iconizable) = self.iconizable.lock().unwrap().as_ref() { iconizable.delete()?; } Ok(()) } pub(crate) fn update_frame(&self) -> Result<()> { if let Some(iconizable) = self.iconizable.lock().unwrap().as_ref() { iconizable.update_frame()?; } Ok(()) } } impl Drop for IconizableWrapper { fn drop(&mut self) { if let Some(iconizable) = self.iconizable.lock().unwrap().as_ref() { iconizable.clear_callback(); } } }