ui/src/elements/mod.rs
2024-04-04 09:11:42 +02:00

359 lines
8.8 KiB
Rust

use crate::{guihandler::gui::iconizable::IconBuilderType, prelude::*};
use anyhow::Result;
use std::sync::{
atomic::{AtomicU32, Ordering::SeqCst},
Arc, Mutex, RwLock,
};
use utilities::prelude::*;
use vulkan_rs::prelude::*;
use self::fill_type::FillType;
pub mod button;
pub mod fill_type;
pub mod grid;
pub mod icon;
pub mod label;
pub mod multi_line_label;
pub mod multi_line_textfield;
pub mod progress_bar;
pub mod textfield;
pub mod uielement;
pub mod traits;
mod callback_builder;
pub mod prelude;
pub(crate) struct TextableWrapper {
framable: Arc<Framable>,
textable: Mutex<Option<Arc<Textable>>>,
color: Mutex<Color>,
ratio: Mutex<f32>,
alignment: Mutex<TextAlignment>,
}
impl TextableWrapper {
pub(crate) fn new(
framable: Arc<Framable>,
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<Option<String>> {
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<Framable>,
iconizable: Mutex<Option<Arc<Iconizable>>>,
margin: AtomicU32,
}
impl IconizableWrapper {
pub(crate) fn new(
framable: Arc<Framable>,
builder: Option<IconBuilderType>,
margin: u32,
) -> Result<Self> {
let iconizable: Option<Result<Arc<Iconizable>>> = builder.map(|content| {
let iconizable = Iconizable::new(framable.clone(), content)?;
iconizable.set_margin(margin)?;
Ok(iconizable)
});
let iconizable = iconizable.transpose()?;
Ok(Self {
framable,
iconizable: Mutex::new(iconizable),
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<IconBuilderType>,
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)?;
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<Option<Arc<Image>>> {
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();
}
}
}
pub(crate) fn set_background(
visible: bool,
framable: &Arc<Framable>,
current: &RwLock<Option<FillType>>,
new: impl Into<FillTypeInfo>,
) -> Result<()> {
let mut current_background = current.write().unwrap();
let fill_info = new.into();
let update = match &*current_background {
Some(bg) => *bg != fill_info,
None => true,
};
if update {
let fill_type = FillType::new(framable.clone(), fill_info)?;
if framable.is_framed() {
fill_type.update_frame()?;
}
if visible {
fill_type.enable()?;
}
*current_background = Some(fill_type);
}
Ok(())
}