Skip to main content

phosphor_app/state/
transport_ui.rs

1//! Transport UI state — navigable elements in the transport bar.
2//!
3//! Pattern matches TrackElement: h/l navigates, Enter activates/locks, Esc releases.
4
5/// Navigable elements in the transport bar.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum TransportElement {
8    Bpm,
9    Record,
10    Loop,
11    Metronome,
12}
13
14impl TransportElement {
15    pub fn move_right(self) -> Self {
16        match self {
17            Self::Bpm => Self::Record,
18            Self::Record => Self::Loop,
19            Self::Loop => Self::Metronome,
20            Self::Metronome => Self::Metronome,
21        }
22    }
23
24    pub fn move_left(self) -> Self {
25        match self {
26            Self::Bpm => Self::Bpm,
27            Self::Record => Self::Bpm,
28            Self::Loop => Self::Record,
29            Self::Metronome => Self::Loop,
30        }
31    }
32
33    pub fn label(self) -> &'static str {
34        match self {
35            Self::Bpm => "bpm",
36            Self::Record => "rec",
37            Self::Loop => "loop",
38            Self::Metronome => "met",
39        }
40    }
41}
42
43/// State for transport pane navigation.
44#[derive(Debug)]
45pub struct TransportUiState {
46    /// Which element the cursor is on.
47    pub element: TransportElement,
48    /// Whether the current element is "entered" (controls locked to it).
49    pub editing: bool,
50}
51
52impl Default for TransportUiState {
53    fn default() -> Self { Self::new() }
54}
55
56impl TransportUiState {
57    pub fn new() -> Self {
58        Self {
59            element: TransportElement::Bpm,
60            editing: false,
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn element_navigation() {
71        let e = TransportElement::Bpm;
72        assert_eq!(e.move_right(), TransportElement::Record);
73        assert_eq!(e.move_right().move_right(), TransportElement::Loop);
74        assert_eq!(e.move_right().move_right().move_right(), TransportElement::Metronome);
75        assert_eq!(TransportElement::Metronome.move_right(), TransportElement::Metronome);
76    }
77
78    #[test]
79    fn element_left_navigation() {
80        assert_eq!(TransportElement::Metronome.move_left(), TransportElement::Loop);
81        assert_eq!(TransportElement::Loop.move_left(), TransportElement::Record);
82        assert_eq!(TransportElement::Record.move_left(), TransportElement::Bpm);
83        assert_eq!(TransportElement::Bpm.move_left(), TransportElement::Bpm);
84    }
85}