sbom_tools/tui/viewmodel/
filter.rs1pub trait CycleFilter: Clone + Copy + Default {
50 fn next(&self) -> Self;
52
53 fn prev(&self) -> Self;
55
56 fn display_name(&self) -> &str;
58}
59
60#[derive(Debug, Clone)]
65pub struct FilterState<F: CycleFilter> {
66 pub current: F,
68}
69
70impl<F: CycleFilter> Default for FilterState<F> {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl<F: CycleFilter> FilterState<F> {
77 pub fn new() -> Self {
79 Self {
80 current: F::default(),
81 }
82 }
83
84 pub fn with_filter(filter: F) -> Self {
86 Self { current: filter }
87 }
88
89 pub fn next(&mut self) {
91 self.current = self.current.next();
92 }
93
94 pub fn prev(&mut self) {
96 self.current = self.current.prev();
97 }
98
99 pub fn set(&mut self, filter: F) {
101 self.current = filter;
102 }
103
104 pub fn reset(&mut self) {
106 self.current = F::default();
107 }
108
109 pub fn display_name(&self) -> &str {
111 self.current.display_name()
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
121 enum TestFilter {
122 #[default]
123 All,
124 FilterA,
125 FilterB,
126 }
127
128 impl CycleFilter for TestFilter {
129 fn next(&self) -> Self {
130 match self {
131 Self::All => Self::FilterA,
132 Self::FilterA => Self::FilterB,
133 Self::FilterB => Self::All,
134 }
135 }
136
137 fn prev(&self) -> Self {
138 match self {
139 Self::All => Self::FilterB,
140 Self::FilterA => Self::All,
141 Self::FilterB => Self::FilterA,
142 }
143 }
144
145 fn display_name(&self) -> &str {
146 match self {
147 Self::All => "All Items",
148 Self::FilterA => "Filter A",
149 Self::FilterB => "Filter B",
150 }
151 }
152 }
153
154 #[test]
155 fn test_filter_state_cycling() {
156 let mut state = FilterState::<TestFilter>::new();
157
158 assert_eq!(state.current, TestFilter::All);
159 assert_eq!(state.display_name(), "All Items");
160
161 state.next();
162 assert_eq!(state.current, TestFilter::FilterA);
163 assert_eq!(state.display_name(), "Filter A");
164
165 state.next();
166 assert_eq!(state.current, TestFilter::FilterB);
167
168 state.next();
169 assert_eq!(state.current, TestFilter::All);
170
171 state.prev();
172 assert_eq!(state.current, TestFilter::FilterB);
173 }
174
175 #[test]
176 fn test_filter_state_set_reset() {
177 let mut state = FilterState::<TestFilter>::new();
178
179 state.set(TestFilter::FilterB);
180 assert_eq!(state.current, TestFilter::FilterB);
181
182 state.reset();
183 assert_eq!(state.current, TestFilter::All);
184 }
185
186 #[test]
187 fn test_filter_state_with_initial() {
188 let state = FilterState::with_filter(TestFilter::FilterA);
189 assert_eq!(state.current, TestFilter::FilterA);
190 }
191}