gui/
widget.rs

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