ratatui_toolkit/widgets/code_diff/extensions/file_tree/methods/
navigation.rs1use crate::primitives::tree_view::{get_visible_paths_filtered, matches_filter, TreeNavigator};
6use crate::widgets::code_diff::diff_file_tree::{DiffFileEntry, DiffFileTree};
7
8impl DiffFileTree {
9 fn filter_matcher() -> impl Fn(&DiffFileEntry, &Option<String>) -> bool + Copy {
11 |entry: &DiffFileEntry, filter: &Option<String>| matches_filter(&entry.name, filter)
12 }
13
14 pub fn select_next(&mut self) {
18 let navigator = TreeNavigator::new();
19 navigator.select_next_filtered(&self.nodes, &mut self.state, Self::filter_matcher());
20 }
21
22 pub fn select_prev(&mut self) {
26 let navigator = TreeNavigator::new();
27 navigator.select_previous_filtered(&self.nodes, &mut self.state, Self::filter_matcher());
28 }
29
30 pub fn toggle_expand(&mut self) {
34 let navigator = TreeNavigator::new();
35 navigator.toggle_selected(&self.nodes, &mut self.state);
36 }
37
38 pub fn expand_selected(&mut self) {
42 let navigator = TreeNavigator::new();
43 navigator.expand_selected(&self.nodes, &mut self.state);
44 }
45
46 pub fn collapse_selected(&mut self) -> bool {
53 if let Some(path) = self.state.selected_path.clone() {
54 if self.state.is_expanded(&path) {
55 if let Some(node) = self.get_node_at_path(&path) {
57 if node.data.is_dir {
58 self.state.collapse(path);
59 return true;
60 }
61 }
62 }
63 }
64 false
65 }
66
67 pub fn go_to_parent(&mut self) {
71 if let Some(path) = &self.state.selected_path {
72 if path.len() > 1 {
73 let parent = path[..path.len() - 1].to_vec();
75 self.state.select(parent);
76 }
77 }
78 }
79
80 pub fn goto_top(&mut self) {
84 let navigator = TreeNavigator::new();
85 navigator.goto_top_filtered(&self.nodes, &mut self.state, Self::filter_matcher());
86 }
87
88 pub fn goto_bottom(&mut self) {
92 let navigator = TreeNavigator::new();
93 navigator.goto_bottom_filtered(&self.nodes, &mut self.state, Self::filter_matcher());
94 }
95
96 #[must_use]
103 pub fn selected_is_dir(&self) -> Option<bool> {
104 let path = self.state.selected_path.as_ref()?;
105 let node = self.get_node_at_path(path)?;
106 Some(node.data.is_dir)
107 }
108
109 #[must_use]
113 pub fn visible_count(&self) -> usize {
114 get_visible_paths_filtered(&self.nodes, &self.state, Self::filter_matcher()).len()
115 }
116
117 pub fn set_selected_index(&mut self, index: usize) {
125 let visible_paths =
126 get_visible_paths_filtered(&self.nodes, &self.state, Self::filter_matcher());
127 if let Some(path) = visible_paths.get(index) {
128 self.state.select(path.clone());
129 }
130 }
131
132 pub(crate) fn get_node_at_path(
134 &self,
135 path: &[usize],
136 ) -> Option<
137 &crate::primitives::tree_view::TreeNode<
138 crate::widgets::code_diff::diff_file_tree::DiffFileEntry,
139 >,
140 > {
141 if path.is_empty() {
142 return None;
143 }
144
145 let mut current_nodes = &self.nodes;
146 let mut node = None;
147
148 for &idx in path {
149 node = current_nodes.get(idx);
150 if let Some(n) = node {
151 current_nodes = &n.children;
152 } else {
153 return None;
154 }
155 }
156
157 node
158 }
159}