use crate::{ builder::validator::iconinfo::IconInfo, gui_handler::gui::iconizable::IconizablePositioning, prelude::*, }; use anyhow::Result; use assetpath::AssetPath; use ecs::World; use utilities::prelude::*; use vulkan_rs::prelude::*; use std::sync::{ Arc, RwLock, atomic::{AtomicBool, Ordering::SeqCst}, }; use super::{ IconBuilderType, fill_type::FillType, wrapper::{IconizableWrapper, TextableWrapper}, }; pub struct IconBuilder { content: Option, background: Option, margin: u32, text: Option, text_color: Color, text_ratio: f32, } impl IconBuilder { pub fn set_margin(mut self, margin: u32) -> Self { self.margin = margin; self } pub fn set_content(mut self, content: impl Into) -> Self { self.content = Some(content.into()); self } pub fn set_background(mut self, background: FillTypeInfo) -> Self { self.background = Some(background); self } pub fn set_text(mut self, text: &str) -> Self { self.text = Some(text.to_string()); self } pub fn set_text_color(mut self, color: Color) -> Self { self.text_color = color; self } pub fn set_text_ratio(mut self, ratio: f32) -> Self { self.text_ratio = ratio; self } pub fn build(self, gui_handler: &mut GuiHandler) -> Result> { let framable = Framable::new(gui_handler.width(), gui_handler.height(), false)?; let iconizable_wrapper = IconizableWrapper::new( gui_handler, framable.clone(), self.content, None, self.margin, )?; let background = RwLock::new( self.background .map(|info| FillType::new(gui_handler, framable.clone(), info)) .transpose()?, ); let textable_wrapper = TextableWrapper::new( framable.clone(), self.text_color, self.text_ratio, TextAlignment::Center, ); if let Some(text) = self.text { textable_wrapper.set_text(gui_handler, &text, false)?; } let info_icon = IconizableWrapper::new( gui_handler, framable.clone(), None, Some(IconizablePositioning { left: 1.2, right: 0.0, top: 1.2, bottom: 0.0, }), 0, )?; Ok(Arc::new(Icon { framable, background, iconizable_wrapper, textable_wrapper, info_icon, visible: AtomicBool::new(false), })) } } pub struct Icon { framable: Arc, background: RwLock>, iconizable_wrapper: IconizableWrapper, textable_wrapper: TextableWrapper, info_icon: IconizableWrapper, visible: AtomicBool, } impl Icon { pub fn builder() -> IconBuilder { IconBuilder { content: None, background: None, margin: 0, text: None, text_color: Color::Black, text_ratio: 0.7, } } pub fn clear_icon(&self, gui_handler: &mut GuiHandler) -> Result<()> { self.iconizable_wrapper .clear_icon(gui_handler, self.visible()) } pub fn set_icon(&self, gui_handler: &mut GuiHandler, icon: &Arc) -> Result<()> { self.iconizable_wrapper .set_icon(gui_handler, icon, self.visible()) } pub fn set_icon_from_path( &self, gui_handler: &mut GuiHandler, asset_path: AssetPath, ) -> Result<()> { self.iconizable_wrapper .set_icon(gui_handler, asset_path, self.visible()) } pub fn set_margin(&self, gui_handler: &mut GuiHandler, margin: u32) -> Result<()> { self.iconizable_wrapper.set_margin(gui_handler, margin) } pub fn set_background( &self, gui_handler: &mut GuiHandler, background: impl Into, ) -> Result<()> { super::set_background( gui_handler, self.visible(), &self.framable, &self.background, background, ) } pub fn clear_background(&self) { *self.background.write().unwrap() = None; } pub fn set_text(&self, gui_handler: &mut GuiHandler, text: impl ToString) -> Result<()> { self.textable_wrapper .set_text(gui_handler, text, self.visible()) } pub fn clear_text(&self, gui_handler: &mut GuiHandler) -> Result<()> { self.textable_wrapper .set_text(gui_handler, "", self.visible()) } pub fn set_text_color(&self, gui_handler: &mut GuiHandler, color: Color) -> Result<()> { self.textable_wrapper.set_text_color(gui_handler, color) } pub fn set_info_icon(&self, gui_handler: &mut GuiHandler, button: &Arc) -> Result<()> { self.info_icon.set_icon(gui_handler, button, self.visible()) } pub fn clear_info_icon(&self, gui_handler: &mut GuiHandler) -> Result<()> { self.info_icon.clear_icon(gui_handler, self.visible()) } pub fn try_from(icon_info: &IconInfo, gui_handler: &mut GuiHandler) -> Result> { let mut icon_builder = Icon::builder().set_text_color(icon_info.text_color); if let Some(text_ratio) = icon_info.text_ratio { icon_builder = icon_builder.set_text_ratio(text_ratio); } if let Some(margin) = icon_info.margin { icon_builder = icon_builder.set_margin(margin); } if let Some(icon) = &icon_info.icon { icon_builder = icon_builder.set_content(icon.clone()); } if let Some(fill_type_info) = icon_info.background_type.clone() { icon_builder = icon_builder.set_background(fill_type_info); } { let t = icon_info.text.read().unwrap(); let text = t.as_str(); if !text.is_empty() { icon_builder = icon_builder.set_text(text); } } icon_builder.build(gui_handler) } pub fn icon(&self) -> Result>> { self.iconizable_wrapper.icon() } pub fn extent(&self) -> (i32, i32) { ( self.framable.right() - self.framable.left(), self.framable.bottom() - self.framable.top(), ) } fn disable_base(&self, gui_handler: &mut GuiHandler) -> Result<()> { self.framable.delete(gui_handler)?; self.iconizable_wrapper.disable(gui_handler)?; self.textable_wrapper.disable(gui_handler)?; self.info_icon.disable(gui_handler)?; if let Some(background) = self.background.read().unwrap().as_ref() { background.disable(gui_handler)?; } Ok(()) } } impl GuiElementTraits for Icon { fn gridable(&self) -> Option<&dyn Gridable> { Some(self) } fn visibility(&self) -> Option<&dyn Visibility> { Some(self) } fn downcast<'a>(&'a self) -> Option> { Some(GuiElement::Icon(self)) } } impl Visibility for Icon { fn visible(&self) -> bool { self.visible.load(SeqCst) } fn set_visibility(&self, world: &mut World, visibility: bool) -> Result<()> { if visibility != self.visible.load(SeqCst) { let gui_handler = world.resources.get_mut::(); self.visible.store(visibility, SeqCst); if visibility { self.framable.add(gui_handler)?; self.info_icon.enable(gui_handler)?; self.iconizable_wrapper.enable(gui_handler)?; self.textable_wrapper.enable(gui_handler)?; if let Some(background) = self.background.read().unwrap().as_ref() { background.enable(gui_handler)?; } } else { self.disable_base(gui_handler)?; } } Ok(()) } } impl Gridable for Icon { fn set_frame( &self, gui_handler: &mut GuiHandler, x: i32, y: i32, w: u32, h: u32, vert_align: VerticalAlign, hori_align: HorizontalAlign, ) -> Result<()> { self.framable .set_frame(gui_handler, x, y, w, h, vert_align, hori_align); self.iconizable_wrapper.update_frame(gui_handler)?; self.textable_wrapper.update(gui_handler)?; self.info_icon.update_frame(gui_handler)?; if let Some(background) = self.background.read().unwrap().as_ref() { background.update_frame(gui_handler)?; } Ok(()) } fn selectable(&self) -> Option<&Arc> { None } fn type_name(&self) -> &str { "Icon" } fn set_layer(&self, layer: i32) -> Result<()> { self.framable.set_ui_layer(layer); self.iconizable_wrapper.set_ui_layer(layer)?; self.textable_wrapper.set_ui_layer(layer)?; self.info_icon.set_ui_layer(layer)?; if let Some(background) = self.background.read().unwrap().as_ref() { background.set_ui_layer(layer); } Ok(()) } fn position_extent(&self) -> (i32, i32, u32, u32) { self.framable.position() } }