2024-05-17 12:16:30 +00:00
|
|
|
use crate::{
|
|
|
|
builder::validator::iconinfo::IconInfo, guihandler::gui::iconizable::IconizablePositioning,
|
|
|
|
prelude::*,
|
|
|
|
};
|
2023-01-16 09:53:52 +00:00
|
|
|
use anyhow::Result;
|
2024-08-29 10:37:22 +00:00
|
|
|
use assetpath::AssetPath;
|
2023-01-16 11:58:59 +00:00
|
|
|
use utilities::prelude::*;
|
|
|
|
use vulkan_rs::prelude::*;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
use std::sync::{
|
|
|
|
atomic::{AtomicBool, Ordering::SeqCst},
|
|
|
|
Arc, RwLock,
|
|
|
|
};
|
|
|
|
|
2024-04-04 15:57:50 +00:00
|
|
|
use super::{
|
|
|
|
fill_type::FillType,
|
|
|
|
wrapper::{IconizableWrapper, TextableWrapper},
|
|
|
|
IconBuilderType,
|
|
|
|
};
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
pub struct IconBuilder {
|
|
|
|
content: Option<IconBuilderType>,
|
|
|
|
background: Option<FillTypeInfo>,
|
|
|
|
margin: u32,
|
|
|
|
|
|
|
|
text: Option<String>,
|
|
|
|
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<IconBuilderType>) -> 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: Arc<GuiHandler>) -> Result<Arc<Icon>> {
|
|
|
|
let framable = Framable::new(gui_handler, false)?;
|
|
|
|
|
|
|
|
let iconizable_wrapper =
|
2024-04-04 15:57:50 +00:00
|
|
|
IconizableWrapper::new(framable.clone(), self.content, None, self.margin)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
let background = RwLock::new(
|
|
|
|
self.background
|
|
|
|
.map(|info| FillType::new(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(&text, false)?;
|
|
|
|
}
|
|
|
|
|
2024-05-17 12:16:30 +00:00
|
|
|
let info_icon = IconizableWrapper::new(
|
|
|
|
framable.clone(),
|
|
|
|
None,
|
|
|
|
Some(IconizablePositioning {
|
|
|
|
left: 1.2,
|
|
|
|
right: 0.0,
|
|
|
|
top: 1.2,
|
|
|
|
bottom: 0.0,
|
|
|
|
}),
|
|
|
|
0,
|
|
|
|
)?;
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
Ok(Arc::new(Icon {
|
|
|
|
framable,
|
|
|
|
background,
|
|
|
|
iconizable_wrapper,
|
|
|
|
textable_wrapper,
|
2024-05-17 12:16:30 +00:00
|
|
|
info_icon,
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
visible: AtomicBool::new(false),
|
|
|
|
}))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Icon {
|
|
|
|
framable: Arc<Framable>,
|
|
|
|
background: RwLock<Option<FillType>>,
|
|
|
|
iconizable_wrapper: IconizableWrapper,
|
|
|
|
textable_wrapper: TextableWrapper,
|
2024-05-17 12:16:30 +00:00
|
|
|
info_icon: IconizableWrapper,
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
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) -> Result<()> {
|
|
|
|
self.iconizable_wrapper.clear_icon(self.visible())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_icon(&self, icon: &Arc<Image>) -> Result<()> {
|
|
|
|
self.iconizable_wrapper.set_icon(icon, self.visible())
|
|
|
|
}
|
|
|
|
|
2024-08-29 10:37:22 +00:00
|
|
|
pub fn set_icon_from_path(&self, asset_path: AssetPath) -> Result<()> {
|
|
|
|
self.iconizable_wrapper.set_icon(asset_path, self.visible())
|
|
|
|
}
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
pub fn set_margin(&self, margin: u32) -> Result<()> {
|
|
|
|
self.iconizable_wrapper.set_margin(margin)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_background(&self, background: impl Into<FillTypeInfo>) -> Result<()> {
|
2023-01-19 12:05:48 +00:00
|
|
|
super::set_background(self.visible(), &self.framable, &self.background, background)
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_background(&self) {
|
|
|
|
*self.background.write().unwrap() = None;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_text(&self, text: impl ToString) -> Result<()> {
|
|
|
|
self.textable_wrapper.set_text(text, self.visible())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_text(&self) -> Result<()> {
|
|
|
|
self.textable_wrapper.set_text("", self.visible())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_text_color(&self, color: Color) -> Result<()> {
|
|
|
|
self.textable_wrapper.set_text_color(color)
|
|
|
|
}
|
|
|
|
|
2024-05-17 12:16:30 +00:00
|
|
|
pub fn set_info_icon(&self, button: &Arc<Image>) -> Result<()> {
|
|
|
|
self.info_icon.set_icon(button, self.visible())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_info_icon(&self) -> Result<()> {
|
|
|
|
self.info_icon.clear_icon(self.visible())
|
|
|
|
}
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
pub fn try_from(icon_info: &IconInfo, gui_handler: &Arc<GuiHandler>) -> Result<Arc<Self>> {
|
|
|
|
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.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn icon(&self) -> Result<Option<Arc<Image>>> {
|
|
|
|
self.iconizable_wrapper.icon()
|
|
|
|
}
|
|
|
|
|
2023-01-18 08:45:16 +00:00
|
|
|
pub fn extent(&self) -> (i32, i32) {
|
|
|
|
(
|
|
|
|
self.framable.right() - self.framable.left(),
|
|
|
|
self.framable.bottom() - self.framable.top(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-01-16 09:53:52 +00:00
|
|
|
fn disable_base(&self) -> Result<()> {
|
|
|
|
self.framable.delete()?;
|
|
|
|
|
|
|
|
self.iconizable_wrapper.disable()?;
|
|
|
|
self.textable_wrapper.disable()?;
|
2024-05-17 12:16:30 +00:00
|
|
|
self.info_icon.disable()?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
if let Some(background) = self.background.read().unwrap().as_ref() {
|
|
|
|
background.disable()?;
|
|
|
|
}
|
|
|
|
|
|
|
|
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<GuiElement<'a>> {
|
|
|
|
Some(GuiElement::Icon(self))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Visibility for Icon {
|
|
|
|
fn visible(&self) -> bool {
|
|
|
|
self.visible.load(SeqCst)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn set_visibility(&self, visibility: bool) -> Result<()> {
|
|
|
|
if visibility != self.visible.load(SeqCst) {
|
|
|
|
self.visible.store(visibility, SeqCst);
|
|
|
|
|
|
|
|
if visibility {
|
|
|
|
self.framable.add()?;
|
|
|
|
|
2024-05-17 12:21:43 +00:00
|
|
|
self.info_icon.enable()?;
|
2023-01-16 09:53:52 +00:00
|
|
|
self.iconizable_wrapper.enable()?;
|
|
|
|
self.textable_wrapper.enable()?;
|
|
|
|
|
|
|
|
if let Some(background) = self.background.read().unwrap().as_ref() {
|
|
|
|
background.enable()?;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
self.disable_base()?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Gridable for Icon {
|
|
|
|
fn set_frame(
|
|
|
|
&self,
|
|
|
|
x: i32,
|
|
|
|
y: i32,
|
|
|
|
w: u32,
|
|
|
|
h: u32,
|
|
|
|
vert_align: VerticalAlign,
|
|
|
|
hori_align: HorizontalAlign,
|
|
|
|
) -> Result<()> {
|
|
|
|
self.framable.set_frame(x, y, w, h, vert_align, hori_align);
|
|
|
|
|
|
|
|
self.iconizable_wrapper.update_frame()?;
|
|
|
|
self.textable_wrapper.update()?;
|
2024-05-17 12:16:30 +00:00
|
|
|
self.info_icon.update_frame()?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
if let Some(background) = self.background.read().unwrap().as_ref() {
|
|
|
|
background.update_frame()?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn selectable(&self) -> Option<&Arc<Selectable>> {
|
|
|
|
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)?;
|
2024-05-17 12:29:22 +00:00
|
|
|
self.info_icon.set_ui_layer(layer)?;
|
2023-01-16 09:53:52 +00:00
|
|
|
|
|
|
|
if let Some(background) = self.background.read().unwrap().as_ref() {
|
|
|
|
background.set_ui_layer(layer);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2024-04-21 05:41:08 +00:00
|
|
|
|
|
|
|
fn position_extent(&self) -> (i32, i32, u32, u32) {
|
|
|
|
self.framable.position()
|
|
|
|
}
|
2023-01-16 09:53:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Icon {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
if self.visible.load(SeqCst) {
|
|
|
|
self.disable_base().unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|