mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
wip: command palette
This commit is contained in:
parent
6a738375e2
commit
145827913a
4 changed files with 137 additions and 15 deletions
|
|
@ -46,7 +46,11 @@ fn handle_device (state: &mut App, e: &AppEvent) -> Usually<bool> {
|
||||||
.map(|x|x.unwrap_or(false))
|
.map(|x|x.unwrap_or(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
const KEYMAP_FOCUS: &'static [KeyBinding<App>] = keymap!(App {
|
pub const KEYMAP_FOCUS: &'static [KeyBinding<App>] = keymap!(App {
|
||||||
|
[Char(';'), NONE, "command", "open command palette", |app: &mut App| {
|
||||||
|
app.modal = Some(Box::new(crate::view::HelpModal::new()));
|
||||||
|
Ok(true)
|
||||||
|
}],
|
||||||
[Tab, NONE, "focus_next", "focus next area", focus_next],
|
[Tab, NONE, "focus_next", "focus next area", focus_next],
|
||||||
[Tab, SHIFT, "focus_prev", "focus previous area", focus_prev],
|
[Tab, SHIFT, "focus_prev", "focus previous area", focus_prev],
|
||||||
[Esc, NONE, "focus_exit", "unfocus", |app: &mut App|{
|
[Esc, NONE, "focus_exit", "unfocus", |app: &mut App|{
|
||||||
|
|
@ -59,8 +63,8 @@ const KEYMAP_FOCUS: &'static [KeyBinding<App>] = keymap!(App {
|
||||||
}],
|
}],
|
||||||
});
|
});
|
||||||
|
|
||||||
const KEYMAP: &'static [KeyBinding<App>] = keymap!(App {
|
pub const KEYMAP: &'static [KeyBinding<App>] = keymap!(App {
|
||||||
[F(1), NONE, "help_toggle", "toggle help", |_: &mut App| {Ok(true)}],
|
//[F(1), NONE, "help_toggle", "toggle help", |_: &mut App| {Ok(true)}],
|
||||||
|
|
||||||
[Up, NONE, "focus_prev", "focus previous area", |app: &mut App|match app.track_cursor {
|
[Up, NONE, "focus_prev", "focus previous area", |app: &mut App|match app.track_cursor {
|
||||||
0 => {app.section = AppSection::Arranger;Ok(true)},
|
0 => {app.section = AppSection::Arranger;Ok(true)},
|
||||||
|
|
@ -88,20 +92,20 @@ const KEYMAP: &'static [KeyBinding<App>] = keymap!(App {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}],
|
}],
|
||||||
|
|
||||||
[Char('+'), NONE, "quant_inc", "Quantize coarser", |app: &mut App| {
|
[Char('+'), NONE, "quant_inc", "quantize coarser", |app: &mut App| {
|
||||||
app.transport.quant = next_note_length(app.transport.quant);
|
app.transport.quant = next_note_length(app.transport.quant);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}],
|
}],
|
||||||
[Char('_'), NONE, "quant_dec", "Quantize finer", |app: &mut App| {
|
[Char('_'), NONE, "quant_dec", "quantize finer", |app: &mut App| {
|
||||||
app.transport.quant = prev_note_length(app.transport.quant);
|
app.transport.quant = prev_note_length(app.transport.quant);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}],
|
}],
|
||||||
|
|
||||||
[Char('='), NONE, "zoom_in", "Zoom in", |app: &mut App| {
|
[Char('='), NONE, "zoom_in", "show fewer ticks per block", |app: &mut App| {
|
||||||
app.seq_buf.time_zoom = prev_note_length(app.seq_buf.time_zoom);
|
app.seq_buf.time_zoom = prev_note_length(app.seq_buf.time_zoom);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}],
|
}],
|
||||||
[Char('-'), NONE, "zoom_out", "Zoom out", |app: &mut App| {
|
[Char('-'), NONE, "zoom_out", "show more ticks per block", |app: &mut App| {
|
||||||
app.seq_buf.time_zoom = next_note_length(app.seq_buf.time_zoom);
|
app.seq_buf.time_zoom = next_note_length(app.seq_buf.time_zoom);
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}],
|
}],
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,20 @@ pub(crate) use ratatui::layout::Rect;
|
||||||
pub(crate) use ratatui::buffer::{Buffer, Cell};
|
pub(crate) use ratatui::buffer::{Buffer, Cell};
|
||||||
use ratatui::widgets::WidgetRef;
|
use ratatui::widgets::WidgetRef;
|
||||||
|
|
||||||
|
pub fn fill_fg (buf: &mut Buffer, area: Rect, color: Color) {
|
||||||
|
let Rect { x, y, width, height } = area;
|
||||||
|
for y in y..y+height {
|
||||||
|
if y >= buf.area.height {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for x in x..x+width {
|
||||||
|
if x >= buf.area.width {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf.get_mut(x, y).set_fg(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn fill_bg (buf: &mut Buffer, area: Rect, color: Color) {
|
pub fn fill_bg (buf: &mut Buffer, area: Rect, color: Color) {
|
||||||
let Rect { x, y, width, height } = area;
|
let Rect { x, y, width, height } = area;
|
||||||
for y in y..y+height {
|
for y in y..y+height {
|
||||||
|
|
@ -19,6 +33,20 @@ pub fn fill_bg (buf: &mut Buffer, area: Rect, color: Color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn fill_char (buf: &mut Buffer, area: Rect, c: char) {
|
||||||
|
let Rect { x, y, width, height } = area;
|
||||||
|
for y in y..y+height {
|
||||||
|
if y >= buf.area.height {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
for x in x..x+width {
|
||||||
|
if x >= buf.area.width {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
buf.get_mut(x, y).set_char(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Blit {
|
pub trait Blit {
|
||||||
// Render something to X, Y coordinates in a buffer, ignoring width/height.
|
// Render something to X, Y coordinates in a buffer, ignoring width/height.
|
||||||
|
|
|
||||||
18
src/view.rs
18
src/view.rs
|
|
@ -1,18 +1,20 @@
|
||||||
pub mod chain;
|
|
||||||
pub mod arranger;
|
pub mod arranger;
|
||||||
pub mod sequencer;
|
|
||||||
pub mod transport;
|
|
||||||
pub mod plugin;
|
|
||||||
pub mod border;
|
pub mod border;
|
||||||
pub mod theme;
|
pub mod chain;
|
||||||
|
pub mod help;
|
||||||
|
pub mod plugin;
|
||||||
|
pub mod sequencer;
|
||||||
pub mod split;
|
pub mod split;
|
||||||
|
pub mod theme;
|
||||||
|
pub mod transport;
|
||||||
|
|
||||||
pub use self::split::*;
|
|
||||||
pub use self::border::*;
|
|
||||||
pub use self::theme::*;
|
|
||||||
pub use self::arranger::*;
|
pub use self::arranger::*;
|
||||||
|
pub use self::border::*;
|
||||||
pub use self::chain::ChainView;
|
pub use self::chain::ChainView;
|
||||||
|
pub use self::help::*;
|
||||||
pub use self::sequencer::{SequencerView, BufferedSequencerView};
|
pub use self::sequencer::{SequencerView, BufferedSequencerView};
|
||||||
|
pub use self::split::*;
|
||||||
|
pub use self::theme::*;
|
||||||
|
|
||||||
use crate::{render, App, core::*};
|
use crate::{render, App, core::*};
|
||||||
|
|
||||||
|
|
|
||||||
88
src/view/help.rs
Normal file
88
src/view/help.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
use crate::{core::*, view::*};
|
||||||
|
|
||||||
|
pub struct HelpModal {
|
||||||
|
cursor: usize,
|
||||||
|
search: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HelpModal {
|
||||||
|
pub fn new () -> Self {
|
||||||
|
Self { cursor: 0, search: None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render!(HelpModal |self, buf, area|{
|
||||||
|
for cell in buf.content.iter_mut() {
|
||||||
|
cell.bg = ratatui::style::Color::Rgb(44,44,44);
|
||||||
|
cell.fg = ratatui::style::Color::Rgb(88,88,88);
|
||||||
|
cell.modifier = ratatui::style::Modifier::DIM;
|
||||||
|
}
|
||||||
|
let width = 64.min(area.width * 3 / 5);
|
||||||
|
let height = 20.min(area.width * 3 / 5);
|
||||||
|
let x = area.x + (area.width - width) / 2;
|
||||||
|
let y = area.y + (area.height - height) / 2;
|
||||||
|
let area = Rect { x, y, width, height };
|
||||||
|
fill_fg(buf, area, Color::Reset);
|
||||||
|
fill_bg(buf, area, Nord::bg_lo(true, true));
|
||||||
|
fill_char(buf, area, ' ');
|
||||||
|
let x = area.x + 2;
|
||||||
|
let y = area.y + 1;
|
||||||
|
"Command:"
|
||||||
|
.blit(buf, x, y, Some(Style::default().bold()))?;
|
||||||
|
" ".repeat(area.width as usize - 13)
|
||||||
|
.blit(buf, x + 9, y, Some(Style::default().bg(Color::Reset)))?;
|
||||||
|
if let Some(search) = self.search.as_ref() {
|
||||||
|
search.blit(buf, x + 9, y, Some(Style::default().not_dim()))?;
|
||||||
|
}
|
||||||
|
let y = y + 1;
|
||||||
|
fill_char(buf, Rect { y, height: 1, ..area }, '-');
|
||||||
|
let y = y + 1;
|
||||||
|
for i in 0..height-3 {
|
||||||
|
let y = y + i;
|
||||||
|
if let Some(command) = crate::control::KEYMAP_FOCUS.get(i as usize) {
|
||||||
|
format!("{:?}", command.0).blit(buf, x, y, Some(Style::default().bold()))?;
|
||||||
|
command.2.blit(buf, x + 11, y, Some(Style::default().bold()))?;
|
||||||
|
command.3.blit(buf, x + 26, y, None)?;
|
||||||
|
} else if let Some(command) = crate::control::KEYMAP.get((i as usize) - crate::control::KEYMAP_FOCUS.len()) {
|
||||||
|
format!("{:?}", command.0).blit(buf, x, y, Some(Style::default().bold()))?;
|
||||||
|
command.2.blit(buf, x + 11, y, Some(Style::default().bold()))?;
|
||||||
|
command.3.blit(buf, x + 26, y, None)?;
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let hi_area = Rect { x: area.x + 1, width: area.width - 2, y: area.y + 3 + self.cursor as u16, height: 1 };
|
||||||
|
fill_bg(buf, hi_area, Nord::bg_hi(true, true));
|
||||||
|
fill_fg(buf, hi_area, Color::Reset);
|
||||||
|
Lozenge(Style::default()).draw(buf, area)
|
||||||
|
});
|
||||||
|
|
||||||
|
handle!(HelpModal |self, e| {
|
||||||
|
Ok(handle_keymap(self, e, KEYMAP_HELP)? || match e {
|
||||||
|
AppEvent::Input(Event::Key(KeyEvent {
|
||||||
|
code: KeyCode::Char(c),
|
||||||
|
modifiers: KeyModifiers::NONE, ..
|
||||||
|
})) => {
|
||||||
|
if self.search.is_none() {
|
||||||
|
self.search = Some(String::new());
|
||||||
|
}
|
||||||
|
self.search.as_mut().unwrap().push(*c);
|
||||||
|
false
|
||||||
|
},
|
||||||
|
_ => false
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const KEYMAP_HELP: &'static [KeyBinding<HelpModal>] = keymap!(HelpModal {
|
||||||
|
[Esc, NONE, "help_close", "close help dialog", |_: &mut HelpModal|{
|
||||||
|
Ok(true)
|
||||||
|
}],
|
||||||
|
[Up, NONE, "help_prev", "select previous command", |modal: &mut HelpModal|{
|
||||||
|
modal.cursor = modal.cursor.saturating_sub(1);
|
||||||
|
Ok(false)
|
||||||
|
}],
|
||||||
|
[Down, NONE, "help_next", "select next command", |modal: &mut HelpModal|{
|
||||||
|
modal.cursor = modal.cursor + 1;
|
||||||
|
Ok(false)
|
||||||
|
}],
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue