use std::{any::Any, collections::HashMap, sync::Arc}; use assetpath::AssetPath; use super::validator::{ buttoninfo::NeighbourInfo, uiinfoelement::UiInfoElement, validator::{handle_function_suffix, Validator}, }; use crate::prelude::*; use anyhow::Result; pub struct GuiSnippet { grid: Arc, ids: HashMap, } impl GuiSnippet { pub fn new(gui_handler: Arc, path: &AssetPath) -> Result> { let validator = Validator::new( #[cfg(feature = "audio")] &gui_handler, path, )?; let root = validator.root(); let mut ids = HashMap::new(); let mut custom_neighbours = Vec::new(); if root.children.len() != 1 { return Err(anyhow::Error::msg(format!( "Expected exact 1 root in {}. Found {} roots", path.full_path(), root.children.len() ))); } let grid_info = &root.children[0]; let grid = Grid::try_from(grid_info, &gui_handler, false)?; GuiBuilder::insert_id(&mut ids, &grid_info.id, &grid)?; for child in grid_info.children.read().unwrap().iter() { Self::create_child(&gui_handler, child, &grid, &mut ids, &mut custom_neighbours)?; } GuiBuilder::connect_custom_neighbours(&ids, custom_neighbours)?; Ok(Arc::new(GuiSnippet { grid, ids })) } } macro_rules! impl_element { ($data_type:ident $(< $($lt:lifetime),+ >)?) => { impl GetElement<$data_type$(<$($lt,)+>)?> for GuiSnippet { fn element(&self, id: &str) -> Result)?>> { self.ids.element(id) } } }; } impl_element!(Button); impl_element!(Grid); impl_element!(Label); impl_element!(TextField); impl_element!(Icon); impl_element!(ProgressBar); impl_element!(MultiLineLabel); impl_element!(MultiLineTextField); impl Visibility for GuiSnippet { fn visible(&self) -> bool { self.grid.visible() } fn set_visibility(&self, visibility: bool) -> Result<()> { self.grid.set_visibility(visibility) } } impl GuiElementTraits for GuiSnippet { fn gridable(&self) -> Option<&dyn Gridable> { Some(self) } fn visibility(&self) -> Option<&dyn Visibility> { Some(self) } fn downcast<'a>(&'a self) -> Option> { Some(GuiElement::GuiSnippet(self)) } } impl Gridable for GuiSnippet { fn set_frame( &self, x: i32, y: i32, w: u32, h: u32, vert_align: VerticalAlign, hori_align: HorizontalAlign, ) -> Result<()> { self.grid.set_frame(x, y, w, h, vert_align, hori_align) } fn selectable(&self) -> Option<&Arc> { self.grid.selectable() } fn type_name(&self) -> &str { "GuiSnippet" } fn set_layer(&self, layer: i32) -> Result<()> { self.grid.set_layer(layer) } } impl Functionality for GuiSnippet { fn set_click_callbacks( &self, functions: Vec<(&str, Box Result<()> + Send + Sync>)>, ) -> Result<()> { for (function_name, callback) in functions { let suffix_less_function_name = handle_function_suffix(function_name); let button: Arc