use std::hash::Hash; use std::{hash::Hasher, rc::Rc}; use crate::{ any::AnyTrait, event::{CallbackDataCommon, EventListenerID}, layout::WidgetID, }; pub mod button; pub mod checkbox; pub mod radio_group; pub mod slider; pub mod tabs; pub mod tooltip; pub struct RefreshData<'a> { pub common: &'a mut CallbackDataCommon<'a>, } // common component data #[derive(Default)] pub struct ComponentBase { #[allow(dead_code)] lhandles: Vec, id: WidgetID, } impl ComponentBase { pub const fn get_id(&self) -> WidgetID { self.id } } pub trait ComponentTrait: AnyTrait { fn base(&self) -> &ComponentBase; fn base_mut(&mut self) -> &mut ComponentBase; fn refresh(&self, data: &mut RefreshData); } #[derive(Clone)] pub struct Component(pub Rc); pub type ComponentWeak = std::rc::Weak; impl Component { pub fn weak(&self) -> ComponentWeak { Rc::downgrade(&self.0) } pub fn try_cast(&self) -> anyhow::Result> { if !(*self.0).as_any().is::() { anyhow::bail!("try_cast: type not matching"); } // safety: we already checked it above, should be safe to directly cast it unsafe { Ok(Rc::from_raw(Rc::into_raw(self.0.clone()).cast())) } } } // these hash/eq impls are required in case we want to do something like HashSet for convenience reasons. // hash by address impl Hash for Component { fn hash(&self, state: &mut H) { std::ptr::hash(&raw const self.0, state); } } // match by address impl PartialEq for Component { fn eq(&self, other: &Self) -> bool { std::ptr::eq(&raw const self.0, &raw const other.0) } } impl Eq for Component {}