Skip to main content

term_wm_layout_engine/
ordering.rs

1use core::fmt;
2
3/// A flat z-order list. The last element is the top-most (front-most) item.
4#[derive(Debug, Clone)]
5pub struct ZOrder<T>(Vec<T>);
6
7impl<T> ZOrder<T> {
8    pub fn new() -> Self {
9        Self(Vec::new())
10    }
11
12    pub fn push(&mut self, id: T) {
13        self.0.push(id);
14    }
15
16    pub fn order(&self) -> &[T] {
17        &self.0
18    }
19
20    pub fn is_empty(&self) -> bool {
21        self.0.is_empty()
22    }
23
24    pub fn len(&self) -> usize {
25        self.0.len()
26    }
27
28    pub fn contains(&self, id: &T) -> bool
29    where
30        T: PartialEq,
31    {
32        self.0.contains(id)
33    }
34}
35
36impl<T: PartialEq> ZOrder<T> {
37    pub fn remove(&mut self, id: &T) {
38        self.0.retain(|x| x != id);
39    }
40
41    pub fn bring_to_front(&mut self, id: T) {
42        self.remove(&id);
43        self.0.push(id);
44    }
45
46    pub fn retain(&mut self, f: impl FnMut(&T) -> bool) {
47        self.0.retain(f);
48    }
49}
50
51impl<T> Default for ZOrder<T> {
52    fn default() -> Self {
53        Self::new()
54    }
55}
56
57/// A cyclic focus ring with a single current item.
58#[derive(Debug, Clone)]
59pub struct FocusRing<T> {
60    order: Vec<T>,
61    current: T,
62}
63
64impl<T: Copy + Eq> FocusRing<T> {
65    pub fn new(current: T) -> Self {
66        Self {
67            order: vec![current],
68            current,
69        }
70    }
71
72    pub fn current(&self) -> &T {
73        &self.current
74    }
75
76    pub fn set_current(&mut self, id: T) {
77        self.current = id;
78    }
79
80    pub fn set_order(&mut self, order: Vec<T>) {
81        self.order = order;
82        if !self.order.contains(&self.current)
83            && let Some(first) = self.order.first().copied()
84        {
85            self.current = first;
86        }
87    }
88
89    pub fn order(&self) -> &[T] {
90        &self.order
91    }
92
93    pub fn advance(&mut self, forward: bool) -> T {
94        if self.order.len() <= 1 {
95            return self.current;
96        }
97        let pos = self
98            .order
99            .iter()
100            .position(|x| *x == self.current)
101            .unwrap_or(0);
102        let len = self.order.len();
103        let next = if forward {
104            (pos + 1).rem_euclid(len)
105        } else {
106            (pos + len - 1).rem_euclid(len)
107        };
108        self.current = self.order[next];
109        self.current
110    }
111}
112
113impl<T: fmt::Debug + Copy + Eq> fmt::Display for FocusRing<T> {
114    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115        write!(
116            f,
117            "FocusRing {{ current: {:?}, order: {:?} }}",
118            self.current, self.order
119        )
120    }
121}
122
123#[cfg(test)]
124mod tests {
125    use super::*;
126
127    #[test]
128    fn zorder_push_and_contains() {
129        let mut zo = ZOrder::new();
130        zo.push(1);
131        zo.push(2);
132        assert!(zo.contains(&1));
133        assert!(zo.contains(&2));
134        assert_eq!(zo.len(), 2);
135    }
136
137    #[test]
138    fn zorder_bring_to_front() {
139        let mut zo = ZOrder::new();
140        zo.push(1);
141        zo.push(2);
142        zo.push(3);
143        zo.bring_to_front(1);
144        assert_eq!(zo.order(), &[2, 3, 1]);
145    }
146
147    #[test]
148    fn zorder_remove() {
149        let mut zo = ZOrder::new();
150        zo.push(1);
151        zo.push(2);
152        zo.push(3);
153        zo.remove(&2);
154        assert_eq!(zo.order(), &[1, 3]);
155    }
156
157    #[test]
158    fn focus_ring_advance_forward() {
159        let mut ring = FocusRing::new(1);
160        ring.set_order(vec![1, 2, 3]);
161        assert_eq!(ring.advance(true), 2);
162        assert_eq!(ring.advance(true), 3);
163        assert_eq!(ring.advance(true), 1);
164    }
165
166    #[test]
167    fn focus_ring_advance_backward() {
168        let mut ring = FocusRing::new(1);
169        ring.set_order(vec![1, 2, 3]);
170        assert_eq!(ring.advance(false), 3);
171        assert_eq!(ring.advance(false), 2);
172    }
173
174    #[test]
175    fn focus_ring_single_element() {
176        let mut ring = FocusRing::new(42);
177        assert_eq!(ring.advance(true), 42);
178        assert_eq!(ring.advance(false), 42);
179    }
180
181    #[test]
182    fn focus_ring_set_order_falls_back_to_first() {
183        let mut ring = FocusRing::new(1);
184        ring.set_order(vec![2, 3]);
185        assert_eq!(*ring.current(), 2);
186    }
187}