mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
very colorized
This commit is contained in:
parent
a20b8e5518
commit
0d1d7a05b9
3 changed files with 46 additions and 31 deletions
|
|
@ -2,6 +2,7 @@ use crate::{*, api::ClockCommand::{Play, Pause}};
|
|||
use KeyCode::{Tab, BackTab, Char};
|
||||
use SequencerCommand::*;
|
||||
use PhraseCommand::*;
|
||||
use PhrasePoolCommand::*;
|
||||
|
||||
/// Create app state from JACK handle.
|
||||
impl TryFrom<&Arc<RwLock<JackClient>>> for SequencerTui {
|
||||
|
|
@ -58,17 +59,29 @@ impl Command<SequencerTui> for SequencerCommand {
|
|||
fn execute (self, state: &mut SequencerTui) -> Perhaps<Self> {
|
||||
Ok(match self {
|
||||
Self::Phrases(cmd) => {
|
||||
let mut default = |cmd: PhrasesCommand|cmd.execute(&mut state.phrases).map(|x|x.map(Phrases));
|
||||
match cmd {
|
||||
// autoselect: automatically load selected phrase in editor
|
||||
PhrasesCommand::Select(_) => {
|
||||
let undo = cmd.execute(&mut state.phrases)?.map(Phrases);
|
||||
Editor(Show(Some(state.phrases.phrase().clone()))).execute(state)?;
|
||||
let undo = default(cmd)?;
|
||||
state.editor.set_phrase(Some(state.phrases.phrase()));
|
||||
undo
|
||||
},
|
||||
_ => cmd.execute(&mut state.phrases)?.map(Phrases)
|
||||
// update color in all places simultaneously
|
||||
PhrasesCommand::Phrase(SetColor(index, _)) => {
|
||||
let undo = default(cmd)?;
|
||||
state.editor.set_phrase(Some(state.phrases.phrase()));
|
||||
undo
|
||||
},
|
||||
_ => default(cmd)?
|
||||
}
|
||||
},
|
||||
Self::Editor(cmd) => {
|
||||
let default = ||cmd.execute(&mut state.editor).map(|x|x.map(Editor));
|
||||
match cmd {
|
||||
_ => default()?
|
||||
}
|
||||
},
|
||||
Self::Editor(cmd) => cmd.execute(&mut state.editor)?.map(Editor),
|
||||
Self::Clock(cmd) => cmd.execute(state)?.map(Clock),
|
||||
Self::Enqueue(phrase) => {
|
||||
state.player.enqueue_next(phrase.as_ref());
|
||||
|
|
@ -85,41 +98,41 @@ impl Command<SequencerTui> for SequencerCommand {
|
|||
impl InputToCommand<Tui, SequencerTui> for SequencerCommand {
|
||||
fn input_to_command (state: &SequencerTui, input: &TuiInput) -> Option<Self> {
|
||||
Some(match input.event() {
|
||||
// TODO: u: undo
|
||||
key_pat!(Char('u')) => { todo!("undo") },
|
||||
// TODO: Shift-U: redo
|
||||
key_pat!(Char('U')) => { todo!("redo") },
|
||||
// TODO: k: toggle on-screen keyboard
|
||||
key_pat!(Ctrl-Char('k')) => { todo!("keyboard") },
|
||||
|
||||
// Toggle visibility of phrase pool column
|
||||
// Tab: Toggle visibility of phrase pool column
|
||||
key_pat!(Tab) => ShowPool(!state.show_pool),
|
||||
// Enqueue currently edited phrase
|
||||
// q: Enqueue currently edited phrase
|
||||
key_pat!(Char('q')) => Enqueue(Some(state.phrases.phrase().clone())),
|
||||
// 0: Enqueue phrase 0 (stop all)
|
||||
key_pat!(Char('0')) => Enqueue(Some(state.phrases.phrases()[0].clone())),
|
||||
// E: Toggle between editing currently playing or other phrase
|
||||
key_pat!(Char('e')) => if let Some((_, Some(playing_phrase))) = state.player.play_phrase() {
|
||||
let editing_phrase = state.editor.phrase().as_ref().map(|p|p.read().unwrap().clone());
|
||||
let selected_phrase = state.phrases.phrase().clone();
|
||||
if Some(selected_phrase.read().unwrap().clone()) != editing_phrase {
|
||||
Editor(Show(Some(selected_phrase)))
|
||||
// e: Toggle between editing currently playing or other phrase
|
||||
key_pat!(Char('e')) => if let Some((_, Some(playing))) = state.player.play_phrase() {
|
||||
let editing = state.editor.phrase().as_ref().map(|p|p.read().unwrap().clone());
|
||||
let selected = state.phrases.phrase().clone();
|
||||
Editor(Show(Some(if Some(selected.read().unwrap().clone()) != editing {
|
||||
selected
|
||||
} else {
|
||||
Editor(Show(Some(playing_phrase.clone())))
|
||||
}
|
||||
playing.clone()
|
||||
})))
|
||||
} else {
|
||||
return None
|
||||
},
|
||||
|
||||
// Transport: Play/pause
|
||||
key_pat!(Char(' ')) => Clock(if state.clock().is_stopped() {
|
||||
Play(None)
|
||||
} else {
|
||||
Pause(None)
|
||||
}),
|
||||
Play(None) } else { Pause(None) }),
|
||||
|
||||
// Transport: Play from start or rewind to start
|
||||
key_pat!(Shift-Char(' ')) => Clock(if state.clock().is_stopped() {
|
||||
Play(Some(0))
|
||||
} else {
|
||||
Pause(Some(0))
|
||||
}),
|
||||
// Delegate to components:
|
||||
Play(Some(0)) } else { Pause(Some(0)) }),
|
||||
|
||||
// For the rest, use the default keybindings of the components.
|
||||
// The ones defined above supersede them.
|
||||
_ => if let Some(command) = PhraseCommand::input_to_command(&state.editor, input) {
|
||||
Editor(command)
|
||||
} else if let Some(command) = PhrasesCommand::input_to_command(&state.phrases, input) {
|
||||
|
|
@ -314,7 +327,8 @@ render!(|self: SequencerStatusBar|Tui::fixed_y(2, lay!([
|
|||
Tui::fg_bg(TuiTheme::g(255), TuiTheme::g(50), row!([
|
||||
single("SPACE", "play/pause"),
|
||||
double((" ✣", "cursor"), ("C-✣", "scroll"), ),
|
||||
double((",.", "note"), ("<>", "triplet"),),
|
||||
double(("a", "append"), ("s", "set note"),),
|
||||
double((",.", "note"), ("<>", "triplet"), ),
|
||||
double(("[]", "phrase"), ("{}", "order"), ),
|
||||
double(("q", "enqueue"), ("e", "edit"), ),
|
||||
]))
|
||||
|
|
|
|||
|
|
@ -107,13 +107,14 @@ impl Command<PhraseEditorModel> for PhraseCommand {
|
|||
pub struct PhraseEditorModel {
|
||||
/// Renders the phrase
|
||||
pub mode: Box<dyn PhraseViewMode>,
|
||||
|
||||
pub size: Measure<Tui>
|
||||
}
|
||||
|
||||
impl Default for PhraseEditorModel {
|
||||
fn default () -> Self {
|
||||
Self { mode: Box::new(PianoHorizontal::new(None)), size: Measure::new() }
|
||||
let mut mode = Box::new(PianoHorizontal::new(None));
|
||||
mode.redraw();
|
||||
Self { mode, size: Measure::new() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ render!(|self: PianoHorizontal|{
|
|||
let notes = move||PianoHorizontalNotes { range, buffer };
|
||||
let cursor = move||PianoHorizontalCursor { range, point };
|
||||
let keys_width = 5;
|
||||
Tui::fill_xy(Tui::bg(color.dark.rgb, Bsp::s(
|
||||
Tui::fill_xy(Tui::bg(color.darker.rgb, Bsp::s(
|
||||
Tui::fill_x(Tui::push_x(keys_width, timeline())),
|
||||
Bsp::w(
|
||||
Tui::shrink_x(keys_width, Tui::fill_xy(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue