1
use paste::paste;
2
use uniplate::Uniplate;
3

            
4
macro_rules! event_handlers {
5
    (
6
        directions: [$($dir:ident),*]
7
    ) => {
8

            
9
        paste! {
10
        pub(crate) struct EventHandlers<T, M> {
11
            $(
12
                [<before_ $dir>]: Vec<fn(&T, &mut M)>,
13
                [<after_ $dir>]: Vec<fn(&T, &mut M)>,
14
            )*
15
        }
16

            
17
        impl<T: Uniplate, M> EventHandlers<T, M> {
18
            pub(crate) fn new() -> Self {
19
                Self {
20
                    $(
21
                        [<before_ $dir>]: vec![],
22
                        [<after_ $dir>]: vec![],
23
                    )*
24
                }
25
            }
26

            
27
            $(
28
                pub(crate) fn [<trigger_before_ $dir>](&self, node: &T, meta: &mut M) {
29
                    for f in &self.[<before_ $dir>] {
30
                        f(node, meta)
31
                    }
32
                }
33
                pub(crate) fn [<trigger_after_ $dir>](&self, node: &T, meta: &mut M) {
34
                    for f in &self.[<after_ $dir>] {
35
                        f(node, meta)
36
                    }
37
                }
38
                pub(crate) fn [<add_before_ $dir>](&mut self, handler: fn(&T, &mut M)) {
39
                    self.[<before_ $dir>].push(handler);
40
                }
41
                pub(crate) fn [<add_after_ $dir>](&mut self, handler: fn(&T, &mut M)) {
42
                    self.[<after_ $dir>].push(handler);
43
                }
44
            )*
45
        }
46
    }};
47
}
48

            
49
// We don't need event handlers for "left" since we never move left
50
event_handlers! {
51
    directions: [up, down, right]
52
}