layer-system 0.1.2

A system for handling different kinds of events
Documentation
/// The action, that will be done after handling an event by a layer.
pub enum Change<S, E> {
    /// Don't do anything
    Stay, 
    /// Pass the event to the next layer.
    Defer,
    /// Add a new layer on top of the current layer.
    Add(Box<dyn Layer<S, E>>),
    /// Remove the current layer.
    Remove,
    /// Replace the current layer with a new layer.
    Replace(Box<dyn Layer<S, E>>),
    /// Clear all layers and replace them with a new layer.
    Clear(Box<dyn Layer<S, E>>),
    /// Remove all layers.
    Close,
}

/// A trait, every layer has to implement, in order to be used by the layer manager;
pub trait Layer<S, E> {
    /// Executed for all layers from bottom to top. Most useful for rendering.
    fn passive_update(&mut self, _state: &mut S, _event: &E) {}

    /// Executed for top layer and optionally for more layers. Most useful for click events.
    fn update(&mut self, _state: &mut S, _event: &E) -> Change<S, E>;
}

/// The layer manager deals with the layers you create.
pub struct LayerManager<'m, S, E>(Vec<Box<dyn Layer<S, E> + 'm>>);

impl<'m, S, E> LayerManager<'m, S, E> {
    /// Create a new layer manager.
    pub fn new() -> Self {
        let list = Vec::new();
        LayerManager::<S, E>(list)
    }

    /// Add a new layer on the top for the layer manager. Normally useful for initializing the Layer manager.
    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>);
    }

    /// Checks if the layer manger is still active. When not active, the program should terminate or new layers should be added before calling `update` again.
    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(),
            _ => (),
        }
    }
    
    /// Everytime the program recieves or generates an event, which should be handled by a layer, this method has to be called.
    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);
        }
    }
}