clankerdiff_theme/
selection.rs1use 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}