Feat: more mouse support
This commit is contained in:
@@ -6,8 +6,8 @@ use ratatui::layout::{Constraint, Layout, Rect};
|
||||
use crate::commands::AppCommand;
|
||||
use crate::page::Page;
|
||||
use crate::state::{
|
||||
DeviceKind, DictFocus, EngineSection, HelpFocus, MinimapMode, Modal, OptionsFocus,
|
||||
PatternsColumn, SettingKind,
|
||||
DeviceKind, DictFocus, EditorTarget, EngineSection, HelpFocus, MinimapMode, Modal,
|
||||
OptionsFocus, PatternsColumn, SettingKind,
|
||||
};
|
||||
use crate::views::{dict_view, engine_view, help_view, main_view, patterns_view, script_view};
|
||||
|
||||
@@ -94,14 +94,22 @@ fn handle_editor_drag(ctx: &mut InputContext, col: u16, row: u16, term: Rect) {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
fn editor_modal_rect(term: Rect) -> Rect {
|
||||
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;
|
||||
Rect::new(mx, my, modal_w, modal_h)
|
||||
}
|
||||
|
||||
fn handle_editor_mouse(ctx: &mut InputContext, col: u16, row: u16, term: Rect, dragging: bool) {
|
||||
let modal = editor_modal_rect(term);
|
||||
let mx = modal.x;
|
||||
let my = modal.y;
|
||||
let modal_w = modal.width;
|
||||
let modal_h = modal.height;
|
||||
// inner = area inside 1-cell border
|
||||
let inner_x = mx + 1;
|
||||
let inner_y = my + 1;
|
||||
@@ -180,6 +188,18 @@ fn handle_scroll(ctx: &mut InputContext, col: u16, row: u16, term: Rect, up: boo
|
||||
return;
|
||||
}
|
||||
|
||||
if matches!(ctx.app.ui.modal, Modal::Editor) {
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
let code = if up { KeyCode::Up } else { KeyCode::Down };
|
||||
for _ in 0..3 {
|
||||
ctx.app
|
||||
.editor_ctx
|
||||
.editor
|
||||
.input(KeyEvent::new(code, KeyModifiers::empty()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if !matches!(ctx.app.ui.modal, Modal::None) {
|
||||
return;
|
||||
}
|
||||
@@ -1057,13 +1077,28 @@ fn handle_engine_click(ctx: &mut InputContext, col: u16, row: u16, area: Rect, k
|
||||
fn handle_modal_click(ctx: &mut InputContext, col: u16, row: u16, term: Rect) {
|
||||
match &ctx.app.ui.modal {
|
||||
Modal::Editor => {
|
||||
handle_editor_mouse(ctx, col, row, term, false);
|
||||
let modal_area = editor_modal_rect(term);
|
||||
if contains(modal_area, col, row) {
|
||||
handle_editor_mouse(ctx, col, row, term, false);
|
||||
} else {
|
||||
match ctx.app.editor_ctx.target {
|
||||
EditorTarget::Step => {
|
||||
ctx.dispatch(AppCommand::SaveEditorToStep);
|
||||
ctx.dispatch(AppCommand::CompileCurrentStep);
|
||||
}
|
||||
EditorTarget::Prelude => {
|
||||
ctx.dispatch(AppCommand::SavePrelude);
|
||||
ctx.dispatch(AppCommand::EvaluatePrelude);
|
||||
ctx.dispatch(AppCommand::ClosePreludeEditor);
|
||||
}
|
||||
}
|
||||
ctx.dispatch(AppCommand::CloseModal);
|
||||
}
|
||||
}
|
||||
Modal::Confirm { .. } => {
|
||||
handle_confirm_click(ctx, col, row, term);
|
||||
}
|
||||
Modal::KeybindingsHelp { .. } => {
|
||||
// Click outside keybindings help to dismiss
|
||||
let padded = padded(term);
|
||||
let width = (padded.width * 80 / 100).clamp(60, 100);
|
||||
let height = (padded.height * 80 / 100).max(15);
|
||||
@@ -1073,7 +1108,20 @@ fn handle_modal_click(ctx: &mut InputContext, col: u16, row: u16, term: Rect) {
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// For other modals, don't dismiss on click (they have their own input)
|
||||
let (w, h) = match &ctx.app.ui.modal {
|
||||
Modal::PatternProps { .. } => (50, 18),
|
||||
Modal::EuclideanDistribution { .. } => (50, 11),
|
||||
Modal::Onboarding { .. } => (57, 20),
|
||||
Modal::FileBrowser(_) | Modal::AddSamplePath(_) => (60, 18),
|
||||
Modal::Rename { .. } => (40, 5),
|
||||
Modal::SetPattern { .. } | Modal::SetScript { .. } => (45, 5),
|
||||
Modal::SetTempo(_) | Modal::JumpToStep(_) => (30, 5),
|
||||
_ => return,
|
||||
};
|
||||
let modal_area = centered_rect(term, w, h);
|
||||
if !contains(modal_area, col, row) {
|
||||
ctx.dispatch(AppCommand::CloseModal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user