use crate::prelude::*; use anyhow::Result; use std::{any::Any, collections::HashMap, sync::Arc}; // simulate trait upcasting pub trait TopLevelGui: Send + Sync { fn gui_traits(&self) -> &dyn GuiElementTraits; fn top_gui(&self) -> Option<&dyn TopGui>; fn elements(&self) -> Option<&HashMap>; fn functionality(&self) -> Option<&dyn Functionality>; fn enable(&self) -> Result<()>; fn disable(&self) -> Result<()>; } pub fn any_to(any: &dyn Any) -> Result<&T> where T: 'static, { match any.downcast_ref::() { Some(data) => Ok(data), None => Err(anyhow::Error::msg("Unable to downcast")), } } pub trait Functionality { fn set_click_callbacks( &self, callbacks: Vec<(&str, Box Result<()> + Send + Sync>)>, ) -> Result<()>; fn set_select_callbacks( &self, callbacks: Vec<(&str, Box>)>, ) -> Result<()>; fn set_custom_callbacks( &self, callbacks: Vec<(&str, Box>)>, ) -> Result<()>; fn set_vec_callbacks( &self, callbacks: Vec<(&str, Box Result<()> + Send + Sync>)>, ) -> Result<()>; } pub trait GuiElementTraits: Send + Sync { fn gridable(&self) -> Option<&dyn Gridable>; fn visibility(&self) -> Option<&dyn Visibility>; fn downcast<'a>(&'a self) -> Option>; } pub trait Gridable { fn set_frame( &self, x: i32, y: i32, w: u32, h: u32, vert_align: VerticalAlign, hori_align: HorizontalAlign, ) -> Result<()>; fn selectable(&self) -> Option<&Arc>; fn type_name(&self) -> &str; fn set_layer(&self, layer: i32) -> Result<()>; fn position_extent(&self) -> (i32, i32, u32, u32); } pub trait Visibility { fn visible(&self) -> bool; fn set_visibility(&self, visibility: bool) -> Result<()>; } pub enum GuiElement<'a> { Button(&'a Button), Grid(&'a Grid), Label(&'a Label), MultiLineLabel(&'a MultiLineLabel), MultiLineTextField(&'a MultiLineTextField), TextField(&'a TextField), Icon(&'a Icon), ProgressBar(&'a ProgressBar), GuiSnippet(&'a GuiSnippet), GuiBuilder(&'a GuiBuilder), Custom(&'a dyn Any), } impl<'a> GuiElement<'a> { pub fn button(&self) -> Option<&Button> { match self { Self::Button(button) => Some(button), _ => None, } } pub fn grid(&self) -> Option<&Grid> { match self { Self::Grid(grid) => Some(grid), _ => None, } } pub fn label(&self) -> Option<&Label> { match self { Self::Label(label) => Some(label), _ => None, } } pub fn multi_line_label(&self) -> Option<&MultiLineLabel> { match self { Self::MultiLineLabel(multi_line_label) => Some(multi_line_label), _ => None, } } pub fn multi_line_text_field(&self) -> Option<&MultiLineTextField> { 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, } } }