pub enum Change<S, E> {
Stay,
Defer,
Add(Box<dyn Layer<S, E>>),
Remove,
Replace(Box<dyn Layer<S, E>>),
Clear(Box<dyn Layer<S, E>>),
Close,
}
pub trait Layer<S, E> {
fn passive_update(&mut self, _state: &mut S, _event: &E) {}
fn update(&mut self, _state: &mut S, _event: &E) -> Change<S, E>;
}
pub struct LayerManager<'m, S, E>(Vec<Box<dyn Layer<S, E> + 'm>>);
impl<'m, S, E> LayerManager<'m, S, E> {
pub fn new() -> Self {
let list = Vec::new();
LayerManager::<S, E>(list)
}
pub fn add<L: Layer<S, E> + 'm>(&mut self, layer: L) {
self.0.push(Box::new(layer) as Box<dyn Layer<S, E> + 'm>);
}
pub fn is_active(&self) -> bool {
!self.0.is_empty()
}
fn change_layer(&mut self, change: Change<S, E>, index: usize) {
use self::Change::*;
match change {
Add(layer) => {
self.0.insert(index + 1, layer);
}
Remove => {
self.0.remove(index);
}
Replace(layer) => {
self.0.remove(index);
self.0.insert(index, layer);
}
Clear(layer) => {
self.0.clear();
self.0.push(layer);
}
Close => self.0.clear(),
_ => (),
}
}
pub fn update(&mut self, state: &mut S, event: E) {
let (change, index) = 'change: loop {
use self::Change::*;
for (i, layer) in self.0.iter_mut().enumerate().rev() {
match layer.update(state, &event) {
Defer => continue,
change => break 'change (change, i),
}
}
break (Defer, 0);
};
for layer in self.0.iter_mut() {
layer.passive_update(state, &event);
}
self.change_layer(change, index);
}
}
#[cfg(test)]
mod tests {
use crate::*;
pub enum Event {
Idle,
Input,
Exit,
}
pub struct GlobalState;
pub struct MainLayer;
impl Layer<GlobalState, Event> for MainLayer {
fn update(&mut self, _state: &mut GlobalState, event: &Event) -> Change<GlobalState, Event> {
match event {
Event::Input => Change::Add(Box::new(TopLayer)),
Event::Idle => Change::Stay,
Event::Exit => Change::Remove,
}
}
}
pub struct TopLayer;
impl Layer<GlobalState, Event> for TopLayer {
fn update(&mut self, _state: &mut GlobalState, event: &Event) -> Change<GlobalState, Event> {
match event {
Event::Input => Change::Defer,
Event::Idle => Change::Stay,
Event::Exit => Change::Remove,
}
}
}
#[test]
fn example() {
let mut manager = LayerManager::new();
let mut state = GlobalState;
manager.add(MainLayer);
manager.add(TopLayer);
manager.update(&mut state, Event::Idle);
manager.update(&mut state, Event::Input);
manager.update(&mut state, Event::Idle);
while manager.is_active() {
manager.update(&mut state, Event::Exit);
}
}
}