Fix service selection cursor highlighting and bounds checking
Visual Highlighting Fixes: - Apply selection highlighting to individual text spans instead of entire paragraph - Eliminates highlighting of empty space below services on single-service hosts - Selection now only highlights actual service text content Selection Logic Improvements: - Add proper bounds checking in select_next() to prevent invalid selections - Automatically clamp selection index when services are updated - Add debug logging to track selection state and movement Bounds Safety: - Ensure selection index stays valid when service lists change - Prevent out-of-bounds access during service updates - Reset selection to last valid index when services are removed This fixes the issues where: 1. Single service hosts showed empty space highlighting 2. Multi-service hosts had no visible selection cursor 3. Selection could become invalid when services changed
This commit is contained in:
parent
c851590aaa
commit
999e7b5db5
@ -202,13 +202,15 @@ impl ServicesWidget {
|
||||
if self.selected_index > 0 {
|
||||
self.selected_index -= 1;
|
||||
}
|
||||
debug!("Service selection moved up to: {}", self.selected_index);
|
||||
}
|
||||
|
||||
/// Move selection down
|
||||
pub fn select_next(&mut self, total_services: usize) {
|
||||
if self.selected_index < total_services.saturating_sub(1) {
|
||||
if total_services > 0 && self.selected_index < total_services.saturating_sub(1) {
|
||||
self.selected_index += 1;
|
||||
}
|
||||
debug!("Service selection: {}/{}", self.selected_index, total_services);
|
||||
}
|
||||
|
||||
/// Get currently selected service name (for actions)
|
||||
@ -361,10 +363,18 @@ impl Widget for ServicesWidget {
|
||||
|
||||
self.has_data = !self.parent_services.is_empty() || !self.sub_services.is_empty();
|
||||
|
||||
// Ensure selection index is within bounds after update
|
||||
let total_count = self.get_total_services_count();
|
||||
if self.selected_index >= total_count && total_count > 0 {
|
||||
self.selected_index = total_count - 1;
|
||||
}
|
||||
|
||||
debug!(
|
||||
"Services widget updated: {} parent services, {} sub-service groups, status={:?}",
|
||||
"Services widget updated: {} parent services, {} sub-service groups, total={}, selected={}, status={:?}",
|
||||
self.parent_services.len(),
|
||||
self.sub_services.len(),
|
||||
total_count,
|
||||
self.selected_index,
|
||||
self.status
|
||||
);
|
||||
}
|
||||
@ -473,7 +483,7 @@ impl ServicesWidget {
|
||||
let actual_index = effective_scroll + i; // Real index in the full list
|
||||
let is_selected = actual_index == self.selected_index;
|
||||
|
||||
let spans = if *is_sub && sub_info.is_some() {
|
||||
let mut spans = if *is_sub && sub_info.is_some() {
|
||||
// Use custom sub-service span creation
|
||||
let (service_info, is_last) = sub_info.as_ref().unwrap();
|
||||
self.create_sub_service_spans(line_text, service_info, *is_last)
|
||||
@ -482,17 +492,17 @@ impl ServicesWidget {
|
||||
StatusIcons::create_status_spans(*line_status, line_text)
|
||||
};
|
||||
|
||||
let mut service_para = Paragraph::new(ratatui::text::Line::from(spans));
|
||||
|
||||
// Apply selection highlighting
|
||||
// Apply selection highlighting to spans
|
||||
if is_selected {
|
||||
service_para = service_para.style(
|
||||
Style::default()
|
||||
for span in spans.iter_mut() {
|
||||
span.style = span.style
|
||||
.bg(Theme::highlight())
|
||||
.fg(Theme::background())
|
||||
);
|
||||
.fg(Theme::background());
|
||||
}
|
||||
}
|
||||
|
||||
let service_para = Paragraph::new(ratatui::text::Line::from(spans));
|
||||
|
||||
frame.render_widget(service_para, service_chunks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user