lokey/
layer.rs

1use alloc::collections::BTreeMap;
2use core::cell::RefCell;
3use embassy_sync::blocking_mutex::{Mutex, raw::CriticalSectionRawMutex};
4
5/// The ID of a layer.
6#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
7pub struct LayerId(pub u8);
8
9/// Handle to an entry in [`LayerManager`].
10#[derive(PartialEq, Eq, PartialOrd, Ord)]
11pub struct LayerManagerEntry(u64);
12
13static LAYER_MANAGER_MAP: Mutex<CriticalSectionRawMutex, RefCell<BTreeMap<u64, LayerId>>> =
14    Mutex::new(RefCell::new(BTreeMap::new()));
15
16/// Type for managing the currently active layers.
17///
18/// Internally a stack-like datastructure is used to keep track of the order in which the layers got
19/// activated. When pushing a new layer ID to the [`LayerManager`] it will become the active one and
20/// a [`LayerManagerEntry`] is returned that can be used to deactive the layer again.
21#[derive(Clone, Copy, Default)]
22#[non_exhaustive]
23pub struct LayerManager {}
24
25impl LayerManager {
26    /// Creates a new [`LayerManager`].
27    pub fn new() -> Self {
28        Self {}
29    }
30
31    /// Sets the active layer to the layer with the specified ID.
32    pub fn push(&self, layer: LayerId) -> LayerManagerEntry {
33        LAYER_MANAGER_MAP.lock(|map| {
34            let mut map = map.borrow_mut();
35            let new_id = match map.last_key_value() {
36                Some((last_id, _)) => last_id + 1,
37                None => 0,
38            };
39            assert!(!map.contains_key(&new_id));
40            map.insert(new_id, layer);
41            LayerManagerEntry(new_id)
42        })
43    }
44
45    /// Deactivates the layer that was pushed to the stack with the specified [`LayerManagerEntry`].
46    pub fn remove(&self, entry: LayerManagerEntry) -> LayerId {
47        LAYER_MANAGER_MAP.lock(|map| map.borrow_mut().remove(&entry.0).unwrap())
48    }
49
50    /// Returns the ID of the currently active layer (i.e. the layer ID that was last pushed to the stack).
51    pub fn active(&self) -> LayerId {
52        LAYER_MANAGER_MAP.lock(|map| match map.borrow().last_key_value() {
53            Some((_, layer)) => *layer,
54            None => LayerId(0),
55        })
56    }
57}