vtcode_tui/core_tui/session/file_palette/
navigation.rs1use super::{FileEntry, FilePalette, PAGE_SIZE};
2
3impl FilePalette {
4 pub fn move_selection_up(&mut self) {
5 if self.filtered_files.is_empty() {
6 return;
7 }
8 if self.selected_index > 0 {
9 self.selected_index -= 1;
10 } else {
11 self.selected_index = self.filtered_files.len().saturating_sub(1);
12 }
13 self.update_page_from_selection();
14 }
15
16 pub fn move_selection_down(&mut self) {
17 if self.filtered_files.is_empty() {
18 return;
19 }
20 if self.selected_index + 1 < self.filtered_files.len() {
21 self.selected_index += 1;
22 } else {
23 self.selected_index = 0;
24 }
25 self.update_page_from_selection();
26 }
27
28 pub fn move_to_first(&mut self) {
29 if !self.filtered_files.is_empty() {
30 self.selected_index = 0;
31 self.current_page = 0;
32 }
33 }
34
35 pub fn move_to_last(&mut self) {
36 if !self.filtered_files.is_empty() {
37 self.selected_index = self.filtered_files.len().saturating_sub(1);
38 self.update_page_from_selection();
39 }
40 }
41
42 pub fn page_up(&mut self) {
43 if self.current_page > 0 {
44 self.current_page -= 1;
45 self.selected_index = self.current_page * PAGE_SIZE;
46 }
47 }
48
49 pub fn page_down(&mut self) {
50 let total_pages = self.total_pages();
51 if self.current_page + 1 < total_pages {
52 self.current_page += 1;
53 self.selected_index = self.current_page * PAGE_SIZE;
54 }
55 }
56
57 fn update_page_from_selection(&mut self) {
58 self.current_page = self.selected_index / PAGE_SIZE;
59 }
60
61 pub fn get_selected(&self) -> Option<&FileEntry> {
62 self.filtered_files.get(self.selected_index)
63 }
64
65 #[allow(dead_code)]
68 pub fn get_best_match(&self) -> Option<&FileEntry> {
69 self.filtered_files.first()
71 }
72
73 pub fn select_best_match(&mut self) {
75 if !self.filtered_files.is_empty() {
76 self.selected_index = 0;
77 self.current_page = 0;
78 }
79 }
80
81 pub fn current_page_items(&self) -> Vec<(usize, &FileEntry, bool)> {
82 let start = self.current_page * PAGE_SIZE;
83 let end = (start + PAGE_SIZE).min(self.filtered_files.len());
84
85 self.filtered_files[start..end]
86 .iter()
87 .enumerate()
88 .map(|(idx, entry)| {
89 let global_idx = start + idx;
90 let is_selected = global_idx == self.selected_index;
91 (global_idx, entry, is_selected)
92 })
93 .collect()
94 }
95
96 pub fn total_pages(&self) -> usize {
97 if self.filtered_files.is_empty() {
98 1
99 } else {
100 self.filtered_files.len().div_ceil(PAGE_SIZE)
101 }
102 }
103
104 pub fn current_page_number(&self) -> usize {
105 self.current_page + 1
106 }
107
108 pub fn total_items(&self) -> usize {
109 self.filtered_files.len()
110 }
111
112 pub fn is_empty(&self) -> bool {
113 self.filtered_files.is_empty()
114 }
115
116 pub fn filter_query(&self) -> &str {
117 &self.filter_query
118 }
119
120 pub fn has_files(&self) -> bool {
121 !self.all_files.is_empty()
122 }
123
124 pub fn has_more_items(&self) -> bool {
125 let end = ((self.current_page + 1) * PAGE_SIZE).min(self.filtered_files.len());
126 end < self.filtered_files.len()
127 }
128}