diff --git a/src/control/focus.rs b/src/control/focus.rs index 6a5b3f75..23678fe3 100644 --- a/src/control/focus.rs +++ b/src/control/focus.rs @@ -10,10 +10,14 @@ pub const KEYMAP_FOCUS: &'static [KeyBinding] = keymap!(App { [Tab, SHIFT, "focus_prev", "focus previous area", focus_prev], [Esc, NONE, "focus_exit", "unfocus", |app: &mut App|{ app.entered = false; + app.transport.entered = app.entered; + app.arranger.entered = app.entered; Ok(true) }], [Enter, NONE, "focus_enter", "activate item at cursor", |app: &mut App|{ app.entered = true; + app.transport.entered = app.entered; + app.arranger.entered = app.entered; Ok(true) }], }); @@ -22,6 +26,8 @@ pub fn focus_next (app: &mut App) -> Usually { app.section.next(); app.transport.focused = app.section == AppFocus::Transport; app.transport.entered = app.entered; + app.arranger.focused = app.section == AppFocus::Arranger; + app.arranger.entered = app.entered; Ok(true) } @@ -29,5 +35,7 @@ pub fn focus_prev (app: &mut App) -> Usually { app.section.prev(); app.transport.focused = app.section == AppFocus::Transport; app.transport.entered = app.entered; + app.arranger.focused = app.section == AppFocus::Arranger; + app.arranger.entered = app.entered; Ok(true) } diff --git a/src/model/arranger.rs b/src/model/arranger.rs index 91c0da4d..de1576c8 100644 --- a/src/model/arranger.rs +++ b/src/model/arranger.rs @@ -1,98 +1,20 @@ use crate::{core::*, model::*}; +/// Represents the tracks and scenes of the composition. pub struct Arranger { /// Display mode of arranger - pub mode: bool, + pub mode: bool, /// Currently selected element. - pub selected: ArrangerFocus, + pub selected: ArrangerFocus, /// Collection of tracks. - pub tracks: Vec, + pub tracks: Vec, /// Collection of scenes. - pub scenes: Vec, + pub scenes: Vec, + + pub focused: bool, + pub entered: bool, } -#[derive(PartialEq)] -pub enum ArrangerFocus { - /// The whole mix is selected - Mix, - /// A track is selected. - Track(usize), - /// A scene is selected. - Scene(usize), - /// A clip (track × scene) is selected. - Clip(usize, usize), -} - -/// Identification methods -impl ArrangerFocus { - pub fn is_track (&self) -> bool { - match self { Self::Track(_) => true, _ => false } - } - pub fn is_scene (&self) -> bool { - match self { Self::Scene(_) => true, _ => false } - } - pub fn is_clip (&self) -> bool { - match self { Self::Clip(_, _) => true, _ => false } - } -} - -/// Track methods -impl ArrangerFocus { - pub fn track (&self) -> Option { - match self { - Self::Clip(t, _) => Some(*t), - Self::Track(t) => Some(*t), - _ => None - } - } - pub fn track_next (&mut self, last_track: usize) { - *self = match self { - Self::Mix => Self::Track(0), - Self::Track(t) => Self::Track(last_track.min(*t + 1)), - Self::Scene(s) => Self::Clip(0, *s), - Self::Clip(t, s) => Self::Clip(last_track.min(*t + 1), *s), - } - } - pub fn track_prev (&mut self) { - *self = match self { - Self::Mix => Self::Mix, - Self::Scene(s) => Self::Scene(*s), - Self::Track(0) => Self::Mix, - Self::Track(t) => Self::Track(*t - 1), - Self::Clip(t, s) => Self::Clip(t.saturating_sub(1), *s), - } - } -} - -/// Scene methods -impl ArrangerFocus { - pub fn scene (&self) -> Option { - match self { - Self::Clip(_, s) => Some(*s), - Self::Scene(s) => Some(*s), - _ => None - } - } - pub fn scene_next (&mut self, last_scene: usize) { - *self = match self { - Self::Mix => Self::Scene(0), - Self::Track(t) => Self::Scene(*t), - Self::Scene(s) => Self::Scene(last_scene.min(*s + 1)), - Self::Clip(t, s) => Self::Clip(*t, last_scene.min(*s + 1)), - } - } - pub fn scene_prev (&mut self) { - *self = match self { - Self::Mix => Self::Mix, - Self::Track(t) => Self::Track(*t), - Self::Scene(0) => Self::Mix, - Self::Scene(s) => Self::Scene(*s - 1), - Self::Clip(t, s) => Self::Clip(*t, s.saturating_sub(1)), - } - } -} - -/// Represents the tracks and scenes of the composition. impl Arranger { pub fn new () -> Self { Self { @@ -100,6 +22,8 @@ impl Arranger { selected: ArrangerFocus::Mix, scenes: vec![], tracks: vec![], + entered: true, + focused: true, } } pub fn activate (&mut self) { @@ -226,3 +150,85 @@ impl Arranger { //} } } + +#[derive(PartialEq)] +/// Represents the current user selection in the arranger +pub enum ArrangerFocus { + /// The whole mix is selected + Mix, + /// A track is selected. + Track(usize), + /// A scene is selected. + Scene(usize), + /// A clip (track × scene) is selected. + Clip(usize, usize), +} + +/// Identification methods +impl ArrangerFocus { + pub fn is_track (&self) -> bool { + match self { Self::Track(_) => true, _ => false } + } + pub fn is_scene (&self) -> bool { + match self { Self::Scene(_) => true, _ => false } + } + pub fn is_clip (&self) -> bool { + match self { Self::Clip(_, _) => true, _ => false } + } +} + +/// Track methods +impl ArrangerFocus { + pub fn track (&self) -> Option { + match self { + Self::Clip(t, _) => Some(*t), + Self::Track(t) => Some(*t), + _ => None + } + } + pub fn track_next (&mut self, last_track: usize) { + *self = match self { + Self::Mix => Self::Track(0), + Self::Track(t) => Self::Track(last_track.min(*t + 1)), + Self::Scene(s) => Self::Clip(0, *s), + Self::Clip(t, s) => Self::Clip(last_track.min(*t + 1), *s), + } + } + pub fn track_prev (&mut self) { + *self = match self { + Self::Mix => Self::Mix, + Self::Scene(s) => Self::Scene(*s), + Self::Track(0) => Self::Mix, + Self::Track(t) => Self::Track(*t - 1), + Self::Clip(t, s) => Self::Clip(t.saturating_sub(1), *s), + } + } +} + +/// Scene methods +impl ArrangerFocus { + pub fn scene (&self) -> Option { + match self { + Self::Clip(_, s) => Some(*s), + Self::Scene(s) => Some(*s), + _ => None + } + } + pub fn scene_next (&mut self, last_scene: usize) { + *self = match self { + Self::Mix => Self::Scene(0), + Self::Track(t) => Self::Scene(*t), + Self::Scene(s) => Self::Scene(last_scene.min(*s + 1)), + Self::Clip(t, s) => Self::Clip(*t, last_scene.min(*s + 1)), + } + } + pub fn scene_prev (&mut self) { + *self = match self { + Self::Mix => Self::Mix, + Self::Track(t) => Self::Track(*t), + Self::Scene(0) => Self::Mix, + Self::Scene(s) => Self::Scene(*s - 1), + Self::Clip(t, s) => Self::Clip(*t, s.saturating_sub(1)), + } + } +} diff --git a/src/view.rs b/src/view.rs index d8c33a25..bc8eafc4 100644 --- a/src/view.rs +++ b/src/view.rs @@ -9,7 +9,7 @@ submod! { render!(App |self, buf, area| { Split::down([ &self.transport, - &ArrangerView::new(&self, !self.arranger.mode), + &self.arranger, &If(self.arranger.selected.is_clip(), &Split::right([ &ChainView::vertical(&self), &SequencerView::new(&self), diff --git a/src/view/arranger.rs b/src/view/arranger.rs index 3880f3d9..12c5afc8 100644 --- a/src/view/arranger.rs +++ b/src/view/arranger.rs @@ -1,55 +1,25 @@ -use crate::core::*; -use crate::model::*; -use crate::view::*; +use crate::{core::*, model::*, view::*}; -pub struct ArrangerView<'a> { - scenes: &'a[Scene], - tracks: &'a[Track], - cursor: (usize, usize), - focused: bool, - entered: bool, - vertical: bool, -} - -impl<'a> ArrangerView<'a> { - pub fn new (app: &'a App, vertical: bool) -> Self { - Self { - vertical, - focused: app.section == AppFocus::Arranger, - entered: app.entered, - scenes: &app.arranger.scenes, - tracks: &app.arranger.tracks, - cursor: match app.arranger.selected { - ArrangerFocus::Mix => (0, 0), - ArrangerFocus::Scene(s) => (0, s + 1), - ArrangerFocus::Track(t) => (t + 1, 0), - ArrangerFocus::Clip(t, s) => (t + 1, s + 1), - }, - } +render!(Arranger |self, buf, area| { + let mut area = area; + area.height = area.height.min(1 + if self.mode { + self.tracks.len() as u16 * 2 + } else { + self.scenes.len() as u16 * 2 + }); + fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered)); + area = if self.mode { + self.draw_horizontal(buf, area) + } else { + self.draw_vertical(buf, area) + }?; + if self.focused && self.entered { + Corners(Style::default().green().not_dim()).draw(buf, area)?; } -} + Ok(area) +}); -impl<'a> Render for ArrangerView<'a> { - fn render (&self, buf: &mut Buffer, mut area: Rect) -> Usually { - area.height = area.height.min(1 + if self.vertical { - self.scenes.len() as u16 * 2 - } else { - self.tracks.len() as u16 * 2 - }); - fill_bg(buf, area, Nord::bg_lo(self.focused, self.entered)); - area = if self.vertical { - self.draw_vertical(buf, area) - } else { - self.draw_horizontal(buf, area) - }?; - if self.focused && self.entered { - Corners(Style::default().green().not_dim()).draw(buf, area)?; - } - Ok(area) - } -} - -impl<'a> ArrangerView<'a> { +impl Arranger { fn draw_vertical (&self, buf: &mut Buffer, area: Rect) -> Usually { @@ -62,10 +32,8 @@ impl<'a> ArrangerView<'a> { if y + 2 * scene_index as u16 >= height { break } - let style = Some(Nord::style_hi( - self.focused, - (0 == self.cursor.0) && (scene_index + 1 == self.cursor.1) - ).bold()); + let active = self.selected == ArrangerFocus::Scene(scene_index); + let style = Some(Nord::style_hi(self.focused, active).bold()); let y = 1 + y + 2 * scene_index as u16; let playing = scene.clips.iter().enumerate() .all(|(track_index, phrase_index)|match phrase_index { @@ -89,6 +57,7 @@ impl<'a> ArrangerView<'a> { } let width = 16u16; track.name.blit(buf, x, y, Some(Style::default().bold()))?; + let bg = Nord::bg_hi(self.focused, self.entered); for (scene_index, scene) in self.scenes.iter().enumerate() { if y + 2 * scene_index as u16 >= height { break @@ -102,22 +71,20 @@ impl<'a> ArrangerView<'a> { }, _ => format!("┊ ········") }; - let hi = (track_index + 1 == self.cursor.0) && (scene_index + 1 == self.cursor.1); + let hi = self.selected == ArrangerFocus::Clip(track_index, scene_index); let style = Some(Nord::style_hi(self.focused, hi)); let y = 1 + y + 2 * scene_index as u16; "┊".blit(buf, x, y + 1, style)?; label.blit(buf, x, y, style)?; - } - if track_index + 1 == self.cursor.0 { - let bg = Nord::bg_hi(self.focused, self.entered); - if self.cursor.1 == 0 { + if self.selected == ArrangerFocus::Clip(track_index, scene_index) { let y = area.y; fill_bg(buf, Rect { x, y, width, height: 1 }, bg) - } else { - let y = 1 + area.y + 2 * (self.cursor.1 as u16 - 1); - fill_bg(buf, Rect { x, y, width, height: 2 }, bg) } - }; + } + if self.selected == ArrangerFocus::Track(track_index) { + let y = 1 + area.y + 2 * track_index as u16; + fill_bg(buf, Rect { x, y, width, height: 2 }, bg) + } x = x + width as u16; } Ok(Rect { x: area.x, y, width: x - area.x, height }) @@ -144,10 +111,8 @@ impl<'a> ArrangerView<'a> { width = width.max( track.name.blit(buf, area.x + 1, area.y + y, style5)?.width ); - if self.cursor.0 > 0 { - if index == self.cursor.0 - 1 { - "".blit(buf, area.x, area.y + y, style3)?; - } + if self.selected == ArrangerFocus::Track(index) { + "".blit(buf, area.x, area.y + y, style3)?; } } else { area.height = y; @@ -271,7 +236,7 @@ impl<'a> ArrangerView<'a> { let mut x2 = 0; let Rect { x, y, height, .. } = area; for (i, scene) in self.scenes.iter().enumerate() { - let active_scene = self.cursor.1 > 0 && self.cursor.1 - 1 == i; + let active_scene = false;//self.selected == ArrangerFocus::Scene(i) || cursor.1 > 0 && self.cursor.1 - 1 == i; let sep = Some(if active_scene { Style::default().yellow().not_dim() } else { @@ -286,7 +251,7 @@ impl<'a> ArrangerView<'a> { let mut x3 = scene.name.len() as u16; scene.name.blit(buf, x + x2, y, Some(Style::default().bold().not_dim()))?; for (i, clip) in scene.clips.iter().enumerate() { - let active_track = self.cursor.0 > 0 && self.cursor.0 - 1 == i; + let active_track = false;//self.cursor.0 > 0 && self.cursor.0 - 1 == i; if let Some(clip) = clip { let y2 = y + 1 + i as u16 * 2; let label = format!("{}", if let Some(phrase) = self.tracks[i].phrases.get(*clip) {