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
33
            pub(crate) fn new() -> Self {
19
33
                Self {
20
33
                    $(
21
33
                        [<before_ $dir>]: vec![],
22
33
                        [<after_ $dir>]: vec![],
23
33
                    )*
24
33
                }
25
33
            }
26

            
27
            $(
28
73
                pub(crate) fn [<trigger_before_ $dir>](&self, node: &T, meta: &mut M) {
29
73
                    for f in &self.[<before_ $dir>] {
30
11
                        f(node, meta)
31
                    }
32
73
                }
33
73
                pub(crate) fn [<trigger_after_ $dir>](&self, node: &T, meta: &mut M) {
34
73
                    for f in &self.[<after_ $dir>] {
35
11
                        f(node, meta)
36
                    }
37
73
                }
38
7
                pub(crate) fn [<add_before_ $dir>](&mut self, handler: fn(&T, &mut M)) {
39
7
                    self.[<before_ $dir>].push(handler);
40
7
                }
41
7
                pub(crate) fn [<add_after_ $dir>](&mut self, handler: fn(&T, &mut M)) {
42
7
                    self.[<after_ $dir>].push(handler);
43
7
                }
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
}