PhrasesMode -> PhraseListMode

This commit is contained in:
🪞👃🪞 2024-12-12 10:47:13 +01:00
parent a7ff74e27c
commit 69faadac2b
7 changed files with 65 additions and 62 deletions

View file

@ -5,6 +5,10 @@ pub trait HasPhrases {
fn phrases_mut (&mut self) -> &mut Vec<Arc<RwLock<Phrase>>>;
}
pub trait HasPhrase {
fn phrase (&self) -> &Arc<RwLock<Phrase>>;
}
#[derive(Clone, Debug, PartialEq)]
pub enum PhrasePoolCommand {
Add(usize, Phrase),

View file

@ -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<PhraseListMode> {
&self.phrases.mode
}
fn phrase_index (&self) -> usize {
self.phrases.phrase.load(Ordering::Relaxed)
}
}
impl HasEditor for ArrangerTui {
fn editor (&self) -> &PhraseEditorModel {
&self.editor

View file

@ -148,7 +148,7 @@ impl HasPhraseList for SequencerTui {
fn phrases_entered (&self) -> bool {
true
}
fn phrases_mode (&self) -> &Option<PhrasesMode> {
fn phrases_mode (&self) -> &Option<PhraseListMode> {
&self.phrases.mode
}
fn phrase_index (&self) -> usize {

View file

@ -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<PhraseListModel> 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<PhraseListModel> for FileBrowserCommand {
impl InputToCommand<Tui, PhraseListModel> for FileBrowserCommand {
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
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<Tui, PhraseListModel> 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<Tui, PhraseListModel> for FileBrowserCommand {
impl InputToCommand<Tui, PhraseListModel> for PhraseLengthCommand {
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
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,

View file

@ -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<PhraseListModel> for PhraseLengthCommand {
fn execute (self, state: &mut PhraseListModel) -> Perhaps<Self> {
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() },

View file

@ -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<PhrasesMode>,
pub(crate) mode: Option<PhraseListMode>,
}
/// 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<PhrasesMode> {
pub(crate) fn phrases_mode (&self) -> &Option<PhraseListMode> {
&self.mode
}
pub(crate) fn phrases_mode_mut (&mut self) -> &mut Option<PhrasesMode> {
pub(crate) fn phrases_mode_mut (&mut self) -> &mut Option<PhraseListMode> {
&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<PhrasesMode>;
fn phrases_mode (&self) -> &Option<PhraseListMode>;
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<PhrasesMode> {
&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<Arc<RwLock<Phrase>>>,
pub(crate) index: usize,
pub(crate) mode: &'a Option<PhrasesMode>
pub(crate) mode: &'a Option<PhraseListMode>
}
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<PhraseListModel> 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<PhraseListModel> 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<PhraseListModel> 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<PhraseListModel> 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<Tui, PhraseListModel> for PhrasesCommand {
fn input_to_command (state: &PhraseListModel, input: &TuiInput) -> Option<Self> {
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)?
})
}

View file

@ -12,7 +12,7 @@ impl Command<PhraseListModel> for PhraseRenameCommand {
fn execute (self, state: &mut PhraseListModel) -> Perhaps<Self> {
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<PhraseListModel> for PhraseRenameCommand {
impl InputToCommand<Tui, PhraseListModel> for PhraseRenameCommand {
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
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();