Skip to main content

layer_system/
lib.rs

1#![deny(missing_docs)]
2/*!
3A simple, flexible layer system for managing UI states, game modes, and event handling.
4
5Layers process events **top-to-bottom** for `update` and **bottom-to-top** for `passive_update`.
6
7Key features:
8- Easy stacking/replacing/removing of layers via `Change`.
9- Generic over state `S` and events `E`.
10- Efficient for small stacks.
11*/
12
13/// A special action for the layer.
14#[derive(Copy, Clone, Debug, PartialEq, Eq)]
15pub enum ChangeAction {
16    /// No special action to the layer.
17    None,
18    /// Remove the current layer.
19    Remove,
20    /// Remove all layers.
21    Clear,
22}
23
24/// The action, that will be done after handling an event by a layer.
25pub struct Change<S, E> {
26    /// Add new layers on top of the current layer.
27    add: Box<[Box<dyn Layer<S, E>>]>,
28    /// Special actions.
29    action: ChangeAction,
30    /// Pass the event to the next layer.
31    pass: bool,
32}
33
34impl<S, E> Change<S, E> {
35    /// A simple change doing nothing.
36    pub fn none() -> Self {
37        Self {
38            add: [].into(),
39            action: ChangeAction::None,
40            pass: false,
41        }
42    }
43
44    /// A change passing the event to the next layer.
45    pub fn pass() -> Self {
46        Self {
47            add: [].into(),
48            action: ChangeAction::None,
49            pass: true,
50        }
51    }
52
53    /// A change adding new layers.
54    pub fn add(add: Box<[Box<dyn Layer<S, E>>]>) -> Self {
55        Self {
56            add,
57            action: ChangeAction::None,
58            pass: false,
59        }
60    }
61
62    /// A change adding a single new layer.
63    pub fn add_single(add: Box<dyn Layer<S, E>>) -> Self {
64        Self {
65            add: [add].into(),
66            action: ChangeAction::None,
67            pass: false,
68        }
69    }
70
71    /// A simple change removing the current layer.
72    pub fn remove() -> Self {
73        Self {
74            add: [].into(),
75            action: ChangeAction::Remove,
76            pass: false,
77        }
78    }
79
80    /// A change replacing the current layer with new layers.
81    pub fn replace(add: Box<[Box<dyn Layer<S, E>>]>) -> Self {
82        Self {
83            add,
84            action: ChangeAction::Remove,
85            pass: false,
86        }
87    }
88
89    /// A change replacing the current layer with a single new layer.
90    pub fn replace_single(add: Box<dyn Layer<S, E>>) -> Self {
91        Self {
92            add: [add].into(),
93            action: ChangeAction::Remove,
94            pass: false,
95        }
96    }
97
98    /// A change removing all layers.
99    pub fn close() -> Self {
100        Self {
101            add: [].into(),
102            action: ChangeAction::Clear,
103            pass: false,
104        }
105    }
106
107    /// A change replacing all layers with a new stack of layers.
108    pub fn clear(add: Box<[Box<dyn Layer<S, E>>]>) -> Self {
109        Self {
110            add,
111            action: ChangeAction::Clear,
112            pass: false,
113        }
114    }
115
116    /// A change replacing all layers with a single new layer.
117    pub fn clear_single(add: Box<dyn Layer<S, E>>) -> Self {
118        Self {
119            add: [add].into(),
120            action: ChangeAction::Clear,
121            pass: false,
122        }
123    }
124}
125
126/// A trait, every layer has to implement, in order to be used by the layer manager;
127pub trait Layer<S, E> {
128    /// Executed for all layers from bottom to top. Most useful for rendering.
129    fn passive_update(&mut self, _state: &mut S, _event: &E) {}
130
131    /// Executed for top layer and optionally for more layers. Most useful for click events.
132    fn update(&mut self, _state: &mut S, _event: &E) -> Change<S, E>;
133}
134
135/// The layer manager deals with the layers you create.
136pub struct LayerManager<S, E> {
137    layers: Vec<Box<dyn Layer<S, E>>>,
138}
139
140impl<S, E> LayerManager<S, E> {
141    /// Create a new layer manager containing specified initial layers.
142    pub fn new(layers: Vec<Box<dyn Layer<S, E>>>) -> Self {
143        Self { layers }
144    }
145
146    /// Checks if the layer manager is still active. When not active, the program should terminate or new layers should be added before calling `update` again.
147    pub fn is_active(&self) -> bool {
148        !self.layers.is_empty()
149    }
150
151    /// Everytime the program recieves or generates an event, which should be handled by a layer, this method has to be called.
152    pub fn update(&mut self, state: &mut S, event: E) {
153        for i in (0..self.layers.len()).rev() {
154            let layer = &mut self.layers[i];
155            let Change { add, action, pass } = layer.update(state, &event);
156
157            use ChangeAction::*;
158            let add_index = match action {
159                None => i + 1,
160                Remove => {
161                    self.layers.remove(i);
162                    i
163                }
164                Clear => {
165                    self.layers.clear();
166                    0
167                }
168            };
169
170            for added in add.into_iter().rev() {
171                self.layers.insert(add_index, added);
172            }
173
174            if !pass {
175                break;
176            }
177        }
178
179        for layer in &mut self.layers {
180            layer.passive_update(state, &event);
181        }
182    }
183}
184
185#[cfg(test)]
186mod tests {
187    use crate::*;
188
189    pub enum Event {
190        Idle,
191        Input,
192        Exit,
193    }
194
195    pub struct GlobalState;
196
197    pub struct MainLayer;
198
199    impl Layer<GlobalState, Event> for MainLayer {
200        fn update(
201            &mut self,
202            _state: &mut GlobalState,
203            event: &Event,
204        ) -> Change<GlobalState, Event> {
205            match event {
206                Event::Input => Change::add_single(Box::new(TopLayer)),
207                Event::Idle => Change::none(),
208                Event::Exit => Change::remove(),
209            }
210        }
211    }
212
213    pub struct TopLayer;
214
215    impl Layer<GlobalState, Event> for TopLayer {
216        fn update(
217            &mut self,
218            _state: &mut GlobalState,
219            event: &Event,
220        ) -> Change<GlobalState, Event> {
221            match event {
222                Event::Input => Change::pass(),
223                Event::Idle => Change::none(),
224                Event::Exit => Change::remove(),
225            }
226        }
227    }
228
229    #[test]
230    fn example() {
231        let mut manager = LayerManager::new(vec![Box::new(MainLayer), Box::new(TopLayer)]);
232        let mut state = GlobalState;
233
234        manager.update(&mut state, Event::Idle);
235        manager.update(&mut state, Event::Input);
236        manager.update(&mut state, Event::Idle);
237
238        manager.update(&mut state, Event::Exit);
239        assert_eq!(manager.layers.len(), 2);
240        assert!(manager.is_active());
241
242        manager.update(&mut state, Event::Exit);
243        assert_eq!(manager.layers.len(), 1);
244        assert!(manager.is_active());
245
246        manager.update(&mut state, Event::Exit);
247        assert!(manager.layers.is_empty());
248        assert!(!manager.is_active());
249    }
250}