1use std::marker::PhantomData;
2use std::any::{TypeId, Any};
3use std::fmt::Debug;
4use std::collections::BTreeMap;
5use std::cmp::Ordering;
6use std::mem;
7
8use minidom::Element;
9
10/// A marker trait which marks all events.
11pub trait Event: Any + Debug {}
12
13/// A trait which is implemented for all event handlers.
14trait EventHandler: Any {
15 /// Handle an event, returns whether to propagate the event to the remaining handlers.
16 fn handle(&self, event: &AbstractEvent) -> Propagation;
17}
18
19/// An abstract event.
20pub struct AbstractEvent {
21 inner: Box<Any>,
22}
23
24impl AbstractEvent {
25 /// Creates an abstract event from a concrete event.
26 pub fn new<E: Event>(event: E) -> AbstractEvent {
27 AbstractEvent {
28 inner: Box::new(event),
29 }
30 }
31
32 /// Downcasts this abstract event into a concrete event.
33 pub fn downcast<E: Event + 'static>(&self) -> Option<&E> {
34 self.inner.downcast_ref::<E>()
35 }
36
37 /// Checks whether this abstract event is a specific concrete event.
38 pub fn is<E: Event + 'static>(&self) -> bool {
39 self.inner.is::<E>()
40 }
41}
42
43struct Record<P, T>(P, T);
44
45impl<P: PartialEq, T> PartialEq for Record<P, T> {
46 fn eq(&self, other: &Record<P, T>) -> bool {
47 self.0 == other.0
48 }
49}
50
51impl<P: Eq, T> Eq for Record<P, T> {}
52
53impl<P: PartialOrd, T> PartialOrd for Record<P, T> {
54 fn partial_cmp(&self, other: &Record<P, T>) -> Option<Ordering> {
55 self.0.partial_cmp(&other.0)
56 }
57}
58
59impl<P: Ord, T> Ord for Record<P, T> {
60 fn cmp(&self, other: &Record<P, T>) -> Ordering {
61 self.0.cmp(&other.0)
62 }
63}
64
65/// An enum representing whether to keep propagating an event or to stop the propagation.
66pub enum Propagation {
67 /// Stop the propagation of the event, the remaining handlers will not get invoked.
68 Stop,
69 /// Continue propagating the event.
70 Continue,
71}
72
73/// An event dispatcher, this takes care of dispatching events to their respective handlers.
74pub struct Dispatcher {
75 handlers: BTreeMap<TypeId, Vec<Record<Priority, Box<EventHandler>>>>,
76 queue: Vec<(TypeId, AbstractEvent)>,
77}
78
79impl Dispatcher {
80 /// Create a new `Dispatcher`.
81 pub fn new() -> Dispatcher {
82 Dispatcher {
83 handlers: BTreeMap::new(),
84 queue: Vec::new(),
85 }
86 }
87
88 /// Register an event handler.
89 pub fn register<E, F>(&mut self, priority: Priority, func: F)
90 where
91 E: Event,
92 F: Fn(&E) -> Propagation + 'static {
93 struct Handler<E, F> where E: Event, F: Fn(&E) -> Propagation {
94 func: F,
95 _marker: PhantomData<E>,
96 }
97
98 impl<E: Event, F: Fn(&E) -> Propagation + 'static> EventHandler for Handler<E, F> {
99 fn handle(&self, evt: &AbstractEvent) -> Propagation {
100 if let Some(e) = evt.downcast::<E>() {
101 (self.func)(e)
102 }
103 else {
104 Propagation::Continue
105 }
106 }
107 }
108
109 let handler: Box<EventHandler> = Box::new(Handler {
110 func: func,
111 _marker: PhantomData,
112 }) as Box<EventHandler>;
113 let ent = self.handlers.entry(TypeId::of::<E>())
114 .or_insert_with(|| Vec::new());
115 ent.push(Record(priority, handler));
116 ent.sort();
117 }
118
119 /// Append an event to the queue.
120 pub fn dispatch<E>(&mut self, event: E) where E: Event {
121 self.queue.push((TypeId::of::<E>(), AbstractEvent::new(event)));
122 }
123
124 /// Flush all events in the queue so they can be handled by their respective handlers.
125 /// Returns whether there are still pending events.
126 pub fn flush(&mut self) -> bool {
127 let mut q = Vec::new();
128 mem::swap(&mut self.queue, &mut q);
129 'evts: for (t, evt) in q {
130 if let Some(handlers) = self.handlers.get_mut(&t) {
131 for &mut Record(_, ref mut handler) in handlers {
132 match handler.handle(&evt) {
133 Propagation::Stop => { continue 'evts; },
134 Propagation::Continue => (),
135 }
136 }
137 }
138 }
139 !self.queue.is_empty()
140 }
141
142 /// Flushes all events, like `flush`, but keeps doing this until there is nothing left in the
143 /// queue.
144 pub fn flush_all(&mut self) {
145 while self.flush() {}
146 }
147}
148
149#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
150pub enum Priority {
151 Max,
152 Default,
153 Min,
154}
155
156impl Default for Priority {
157 fn default() -> Priority {
158 Priority::Default
159 }
160}
161
162#[derive(Debug)]
163pub struct SendElement(pub Element);
164
165impl Event for SendElement {}
166
167#[derive(Debug)]
168pub struct ReceiveElement(pub Element);
169
170impl Event for ReceiveElement {}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 #[should_panic(expected = "success")]
178 fn test() {
179 let mut disp = Dispatcher::new();
180
181 #[derive(Debug)]
182 struct MyEvent {
183 should_be_42: u32,
184 }
185
186 impl Event for MyEvent {}
187
188 disp.register(Priority::Max, |evt: &MyEvent| {
189 if evt.should_be_42 == 42 {
190 Propagation::Continue
191 }
192 else {
193 Propagation::Stop
194 }
195 });
196
197 disp.register(Priority::Min, |_: &MyEvent| {
198 panic!("should not be called");
199 });
200
201 disp.register(Priority::Default, |evt: &MyEvent| {
202 if evt.should_be_42 == 42 {
203 panic!("success");
204 }
205 else {
206 panic!("not 42");
207 }
208 });
209
210 disp.register(Priority::Min, |_: &MyEvent| {
211 panic!("should not be called");
212 });
213
214 disp.dispatch(MyEvent {
215 should_be_42: 39,
216 });
217
218 disp.dispatch(MyEvent {
219 should_be_42: 42,
220 });
221
222 disp.flush();
223 }
224}