pub mod chain; pub mod arranger; pub mod layout; pub mod sampler; pub mod sequencer; pub mod transport; pub mod plugin; pub mod border; pub use self::border::*; pub use self::layout::*; pub use self::transport::TransportView; pub use self::arranger::*; pub use self::chain::ChainView; pub use self::sequencer::SequencerView; use crate::{render, App, core::*}; render!(App |self, buf, area| { Split::down([ &TransportView::new(self), &Split::down([ &ArrangerView::new(&self, !self.arranger_mode), &If(self.track_cursor > 0, &Split::right([ &ChainView::vertical(&self), &SequencerView::new(&self), ])) ]) ]).render(buf, area)?; if let Some(ref modal) = self.modal { modal.render(buf, area)?; } Ok(area) }); pub struct If<'a>(pub bool, pub &'a (dyn Render + Sync)); impl<'a> Render for If<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { if self.0 { self.1.render(buf, area) } else { ().render(buf, area) } } } pub enum Direction { Down, Right, } pub struct Split<'a, const N: usize>(pub Direction, pub [&'a (dyn Render + Sync);N]); impl<'a, const N: usize> Split<'a, N> { pub fn down (items: [&'a (dyn Render + Sync);N]) -> Self { Self(Direction::Down, items) } pub fn right (items: [&'a (dyn Render + Sync);N]) -> Self { Self(Direction::Right, items) } } impl<'a, const N: usize> Render for Split<'a, N> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Rect { mut x, mut y, mut width, mut height } = area; for item in self.1 { if width == 0 || height == 0 { break } let result = item.render(buf, Rect { x, y, width, height })?; match self.0 { Direction::Down => { y = y + result.height; height = height.saturating_sub(result.height); }, Direction::Right => { x = x + result.width; width = width.saturating_sub(result.width); }, } } Ok(area) } }