Feat: text selection using mouse
This commit is contained in:
@@ -26,6 +26,12 @@ pub fn handle_mouse(ctx: &mut InputContext, mouse: MouseEvent, term: Rect) {
|
||||
|
||||
match kind {
|
||||
MouseEventKind::Down(MouseButton::Left) => handle_click(ctx, col, row, term),
|
||||
MouseEventKind::Drag(MouseButton::Left) | MouseEventKind::Moved => {
|
||||
handle_editor_drag(ctx, col, row, term);
|
||||
}
|
||||
MouseEventKind::Up(MouseButton::Left) => {
|
||||
ctx.app.editor_ctx.mouse_selecting = false;
|
||||
}
|
||||
MouseEventKind::ScrollUp => handle_scroll(ctx, col, row, term, true),
|
||||
MouseEventKind::ScrollDown => handle_scroll(ctx, col, row, term, false),
|
||||
_ => {}
|
||||
@@ -59,6 +65,55 @@ fn contains(area: Rect, col: u16, row: u16) -> bool {
|
||||
col >= area.x && col < area.x + area.width && row >= area.y && row < area.y + area.height
|
||||
}
|
||||
|
||||
fn handle_editor_drag(ctx: &mut InputContext, col: u16, row: u16, term: Rect) {
|
||||
if ctx.app.editor_ctx.mouse_selecting {
|
||||
handle_editor_mouse(ctx, col, row, term, true);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_editor_mouse(ctx: &mut InputContext, col: u16, row: u16, term: Rect, dragging: bool) {
|
||||
// Reconstruct editor area (mirrors render_modal_editor / ModalFrame::render_centered)
|
||||
let width = (term.width * 80 / 100).max(40);
|
||||
let height = (term.height * 60 / 100).max(10);
|
||||
let modal_w = width.min(term.width.saturating_sub(4));
|
||||
let modal_h = height.min(term.height.saturating_sub(4));
|
||||
let mx = term.x + (term.width.saturating_sub(modal_w)) / 2;
|
||||
let my = term.y + (term.height.saturating_sub(modal_h)) / 2;
|
||||
// inner = area inside 1-cell border
|
||||
let inner_x = mx + 1;
|
||||
let inner_y = my + 1;
|
||||
let inner_w = modal_w.saturating_sub(2);
|
||||
let inner_h = modal_h.saturating_sub(2);
|
||||
|
||||
let show_search = ctx.app.editor_ctx.editor.search_active()
|
||||
|| !ctx.app.editor_ctx.editor.search_query().is_empty();
|
||||
let reserved = 1 + if show_search { 1 } else { 0 };
|
||||
let editor_y = inner_y + if show_search { 1 } else { 0 };
|
||||
let editor_h = inner_h.saturating_sub(reserved);
|
||||
|
||||
if col < inner_x || col >= inner_x + inner_w || row < editor_y || row >= editor_y + editor_h {
|
||||
return;
|
||||
}
|
||||
|
||||
let scroll = ctx.app.editor_ctx.editor.scroll_offset();
|
||||
let text_row = (row - editor_y) + scroll;
|
||||
let text_col = col - inner_x;
|
||||
|
||||
if dragging {
|
||||
if !ctx.app.editor_ctx.editor.is_selecting() {
|
||||
ctx.app.editor_ctx.editor.start_selection();
|
||||
}
|
||||
} else {
|
||||
ctx.app.editor_ctx.mouse_selecting = true;
|
||||
ctx.app.editor_ctx.editor.cancel_selection();
|
||||
}
|
||||
|
||||
ctx.app
|
||||
.editor_ctx
|
||||
.editor
|
||||
.move_cursor_to(text_row, text_col);
|
||||
}
|
||||
|
||||
fn handle_click(ctx: &mut InputContext, col: u16, row: u16, term: Rect) {
|
||||
// Sticky minimap intercepts all clicks
|
||||
if matches!(ctx.app.ui.minimap, MinimapMode::Sticky) {
|
||||
@@ -745,8 +800,11 @@ fn handle_engine_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect) {
|
||||
|
||||
fn handle_modal_click(ctx: &mut InputContext, col: u16, row: u16, term: Rect) {
|
||||
match &ctx.app.ui.modal {
|
||||
Modal::Editor | Modal::Preview => {
|
||||
// Don't dismiss editor/preview on click
|
||||
Modal::Editor => {
|
||||
handle_editor_mouse(ctx, col, row, term, false);
|
||||
}
|
||||
Modal::Preview => {
|
||||
// Don't dismiss preview on click
|
||||
}
|
||||
Modal::Confirm { .. } => {
|
||||
handle_confirm_click(ctx, col, row, term);
|
||||
|
||||
Reference in New Issue
Block a user