From 69faadac2bc5c65dd7c4b15161135062133309fa Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 12 Dec 2024 10:47:13 +0100 Subject: [PATCH] PhrasesMode -> PhraseListMode --- crates/tek/src/api/phrase.rs | 4 ++ crates/tek/src/tui/app_arranger.rs | 15 ++++++ crates/tek/src/tui/app_sequencer.rs | 2 +- crates/tek/src/tui/file_browser.rs | 12 ++--- crates/tek/src/tui/phrase_length.rs | 12 ++--- crates/tek/src/tui/phrase_list.rs | 78 ++++++++++++----------------- crates/tek/src/tui/phrase_rename.rs | 4 +- 7 files changed, 65 insertions(+), 62 deletions(-) diff --git a/crates/tek/src/api/phrase.rs b/crates/tek/src/api/phrase.rs index 94aa24c2..3f8ca6b8 100644 --- a/crates/tek/src/api/phrase.rs +++ b/crates/tek/src/api/phrase.rs @@ -5,6 +5,10 @@ pub trait HasPhrases { fn phrases_mut (&mut self) -> &mut Vec>>; } +pub trait HasPhrase { + fn phrase (&self) -> &Arc>; +} + #[derive(Clone, Debug, PartialEq)] pub enum PhrasePoolCommand { Add(usize, Phrase), diff --git a/crates/tek/src/tui/app_arranger.rs b/crates/tek/src/tui/app_arranger.rs index 9d88445b..f8813c96 100644 --- a/crates/tek/src/tui/app_arranger.rs +++ b/crates/tek/src/tui/app_arranger.rs @@ -168,6 +168,21 @@ impl HasPhrases for ArrangerTui { } } +impl HasPhraseList for ArrangerTui { + fn phrases_focused (&self) -> bool { + self.focused() == ArrangerFocus::Phrases + } + fn phrases_entered (&self) -> bool { + self.entered() && self.phrases_focused() + } + fn phrases_mode (&self) -> &Option { + &self.phrases.mode + } + fn phrase_index (&self) -> usize { + self.phrases.phrase.load(Ordering::Relaxed) + } +} + impl HasEditor for ArrangerTui { fn editor (&self) -> &PhraseEditorModel { &self.editor diff --git a/crates/tek/src/tui/app_sequencer.rs b/crates/tek/src/tui/app_sequencer.rs index 869b4ab1..db3e575e 100644 --- a/crates/tek/src/tui/app_sequencer.rs +++ b/crates/tek/src/tui/app_sequencer.rs @@ -148,7 +148,7 @@ impl HasPhraseList for SequencerTui { fn phrases_entered (&self) -> bool { true } - fn phrases_mode (&self) -> &Option { + fn phrases_mode (&self) -> &Option { &self.phrases.mode } fn phrase_index (&self) -> usize { diff --git a/crates/tek/src/tui/file_browser.rs b/crates/tek/src/tui/file_browser.rs index 436a3220..26a40c30 100644 --- a/crates/tek/src/tui/file_browser.rs +++ b/crates/tek/src/tui/file_browser.rs @@ -1,7 +1,7 @@ use crate::*; use KeyCode::{Up, Down, Right, Left, Enter, Esc, Char, Backspace}; use FileBrowserCommand::*; -use super::phrase_list::PhrasesMode::{Import, Export}; +use super::phrase_list::PhraseListMode::{Import, Export}; /// Browses for phrase to import/export #[derive(Debug, Clone)] @@ -121,12 +121,12 @@ impl Command for FileBrowserCommand { }, _ => todo!(), }, - Some(PhrasesMode::Export(index, ref mut browser)) => match self { + Some(PhraseListMode::Export(index, ref mut browser)) => match self { Cancel => { *mode = None; }, Chdir(cwd) => { - *mode = Some(PhrasesMode::Export(*index, FileBrowser::new(Some(cwd))?)); + *mode = Some(PhraseListMode::Export(*index, FileBrowser::new(Some(cwd))?)); }, Select(index) => { browser.index = index; @@ -141,7 +141,7 @@ impl Command for FileBrowserCommand { impl InputToCommand for FileBrowserCommand { fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { - if let Some(PhrasesMode::Import(_index, browser)) = state.phrases_mode() { + if let Some(PhraseListMode::Import(_index, browser)) = state.phrases_mode() { Some(match from.event() { key!(Up) => Select( browser.index.overflowing_sub(1).0.min(browser.len().saturating_sub(1)) @@ -157,7 +157,7 @@ impl InputToCommand for FileBrowserCommand { key!(Esc) => Self::Cancel, _ => return None }) - } else if let Some(PhrasesMode::Export(_index, browser)) = state.phrases_mode() { + } else if let Some(PhraseListMode::Export(_index, browser)) = state.phrases_mode() { Some(match from.event() { key!(Up) => Select(browser.index.overflowing_sub(1).0.min(browser.len())), key!(Down) => Select(browser.index.saturating_add(1) % browser.len()), @@ -177,7 +177,7 @@ impl InputToCommand for FileBrowserCommand { impl InputToCommand for PhraseLengthCommand { fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { - if let Some(PhrasesMode::Length(_, length, _)) = state.phrases_mode() { + if let Some(PhraseListMode::Length(_, length, _)) = state.phrases_mode() { Some(match from.event() { key!(Up) => Self::Inc, key!(Down) => Self::Dec, diff --git a/crates/tek/src/tui/phrase_length.rs b/crates/tek/src/tui/phrase_length.rs index 675fa946..f6f49cde 100644 --- a/crates/tek/src/tui/phrase_length.rs +++ b/crates/tek/src/tui/phrase_length.rs @@ -1,5 +1,5 @@ use crate::*; -use super::phrase_list::{PhraseListModel, PhrasesMode}; +use super::phrase_list::{PhraseListModel, PhraseListMode}; use PhraseLengthFocus::*; use PhraseLengthCommand::*; @@ -75,13 +75,13 @@ render!(|self: PhraseLength|{ let ticks = ||self.ticks_string(); row!(move|add|match self.focus { None => - add(&row!([" ", bars(), "B", beats(), "b", ticks(), "T"])), + add(&row!([" ", bars(), ".", beats(), ".", ticks()])), Some(PhraseLengthFocus::Bar) => - add(&row!(["[", bars(), "]", beats(), "b", ticks(), "T"])), + add(&row!(["[", bars(), "]", beats(), ".", ticks()])), Some(PhraseLengthFocus::Beat) => - add(&row!([" ", bars(), "[", beats(), "]", ticks(), "T"])), + add(&row!([" ", bars(), "[", beats(), "]", ticks()])), Some(PhraseLengthFocus::Tick) => - add(&row!([" ", bars(), "B", beats(), "[", ticks(), "]"])), + add(&row!([" ", bars(), ".", beats(), "[", ticks()])), }) }); @@ -99,7 +99,7 @@ pub enum PhraseLengthCommand { impl Command for PhraseLengthCommand { fn execute (self, state: &mut PhraseListModel) -> Perhaps { match state.phrases_mode_mut().clone() { - Some(PhrasesMode::Length(phrase, ref mut length, ref mut focus)) => match self { + Some(PhraseListMode::Length(phrase, ref mut length, ref mut focus)) => match self { Cancel => { *state.phrases_mode_mut() = None; }, Prev => { focus.prev() }, Next => { focus.next() }, diff --git a/crates/tek/src/tui/phrase_list.rs b/crates/tek/src/tui/phrase_list.rs index 1e7a559e..7c301d55 100644 --- a/crates/tek/src/tui/phrase_list.rs +++ b/crates/tek/src/tui/phrase_list.rs @@ -1,6 +1,5 @@ use super::*; use crate::{ - *, api::PhrasePoolCommand as Pool, tui::{ phrase_rename::PhraseRenameCommand as Rename, @@ -16,9 +15,22 @@ pub struct PhraseListModel { /// Selected phrase pub(crate) phrase: AtomicUsize, /// Scroll offset - pub(crate) scroll: usize, + pub scroll: usize, /// Mode switch - pub(crate) mode: Option, + pub(crate) mode: Option, +} + +/// Modes for phrase pool +#[derive(Debug, Clone)] +pub enum PhraseListMode { + /// Renaming a pattern + Rename(usize, String), + /// Editing the length of a pattern + Length(usize, usize, PhraseLengthFocus), + /// Load phrase from disk + Import(usize, FileBrowser), + /// Save phrase to disk + Export(usize, FileBrowser), } impl Default for PhraseListModel { @@ -42,56 +54,28 @@ impl PhraseListModel { pub(crate) fn set_phrase_index (&self, value: usize) { self.phrase.store(value, Ordering::Relaxed); } - pub(crate) fn phrases_mode (&self) -> &Option { + pub(crate) fn phrases_mode (&self) -> &Option { &self.mode } - pub(crate) fn phrases_mode_mut (&mut self) -> &mut Option { + pub(crate) fn phrases_mode_mut (&mut self) -> &mut Option { &mut self.mode } } -/// Modes for phrase pool -#[derive(Debug, Clone)] -pub enum PhrasesMode { - /// Renaming a pattern - Rename(usize, String), - /// Editing the length of a pattern - Length(usize, usize, PhraseLengthFocus), - /// Load phrase from disk - Import(usize, FileBrowser), - /// Save phrase to disk - Export(usize, FileBrowser), -} - pub trait HasPhraseList: HasPhrases { fn phrases_focused (&self) -> bool; fn phrases_entered (&self) -> bool; - fn phrases_mode (&self) -> &Option; + fn phrases_mode (&self) -> &Option; fn phrase_index (&self) -> usize; } -impl HasPhraseList for ArrangerTui { - fn phrases_focused (&self) -> bool { - self.focused() == ArrangerFocus::Phrases - } - fn phrases_entered (&self) -> bool { - self.entered() && self.phrases_focused() - } - fn phrases_mode (&self) -> &Option { - &self.phrases.mode - } - fn phrase_index (&self) -> usize { - self.phrases.phrase.load(Ordering::Relaxed) - } -} - pub struct PhraseListView<'a> { pub(crate) title: &'static str, pub(crate) focused: bool, pub(crate) entered: bool, pub(crate) phrases: &'a Vec>>, pub(crate) index: usize, - pub(crate) mode: &'a Option + pub(crate) mode: &'a Option } impl<'a, T: HasPhraseList> From<&'a T> for PhraseListView<'a> { @@ -117,13 +101,13 @@ render!(|self: PhraseListView<'a>|{ Tui::bg(bg, lay!(move|add|{ //add(&Lozenge(Style::default().bg(border_bg).fg(border_color)))?; add(&Tui::inset_xy(0, 1, Tui::fill_xy(col!(move|add|match mode { - Some(PhrasesMode::Import(_, ref file_picker)) => add(file_picker), - Some(PhrasesMode::Export(_, ref file_picker)) => add(file_picker), + Some(PhraseListMode::Import(_, ref file_picker)) => add(file_picker), + Some(PhraseListMode::Export(_, ref file_picker)) => add(file_picker), _ => Ok(for (i, phrase) in phrases.iter().enumerate() { add(&lay!(|add|{ let Phrase { ref name, color, length, .. } = *phrase.read().unwrap(); let mut length = PhraseLength::new(length, None); - if let Some(PhrasesMode::Length(phrase, new_length, focus)) = mode { + if let Some(PhraseListMode::Length(phrase, new_length, focus)) = mode { if *focused && i == *phrase { length.pulses = *new_length; length.focus = Some(*focus); @@ -136,7 +120,7 @@ render!(|self: PhraseListView<'a>|{ })), Tui::bold(true, { let mut row2 = format!(" {name}"); - if let Some(PhrasesMode::Rename(phrase, _)) = mode { + if let Some(PhraseListMode::Rename(phrase, _)) = mode { if *focused && i == *phrase { row2 = format!("{row2}▄"); } @@ -175,7 +159,7 @@ impl Command for PhrasesCommand { PhraseRenameCommand::Begin => { let length = state.phrases()[state.phrase_index()].read().unwrap().length; *state.phrases_mode_mut() = Some( - PhrasesMode::Length(state.phrase_index(), length, PhraseLengthFocus::Bar) + PhraseListMode::Length(state.phrase_index(), length, PhraseLengthFocus::Bar) ); None }, @@ -185,7 +169,7 @@ impl Command for PhrasesCommand { PhraseLengthCommand::Begin => { let name = state.phrases()[state.phrase_index()].read().unwrap().name.clone(); *state.phrases_mode_mut() = Some( - PhrasesMode::Rename(state.phrase_index(), name) + PhraseListMode::Rename(state.phrase_index(), name) ); None }, @@ -194,7 +178,7 @@ impl Command for PhrasesCommand { Import(command) => match command { FileBrowserCommand::Begin => { *state.phrases_mode_mut() = Some( - PhrasesMode::Import(state.phrase_index(), FileBrowser::new(None)?) + PhraseListMode::Import(state.phrase_index(), FileBrowser::new(None)?) ); None }, @@ -203,7 +187,7 @@ impl Command for PhrasesCommand { Export(command) => match command { FileBrowserCommand::Begin => { *state.phrases_mode_mut() = Some( - PhrasesMode::Export(state.phrase_index(), FileBrowser::new(None)?) + PhraseListMode::Export(state.phrase_index(), FileBrowser::new(None)?) ); None }, @@ -229,10 +213,10 @@ impl HasPhrases for PhraseListModel { impl InputToCommand for PhrasesCommand { fn input_to_command (state: &PhraseListModel, input: &TuiInput) -> Option { Some(match state.phrases_mode() { - Some(PhrasesMode::Rename(..)) => Self::Rename(Rename::input_to_command(state, input)?), - Some(PhrasesMode::Length(..)) => Self::Length(Length::input_to_command(state, input)?), - Some(PhrasesMode::Import(..)) => Self::Import(Browse::input_to_command(state, input)?), - Some(PhrasesMode::Export(..)) => Self::Export(Browse::input_to_command(state, input)?), + Some(PhraseListMode::Rename(..)) => Self::Rename(Rename::input_to_command(state, input)?), + Some(PhraseListMode::Length(..)) => Self::Length(Length::input_to_command(state, input)?), + Some(PhraseListMode::Import(..)) => Self::Import(Browse::input_to_command(state, input)?), + Some(PhraseListMode::Export(..)) => Self::Export(Browse::input_to_command(state, input)?), _ => to_phrases_command(state, input)? }) } diff --git a/crates/tek/src/tui/phrase_rename.rs b/crates/tek/src/tui/phrase_rename.rs index bd90e91b..c2bab07a 100644 --- a/crates/tek/src/tui/phrase_rename.rs +++ b/crates/tek/src/tui/phrase_rename.rs @@ -12,7 +12,7 @@ impl Command for PhraseRenameCommand { fn execute (self, state: &mut PhraseListModel) -> Perhaps { use PhraseRenameCommand::*; match state.phrases_mode_mut().clone() { - Some(PhrasesMode::Rename(phrase, ref mut old_name)) => match self { + Some(PhraseListMode::Rename(phrase, ref mut old_name)) => match self { Set(s) => { state.phrases()[phrase].write().unwrap().name = s.into(); return Ok(Some(Self::Set(old_name.clone()))) @@ -36,7 +36,7 @@ impl Command for PhraseRenameCommand { impl InputToCommand for PhraseRenameCommand { fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option { use KeyCode::{Char, Backspace, Enter, Esc}; - if let Some(PhrasesMode::Rename(_, ref old_name)) = state.phrases_mode() { + if let Some(PhraseListMode::Rename(_, ref old_name)) = state.phrases_mode() { Some(match from.event() { key!(Char(c)) => { let mut new_name = old_name.clone();