ui/src/elements/traits.rs

165 lines
4.1 KiB
Rust
Raw Normal View History

2023-01-16 09:53:52 +00:00
use crate::prelude::*;
use anyhow::Result;
use std::{any::Any, collections::HashMap, sync::Arc};
// simulate trait upcasting
2025-03-04 11:25:02 +00:00
pub trait TopLevelGui: Send + Sync {
fn gui_traits(&self) -> &dyn GuiElementTraits;
2023-01-16 09:53:52 +00:00
fn top_gui(&self) -> Option<&dyn TopGui>;
2025-03-04 11:25:02 +00:00
fn elements(&self) -> Option<&HashMap<String, UiElement>>;
2023-01-16 09:53:52 +00:00
fn functionality(&self) -> Option<&dyn Functionality>;
fn enable(&self) -> Result<()>;
fn disable(&self) -> Result<()>;
}
pub fn any_to<T>(any: &dyn Any) -> Result<&T>
where
T: 'static,
{
match any.downcast_ref::<T>() {
Some(data) => Ok(data),
None => Err(anyhow::Error::msg("Unable to downcast")),
}
}
pub trait Functionality {
fn set_click_callbacks(
&self,
callbacks: Vec<(&str, Box<dyn Fn() -> Result<()> + Send + Sync>)>,
) -> Result<()>;
fn set_select_callbacks(
&self,
callbacks: Vec<(&str, Box<CustomCallback<bool, ()>>)>,
) -> Result<()>;
fn set_custom_callbacks(
&self,
callbacks: Vec<(&str, Box<CustomCallback<ControllerButton, bool>>)>,
) -> Result<()>;
fn set_vec_callbacks(
&self,
callbacks: Vec<(&str, Box<dyn Fn(&dyn Any) -> Result<()> + Send + Sync>)>,
) -> Result<()>;
}
2025-03-04 11:25:02 +00:00
pub trait GuiElementTraits: Send + Sync {
fn gridable(&self) -> Option<&dyn Gridable>;
2023-01-16 09:53:52 +00:00
fn visibility(&self) -> Option<&dyn Visibility>;
2025-03-04 11:25:02 +00:00
fn downcast<'a>(&'a self) -> Option<GuiElement<'a>>;
2023-01-16 09:53:52 +00:00
}
2025-03-04 11:25:02 +00:00
pub trait Gridable {
2023-01-16 09:53:52 +00:00
fn set_frame(
&self,
2025-03-04 11:25:02 +00:00
gui_handler: &mut GuiHandler,
2023-01-16 09:53:52 +00:00
x: i32,
y: i32,
w: u32,
h: u32,
vert_align: VerticalAlign,
hori_align: HorizontalAlign,
) -> Result<()>;
2025-03-04 11:25:02 +00:00
fn selectable(&self) -> Option<&Arc<Selectable>>;
2023-01-16 09:53:52 +00:00
fn type_name(&self) -> &str;
fn set_layer(&self, layer: i32) -> Result<()>;
2024-04-21 05:41:08 +00:00
fn position_extent(&self) -> (i32, i32, u32, u32);
2023-01-16 09:53:52 +00:00
}
pub trait Visibility {
fn visible(&self) -> bool;
2025-03-04 11:25:02 +00:00
fn set_visibility(&self, gui_handler: &mut GuiHandler, visibility: bool) -> Result<()>;
2023-01-16 09:53:52 +00:00
}
pub enum GuiElement<'a> {
2025-03-04 11:25:02 +00:00
Button(&'a Button),
Grid(&'a Grid),
2023-01-16 09:53:52 +00:00
Label(&'a Label),
2025-03-04 11:25:02 +00:00
MultiLineLabel(&'a MultiLineLabel),
MultiLineTextField(&'a MultiLineTextField),
2023-01-16 09:53:52 +00:00
TextField(&'a TextField),
Icon(&'a Icon),
ProgressBar(&'a ProgressBar),
GuiSnippet(&'a GuiSnippet),
GuiBuilder(&'a GuiBuilder),
Custom(&'a dyn Any),
}
impl<'a> GuiElement<'a> {
2025-03-04 11:25:02 +00:00
pub fn button(&self) -> Option<&Button> {
2023-01-16 09:53:52 +00:00
match self {
Self::Button(button) => Some(button),
_ => None,
}
}
2025-03-04 11:25:02 +00:00
pub fn grid(&self) -> Option<&Grid> {
2023-01-16 09:53:52 +00:00
match self {
Self::Grid(grid) => Some(grid),
_ => None,
}
}
pub fn label(&self) -> Option<&Label> {
match self {
Self::Label(label) => Some(label),
_ => None,
}
}
2025-03-04 11:25:02 +00:00
pub fn multi_line_label(&self) -> Option<&MultiLineLabel> {
2023-01-16 09:53:52 +00:00
match self {
Self::MultiLineLabel(multi_line_label) => Some(multi_line_label),
_ => None,
}
}
2025-03-04 11:25:02 +00:00
pub fn multi_line_text_field(&self) -> Option<&MultiLineTextField> {
2023-01-16 09:53:52 +00:00
match self {
Self::MultiLineTextField(multi_line_text_field) => Some(multi_line_text_field),
_ => None,
}
}
pub fn text_field(&self) -> Option<&TextField> {
match self {
Self::TextField(text_field) => Some(text_field),
_ => None,
}
}
pub fn icon(&self) -> Option<&Icon> {
match self {
Self::Icon(icon) => Some(icon),
_ => None,
}
}
pub fn progress_bar(&self) -> Option<&ProgressBar> {
match self {
Self::ProgressBar(progress_bar) => Some(progress_bar),
_ => None,
}
}
pub fn gui_snippet(&self) -> Option<&GuiSnippet> {
match self {
Self::GuiSnippet(gui_snippet) => Some(gui_snippet),
_ => None,
}
}
pub fn gui_builder(&self) -> Option<&GuiBuilder> {
match self {
Self::GuiBuilder(gui_builder) => Some(gui_builder),
_ => None,
}
}
}