Skip to main content

cursive_tree/view/
selection.rs

1use super::{
2    super::{backend::*, model::*},
3    tree::*,
4};
5
6use {cursive::*, std::cmp::*};
7
8impl<BackendT> TreeView<BackendT>
9where
10    BackendT: TreeBackend,
11{
12    /// The selected row.
13    pub fn selected_row(&self) -> Option<usize> {
14        self.selected_row
15    }
16
17    /// The selected node.
18    pub fn selected_node(&self) -> Option<&Node<BackendT>> {
19        self.selected_row.and_then(|selected_row| self.model.at_row(selected_row))
20    }
21
22    /// The selected path.
23    pub fn selected_path(&self) -> Option<NodePath> {
24        self.selected_node().and_then(|node| self.model.path(node))
25    }
26
27    /// The selected node.
28    pub fn selected_node_mut(&mut self) -> Option<&mut Node<BackendT>> {
29        self.selected_path().and_then(|path| self.model.at_path_mut(path))
30    }
31
32    /// Whether the row is selected.
33    pub fn is_selected(&self, row: usize) -> bool {
34        self.selected_row.map(|selected_row| selected_row == row).unwrap_or_default()
35    }
36
37    /// Set selected row.
38    ///
39    /// If the row is invalid will set the selection to [None].
40    ///
41    /// If the selection is changed will call
42    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
43    pub fn select(&mut self, row: usize, cursive: &mut Cursive)
44    where
45        BackendT::Context: Clone,
46    {
47        let last_selected_row = self.selected_row;
48        self.selected_row = if self.model.is_empty() || row >= self.model.extents().y { None } else { Some(row) };
49        if self.selected_row != last_selected_row {
50            BackendT::handle_selection_changed(cursive, self.model.context.clone());
51        }
52    }
53
54    /// Select top row.
55    ///
56    /// If the tree is empty will set the selection to [None].
57    ///
58    /// If the selection is changed will call
59    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
60    pub fn select_top(&mut self, cursive: &mut Cursive)
61    where
62        BackendT::Context: Clone,
63    {
64        let last_selected_row = self.selected_row;
65        self.select_top_();
66        if self.selected_row != last_selected_row {
67            BackendT::handle_selection_changed(cursive, self.model.context.clone());
68        }
69    }
70
71    /// Select bottom row.
72    ///
73    /// If the tree is empty will set the selection to [None].
74    ///
75    /// If the selection is changed will call
76    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
77    pub fn select_bottom(&mut self, cursive: &mut Cursive)
78    where
79        BackendT::Context: Clone,
80    {
81        let last_selected_row = self.selected_row;
82        self.select_bottom_();
83        if self.selected_row != last_selected_row {
84            BackendT::handle_selection_changed(cursive, self.model.context.clone());
85        }
86    }
87
88    /// Move selection by delta rows if possible.
89    ///
90    /// If the selection is [None] will select the top row.
91    ///
92    /// If the selection is changed will call
93    /// [handle_selection_changed](TreeBackend::handle_selection_changed).
94    pub fn move_selection(&mut self, delta: isize, cursive: &mut Cursive)
95    where
96        BackendT::Context: Clone,
97    {
98        let last_selected_row = self.selected_row;
99        self.move_selection_(delta);
100        if self.selected_row != last_selected_row {
101            BackendT::handle_selection_changed(cursive, self.model.context.clone());
102        }
103    }
104
105    // Select top row.
106    pub(crate) fn select_top_(&mut self) {
107        self.selected_row = if self.model.is_empty() || self.model.extents().y == 0 { None } else { Some(0) }
108    }
109
110    // Select bottom row.
111    pub(crate) fn select_bottom_(&mut self) {
112        self.selected_row = if self.model.is_empty() {
113            None
114        } else {
115            let height = self.model.extents().y;
116            if height == 0 { None } else { Some(height - 1) }
117        };
118    }
119
120    // Move selection by delta rows.
121    pub(crate) fn move_selection_(&mut self, delta: isize) {
122        if delta == 0 {
123            return;
124        }
125
126        self.selected_row = if self.model.is_empty() {
127            None
128        } else {
129            let height = self.model.extents().y;
130            if height == 0 {
131                None
132            } else {
133                Some(
134                    self.selected_row
135                        .map(|selected_row| min(selected_row.checked_add_signed(delta).unwrap_or_default(), height - 1))
136                        .unwrap_or_default(),
137                )
138            }
139        };
140    }
141}