arranger/sequencer control

This commit is contained in:
🪞👃🪞 2024-08-18 20:01:09 +03:00
parent a533951fc6
commit 52e9613d52
6 changed files with 243 additions and 209 deletions

View file

@ -46,6 +46,7 @@ submod! {
handle
render
render_split
render_border
time_base
time_note
time_tick

View file

@ -311,166 +311,6 @@ impl Theme for Nord {
const SEPARATOR: Color = Color::Rgb(0, 0, 0);
}
pub trait BorderStyle {
const NW: &'static str = "";
const N: &'static str = "";
const NE: &'static str = "";
const E: &'static str = "";
const SE: &'static str = "";
const S: &'static str = "";
const SW: &'static str = "";
const W: &'static str = "";
#[inline]
fn draw (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
self.draw_horizontal(buf, area, None)?;
self.draw_vertical(buf, area, None)?;
self.draw_corners(buf, area, None)?;
Ok(area)
}
#[inline]
fn draw_horizontal (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) -> Usually<Rect> {
let style = style.or_else(||self.style_horizontal());
for x in area.x..(area.x+area.width).saturating_sub(1) {
self.draw_north(buf, x, area.y, style)?;
self.draw_south(buf, x, (area.y + area.height).saturating_sub(1), style)?;
}
Ok(area)
}
#[inline]
fn draw_north (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect> {
Self::N.blit(buf, x, y, style)
}
#[inline]
fn draw_south (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect> {
Self::S.blit(buf, x, y, style)
}
#[inline]
fn draw_vertical (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) -> Usually<Rect> {
let style = style.or_else(||self.style_vertical());
for y in area.y..(area.y+area.height).saturating_sub(1) {
Self::W.blit(buf, area.x, y, style)?;
Self::E.blit(buf, area.x + area.width - 1, y, style)?;
}
Ok(area)
}
#[inline]
fn draw_corners (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) -> Usually<Rect> {
let style = style.or_else(||self.style_corners());
Self::NW.blit(buf, area.x, area.y, style)?;
Self::NE.blit(buf, area.x + area.width - 1, area.y, style)?;
Self::SW.blit(buf, area.x, area.y + area.height - 1, style)?;
Self::SE.blit(buf, area.x + area.width - 1, area.y + area.height - 1, style)?;
Ok(area)
}
#[inline]
fn style (&self) -> Option<Style> {
None
}
#[inline]
fn style_horizontal (&self) -> Option<Style> {
self.style()
}
#[inline]
fn style_vertical (&self) -> Option<Style> {
self.style()
}
#[inline]
fn style_corners (&self) -> Option<Style> {
self.style()
}
}
macro_rules! border {
($($T:ty {
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
$($x:tt)*
}),+) => {
$(impl BorderStyle for $T {
const NW: &'static str = $nw;
const N: &'static str = $n;
const NE: &'static str = $ne;
const W: &'static str = $w;
const E: &'static str = $e;
const SW: &'static str = $sw;
const S: &'static str = $s;
const SE: &'static str = $se;
$($x)*
})+
}
}
pub struct Lozenge(pub Style);
pub struct LozengeV(pub Style);
pub struct LozengeDotted(pub Style);
pub struct Quarter(pub Style);
pub struct QuarterV(pub Style);
pub struct Chamfer(pub Style);
pub struct Corners(pub Style);
border! {
Lozenge {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
LozengeV {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
LozengeDotted {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Quarter {
"" "" "🮇"
"" "🮇"
"" "" "🮇"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
QuarterV {
"" "" "🮇"
"" "🮇"
"" "" "🮇"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Chamfer {
"🭂" "" "🭍"
"" "🮇"
"🭓" "" "🭞"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Corners {
"🬆" "" "🬊" // 🬴 🬸
"" ""
"🬱" "" "🬵"
fn style (&self) -> Option<Style> {
Some(self.0)
}
}
}
macro_rules! impl_axis_common { ($A:ident $T:ty) => {
impl $A<$T> {
pub fn start_inc (&mut self) -> $T {

View file

@ -0,0 +1,163 @@
use crate::*;
pub trait BorderStyle {
const NW: &'static str = "";
const N: &'static str = "";
const NE: &'static str = "";
const E: &'static str = "";
const SE: &'static str = "";
const S: &'static str = "";
const SW: &'static str = "";
const W: &'static str = "";
#[inline]
fn draw (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
self.draw_horizontal(buf, area, None)?;
self.draw_vertical(buf, area, None)?;
self.draw_corners(buf, area, None)?;
Ok(area)
}
#[inline]
fn draw_horizontal (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) -> Usually<Rect> {
let style = style.or_else(||self.style_horizontal());
for x in area.x..(area.x+area.width).saturating_sub(1) {
self.draw_north(buf, x, area.y, style)?;
self.draw_south(buf, x, (area.y + area.height).saturating_sub(1), style)?;
}
Ok(area)
}
#[inline]
fn draw_north (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect> {
Self::N.blit(buf, x, y, style)
}
#[inline]
fn draw_south (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) -> Usually<Rect> {
Self::S.blit(buf, x, y, style)
}
#[inline]
fn draw_vertical (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) -> Usually<Rect> {
let style = style.or_else(||self.style_vertical());
for y in area.y..(area.y+area.height).saturating_sub(1) {
Self::W.blit(buf, area.x, y, style)?;
Self::E.blit(buf, area.x + area.width - 1, y, style)?;
}
Ok(area)
}
#[inline]
fn draw_corners (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) -> Usually<Rect> {
let style = style.or_else(||self.style_corners());
if area.width > 0 && area.height > 0 {
Self::NW.blit(buf, area.x, area.y, style)?;
Self::NE.blit(buf, area.x + area.width - 1, area.y, style)?;
Self::SW.blit(buf, area.x, area.y + area.height - 1, style)?;
Self::SE.blit(buf, area.x + area.width - 1, area.y + area.height - 1, style)?;
}
Ok(area)
}
#[inline]
fn style (&self) -> Option<Style> {
None
}
#[inline]
fn style_horizontal (&self) -> Option<Style> {
self.style()
}
#[inline]
fn style_vertical (&self) -> Option<Style> {
self.style()
}
#[inline]
fn style_corners (&self) -> Option<Style> {
self.style()
}
}
macro_rules! border {
($($T:ty {
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
$($x:tt)*
}),+) => {
$(impl BorderStyle for $T {
const NW: &'static str = $nw;
const N: &'static str = $n;
const NE: &'static str = $ne;
const W: &'static str = $w;
const E: &'static str = $e;
const SW: &'static str = $sw;
const S: &'static str = $s;
const SE: &'static str = $se;
$($x)*
})+
}
}
pub struct Lozenge(pub Style);
pub struct LozengeV(pub Style);
pub struct LozengeDotted(pub Style);
pub struct Quarter(pub Style);
pub struct QuarterV(pub Style);
pub struct Chamfer(pub Style);
pub struct Corners(pub Style);
border! {
Lozenge {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
LozengeV {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
LozengeDotted {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Quarter {
"" "" "🮇"
"" "🮇"
"" "" "🮇"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
QuarterV {
"" "" "🮇"
"" "🮇"
"" "" "🮇"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Chamfer {
"🭂" "" "🭍"
"" "🮇"
"🭓" "" "🭞"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Corners {
"🬆" "" "🬊" // 🬴 🬸
"" ""
"🬱" "" "🬵"
fn style (&self) -> Option<Style> {
Some(self.0)
}
}
}

View file

@ -6,63 +6,35 @@ use tek_core::Direction;
/// Represents the tracks and scenes of the composition.
pub struct Arranger {
/// Name of arranger
pub name: String,
pub name: String,
/// Display mode of arranger
pub mode: ArrangerViewMode,
pub mode: ArrangerViewMode,
/// Currently selected element.
pub selected: ArrangerFocus,
pub selected: ArrangerFocus,
/// Collection of tracks.
pub tracks: Vec<Sequencer>,
pub tracks: Vec<Sequencer>,
/// Collection of scenes.
pub scenes: Vec<Scene>,
pub focused: bool,
pub entered: bool,
pub transport: Option<Arc<RwLock<TransportToolbar>>>,
pub show_sequencer: Option<Direction>
pub scenes: Vec<Scene>,
pub focused: bool,
pub entered: bool,
pub transport: Option<Arc<RwLock<TransportToolbar>>>,
pub show_sequencer: Option<Direction>,
pub focus_sequencer: bool,
}
render!(Arranger |self, buf, area| {
let arrangement = |buf, area| match self.mode {
ArrangerViewMode::Horizontal =>
super::arranger_view_h::draw(self, buf, area),
ArrangerViewMode::VerticalCompact1 =>
super::arranger_view_v::draw_compact_1(self, buf, area),
ArrangerViewMode::VerticalCompact2 =>
super::arranger_view_v::draw_compact_2(self, buf, area),
ArrangerViewMode::VerticalExpanded =>
super::arranger_view_v::draw_expanded(self, buf, area),
};
if let Some(direction) = self.show_sequencer {
let used = arrangement(buf, area)?;
match direction {
Direction::Down => {
let area = Rect {
y: area.y + used.height,
height: area.height - used.height,
..area
};
self.sequencer().map(|sequencer|sequencer.render(buf, area));
},
_ => unimplemented!()
}
Ok(area)
} else {
arrangement(buf, area)
}
});
impl Arranger {
pub fn new (name: &str) -> Self {
Self {
name: name.into(),
mode: ArrangerViewMode::VerticalCompact2,
selected: ArrangerFocus::Clip(0, 0),
scenes: vec![],
tracks: vec![],
entered: true,
focused: true,
transport: None,
show_sequencer: Some(Direction::Down),
name: name.into(),
mode: ArrangerViewMode::VerticalCompact2,
selected: ArrangerFocus::Clip(0, 0),
scenes: vec![],
tracks: vec![],
entered: true,
focused: true,
transport: None,
show_sequencer: Some(Direction::Down),
focus_sequencer: false,
}
}
pub fn activate (&mut self) {

View file

@ -1,6 +1,24 @@
use crate::*;
handle!(Arranger |self, e| handle_keymap(self, e, KEYMAP_ARRANGER));
handle!(Arranger |self, e| {
match e {
AppEvent::Input(Event::Key(k)) => {
if k.code == KeyCode::Tab {
self.focus_sequencer = !self.focus_sequencer;
Ok(true)
} else if self.focus_sequencer {
if let Some(sequencer) = self.sequencer_mut() {
handle_keymap(sequencer, e, KEYMAP_SEQUENCER)
} else {
Ok(false)
}
} else {
handle_keymap(self, e, KEYMAP_ARRANGER)
}
},
_ => Ok(false),
}
});
/// Key bindings for arranger section.
pub const KEYMAP_ARRANGER: &'static [KeyBinding<Arranger>] = keymap!(Arranger {

View file

@ -1,3 +1,6 @@
use crate::*;
use tek_core::Direction;
/// Display mode of arranger
pub enum ArrangerViewMode {
VerticalExpanded,
@ -16,3 +19,40 @@ impl ArrangerViewMode {
}
}
}
render!(Arranger |self, buf, area| {
let arrangement = |buf, area| match self.mode {
ArrangerViewMode::Horizontal =>
super::arranger_view_h::draw(self, buf, area),
ArrangerViewMode::VerticalCompact1 =>
super::arranger_view_v::draw_compact_1(self, buf, area),
ArrangerViewMode::VerticalCompact2 =>
super::arranger_view_v::draw_compact_2(self, buf, area),
ArrangerViewMode::VerticalExpanded =>
super::arranger_view_v::draw_expanded(self, buf, area),
};
if let Some(direction) = self.show_sequencer {
let arrangement = arrangement(buf, area)?;
match direction {
Direction::Down => {
let sequencer = if let Some(sequencer) = self.sequencer() {
sequencer.render(buf, Rect {
y: area.y + arrangement.height,
height: area.height - arrangement.height,
..area
})?
} else {
Rect::default()
};
Corners(Style::default().green().not_dim()).draw(buf, match self.focus_sequencer {
true => sequencer,
false => arrangement,
})?;
},
_ => unimplemented!()
}
Ok(area)
} else {
arrangement(buf, area)
}
});