1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
// Copyright (C) 2018-2024 Daniel Mueller (deso@posteo.net)
// SPDX-License-Identifier: GPL-3.0-or-later
use std::any::TypeId;
use std::fmt::Debug;
use crate::Cap;
use crate::Handleable;
use crate::MutCap;
use crate::Object;
use crate::Renderable;
/// A widget as used by a [`Ui`][crate::Ui].
///
/// In addition to taking care of [`Id`][crate::Id] management and
/// parent-child relationships, the `Ui` is responsible for dispatching
/// events to widgets and rendering them. Hence, a widget usable for the
/// `Ui` needs to implement [`Handleable`], [`Renderable`], and
/// [`Object`].
pub trait Widget<E, M>: Handleable<E, M> + Renderable + Object + Debug {
/// Get the [`TypeId`] of `self`.
fn type_id(&self) -> TypeId;
/// Retrieve a reference to a widget's data.
///
/// # Panics
///
/// This function will panic if the data associated with the object is
/// not of type `D`.
fn data<'c, D>(&self, cap: &'c dyn Cap) -> &'c D
where
Self: Sized,
D: 'static,
{
cap.data(self.id()).downcast_ref::<D>().unwrap()
}
/// Retrieve a mutable reference to a widget's data.
///
/// # Panics
///
/// This function will panic if the data associated with the object is
/// not of type `D`.
fn data_mut<'c, D>(&self, cap: &'c mut dyn MutCap<E, M>) -> &'c mut D
where
Self: Sized,
D: 'static,
{
cap.data_mut(self.id()).downcast_mut::<D>().unwrap()
}
}
impl<E, M> dyn Widget<E, M>
where
E: 'static,
M: 'static,
{
/// Check if the widget is of type `T`.
pub fn is<T: Widget<E, M>>(&self) -> bool {
let t = TypeId::of::<T>();
let own_t = Widget::type_id(self);
t == own_t
}
/// Downcast the widget reference to type `T`.
pub fn downcast_ref<T: Widget<E, M>>(&self) -> Option<&T> {
if self.is::<T>() {
unsafe { Some(&*(self as *const dyn Widget<E, M> as *const T)) }
} else {
None
}
}
/// Downcast the widget reference to type `T`.
pub fn downcast_mut<T: Widget<E, M>>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
unsafe { Some(&mut *(self as *mut dyn Widget<E, M> as *mut T)) }
} else {
None
}
}
}