term_wm_layout_engine/
ordering.rs1use core::fmt;
2
3#[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#[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}