mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
arranger: theme trait
This commit is contained in:
parent
89cb8d7bbe
commit
0b1193722d
6 changed files with 149 additions and 87 deletions
|
|
@ -12,8 +12,8 @@ pub fn delegate <B, C: Command<S>, S> (
|
|||
Ok(cmd.execute(state)?.map(|x|wrap(x)))
|
||||
}
|
||||
|
||||
pub trait MatchInput<E: Engine, S>: Sized {
|
||||
fn match_input (state: &S, input: &E::Input) -> Option<Self>;
|
||||
pub trait InputToCommand<E: Engine, S>: Sized {
|
||||
fn input_to_command (state: &S, input: &E::Input) -> Option<Self>;
|
||||
}
|
||||
pub struct MenuBar<E: Engine, S, C: Command<S>> {
|
||||
pub menus: Vec<Menu<E, S, C>>,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@ pub struct Arranger<E: Engine> {
|
|||
pub size: Measure<E>,
|
||||
/// Menu bar
|
||||
pub menu: MenuBar<E, Self, ArrangerCommand>,
|
||||
/// Command history
|
||||
pub history: Vec<ArrangerCommand>,
|
||||
}
|
||||
/// Sections in the arranger app that may be focused
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
|
|
@ -142,6 +144,7 @@ impl<E: Engine> Arranger<E> {
|
|||
transport: transport.clone(),
|
||||
arrangement,
|
||||
phrases,
|
||||
history: vec![],
|
||||
size: Measure::new(),
|
||||
clock: if let Some(ref transport) = transport {
|
||||
transport.read().unwrap().clock.clone()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ pub enum ArrangerCommand {
|
|||
Phrases(PhrasePoolCommand),
|
||||
Editor(PhraseEditorCommand),
|
||||
Arrangement(ArrangementCommand),
|
||||
EditPhrase,
|
||||
}
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub enum ArrangementCommand {
|
||||
|
|
@ -32,6 +33,7 @@ pub enum ArrangementCommand {
|
|||
GoDown,
|
||||
GoLeft,
|
||||
GoRight,
|
||||
Edit,
|
||||
}
|
||||
|
||||
impl<E: Engine> Command<Arranger<E>> for ArrangerCommand {
|
||||
|
|
@ -54,6 +56,14 @@ impl<E: Engine> Command<Arranger<E>> for ArrangerCommand {
|
|||
} else {
|
||||
Ok(None)
|
||||
},
|
||||
Self::EditPhrase => if let Some(phrase) = state.arrangement.phrase() {
|
||||
state.editor.phrase = Some(phrase.clone());
|
||||
state.focus(ArrangerFocus::PhraseEditor);
|
||||
state.focus_enter();
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}?;
|
||||
state.show_phrase();
|
||||
state.update_status();
|
||||
|
|
@ -67,6 +77,7 @@ impl<E: Engine> Command<Arrangement<E>> for ArrangementCommand {
|
|||
New => todo!(),
|
||||
Load => todo!(),
|
||||
Save => todo!(),
|
||||
Edit => todo!(),
|
||||
ToggleViewMode => { state.mode.to_next(); },
|
||||
Delete => { state.delete(); },
|
||||
Activate => { state.activate(); },
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
use crate::*;
|
||||
|
||||
/// Layout for standalone arranger app.
|
||||
impl Content for Arranger<Tui> {
|
||||
type Engine = Tui;
|
||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
let focused = self.arrangement.focused;
|
||||
let border_color = if focused{Color::Rgb(100, 110, 40)}else{Color::Rgb(70, 80, 50)};
|
||||
let title_color = if focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)};
|
||||
let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color));
|
||||
let focused = self.arrangement.focused;
|
||||
let border_bg = Arranger::<Tui>::border_bg();
|
||||
let border_fg = Arranger::<Tui>::border_fg(focused);
|
||||
let title_fg = Arranger::<Tui>::title_fg(focused);
|
||||
let border = Lozenge(Style::default().bg(border_bg).fg(border_fg));
|
||||
let entered = if self.arrangement.entered { "■" } else { " " };
|
||||
Split::down(
|
||||
1,
|
||||
row!(menu in self.menu.menus.iter() => {
|
||||
|
|
@ -23,11 +26,7 @@ impl Content for Arranger<Tui> {
|
|||
lay!(
|
||||
widget(&self.arrangement).grow_y(1).border(border),
|
||||
widget(&self.arrangement.size),
|
||||
widget(&format!("[{}] Arrangement", if self.arrangement.entered {
|
||||
"■"
|
||||
} else {
|
||||
" "
|
||||
})).fg(title_color).push_x(1),
|
||||
widget(&format!("[{}] Arrangement", entered)).fg(title_fg).push_x(1),
|
||||
),
|
||||
Split::right(
|
||||
self.phrases_split,
|
||||
|
|
@ -53,9 +52,10 @@ impl Content for ArrangerStatusBar {
|
|||
Self::PhraseView => "VIEW SEQ",
|
||||
Self::PhraseEdit => "EDIT SEQ",
|
||||
};
|
||||
let mode = TuiStyle::bg(format!(" {label} "), Color::Rgb(150, 160, 90))
|
||||
.fg(Color::Rgb(0, 0, 0))
|
||||
.bold(true);
|
||||
let status_bar_bg = Arranger::<Tui>::status_bar_bg();
|
||||
let mode_bg = Arranger::<Tui>::mode_bg();
|
||||
let mode_fg = Arranger::<Tui>::mode_fg();
|
||||
let mode = TuiStyle::bold(format!(" {label} "), true).bg(mode_bg).fg(mode_fg);
|
||||
let commands = match self {
|
||||
Self::ArrangementMix => command(&[
|
||||
["", "c", "olor"],
|
||||
|
|
@ -118,13 +118,18 @@ impl Content for ArrangerStatusBar {
|
|||
_ => command(&[])
|
||||
};
|
||||
//let commands = commands.iter().reduce(String::new(), |s, (a, b, c)| format!("{s} {a}{b}{c}"));
|
||||
row!(mode, commands).fill_x().bg(Color::Rgb(28, 35, 25))
|
||||
row!(mode, commands).fill_x().bg(status_bar_bg)
|
||||
}
|
||||
}
|
||||
fn command (commands: &[[impl Widget<Engine = Tui>;3]]) -> impl Widget<Engine = Tui> + '_ {
|
||||
Stack::right(|add|{
|
||||
Ok(for [a, b, c] in commands.iter() {
|
||||
add(&row!(" ", widget(a), widget(b).bold(true).fg(Color::Rgb(255,255,0)), widget(c)))?;
|
||||
add(&row!(
|
||||
" ",
|
||||
widget(a),
|
||||
widget(b).bold(true).fg(Arranger::<Tui>::hotkey_fg()),
|
||||
widget(c),
|
||||
))?;
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
@ -133,15 +138,9 @@ impl Content for Arrangement<Tui> {
|
|||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
Layers::new(move |add|{
|
||||
match self.mode {
|
||||
ArrangementViewMode::Horizontal => {
|
||||
add(&HorizontalArranger(&self))
|
||||
},
|
||||
ArrangementViewMode::Vertical(factor) => {
|
||||
add(&VerticalArranger(&self, factor))
|
||||
},
|
||||
ArrangementViewMode::Horizontal => { add(&HorizontalArranger(&self)) },
|
||||
ArrangementViewMode::Vertical(factor) => { add(&VerticalArranger(&self, factor)) },
|
||||
}?;
|
||||
let color = if self.focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)};
|
||||
//add(&TuiStyle::fg("Project", color).push_x(2))?;
|
||||
add(&self.size)
|
||||
})
|
||||
}
|
||||
|
|
@ -155,7 +154,8 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
|||
let cols = state.track_widths();
|
||||
let rows = Scene::ppqs(scenes, *factor);
|
||||
let bg = state.color;
|
||||
let clip_bg = Color::Rgb(40, 50, 30);
|
||||
let clip_bg = Arranger::<Tui>::border_bg();
|
||||
let sep_fg = Arranger::<Tui>::separator_fg(false);
|
||||
let header_h = 3u16;//5u16;
|
||||
let scenes_w = 3 + Scene::longest_name(scenes) as u16; // x of 1st track
|
||||
let clock = &self.0.clock;
|
||||
|
|
@ -165,7 +165,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
|||
let any_size = |_|Ok(Some([0,0]));
|
||||
// column separators
|
||||
add(&CustomWidget::new(any_size, move|to: &mut TuiOutput|{
|
||||
let style = Some(Style::default().fg(Color::Rgb(0, 0, 0)));
|
||||
let style = Some(Style::default().fg(sep_fg));
|
||||
Ok(for x in cols.iter().map(|col|col.1) {
|
||||
let x = scenes_w + to.area().x() + x as u16;
|
||||
for y in to.area().y()..to.area().y2() { to.blit(&"▎", x, y, style); }
|
||||
|
|
@ -180,7 +180,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
|||
if x < to.buffer.area.x && y < to.buffer.area.y {
|
||||
let cell = to.buffer.get_mut(x, y);
|
||||
cell.modifier = Modifier::UNDERLINED;
|
||||
cell.underline_color = Color::Rgb(0, 0, 0);
|
||||
cell.underline_color = sep_fg;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -307,13 +307,14 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
|||
area
|
||||
},
|
||||
};
|
||||
let bg = Arranger::<Tui>::border_bg();
|
||||
if let Some([x, y, width, height]) = track_area {
|
||||
to.fill_fg([x, y, 1, height], Color::Rgb(70, 80, 50));
|
||||
to.fill_fg([x + width, y, 1, height], Color::Rgb(70, 80, 50));
|
||||
to.fill_fg([x, y, 1, height], bg);
|
||||
to.fill_fg([x + width, y, 1, height], bg);
|
||||
}
|
||||
if let Some([_, y, _, height]) = scene_area {
|
||||
to.fill_ul([area.x(), y - 1, area.w(), 1], Color::Rgb(70, 80, 50));
|
||||
to.fill_ul([area.x(), y + height - 1, area.w(), 1], Color::Rgb(70, 80, 50));
|
||||
to.fill_ul([area.x(), y - 1, area.w(), 1], bg);
|
||||
to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg);
|
||||
}
|
||||
Ok(if focused {
|
||||
to.render_in(if let Some(clip_area) = clip_area { clip_area }
|
||||
|
|
@ -323,7 +324,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
|||
})
|
||||
}))
|
||||
}).bg(bg.rgb);
|
||||
let color = if self.0.focused {Color::Rgb(150, 160, 90)} else {Color::Rgb(120, 130, 100)};
|
||||
let color = Arranger::<Tui>::title_fg(self.0.focused);
|
||||
let size = format!("{}x{}", self.0.size.w(), self.0.size.h());
|
||||
let lower_right = TuiStyle::fg(size, color).pull_x(1).align_se().fill_xy();
|
||||
lay!(arrangement, lower_right)
|
||||
|
|
@ -335,7 +336,7 @@ impl<'a> Content for HorizontalArranger<'a, Tui> {
|
|||
let Arrangement { tracks, focused, .. } = self.0;
|
||||
let _tracks = tracks.as_slice();
|
||||
lay!(
|
||||
focused.then_some(Background(Color::Rgb(40, 50, 30))),
|
||||
focused.then_some(Background(Arranger::<Tui>::border_bg())),
|
||||
row!(
|
||||
// name
|
||||
CustomWidget::new(|_|{todo!()}, |_: &mut TuiOutput|{
|
||||
|
|
@ -538,7 +539,7 @@ impl Handle<Tui> for Arranger<Tui> {
|
|||
return Ok(Some(true))
|
||||
}
|
||||
}
|
||||
Ok(if let Some(command) = ArrangerCommand::match_input(self, i) {
|
||||
Ok(if let Some(command) = ArrangerCommand::input_to_command(self, i) {
|
||||
let _undo = command.execute(self)?;
|
||||
Some(true)
|
||||
} else {
|
||||
|
|
@ -549,7 +550,7 @@ impl Handle<Tui> for Arranger<Tui> {
|
|||
/// Handle events for arrangement.
|
||||
impl Handle<Tui> for Arrangement<Tui> {
|
||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||
Ok(if let Some(command) = ArrangementCommand::match_input(self, from) {
|
||||
Ok(if let Some(command) = ArrangementCommand::input_to_command(self, from) {
|
||||
let _undo = command.execute(self)?;
|
||||
Some(true)
|
||||
} else {
|
||||
|
|
@ -557,8 +558,8 @@ impl Handle<Tui> for Arrangement<Tui> {
|
|||
})
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, Arranger<Tui>> for ArrangerCommand {
|
||||
fn match_input (state: &Arranger<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, Arranger<Tui>> for ArrangerCommand {
|
||||
fn input_to_command (state: &Arranger<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
use FocusCommand::*;
|
||||
use ArrangerCommand::*;
|
||||
match input.event() {
|
||||
|
|
@ -575,46 +576,50 @@ impl MatchInput<Tui, Arranger<Tui>> for ArrangerCommand {
|
|||
key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)),
|
||||
_ => match state.focused() {
|
||||
ArrangerFocus::Transport => state.transport.as_ref()
|
||||
.map(|t|TransportCommand::match_input(&*t.read().unwrap(), input)
|
||||
.map(|t|TransportCommand::input_to_command(&*t.read().unwrap(), input)
|
||||
.map(Transport))
|
||||
.flatten(),
|
||||
ArrangerFocus::PhrasePool =>
|
||||
PhrasePoolCommand::match_input(&*state.phrases.read().unwrap(), input)
|
||||
PhrasePoolCommand::input_to_command(&*state.phrases.read().unwrap(), input)
|
||||
.map(Phrases),
|
||||
ArrangerFocus::PhraseEditor =>
|
||||
PhraseEditorCommand::match_input(&state.editor, input)
|
||||
PhraseEditorCommand::input_to_command(&state.editor, input)
|
||||
.map(Editor),
|
||||
ArrangerFocus::Arrangement =>
|
||||
ArrangementCommand::match_input(&state.arrangement, &input)
|
||||
ArrangerFocus::Arrangement => match input.event() {
|
||||
key!(KeyCode::Char('e')) => Some(EditPhrase),
|
||||
_ => ArrangementCommand::input_to_command(&state.arrangement, &input)
|
||||
.map(Arrangement)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, Arrangement<Tui>> for ArrangementCommand {
|
||||
fn match_input (_: &Arrangement<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, Arrangement<Tui>> for ArrangementCommand {
|
||||
fn input_to_command (_: &Arrangement<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
use ArrangementCommand::*;
|
||||
match input.event() {
|
||||
key!(KeyCode::Char('`')) => Some(Self::ToggleViewMode),
|
||||
key!(KeyCode::Delete) => Some(Self::Delete),
|
||||
key!(KeyCode::Enter) => Some(Self::Activate),
|
||||
key!(KeyCode::Char('.')) => Some(Self::Increment),
|
||||
key!(KeyCode::Char(',')) => Some(Self::Decrement),
|
||||
key!(KeyCode::Char('+')) => Some(Self::ZoomIn),
|
||||
key!(KeyCode::Char('=')) => Some(Self::ZoomOut),
|
||||
key!(KeyCode::Char('_')) => Some(Self::ZoomOut),
|
||||
key!(KeyCode::Char('-')) => Some(Self::ZoomOut),
|
||||
key!(KeyCode::Char('<')) => Some(Self::MoveBack),
|
||||
key!(KeyCode::Char('>')) => Some(Self::MoveForward),
|
||||
key!(KeyCode::Char('c')) => Some(Self::RandomColor),
|
||||
key!(KeyCode::Char('s')) => Some(Self::Put),
|
||||
key!(KeyCode::Char('g')) => Some(Self::Get),
|
||||
key!(Ctrl-KeyCode::Char('a')) => Some(Self::AddScene),
|
||||
key!(Ctrl-KeyCode::Char('t')) => Some(Self::AddTrack),
|
||||
key!(KeyCode::Char('l')) => Some(Self::ToggleLoop),
|
||||
key!(KeyCode::Up) => Some(Self::GoUp),
|
||||
key!(KeyCode::Down) => Some(Self::GoDown),
|
||||
key!(KeyCode::Left) => Some(Self::GoLeft),
|
||||
key!(KeyCode::Right) => Some(Self::GoRight),
|
||||
key!(KeyCode::Char('`')) => Some(ToggleViewMode),
|
||||
key!(KeyCode::Delete) => Some(Delete),
|
||||
key!(KeyCode::Enter) => Some(Activate),
|
||||
key!(KeyCode::Char('.')) => Some(Increment),
|
||||
key!(KeyCode::Char(',')) => Some(Decrement),
|
||||
key!(KeyCode::Char('+')) => Some(ZoomIn),
|
||||
key!(KeyCode::Char('=')) => Some(ZoomOut),
|
||||
key!(KeyCode::Char('_')) => Some(ZoomOut),
|
||||
key!(KeyCode::Char('-')) => Some(ZoomOut),
|
||||
key!(KeyCode::Char('<')) => Some(MoveBack),
|
||||
key!(KeyCode::Char('>')) => Some(MoveForward),
|
||||
key!(KeyCode::Char('c')) => Some(RandomColor),
|
||||
key!(KeyCode::Char('s')) => Some(Put),
|
||||
key!(KeyCode::Char('g')) => Some(Get),
|
||||
key!(KeyCode::Char('e')) => Some(Edit),
|
||||
key!(Ctrl-KeyCode::Char('a')) => Some(AddScene),
|
||||
key!(Ctrl-KeyCode::Char('t')) => Some(AddTrack),
|
||||
key!(KeyCode::Char('l')) => Some(ToggleLoop),
|
||||
key!(KeyCode::Up) => Some(GoUp),
|
||||
key!(KeyCode::Down) => Some(GoDown),
|
||||
key!(KeyCode::Left) => Some(GoLeft),
|
||||
key!(KeyCode::Right) => Some(GoRight),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
|
@ -670,3 +675,41 @@ impl MatchInput<Tui, Arrangement<Tui>> for ArrangementCommand {
|
|||
//Ok(Some(true))
|
||||
//}
|
||||
//}
|
||||
|
||||
trait ArrangerTheme<E: Engine> {
|
||||
fn border_bg () -> Color;
|
||||
fn border_fg (focused: bool) -> Color;
|
||||
fn title_fg (focused: bool) -> Color;
|
||||
fn separator_fg (focused: bool) -> Color;
|
||||
fn hotkey_fg () -> Color;
|
||||
fn mode_bg () -> Color;
|
||||
fn mode_fg () -> Color;
|
||||
fn status_bar_bg () -> Color;
|
||||
}
|
||||
|
||||
impl ArrangerTheme<Tui> for Arranger<Tui> {
|
||||
fn border_bg () -> Color {
|
||||
Color::Rgb(40, 50, 30)
|
||||
}
|
||||
fn border_fg (focused: bool) -> Color {
|
||||
if focused { Color::Rgb(100, 110, 40) } else { Color::Rgb(70, 80, 50) }
|
||||
}
|
||||
fn title_fg (focused: bool) -> Color {
|
||||
if focused { Color::Rgb(150, 160, 90) } else { Color::Rgb(120, 130, 100) }
|
||||
}
|
||||
fn separator_fg (_: bool) -> Color {
|
||||
Color::Rgb(0, 0, 0)
|
||||
}
|
||||
fn hotkey_fg () -> Color {
|
||||
Color::Rgb(255, 255, 0)
|
||||
}
|
||||
fn mode_bg () -> Color {
|
||||
Color::Rgb(150, 160, 90)
|
||||
}
|
||||
fn mode_fg () -> Color {
|
||||
Color::Rgb(255, 255, 255)
|
||||
}
|
||||
fn status_bar_bg () -> Color {
|
||||
Color::Rgb(28, 35, 25)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,15 +22,15 @@ impl Handle<Tui> for Sequencer<Tui> {
|
|||
return Ok(Some(true))
|
||||
}
|
||||
}
|
||||
if let Some(command) = SequencerCommand::match_input(self, i) {
|
||||
if let Some(command) = SequencerCommand::input_to_command(self, i) {
|
||||
let _undo = command.execute(self)?;
|
||||
return Ok(Some(true))
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, Sequencer<Tui>> for SequencerCommand {
|
||||
fn match_input (state: &Sequencer<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, Sequencer<Tui>> for SequencerCommand {
|
||||
fn input_to_command (state: &Sequencer<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
use SequencerCommand::*;
|
||||
use FocusCommand::*;
|
||||
match input.event() {
|
||||
|
|
@ -45,15 +45,15 @@ impl MatchInput<Tui, Sequencer<Tui>> for SequencerCommand {
|
|||
key!(KeyCode::Char(' ')) => Some(Transport(TransportCommand::PlayToggle)),
|
||||
_ => match state.focused() {
|
||||
SequencerFocus::Transport => if let Some(t) = state.transport.as_ref() {
|
||||
TransportCommand::match_input(&*t.read().unwrap(), input).map(Transport)
|
||||
TransportCommand::input_to_command(&*t.read().unwrap(), input).map(Transport)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
SequencerFocus::PhrasePool =>
|
||||
PhrasePoolCommand::match_input(&*state.phrases.read().unwrap(), input)
|
||||
PhrasePoolCommand::input_to_command(&*state.phrases.read().unwrap(), input)
|
||||
.map(Phrases),
|
||||
SequencerFocus::PhraseEditor =>
|
||||
PhraseEditorCommand::match_input(&state.editor, input)
|
||||
PhraseEditorCommand::input_to_command(&state.editor, input)
|
||||
.map(Editor),
|
||||
}
|
||||
}
|
||||
|
|
@ -100,15 +100,15 @@ impl Content for PhrasePool<Tui> {
|
|||
}
|
||||
impl Handle<Tui> for PhrasePool<Tui> {
|
||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||
if let Some(command) = PhrasePoolCommand::match_input(self, from) {
|
||||
if let Some(command) = PhrasePoolCommand::input_to_command(self, from) {
|
||||
let _undo = command.execute(self)?;
|
||||
return Ok(Some(true))
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, PhrasePool<Tui>> for PhrasePoolCommand {
|
||||
fn match_input (state: &PhrasePool<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, PhrasePool<Tui>> for PhrasePoolCommand {
|
||||
fn input_to_command (state: &PhrasePool<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
match input.event() {
|
||||
key!(KeyCode::Up) => Some(Self::Prev),
|
||||
key!(KeyCode::Down) => Some(Self::Next),
|
||||
|
|
@ -122,17 +122,17 @@ impl MatchInput<Tui, PhrasePool<Tui>> for PhrasePoolCommand {
|
|||
key!(KeyCode::Char('n')) => Some(Self::Rename(PhraseRenameCommand::Begin)),
|
||||
key!(KeyCode::Char('t')) => Some(Self::Length(PhraseLengthCommand::Begin)),
|
||||
_ => match state.mode {
|
||||
Some(PhrasePoolMode::Rename(..)) => PhraseRenameCommand::match_input(state, input)
|
||||
Some(PhrasePoolMode::Rename(..)) => PhraseRenameCommand::input_to_command(state, input)
|
||||
.map(Self::Rename),
|
||||
Some(PhrasePoolMode::Length(..)) => PhraseLengthCommand::match_input(state, input)
|
||||
Some(PhrasePoolMode::Length(..)) => PhraseLengthCommand::input_to_command(state, input)
|
||||
.map(Self::Length),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, PhrasePool<Tui>> for PhraseRenameCommand {
|
||||
fn match_input (_: &PhrasePool<Tui>, from: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, PhrasePool<Tui>> for PhraseRenameCommand {
|
||||
fn input_to_command (_: &PhrasePool<Tui>, from: &TuiInput) -> Option<Self> {
|
||||
match from.event() {
|
||||
key!(KeyCode::Backspace) => Some(Self::Backspace),
|
||||
key!(KeyCode::Enter) => Some(Self::Confirm),
|
||||
|
|
@ -142,8 +142,8 @@ impl MatchInput<Tui, PhrasePool<Tui>> for PhraseRenameCommand {
|
|||
}
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, PhrasePool<Tui>> for PhraseLengthCommand {
|
||||
fn match_input (_: &PhrasePool<Tui>, from: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, PhrasePool<Tui>> for PhraseLengthCommand {
|
||||
fn input_to_command (_: &PhrasePool<Tui>, from: &TuiInput) -> Option<Self> {
|
||||
match from.event() {
|
||||
key!(KeyCode::Up) => Some(Self::Inc),
|
||||
key!(KeyCode::Down) => Some(Self::Dec),
|
||||
|
|
@ -307,10 +307,15 @@ impl Content for PhraseEditor<Tui> {
|
|||
//note_clamp.unwrap_or(0),
|
||||
//);
|
||||
}
|
||||
let upper_right = if let Some(phrase) = phrase {
|
||||
format!("┤Length: {}├", phrase.read().unwrap().length)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
lay!(
|
||||
content,
|
||||
TuiStyle::fg(upper_left.to_string(), title_color).push_x(1).align_nw().fill_xy(),
|
||||
//TuiStyle::fg(upper_right.to_string(), title_color).pull_x(1).align_ne().fill_xy(),
|
||||
TuiStyle::fg(upper_right.to_string(), title_color).pull_x(1).align_ne().fill_xy(),
|
||||
TuiStyle::fg(lower_right.to_string(), title_color).pull_x(1).align_se().fill_xy(),
|
||||
)
|
||||
}
|
||||
|
|
@ -456,15 +461,15 @@ pub(crate) fn keys_vert () -> Buffer {
|
|||
}
|
||||
impl Handle<Tui> for PhraseEditor<Tui> {
|
||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||
if let Some(command) = PhraseEditorCommand::match_input(self, from) {
|
||||
if let Some(command) = PhraseEditorCommand::input_to_command(self, from) {
|
||||
let _undo = command.execute(self)?;
|
||||
return Ok(Some(true))
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, PhraseEditor<Tui>> for PhraseEditorCommand {
|
||||
fn match_input (_: &PhraseEditor<Tui>, from: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, PhraseEditor<Tui>> for PhraseEditorCommand {
|
||||
fn input_to_command (_: &PhraseEditor<Tui>, from: &TuiInput) -> Option<Self> {
|
||||
match from.event() {
|
||||
key!(KeyCode::Char('`')) => Some(Self::ToggleDirection),
|
||||
key!(KeyCode::Enter) => Some(Self::EnterEditMode),
|
||||
|
|
|
|||
|
|
@ -47,15 +47,15 @@ impl TransportToolbarFocus {
|
|||
}
|
||||
impl Handle<Tui> for TransportToolbar<Tui> {
|
||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||
if let Some(command) = TransportCommand::match_input(self, from) {
|
||||
if let Some(command) = TransportCommand::input_to_command(self, from) {
|
||||
let _undo = command.execute(self)?;
|
||||
return Ok(Some(true))
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
impl MatchInput<Tui, TransportToolbar<Tui>> for TransportCommand {
|
||||
fn match_input (_: &TransportToolbar<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
impl InputToCommand<Tui, TransportToolbar<Tui>> for TransportCommand {
|
||||
fn input_to_command (_: &TransportToolbar<Tui>, input: &TuiInput) -> Option<Self> {
|
||||
match input.event() {
|
||||
key!(KeyCode::Char(' ')) => Some(Self::FocusPrev),
|
||||
key!(Shift-KeyCode::Char(' ')) => Some(Self::FocusPrev),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue