1
//! Focusable sub-pane model.
2
//!
3
//! Each view declares a static list of its panes; one is always focused.
4
//! Focus is stored by value so reads never need to index.
5

            
6
#[cfg(test)]
7
mod tests;
8

            
9
/// Named pane within a view.
10
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11
pub enum PaneId {
12
    /// The nomiscript input prompt line.
13
    Prompt,
14
    /// The scrollback transcript.
15
    Scrollback,
16
}
17

            
18
/// A view's focusable sub-panes with exactly one always focused.
19
///
20
/// The pane list is `'static` (declared per view); focus is stored by value
21
/// so reads never need to index.
22
#[derive(Debug)]
23
pub struct PaneSet {
24
    panes: &'static [PaneId],
25
    focused: PaneId,
26
}
27

            
28
impl PaneSet {
29
    /// Construct a `PaneSet` with the given static pane list and initial focus.
30
190
    pub const fn new(panes: &'static [PaneId], initial: PaneId) -> Self {
31
190
        Self {
32
190
            panes,
33
190
            focused: initial,
34
190
        }
35
190
    }
36

            
37
    /// The currently focused pane.
38
39
    pub fn focused(&self) -> PaneId {
39
39
        self.focused
40
39
    }
41

            
42
    /// Whether `id` is currently focused.
43
15
    pub fn is_focused(&self, id: PaneId) -> bool {
44
15
        self.focused == id
45
15
    }
46

            
47
    /// Move focus to `id`. A no-op if `id` is not in the pane list.
48
9
    pub fn focus(&mut self, id: PaneId) {
49
9
        if self.panes.contains(&id) {
50
8
            self.focused = id;
51
8
        }
52
9
    }
53

            
54
    /// Cycle focus forward or backward through the pane list, wrapping at
55
    /// both ends.
56
9
    pub fn cycle(&mut self, forward: bool) {
57
13
        if let Some(i) = self.panes.iter().position(|p| *p == self.focused) {
58
9
            let len = self.panes.len();
59
9
            let next = if forward {
60
6
                (i + 1) % len
61
            } else {
62
3
                (i + len - 1) % len
63
            };
64
9
            if let Some(p) = self.panes.get(next) {
65
9
                self.focused = *p;
66
9
            }
67
        }
68
9
    }
69
}