fix renaming of duplicates; remove Arranger::modal

This commit is contained in:
🪞👃🪞 2024-10-11 16:19:06 +03:00
parent de4797ab52
commit f500c717a2
5 changed files with 44 additions and 140 deletions

View file

@ -14,8 +14,6 @@ pub struct Arranger<E: Engine> {
pub editor: PhraseEditor<E>, pub editor: PhraseEditor<E>,
/// This allows the sequencer view to be moved or hidden. /// This allows the sequencer view to be moved or hidden.
pub show_sequencer: Option<tek_core::Direction>, pub show_sequencer: Option<tek_core::Direction>,
/// Slot for modal dialog displayed on top of app.
pub modal: Option<Box<dyn ContentComponent<E>>>,
} }
/// Sections in the arranger app that may be focused /// Sections in the arranger app that may be focused
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
@ -86,14 +84,6 @@ pub struct VerticalArrangerCursor<'a>(
pub struct HorizontalArranger<'a, E: Engine>( pub struct HorizontalArranger<'a, E: Engine>(
pub &'a Arrangement<E> pub &'a Arrangement<E>
); );
pub struct ArrangerRenameModal<E: Engine> {
_engine: std::marker::PhantomData<E>,
pub done: bool,
pub target: ArrangementFocus,
pub value: String,
pub result: Arc<RwLock<String>>,
pub cursor: usize
}
/// Focus layout of arranger app /// Focus layout of arranger app
impl<E: Engine> FocusGrid<ArrangerFocus> for Arranger<E> { impl<E: Engine> FocusGrid<ArrangerFocus> for Arranger<E> {
fn cursor (&self) -> (usize, usize) { self.focus_cursor } fn cursor (&self) -> (usize, usize) { self.focus_cursor }
@ -401,7 +391,7 @@ impl ArrangementFocus {
scenes.get(*s), scenes.get(*s),
) { ) {
if let Some(clip) = scene.clip(*t) { if let Some(clip) = scene.clip(*t) {
format!("T{t} S{s} C{}", &clip.read().unwrap().name.read().unwrap()) format!("T{t} S{s} C{}", &clip.read().unwrap().name)
} else { } else {
format!("T{t} S{s}: Empty") format!("T{t} S{s}: Empty")
} }
@ -498,22 +488,6 @@ impl ArrangementViewMode {
} }
} }
} }
impl<E: Engine> ArrangerRenameModal<E> {
pub fn new (target: ArrangementFocus, value: &Arc<RwLock<String>>) -> Self {
Self {
_engine: Default::default(),
done: false,
value: value.read().unwrap().clone(),
cursor: value.read().unwrap().len(),
result: value.clone(),
target,
}
}
}
impl<E: Engine + Send> Exit for ArrangerRenameModal<E> {
fn exited (&self) -> bool { self.done }
fn exit (&mut self) { self.done = true }
}
impl Scene { impl Scene {
pub fn new ( pub fn new (
name: impl AsRef<str>, name: impl AsRef<str>,

View file

@ -53,7 +53,6 @@ impl ArrangerCli {
focus_cursor: (0, 1), focus_cursor: (0, 1),
transport: self.transport.then_some(transport), transport: self.transport.then_some(transport),
show_sequencer: Some(tek_core::Direction::Down), show_sequencer: Some(tek_core::Direction::Down),
modal: None,
editor: PhraseEditor::new(), editor: PhraseEditor::new(),
arrangement, arrangement,
phrases, phrases,

View file

@ -16,11 +16,11 @@ impl Content for Arranger<Tui> {
add(&self.arrangement) add(&self.arrangement)
} }
}))?; }))?;
if let Some(ref modal) = self.modal { //if let Some(ref modal) = self.modal {
add(&Background(COLOR_BG1))?; //add(&Background(COLOR_BG1))?;
add(&Foreground(COLOR_BG2))?; //add(&Foreground(COLOR_BG2))?;
//add(modal as &dyn Widget<Engine = Tui>)?; ////add(modal as &dyn Widget<Engine = Tui>)?;
} //}
Ok(()) Ok(())
}) })
} }
@ -40,6 +40,7 @@ impl Handle<Tui> for Arranger<Tui> {
}; };
match from.event() { match from.event() {
key!(KeyCode::Char('a')) => handle_phrase()?, key!(KeyCode::Char('a')) => handle_phrase()?,
key!(KeyCode::Char('c')) => handle_phrase()?,
key!(KeyCode::Char('i')) => handle_phrase()?, key!(KeyCode::Char('i')) => handle_phrase()?,
key!(KeyCode::Char('d')) => handle_phrase()?, key!(KeyCode::Char('d')) => handle_phrase()?,
_ => self.arrangement.handle(from)? _ => self.arrangement.handle(from)?
@ -73,22 +74,22 @@ impl Handle<Tui> for Arranger<Tui> {
impl Arranger<Tui> { impl Arranger<Tui> {
pub fn rename_selected (&mut self) { pub fn rename_selected (&mut self) {
let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = self.arrangement; let Arrangement { selected, ref name, ref tracks, ref scenes, .. } = self.arrangement;
self.modal = match selected { //self.modal = match selected {
ArrangementFocus::Mix => { //ArrangementFocus::Mix => {
Some(Box::new(ArrangerRenameModal::new(selected, &name))) //Some(Box::new(ArrangerRenameModal::new(selected, &*name.read().unwrap())))
}, //},
ArrangementFocus::Track(t) => { //ArrangementFocus::Track(t) => {
Some(Box::new(ArrangerRenameModal::new(selected, &tracks[t].name))) //Some(Box::new(ArrangerRenameModal::new(selected, &*tracks[t].name.read().unwrap())))
}, //},
ArrangementFocus::Scene(s) => { //ArrangementFocus::Scene(s) => {
Some(Box::new(ArrangerRenameModal::new(selected, &scenes[s].name))) //Some(Box::new(ArrangerRenameModal::new(selected, &*scenes[s].name.read().unwrap())))
}, //},
ArrangementFocus::Clip(t, s) => if let Some(ref clip) = scenes[s].clips[t] { //ArrangementFocus::Clip(t, s) => if let Some(ref clip) = scenes[s].clips[t] {
Some(Box::new(ArrangerRenameModal::new(selected, &clip.read().unwrap().name))) //Some(Box::new(ArrangerRenameModal::new(selected, &clip.read().unwrap().name)))
} else { //} else {
None //None
} //}
}; //};
} }
} }
impl Handle<Tui> for Arrangement<Tui> { impl Handle<Tui> for Arrangement<Tui> {
@ -103,7 +104,6 @@ impl Handle<Tui> for Arrangement<Tui> {
key!(Ctrl-KeyCode::Char('a')) => { self.scene_add(None)?; }, key!(Ctrl-KeyCode::Char('a')) => { self.scene_add(None)?; },
key!(Ctrl-KeyCode::Char('t')) => { self.track_add(None)?; }, key!(Ctrl-KeyCode::Char('t')) => { self.track_add(None)?; },
key!(KeyCode::Char('n')) => { todo!("rename selected"); }, key!(KeyCode::Char('n')) => { todo!("rename selected"); },
key!(KeyCode::Char('c')) => { todo!("recolor selected"); },
key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() { key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() {
phrase.write().unwrap().toggle_loop() phrase.write().unwrap().toggle_loop()
}, },
@ -188,7 +188,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
match (tracks.get(track), (scene as &Scene).clips.get(track)) { match (tracks.get(track), (scene as &Scene).clips.get(track)) {
(Some(track), Some(Some(phrase))) => { (Some(track), Some(Some(phrase))) => {
let name = &(phrase as &Arc<RwLock<Phrase>>).read().unwrap().name; let name = &(phrase as &Arc<RwLock<Phrase>>).read().unwrap().name;
let name = format!("{}", name.read().unwrap()); let name = format!("{}", name);
add(&name.as_str().push_x(1).fixed_x(w))?; add(&name.as_str().push_x(1).fixed_x(w))?;
color = (phrase as &Arc<RwLock<Phrase>>).read().unwrap().color; color = (phrase as &Arc<RwLock<Phrase>>).read().unwrap().color;
//if let Some(playing_phrase) = &track.player.phrase { //if let Some(playing_phrase) = &track.player.phrase {
@ -526,7 +526,7 @@ impl<'a> Content for HorizontalArranger<'a, Tui> {
let active_track = selected.track() == Some(i); let active_track = selected.track() == Some(i);
if let Some(clip) = clip { if let Some(clip) = clip {
let y2 = y + 2 + i as u16 * 2; let y2 = y + 2 + i as u16 * 2;
let label = format!("{}", clip.read().unwrap().name.read().unwrap()); let label = format!("{}", clip.read().unwrap().name);
to.blit(&label, x + x2, y2, Some(if active_track && active_scene { to.blit(&label, x + x2, y2, Some(if active_track && active_scene {
Style::default().not_dim().yellow().bold() Style::default().not_dim().yellow().bold()
} else { } else {
@ -544,61 +544,3 @@ impl<'a> Content for HorizontalArranger<'a, Tui> {
) )
} }
} }
impl Content for ArrangerRenameModal<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
todo!();
Layers::new(|add|{Ok(())})
//let area = to.area();
//let y = area.y() + area.h() / 2;
//let bg_area = [1, y - 1, area.w() - 2, 3];
//to.fill_bg(bg_area, COLOR_BG1);
//Lozenge(Style::default().bold().white().dim()).draw(to.with_rect(bg_area));
//let label = match self.target {
//ArrangementFocus::Mix => "Rename project:",
//ArrangementFocus::Track(_) => "Rename track:",
//ArrangementFocus::Scene(_) => "Rename scene:",
//ArrangementFocus::Clip(_, _) => "Rename clip:",
//};
//let style = Some(Style::default().not_bold().white().not_dim());
//to.blit(&label, area.x() + 3, y, style);
//let style = Some(Style::default().bold().white().not_dim());
//to.blit(&self.value, area.x() + 3 + label.len() as u16 + 1, y, style);
//let style = Some(Style::default().bold().white().not_dim().reversed());
//to.blit(&"▂", area.x() + 3 + label.len() as u16 + 1 + self.cursor as u16, y, style);
//Ok(Some(area))
//Ok(())
}
}
impl Handle<Tui> for ArrangerRenameModal<Tui> {
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
match from.event() {
TuiEvent::Input(Event::Key(k)) => {
match k.code {
KeyCode::Esc => { self.exit(); },
KeyCode::Enter => {
*self.result.write().unwrap() = self.value.clone();
self.exit();
},
KeyCode::Left => { self.cursor = self.cursor.saturating_sub(1); },
KeyCode::Right => { self.cursor = self.value.len().min(self.cursor + 1) },
KeyCode::Backspace => {
let last = self.value.len().saturating_sub(1);
self.value = format!("{}{}",
&self.value[0..self.cursor.min(last)],
&self.value[self.cursor.min(last)..last]
);
self.cursor = self.cursor.saturating_sub(1)
}
KeyCode::Char(c) => {
self.value.insert(self.cursor, c);
self.cursor = self.value.len().min(self.cursor + 1)
},
_ => {}
}
Ok(Some(true))
},
_ => Ok(None),
}
}
}

View file

@ -40,7 +40,7 @@ pub enum PhrasePoolMode { Rename(usize, String) }
pub struct Phrase { pub struct Phrase {
pub uuid: uuid::Uuid, pub uuid: uuid::Uuid,
/// Name of phrase /// Name of phrase
pub name: Arc<RwLock<String>>, pub name: String,
/// Temporal resolution in pulses per quarter note /// Temporal resolution in pulses per quarter note
pub ppq: usize, pub ppq: usize,
/// Length of phrase in pulses /// Length of phrase in pulses
@ -174,7 +174,7 @@ pub fn random_color () -> Color {
} }
impl Phrase { impl Phrase {
pub fn new ( pub fn new (
name: &str, name: impl AsRef<str>,
loop_on: bool, loop_on: bool,
length: usize, length: usize,
notes: Option<PhraseData>, notes: Option<PhraseData>,
@ -182,7 +182,7 @@ impl Phrase {
) -> Self { ) -> Self {
Self { Self {
uuid: uuid::Uuid::new_v4(), uuid: uuid::Uuid::new_v4(),
name: Arc::new(RwLock::new(name.into())), name: name.as_ref().to_string(),
ppq: PPQ, ppq: PPQ,
length, length,
notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]), notes: notes.unwrap_or(vec![Vec::with_capacity(16);length]),

View file

@ -50,12 +50,12 @@ impl Content for PhrasePool<Tui> {
let row1 = format!(" {i}"); let row1 = format!(" {i}");
let row2 = if let Some(PhrasePoolMode::Rename(phrase, _)) = self.mode { let row2 = if let Some(PhrasePoolMode::Rename(phrase, _)) = self.mode {
if self.focused && i == phrase { if self.focused && i == phrase {
format!(" {}", name.read().unwrap()) format!(" {}", name)
} else { } else {
format!(" {}", name.read().unwrap()) format!(" {}", name)
} }
} else { } else {
format!(" {}", name.read().unwrap()) format!(" {}", name)
}; };
add(&col!(row1, row2).fill_x().bg(if i == self.phrase { add(&col!(row1, row2).fill_x().bg(if i == self.phrase {
color //Color::Rgb(40, 50, 30) color //Color::Rgb(40, 50, 30)
@ -85,24 +85,16 @@ impl Content for PhrasePool<Tui> {
impl Handle<Tui> for PhrasePool<Tui> { impl Handle<Tui> for PhrasePool<Tui> {
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> { fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
match self.mode { match self.mode {
Some(PhrasePoolMode::Rename(phrase, ref mut old_name)) => match from.event() { Some(PhrasePoolMode::Rename(phrase, ref mut old_name)) => {
key!(KeyCode::Backspace) => { let mut phrase = self.phrases[phrase].write().unwrap();
self.phrases[phrase].read().unwrap().name.write().unwrap().pop(); match from.event() {
}, key!(KeyCode::Backspace) => { phrase.name.pop(); },
key!(KeyCode::Char(c)) => { key!(KeyCode::Char(c)) => { phrase.name.push(*c); },
self.phrases[phrase].read().unwrap().name.write().unwrap().push(*c); key!(Shift-KeyCode::Char(c)) => { phrase.name.push(*c); },
}, key!(KeyCode::Esc) => { phrase.name = old_name.clone(); self.mode = None; },
key!(Shift-KeyCode::Char(c)) => { key!(KeyCode::Enter) => { self.mode = None; },
self.phrases[phrase].read().unwrap().name.write().unwrap().push(*c); _ => return Ok(None)
}, }
key!(KeyCode::Esc) => {
*self.phrases[phrase].read().unwrap().name.write().unwrap() = old_name.clone();
self.mode = None;
},
key!(KeyCode::Enter) => {
self.mode = None;
},
_ => return Ok(None)
}, },
None => match from.event() { None => match from.event() {
key!(KeyCode::Up) => self.phrase = if self.phrase > 0 { key!(KeyCode::Up) => self.phrase = if self.phrase > 0 {
@ -115,14 +107,14 @@ impl Handle<Tui> for PhrasePool<Tui> {
}, },
key!(KeyCode::Char('a')) => { // append new key!(KeyCode::Char('a')) => { // append new
let mut phrase = Phrase::default(); let mut phrase = Phrase::default();
phrase.name = Arc::new(RwLock::new("(no name)".to_string())); phrase.name = String::from("(no name)");
phrase.color = random_color(); phrase.color = random_color();
self.phrases.push(Arc::new(RwLock::new(phrase))); self.phrases.push(Arc::new(RwLock::new(phrase)));
self.phrase = self.phrases.len() - 1; self.phrase = self.phrases.len() - 1;
}, },
key!(KeyCode::Char('i')) => { // insert new key!(KeyCode::Char('i')) => { // insert new
let mut phrase = Phrase::default(); let mut phrase = Phrase::default();
phrase.name = Arc::new(RwLock::new("(no name)".to_string())); phrase.name = String::from("(no name)");
phrase.color = random_color(); phrase.color = random_color();
self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase))); self.phrases.insert(self.phrase + 1, Arc::new(RwLock::new(phrase)));
self.phrase += 1; self.phrase += 1;
@ -138,10 +130,7 @@ impl Handle<Tui> for PhrasePool<Tui> {
}, },
key!(KeyCode::Char('n')) => { // change name key!(KeyCode::Char('n')) => { // change name
let phrase = self.phrases[self.phrase].read().unwrap(); let phrase = self.phrases[self.phrase].read().unwrap();
self.mode = Some(PhrasePoolMode::Rename( self.mode = Some(PhrasePoolMode::Rename(self.phrase, phrase.name.clone()));
self.phrase,
phrase.name.read().unwrap().clone()
));
}, },
_ => return Ok(None), _ => return Ok(None),
} }