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
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
use crate::{Entity, State};

use std::any::{Any, TypeId};
use std::fmt::Debug;

/// Determines how the event propagates through the tree
#[derive(Debug, Clone, PartialEq)]
pub enum Propagation {
    /// Events propagate down the tree to the target entity, e.g. from grand-parent to parent to child (target)
    Down,
    /// Events propagate up the tree to the target entity, e.g. from child (target) to parent to grand-parent
    Up,
    /// Events propagate down the tree to the target entity and then back up to the root
    DownUp,
    /// Events propagate from the target entity to all entities below but on the same branch
    Fall,
    /// Events propagate directly to the target entity and to no others
    Direct,
    /// Events propagate to all entities in the tree
    All,
}

// A message is a wrapper around an Any but with the added ability to Clone the message
pub trait Message: Any {
    // An &Any can be cast to a reference to a concrete type.
    fn as_any(&self) -> &dyn Any;

    // Perform the test
    fn equals_a(&self, _: &dyn Message) -> bool;
}

// An Any is not normally clonable. This is a way around that.
// pub trait MessageClone {
//     fn clone_message(&self) -> Box<Message>;
// }

// Implements MessageClone for any type that Implements Message and Clone
// impl<T> MessageClone for T
// where
//     T: 'static + Message + Clone,
// {
//     fn clone_message(&self) -> Box<Message> {
//         Box::new(self.clone())
//     }
// }

// An implementation of clone for boxed messages
// impl Clone for Box<Message> {
//     fn clone(&self) -> Box<Message> {
//         self.clone_message()
//     }
// }

impl dyn Message {
    // Check if a message is a certain type
    pub fn is<T: Message>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let concrete = self.type_id();

        // Compare both TypeIds on equality
        t == concrete
    }

    // Casts a message to the specified type if the message is of that type
    pub fn downcast<T>(&mut self) -> Option<&mut T>
    where
        T: Message,
    {
        if self.is::<T>() {
            unsafe { Some(&mut *(self as *mut dyn Message as *mut T)) }
        } else {
            None
        }
    }
}

// Implements message for any static type that implements Clone
impl<S: 'static + PartialEq> Message for S {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn equals_a(&self, other: &dyn Message) -> bool {
        //other.as_any().type_id() == self.as_any().type_id()

        //println!("{:?} {:?}", other.as_any().type_id(), self.as_any().type_id());
        //println!("{:?} {:?}", other, self);

        other
            .as_any()
            .downcast_ref::<S>()
            .map_or(false, |a| self == a)
    }
}

/// An event is a wrapper around a message and provides metadata on how the event should be propagated through the tree
pub struct Event {
    // The entity that produced the event. Entity::null() for OS events or unspecified.
    pub origin: Entity,
    // The entity the event should be sent to. Entity::null() to send to all entities.
    pub target: Entity,
    // How the event propagates through the tree.
    pub propagation: Propagation,
    // Whether the event can be consumed
    pub consumable: bool,
    // Determines whether the event should continue to be propagated
    pub(crate) consumed: bool,
    // Whether the event is unique (only the latest copy can exist in a queue at a time)
    pub unique: bool,
    // Specifies an order index which is used to sort the event queue
    pub order: i32,
    // The event message
    pub message: Box<dyn Message>,
}

// Allows events to be compared for equality
impl PartialEq for Event {
    fn eq(&self, other: &Event) -> bool {
        self.message.equals_a(&*other.message)
            //&& self.origin == other.origin
            && self.target == other.target
    }
}

impl Event {
    /// Creates a new event with a specified message
    pub fn new<M>(message: M) -> Self
    where
        M: Message,
    {
        Event {
            origin: Entity::null(),
            target: Entity::null(),
            propagation: Propagation::Up,
            consumable: true,
            consumed: false,
            unique: true,
            order: 0,
            message: Box::new(message),
        }
    }

    /// Sets the target of the event
    pub fn target(mut self, entity: Entity) -> Self {
        self.target = entity;
        self
    }

    /// Sets the origin of the event
    pub fn origin(mut self, entity: Entity) -> Self {
        self.origin = entity;
        self
    }

    /// Specifies that the event is unique
    /// (only one of this event type should exist in the event queue at once)
    pub fn unique(mut self) -> Self {
        self.unique = true;
        self
    }

    /// Sets the propagation of the event
    pub fn propagate(mut self, propagation: Propagation) -> Self {
        self.propagation = propagation;

        self
    }

    pub fn direct(mut self, entity: Entity) -> Self {
        self.propagation = Propagation::Direct;
        self.target = entity;
        self
    }

    /// Consumes the event
    /// (prevents the event from continuing on its propagation path)
    pub fn consume(&mut self) {
        self.consumed = true;
    }
}