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,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|