#![deny(missing_docs)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ChangeAction {
None,
Remove,
Clear,
}
pub struct Change<S, E> {
add: Box<[Box<dyn Layer<S, E>>]>,
action: ChangeAction,
pass: bool,
}
impl<S, E> Change<S, E> {
pub fn none() -> Self {
Self {
add: [].into(),
action: ChangeAction::None,
pass: false,
}
}
pub fn pass() -> Self {
Self {
add: [].into(),
action: ChangeAction::None,
pass: true,
}
}
pub fn add(add: Box<[Box<dyn Layer<S, E>>]>) -> Self {
Self {
add,
action: ChangeAction::None,
pass: false,
}
}
pub fn add_single(add: Box<dyn Layer<S, E>>) -> Self {
Self {
add: [add].into(),
action: ChangeAction::None,
pass: false,
}
}
pub fn remove() -> Self {
Self {
add: [].into(),
action: ChangeAction::Remove,
pass: false,
}
}
pub fn replace(add: Box<[Box<dyn Layer<S, E>>]>) -> Self {
Self {
add,
action: ChangeAction::Remove,
pass: false,
}
}
pub fn replace_single(add: Box<dyn Layer<S, E>>) -> Self {
Self {
add: [add].into(),
action: ChangeAction::Remove,
pass: false,
}
}
pub fn close() -> Self {
Self {
add: [].into(),
action: ChangeAction::Clear,
pass: false,
}
}
pub fn clear(add: Box<[Box<dyn Layer<S, E>>]>) -> Self {
Self {
add,
action: ChangeAction::Clear,
pass: false,
}
}
pub fn clear_single(add: Box<dyn Layer<S, E>>) -> Self {
Self {
add: [add].into(),
action: ChangeAction::Clear,
pass: false,
}
}
}
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<S, E> {
layers: Vec<Box<dyn Layer<S, E>>>,
}
impl<S, E> LayerManager<S, E> {
pub fn new(layers: Vec<Box<dyn Layer<S, E>>>) -> Self {
Self { layers }
}
pub fn is_active(&self) -> bool {
!self.layers.is_empty()
}
pub fn update(&mut self, state: &mut S, event: E) {
for i in (0..self.layers.len()).rev() {
let layer = &mut self.layers[i];
let Change { add, action, pass } = layer.update(state, &event);
use ChangeAction::*;
let add_index = match action {
None => i + 1,
Remove => {
self.layers.remove(i);
i
}
Clear => {
self.layers.clear();
0
}
};
for added in add.into_iter().rev() {
self.layers.insert(add_index, added);
}
if !pass {
break;
}
}
for layer in &mut self.layers {
layer.passive_update(state, &event);
}
}
}
#[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_single(Box::new(TopLayer)),
Event::Idle => Change::none(),
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::pass(),
Event::Idle => Change::none(),
Event::Exit => Change::remove(),
}
}
}
#[test]
fn example() {
let mut manager = LayerManager::new(vec![Box::new(MainLayer), Box::new(TopLayer)]);
let mut state = GlobalState;
manager.update(&mut state, Event::Idle);
manager.update(&mut state, Event::Input);
manager.update(&mut state, Event::Idle);
manager.update(&mut state, Event::Exit);
assert_eq!(manager.layers.len(), 2);
assert!(manager.is_active());
manager.update(&mut state, Event::Exit);
assert_eq!(manager.layers.len(), 1);
assert!(manager.is_active());
manager.update(&mut state, Event::Exit);
assert!(manager.layers.is_empty());
assert!(!manager.is_active());
}
}