overriding overflows by using empty spaces as letters
This commit is contained in:
@@ -19,6 +19,7 @@ use ratatui::{
|
||||
widgets::{Block, List, ListItem, Paragraph},
|
||||
Frame,
|
||||
};
|
||||
use unicode_width::UnicodeWidthStr; // Needed for width calculation
|
||||
use crate::state::pages::canvas_state::CanvasState;
|
||||
use crate::state::pages::form::FormState;
|
||||
use crate::state::pages::auth::AuthState;
|
||||
@@ -31,6 +32,7 @@ use crate::state::pages::admin::AdminState;
|
||||
use crate::state::app::highlight::HighlightState;
|
||||
use crate::modes::general::command_navigation::NavigationState;
|
||||
|
||||
// Define a fixed height for the options list in the command palette
|
||||
const PALETTE_MAX_VISIBLE_OPTIONS: usize = 15;
|
||||
|
||||
// ++ New function to render the Find File Palette ++
|
||||
@@ -39,24 +41,23 @@ fn render_find_file_palette(
|
||||
area: Rect,
|
||||
theme: &Theme,
|
||||
palette_input: &str, // Specific input for the palette
|
||||
options: &[String],
|
||||
selected_index: Option<usize>,
|
||||
options: &[String], // These are already filtered options
|
||||
selected_index: Option<usize>, // Index within the filtered `options`
|
||||
) {
|
||||
// Use a regular space character for padding.
|
||||
const PADDING_CHAR: &str = " ";
|
||||
|
||||
let num_total_filtered = options.len();
|
||||
let current_selected_list_idx = selected_index;
|
||||
|
||||
let mut display_start_offset = 0;
|
||||
if num_total_filtered > PALETTE_MAX_VISIBLE_OPTIONS {
|
||||
if let Some(sel_idx) = current_selected_list_idx {
|
||||
// If selected item is below the current view window
|
||||
if sel_idx >= display_start_offset + PALETTE_MAX_VISIBLE_OPTIONS {
|
||||
display_start_offset = sel_idx - PALETTE_MAX_VISIBLE_OPTIONS + 1;
|
||||
}
|
||||
// If selected item is above the current view window
|
||||
else if sel_idx < display_start_offset {
|
||||
} else if sel_idx < display_start_offset {
|
||||
display_start_offset = sel_idx;
|
||||
}
|
||||
// Clamp display_start_offset
|
||||
display_start_offset = display_start_offset
|
||||
.min(num_total_filtered.saturating_sub(PALETTE_MAX_VISIBLE_OPTIONS));
|
||||
}
|
||||
@@ -65,42 +66,78 @@ fn render_find_file_palette(
|
||||
|
||||
let display_end_offset =
|
||||
(display_start_offset + PALETTE_MAX_VISIBLE_OPTIONS).min(num_total_filtered);
|
||||
let visible_options_slice = &options[display_start_offset..display_end_offset];
|
||||
|
||||
let visible_options_slice = if num_total_filtered > 0 {
|
||||
&options[display_start_offset..display_end_offset]
|
||||
} else {
|
||||
&[]
|
||||
};
|
||||
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(1), // For palette input line
|
||||
Constraint::Length(PALETTE_MAX_VISIBLE_OPTIONS as u16), // For options list
|
||||
Constraint::Length(PALETTE_MAX_VISIBLE_OPTIONS as u16), // For options list (fixed height)
|
||||
])
|
||||
.split(area);
|
||||
|
||||
// Draw the palette input line
|
||||
let prompt_text = format!("Find File: {}", palette_input); // Using palette_input
|
||||
let input_paragraph = Paragraph::new(prompt_text)
|
||||
let input_area = chunks[0];
|
||||
let list_area = chunks[1];
|
||||
|
||||
// Draw the palette input line (with padding)
|
||||
let base_prompt_text = format!("Find File: {}", palette_input);
|
||||
let prompt_text_width = UnicodeWidthStr::width(base_prompt_text.as_str());
|
||||
let input_area_width = input_area.width as usize;
|
||||
let input_padding_needed = input_area_width.saturating_sub(prompt_text_width);
|
||||
|
||||
let padded_prompt_text = if input_padding_needed > 0 {
|
||||
format!("{}{}", base_prompt_text, PADDING_CHAR.repeat(input_padding_needed))
|
||||
} else {
|
||||
base_prompt_text // Or truncate if necessary: base_prompt_text.chars().take(input_area_width).collect()
|
||||
};
|
||||
|
||||
let input_paragraph = Paragraph::new(padded_prompt_text)
|
||||
.style(Style::default().fg(theme.accent).bg(theme.bg));
|
||||
f.render_widget(input_paragraph, chunks[0]);
|
||||
f.render_widget(input_paragraph, input_area);
|
||||
|
||||
// Draw the list of options
|
||||
if !visible_options_slice.is_empty() && chunks.len() > 1 {
|
||||
let list_items: Vec<ListItem> = visible_options_slice
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, opt_str)| {
|
||||
let original_list_idx = display_start_offset + idx;
|
||||
let style = if current_selected_list_idx == Some(original_list_idx) {
|
||||
Style::default().fg(theme.bg).bg(theme.accent) // Highlight selected
|
||||
} else {
|
||||
Style::default().fg(theme.fg).bg(theme.bg)
|
||||
};
|
||||
ListItem::new(opt_str.as_str()).style(style)
|
||||
})
|
||||
.collect();
|
||||
// --- Draw the list of options, ensuring all PALETTE_MAX_VISIBLE_OPTIONS rows are covered ---
|
||||
let mut display_list_items: Vec<ListItem> = Vec::with_capacity(PALETTE_MAX_VISIBLE_OPTIONS);
|
||||
|
||||
let options_list = List::new(list_items)
|
||||
.block(Block::default().style(Style::default().bg(theme.bg)));
|
||||
f.render_widget(options_list, chunks[1]);
|
||||
for (idx_in_slice, opt_str) in visible_options_slice.iter().enumerate() {
|
||||
let original_list_idx = display_start_offset + idx_in_slice;
|
||||
let is_selected = current_selected_list_idx == Some(original_list_idx);
|
||||
|
||||
let style = if is_selected {
|
||||
Style::default().fg(theme.bg).bg(theme.accent)
|
||||
} else {
|
||||
Style::default().fg(theme.fg).bg(theme.bg)
|
||||
};
|
||||
|
||||
let opt_width = opt_str.width() as u16;
|
||||
let list_item_width = list_area.width;
|
||||
let padding_amount = list_item_width.saturating_sub(opt_width);
|
||||
let padded_opt_str = format!(
|
||||
"{}{}",
|
||||
opt_str,
|
||||
PADDING_CHAR.repeat(padding_amount as usize)
|
||||
);
|
||||
display_list_items.push(ListItem::new(padded_opt_str).style(style));
|
||||
}
|
||||
|
||||
let num_rendered_options = display_list_items.len();
|
||||
if num_rendered_options < PALETTE_MAX_VISIBLE_OPTIONS {
|
||||
for _ in num_rendered_options..PALETTE_MAX_VISIBLE_OPTIONS {
|
||||
let empty_padded_str = PADDING_CHAR.repeat(list_area.width as usize);
|
||||
display_list_items.push(
|
||||
ListItem::new(empty_padded_str)
|
||||
.style(Style::default().fg(theme.bg).bg(theme.bg)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let options_list_widget = List::new(display_list_items)
|
||||
.block(Block::default().style(Style::default().bg(theme.bg)));
|
||||
f.render_widget(options_list_widget, list_area);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
@@ -135,7 +172,7 @@ pub fn render_ui(
|
||||
let mut bottom_area_constraints: Vec<Constraint> = vec![Constraint::Length(1)]; // Status line
|
||||
|
||||
let command_palette_area_height = if navigation_state.active {
|
||||
1 + PALETTE_MAX_VISIBLE_OPTIONS as u16
|
||||
1 + PALETTE_MAX_VISIBLE_OPTIONS as u16 // Input line + fixed height for options
|
||||
} else if event_handler_command_mode_active {
|
||||
1 // Height for normal command line
|
||||
} else {
|
||||
@@ -258,6 +295,7 @@ pub fn render_ui(
|
||||
area,
|
||||
theme,
|
||||
&navigation_state.input,
|
||||
// Pass the full filtered options to the palette renderer
|
||||
&navigation_state.filtered_options.iter().map(|(_, opt)| opt.clone()).collect::<Vec<_>>(),
|
||||
navigation_state.selected_index,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user