user: fix text selection on wrapped lines
scroll_pane: screen_to_item() now properly accounts for wrapped lines using textwrap to compute actual character positions instead of just using mouse_x directly. selectable: new module with PUA markers for wrap-aware selection. Not yet integrated into chat.rs but ready for future use. Uses continuation markers to track logical vs visual lines. Co-Authored-By: Proof of Concept <poc@bcachefs.org>
This commit is contained in:
parent
ab0f16a3b5
commit
dcd647764c
5 changed files with 632 additions and 1 deletions
|
|
@ -106,7 +106,27 @@ impl ScrollPaneState {
|
|||
let h = self.heights.get(line_idx).copied().unwrap_or(1) as i32;
|
||||
if (mouse_y as i32) < row + h {
|
||||
let line_text: String = lines[line_idx].spans.iter().map(|s| s.content.as_ref()).collect();
|
||||
let col = (mouse_x as usize).min(line_text.len());
|
||||
|
||||
// Which visual row within this wrapped line?
|
||||
let visual_row_in_item = ((mouse_y as i32) - row).max(0) as usize;
|
||||
|
||||
// Use textwrap to find actual break positions
|
||||
let wrap_width = self.cached_width as usize;
|
||||
let wrapped = textwrap::wrap(&line_text, wrap_width);
|
||||
|
||||
// Sum lengths of previous wrapped rows to get char offset base
|
||||
let char_base: usize = wrapped.iter()
|
||||
.take(visual_row_in_item)
|
||||
.map(|s| s.len())
|
||||
.sum();
|
||||
|
||||
// Add mouse x position within current row
|
||||
let current_row_len = wrapped.get(visual_row_in_item)
|
||||
.map(|s| s.len())
|
||||
.unwrap_or(0);
|
||||
let col = char_base + (mouse_x as usize).min(current_row_len);
|
||||
let col = col.min(line_text.len());
|
||||
|
||||
return Some((line_idx, col));
|
||||
}
|
||||
row += h;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue