use crate::app::{color_of, ASH, SIGNAL};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tab {
Overview,
Budget,
Forecast,
Anomalies,
Providers,
}
impl Tab {
pub const ALL: [Tab; 5] = [
Tab::Overview,
Tab::Budget,
Tab::Forecast,
Tab::Anomalies,
Tab::Providers,
];
pub fn label(self) -> &'static str {
match self {
Tab::Overview => "Overview",
Tab::Budget => "Budget",
Tab::Forecast => "Forecast",
Tab::Anomalies => "Anomalies",
Tab::Providers => "Providers",
}
}
pub fn from_digit(digit: usize) -> Option<Tab> {
Tab::ALL.get(digit.checked_sub(1)?).copied()
}
fn position(self) -> usize {
Tab::ALL.iter().position(|&t| t == self).unwrap_or(0)
}
pub fn next(self) -> Tab {
Tab::ALL[(self.position() + 1) % Tab::ALL.len()]
}
pub fn prev(self) -> Tab {
Tab::ALL[(self.position() + Tab::ALL.len() - 1) % Tab::ALL.len()]
}
}
pub fn draw_strip(ui: &mut egui::Ui, selected: Tab) -> Option<Tab> {
let mut clicked = None;
ui.horizontal_wrapped(|ui| {
ui.add_space(8.0);
for tab in Tab::ALL {
let active = tab == selected;
let mut text = egui::RichText::new(tab.label()).monospace();
text = if active {
text.strong().color(color_of(SIGNAL))
} else {
text.color(color_of(ASH))
};
if ui.selectable_label(active, text).clicked() {
clicked = Some(tab);
}
}
});
clicked
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_digit_maps_one_through_five() {
assert_eq!(Tab::from_digit(1), Some(Tab::Overview));
assert_eq!(Tab::from_digit(5), Some(Tab::Providers));
assert_eq!(Tab::from_digit(0), None);
assert_eq!(Tab::from_digit(6), None);
}
#[test]
fn next_and_prev_wrap() {
assert_eq!(Tab::Overview.prev(), Tab::Providers);
assert_eq!(Tab::Providers.next(), Tab::Overview);
assert_eq!(Tab::Overview.next(), Tab::Budget);
assert_eq!(Tab::Budget.prev(), Tab::Overview);
let mut tab = Tab::Overview;
for _ in 0..Tab::ALL.len() {
tab = tab.next();
}
assert_eq!(tab, Tab::Overview);
}
#[test]
fn labels_are_ascii() {
for tab in Tab::ALL {
assert!(tab.label().is_ascii());
}
}
#[test]
fn draw_strip_headless_tick_does_not_panic() {
let ctx = egui::Context::default();
crate::fonts::install(&ctx);
for selected in Tab::ALL {
let _ = ctx.run_ui(egui::RawInput::default(), |ui| {
let _ = draw_strip(ui, selected);
});
}
}
}