use crossterm::event::KeyCode;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RolloverDialog {
pub plans: Vec<(String, String, usize)>,
pub choice: DialogChoice,
pub dismissed: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogChoice {
DoRollover,
Ignore,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DialogEvent {
None,
ConfirmDo,
ConfirmIgnore,
Dismiss,
}
impl RolloverDialog {
pub fn new(plans: Vec<(String, String, usize)>) -> Self {
Self {
plans,
choice: DialogChoice::DoRollover,
dismissed: false,
}
}
pub fn is_active(&self) -> bool {
!self.plans.is_empty() && !self.dismissed
}
pub fn handle_key(&mut self, key: KeyCode) -> DialogEvent {
if !self.is_active() {
return DialogEvent::Dismiss;
}
match key {
KeyCode::Left | KeyCode::Right | KeyCode::Tab => {
self.choice = match self.choice {
DialogChoice::DoRollover => DialogChoice::Ignore,
DialogChoice::Ignore => DialogChoice::DoRollover,
};
DialogEvent::None
}
KeyCode::Esc => {
self.dismissed = true;
DialogEvent::Dismiss
}
KeyCode::Enter => {
self.dismissed = true;
match self.choice {
DialogChoice::DoRollover => DialogEvent::ConfirmDo,
DialogChoice::Ignore => DialogEvent::ConfirmIgnore,
}
}
_ => DialogEvent::None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dialog_choice_toggles() {
let mut dialog = RolloverDialog::new(vec![("Cycle 1".into(), "Cycle 2".into(), 2)]);
assert_eq!(dialog.choice, DialogChoice::DoRollover);
dialog.handle_key(KeyCode::Tab);
assert_eq!(dialog.choice, DialogChoice::Ignore);
}
#[test]
fn enter_confirms_active_choice() {
let mut dialog = RolloverDialog::new(vec![("Cycle 1".into(), "Cycle 2".into(), 2)]);
assert_eq!(dialog.handle_key(KeyCode::Enter), DialogEvent::ConfirmDo);
let mut dialog = RolloverDialog::new(vec![("Cycle 1".into(), "Cycle 2".into(), 2)]);
dialog.handle_key(KeyCode::Right);
assert_eq!(
dialog.handle_key(KeyCode::Enter),
DialogEvent::ConfirmIgnore
);
}
#[test]
fn esc_dismisses_dialog() {
let mut dialog = RolloverDialog::new(vec![("Cycle 1".into(), "Cycle 2".into(), 2)]);
assert_eq!(dialog.handle_key(KeyCode::Esc), DialogEvent::Dismiss);
assert!(!dialog.is_active());
}
}