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
// widget.rs

// *************************************************************************
// * Copyright (C) 2018-2019 Daniel Mueller (deso@posteo.net)              *
// *                                                                       *
// * This program is free software: you can redistribute it and/or modify  *
// * it under the terms of the GNU General Public License as published by  *
// * the Free Software Foundation, either version 3 of the License, or     *
// * (at your option) any later version.                                   *
// *                                                                       *
// * This program is distributed in the hope that it will be useful,       *
// * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
// * GNU General Public License for more details.                          *
// *                                                                       *
// * You should have received a copy of the GNU General Public License     *
// * along with this program.  If not, see <http://www.gnu.org/licenses/>. *
// *************************************************************************

use std::any::TypeId;
use std::fmt::Debug;

use crate::Handleable;
use crate::Object;
use crate::Renderable;


/// A widget as used by a `Ui`.
///
/// In addition to taking care of `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>: Handleable<E> + Renderable + Object + Debug
where
  E: 'static,
{
  /// Get the `TypeId` of `self`.
  fn type_id(&self) -> TypeId;
}

impl<E> dyn Widget<E>
where
  E: 'static,
{
  /// Check if the widget is of type `T`.
  pub fn is<T: Widget<E>>(&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>>(&self) -> Option<&T> {
    if self.is::<T>() {
      unsafe { Some(&*(self as *const dyn Widget<E> as *const T)) }
    } else {
      None
    }
  }

  /// Downcast the widget reference to type `T`.
  pub fn downcast_mut<T: Widget<E>>(&mut self) -> Option<&mut T> {
    if self.is::<T>() {
      unsafe { Some(&mut *(self as *mut dyn Widget<E> as *mut T)) }
    } else {
      None
    }
  }
}