Skip to main content

clankerdiff_theme/
selection.rs

1use crate::ReviewTheme;
2use std::sync::Arc;
3
4#[derive(Debug, Clone)]
5pub struct ThemeChoice {
6    pub name: String,
7    pub theme: ReviewTheme,
8}
9
10impl ThemeChoice {
11    #[must_use]
12    pub fn new(name: impl Into<String>, theme: ReviewTheme) -> Self {
13        Self {
14            name: name.into(),
15            theme,
16        }
17    }
18
19    #[must_use]
20    pub fn catalog() -> Arc<[Self]> {
21        ReviewTheme::catalog()
22            .into_iter()
23            .filter_map(|descriptor| {
24                ReviewTheme::builtin(&descriptor.id)
25                    .ok()
26                    .map(|theme| Self::new(descriptor.name, theme))
27            })
28            .collect()
29    }
30}
31
32#[derive(Debug)]
33pub struct ThemeSelection {
34    themes: Arc<[ThemeChoice]>,
35    selected: usize,
36    original: ReviewTheme,
37}
38
39impl ThemeSelection {
40    #[must_use]
41    pub fn new(current: &ReviewTheme, themes: Arc<[ThemeChoice]>) -> Option<Self> {
42        if themes.is_empty() {
43            return None;
44        }
45        let selected = themes
46            .iter()
47            .position(|choice| choice.theme.id() == current.id())
48            .unwrap_or(0);
49        Some(Self {
50            themes,
51            selected,
52            original: current.clone(),
53        })
54    }
55
56    #[must_use]
57    pub fn themes(&self) -> &[ThemeChoice] {
58        &self.themes
59    }
60
61    #[must_use]
62    pub const fn selected(&self) -> usize {
63        self.selected
64    }
65
66    #[must_use]
67    pub fn selected_theme(&self) -> ReviewTheme {
68        self.themes[self.selected].theme.clone()
69    }
70
71    #[must_use]
72    pub fn cancel(self) -> ReviewTheme {
73        self.original
74    }
75
76    #[must_use]
77    pub fn commit(self) -> ReviewTheme {
78        self.selected_theme()
79    }
80
81    pub fn select_relative(&mut self, delta: isize) -> ReviewTheme {
82        self.selected = self
83            .selected
84            .saturating_add_signed(delta)
85            .min(self.themes.len() - 1);
86        self.selected_theme()
87    }
88
89    pub fn select(&mut self, selected: usize) -> Option<ReviewTheme> {
90        let theme = self.themes.get(selected)?.theme.clone();
91        self.selected = selected;
92        Some(theme)
93    }
94}