vastly improved selection system
This commit is contained in:
145
src/input.rs
145
src/input.rs
@@ -7,7 +7,7 @@ use std::time::{Duration, Instant};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::commands::AppCommand;
|
||||
use crate::engine::{AudioCommand, LinkState, SequencerSnapshot};
|
||||
use crate::engine::{AudioCommand, LinkState, SeqCommand, SequencerSnapshot};
|
||||
use crate::model::PatternSpeed;
|
||||
use crate::page::Page;
|
||||
use crate::state::{
|
||||
@@ -26,6 +26,7 @@ pub struct InputContext<'a> {
|
||||
pub snapshot: &'a SequencerSnapshot,
|
||||
pub playing: &'a Arc<AtomicBool>,
|
||||
pub audio_tx: &'a ArcSwap<Sender<AudioCommand>>,
|
||||
pub seq_cmd_tx: &'a Sender<SeqCommand>,
|
||||
pub nudge_us: &'a Arc<AtomicI64>,
|
||||
}
|
||||
|
||||
@@ -140,6 +141,49 @@ fn handle_modal_input(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Modal::ConfirmDeleteSteps {
|
||||
bank,
|
||||
pattern,
|
||||
steps,
|
||||
selected: _,
|
||||
} => {
|
||||
let (bank, pattern, steps) = (*bank, *pattern, steps.clone());
|
||||
match key.code {
|
||||
KeyCode::Char('y') | KeyCode::Char('Y') => {
|
||||
ctx.dispatch(AppCommand::DeleteSteps {
|
||||
bank,
|
||||
pattern,
|
||||
steps,
|
||||
});
|
||||
ctx.dispatch(AppCommand::CloseModal);
|
||||
}
|
||||
KeyCode::Char('n') | KeyCode::Char('N') | KeyCode::Esc => {
|
||||
ctx.dispatch(AppCommand::CloseModal);
|
||||
}
|
||||
KeyCode::Left | KeyCode::Right => {
|
||||
if let Modal::ConfirmDeleteSteps { selected, .. } = &mut ctx.app.ui.modal {
|
||||
*selected = !*selected;
|
||||
}
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
let do_delete =
|
||||
if let Modal::ConfirmDeleteSteps { selected, .. } = &ctx.app.ui.modal {
|
||||
*selected
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if do_delete {
|
||||
ctx.dispatch(AppCommand::DeleteSteps {
|
||||
bank,
|
||||
pattern,
|
||||
steps,
|
||||
});
|
||||
}
|
||||
ctx.dispatch(AppCommand::CloseModal);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Modal::ConfirmResetPattern {
|
||||
bank,
|
||||
pattern,
|
||||
@@ -650,6 +694,8 @@ fn handle_panel_input(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
|
||||
}
|
||||
|
||||
fn handle_main_page(ctx: &mut InputContext, key: KeyEvent, ctrl: bool) -> InputResult {
|
||||
let shift = key.modifiers.contains(KeyModifiers::SHIFT);
|
||||
|
||||
match key.code {
|
||||
KeyCode::Tab => {
|
||||
if ctx.app.panel.visible {
|
||||
@@ -674,12 +720,54 @@ fn handle_main_page(ctx: &mut InputContext, key: KeyEvent, ctrl: bool) -> InputR
|
||||
ctx.playing
|
||||
.store(ctx.app.playback.playing, Ordering::Relaxed);
|
||||
}
|
||||
KeyCode::Left => ctx.dispatch(AppCommand::PrevStep),
|
||||
KeyCode::Right => ctx.dispatch(AppCommand::NextStep),
|
||||
KeyCode::Up => ctx.dispatch(AppCommand::StepUp),
|
||||
KeyCode::Down => ctx.dispatch(AppCommand::StepDown),
|
||||
KeyCode::Enter => ctx.dispatch(AppCommand::OpenModal(Modal::Editor)),
|
||||
KeyCode::Char('t') => ctx.dispatch(AppCommand::ToggleStep),
|
||||
KeyCode::Left if shift && !ctrl => {
|
||||
if ctx.app.editor_ctx.selection_anchor.is_none() {
|
||||
ctx.app.editor_ctx.selection_anchor = Some(ctx.app.editor_ctx.step);
|
||||
}
|
||||
ctx.dispatch(AppCommand::PrevStep);
|
||||
}
|
||||
KeyCode::Right if shift && !ctrl => {
|
||||
if ctx.app.editor_ctx.selection_anchor.is_none() {
|
||||
ctx.app.editor_ctx.selection_anchor = Some(ctx.app.editor_ctx.step);
|
||||
}
|
||||
ctx.dispatch(AppCommand::NextStep);
|
||||
}
|
||||
KeyCode::Up if shift && !ctrl => {
|
||||
if ctx.app.editor_ctx.selection_anchor.is_none() {
|
||||
ctx.app.editor_ctx.selection_anchor = Some(ctx.app.editor_ctx.step);
|
||||
}
|
||||
ctx.dispatch(AppCommand::StepUp);
|
||||
}
|
||||
KeyCode::Down if shift && !ctrl => {
|
||||
if ctx.app.editor_ctx.selection_anchor.is_none() {
|
||||
ctx.app.editor_ctx.selection_anchor = Some(ctx.app.editor_ctx.step);
|
||||
}
|
||||
ctx.dispatch(AppCommand::StepDown);
|
||||
}
|
||||
KeyCode::Left => {
|
||||
ctx.app.editor_ctx.clear_selection();
|
||||
ctx.dispatch(AppCommand::PrevStep);
|
||||
}
|
||||
KeyCode::Right => {
|
||||
ctx.app.editor_ctx.clear_selection();
|
||||
ctx.dispatch(AppCommand::NextStep);
|
||||
}
|
||||
KeyCode::Up => {
|
||||
ctx.app.editor_ctx.clear_selection();
|
||||
ctx.dispatch(AppCommand::StepUp);
|
||||
}
|
||||
KeyCode::Down => {
|
||||
ctx.app.editor_ctx.clear_selection();
|
||||
ctx.dispatch(AppCommand::StepDown);
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
ctx.app.editor_ctx.clear_selection();
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
ctx.app.editor_ctx.clear_selection();
|
||||
ctx.dispatch(AppCommand::OpenModal(Modal::Editor));
|
||||
}
|
||||
KeyCode::Char('t') => ctx.dispatch(AppCommand::ToggleSteps),
|
||||
KeyCode::Char('s') => {
|
||||
use crate::state::file_browser::FileBrowserState;
|
||||
let initial = ctx
|
||||
@@ -692,10 +780,19 @@ fn handle_main_page(ctx: &mut InputContext, key: KeyEvent, ctrl: bool) -> InputR
|
||||
let state = FileBrowserState::new_save(initial);
|
||||
ctx.dispatch(AppCommand::OpenModal(Modal::FileBrowser(state)));
|
||||
}
|
||||
KeyCode::Char('c') if ctrl => ctx.dispatch(AppCommand::CopyStep),
|
||||
KeyCode::Char('v') if ctrl => ctx.dispatch(AppCommand::PasteStep),
|
||||
KeyCode::Char('b') if ctrl => ctx.dispatch(AppCommand::LinkPasteStep),
|
||||
KeyCode::Char('h') if ctrl => ctx.dispatch(AppCommand::HardenStep),
|
||||
KeyCode::Char('c') if ctrl => {
|
||||
ctx.dispatch(AppCommand::CopySteps);
|
||||
}
|
||||
KeyCode::Char('v') if ctrl => {
|
||||
ctx.dispatch(AppCommand::PasteSteps);
|
||||
}
|
||||
KeyCode::Char('b') if ctrl => {
|
||||
ctx.dispatch(AppCommand::LinkPasteSteps);
|
||||
}
|
||||
KeyCode::Char('d') if ctrl => {
|
||||
ctx.dispatch(AppCommand::DuplicateSteps);
|
||||
}
|
||||
KeyCode::Char('h') if ctrl => ctx.dispatch(AppCommand::HardenSteps),
|
||||
KeyCode::Char('l') => {
|
||||
use crate::state::file_browser::FileBrowserState;
|
||||
let default_dir = ctx
|
||||
@@ -730,13 +827,23 @@ fn handle_main_page(ctx: &mut InputContext, key: KeyEvent, ctrl: bool) -> InputR
|
||||
KeyCode::Char('p') => ctx.dispatch(AppCommand::OpenModal(Modal::Preview)),
|
||||
KeyCode::Delete | KeyCode::Backspace => {
|
||||
let (bank, pattern) = (ctx.app.editor_ctx.bank, ctx.app.editor_ctx.pattern);
|
||||
let step = ctx.app.editor_ctx.step;
|
||||
ctx.dispatch(AppCommand::OpenModal(Modal::ConfirmDeleteStep {
|
||||
bank,
|
||||
pattern,
|
||||
step,
|
||||
selected: false,
|
||||
}));
|
||||
if let Some(range) = ctx.app.editor_ctx.selection_range() {
|
||||
let steps: Vec<usize> = range.collect();
|
||||
ctx.dispatch(AppCommand::OpenModal(Modal::ConfirmDeleteSteps {
|
||||
bank,
|
||||
pattern,
|
||||
steps,
|
||||
selected: false,
|
||||
}));
|
||||
} else {
|
||||
let step = ctx.app.editor_ctx.step;
|
||||
ctx.dispatch(AppCommand::OpenModal(Modal::ConfirmDeleteStep {
|
||||
bank,
|
||||
pattern,
|
||||
step,
|
||||
selected: false,
|
||||
}));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -987,9 +1094,11 @@ fn handle_engine_page(ctx: &mut InputContext, key: KeyEvent) -> InputResult {
|
||||
}
|
||||
KeyCode::Char('h') => {
|
||||
let _ = ctx.audio_tx.load().send(AudioCommand::Hush);
|
||||
let _ = ctx.seq_cmd_tx.send(SeqCommand::StopAll);
|
||||
}
|
||||
KeyCode::Char('p') => {
|
||||
let _ = ctx.audio_tx.load().send(AudioCommand::Panic);
|
||||
let _ = ctx.seq_cmd_tx.send(SeqCommand::StopAll);
|
||||
}
|
||||
KeyCode::Char('r') => ctx.app.metrics.peak_voices = 0,
|
||||
KeyCode::Char('t') => {
|
||||
|
||||
Reference in New Issue
Block a user