mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
521 lines
23 KiB
Rust
521 lines
23 KiB
Rust
use crate::*;
|
|
pub(crate) const HEADER_H: u16 = 0; // 5
|
|
pub(crate) const SCENES_W_OFFSET: u16 = 0;
|
|
render!(TuiOut: (self: Arranger) => {
|
|
let toolbar = |x|Bsp::s(self.toolbar_view(), x);
|
|
let pool = |x|Bsp::w(self.pool_view(), x);
|
|
let editing = |x|Bsp::n(Bsp::e(self.editor.clip_status(), self.editor.edit_status()), x);
|
|
let enclosed = |x|Outer(Style::default().fg(Color::Rgb(72,72,72))).enclose(x);
|
|
let scenes_w = 16;//.max(SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16);
|
|
let arrrrrr = Fixed::y(27, Map::new(
|
|
move||[
|
|
(0, 2, self.output_row_header(), self.output_row_cells()),
|
|
(2, 3, self.elapsed_row_header(), self.elapsed_row_cells()),
|
|
(4, 3, self.next_row_header(), self.next_row_cells()),
|
|
(6, 3, self.track_row_header(), self.track_row_cells()),
|
|
(8, 20, self.scene_row_headers(), self.scene_row_cells()),
|
|
(25, 2, self.input_row_header(), self.input_row_cells()),
|
|
].into_iter(),
|
|
move|(y, h, header, cells), index|map_south(y, h, Fill::x(Align::w(Bsp::e(
|
|
Fixed::xy(scenes_w, h, header),
|
|
Fixed::xy(self.tracks.len() as u16*6, h, cells)
|
|
))))));
|
|
|
|
self.size.of(toolbar(pool(editing(Bsp::s(arrrrrr, enclosed(&self.editor))))))
|
|
|
|
});
|
|
impl Arranger {
|
|
pub const LEFT_SEP: char = '▎';
|
|
pub const TRACK_MIN_WIDTH: usize = 4;
|
|
|
|
/// A 1-row cell.
|
|
fn cell <T: Content<TuiOut>> (color: ItemPalette, field: T) -> impl Content<TuiOut> {
|
|
Tui::fg_bg(color.lightest.rgb, color.base.rgb, Fixed::y(1, field))
|
|
}
|
|
|
|
/// A phat line
|
|
fn phat_lo (fg: Color, bg: Color) -> impl Content<TuiOut> {
|
|
Fixed::y(1, Tui::fg_bg(fg, bg, RepeatH(&"▄")))
|
|
}
|
|
|
|
fn phat_hi (fg: Color, bg: Color) -> impl Content<TuiOut> {
|
|
Fixed::y(1, Tui::fg_bg(fg, bg, RepeatH(&"▀")))
|
|
}
|
|
|
|
/// A cell that is 3-row on its own, but stacks, giving (N+1)*2 rows per N cells.
|
|
fn phat_cell <T: Content<TuiOut>> (color: ItemPalette, last: ItemPalette, field: T) -> impl Content<TuiOut> {
|
|
Bsp::s(
|
|
Self::phat_lo(color.base.rgb, last.base.rgb),
|
|
Bsp::n(
|
|
Self::phat_hi(color.base.rgb, last.base.rgb),
|
|
Fixed::y(1, Fill::x(Tui::fg_bg(color.lightest.rgb, color.base.rgb, field))),
|
|
)
|
|
)
|
|
}
|
|
|
|
fn phat_cell_3 <T: Content<TuiOut>> (top: Color, middle: Color, bottom: Color, field: T) -> impl Content<TuiOut> {
|
|
Bsp::s(
|
|
Self::phat_lo(middle, top),
|
|
Bsp::n(
|
|
Self::phat_hi(bottom, middle),
|
|
Fixed::y(1, Fill::x(Tui::bg(middle, field))),
|
|
)
|
|
)
|
|
}
|
|
|
|
fn output_row_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(||Tui::bold(true, Tui::fg_bg(TuiTheme::g(0), TuiTheme::g(200), "[ ] Out 1: NI")).boxed()).into()
|
|
}
|
|
fn output_row_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
//let scenes_w = 16;//.max(SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16);
|
|
(move||Fixed::y(2, Map::new(||self.tracks_with_widths(), move|(_, track, x1, x2), i| {
|
|
let w = (x2 - x1) as u16;
|
|
let color: ItemPalette = track.color().dark.into();
|
|
let cell = Bsp::s(format!(" M S "), Self::phat_hi(color.dark.rgb, color.darker.rgb));
|
|
map_east(x1 as u16, w, Fixed::x(w, Self::cell(color, cell)))
|
|
})).boxed()).into()
|
|
}
|
|
|
|
fn elapsed_row_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(||Tui::bold(true, Tui::fg(TuiTheme::g(128), "Playing")).boxed()).into()
|
|
}
|
|
fn elapsed_row_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(move||Fixed::y(2, Map::new(||self.tracks_with_widths(), move|(_, track, x1, x2), i| {
|
|
//let color = track.color();
|
|
let color: ItemPalette = track.color().dark.into();
|
|
let timebase = self.clock().timebase();
|
|
let value = Tui::fg_bg(color.lightest.rgb, color.base.rgb,
|
|
if let Some((_, Some(phrase))) = track.player.play_phrase().as_ref() {
|
|
let length = phrase.read().unwrap().length;
|
|
let elapsed = track.player.pulses_since_start().unwrap() as usize;
|
|
format!("+{:>}", timebase.format_beats_1_short((elapsed % length) as f64))
|
|
} else {
|
|
String::new()
|
|
});
|
|
let cell = Bsp::s(value, Self::phat_hi(color.dark.rgb, color.darker.rgb));
|
|
Tui::bg(color.base.rgb, map_east(x1 as u16, (x2 - x1) as u16, cell))
|
|
})).boxed()).into()
|
|
}
|
|
|
|
fn next_row_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(||Tui::bold(true, Tui::fg(TuiTheme::g(128), "Next")).boxed()).into()
|
|
}
|
|
fn next_row_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(move||Fixed::y(2, Map::new(||self.tracks_with_widths(), move|(_, track, x1, x2), i| {
|
|
let color: ItemPalette = track.color();
|
|
let color: ItemPalette = track.color().dark.into();
|
|
let until_next = Self::cell(color, Tui::bold(true, Self::cell_until_next(track, &self.clock().playhead)));
|
|
let value = Tui::fg_bg(color.lightest.rgb, color.base.rgb, until_next);
|
|
let cell = Bsp::s(value, Self::phat_hi(color.dark.rgb, color.darker.rgb));
|
|
Tui::bg(color.base.rgb, map_east(x1 as u16, (x2 - x1) as u16, cell))
|
|
})).boxed()).into()
|
|
}
|
|
|
|
fn track_row_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(||Tui::bold(true, Tui::fg(TuiTheme::g(128), "Track")).boxed()).into()
|
|
}
|
|
fn track_row_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
let iter = ||self.tracks_with_widths();
|
|
(move||Fixed::y(2, Map::new(iter, move|(_, track, x1, x2), i| {
|
|
let color = track.color();
|
|
let name = format!(" {}", &track.name);
|
|
Tui::bg(color.base.rgb, map_east(x1 as u16, (x2 - x1) as u16,
|
|
Tui::fg_bg(color.lightest.rgb, color.base.rgb,
|
|
Self::phat_cell(color, color.darkest.rgb.into(),
|
|
Tui::bold(true, name))))) })).boxed()).into()
|
|
}
|
|
|
|
fn input_row_header <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(||Fill::x(Tui::bold(true, Tui::fg_bg(TuiTheme::g(0), TuiTheme::g(200), "[ ] In 1: Korg"))).boxed()).into()
|
|
}
|
|
fn input_row_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(move||Fixed::y(2, Map::new(||self.tracks_with_widths(), move|(_, track, x1, x2), i| {
|
|
let w = (x2 - x1) as u16;
|
|
let cell = Bsp::s("[Rec]", "[Mon]");
|
|
let color: ItemPalette = track.color().dark.into();
|
|
map_east(x1 as u16, w, Fixed::x(w, Self::cell(color, cell)))
|
|
})).boxed()).into()
|
|
}
|
|
|
|
fn scene_row_headers <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(||{
|
|
let scenes_w = 16;//.max(SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16);
|
|
let last_color = Arc::new(RwLock::new(ItemPalette::from(Color::Rgb(0, 0, 0))));
|
|
Tui::bg(Color::Rgb(0,0,0), Fill::y(Map::new(
|
|
||self.scenes_with_heights(2),
|
|
move|(_, scene, y1, y2), i| {
|
|
let h = (y2 - y1) as u16;
|
|
let color = scene.color();
|
|
let name = format!("🭬{}", &scene.name);
|
|
let cell = Self::phat_cell(color, *last_color.read().unwrap(), name);
|
|
*last_color.write().unwrap() = color;
|
|
map_south(y1 as u16, 2, Fill::x(cell))
|
|
}
|
|
))).boxed()
|
|
}).into()
|
|
}
|
|
fn scene_row_cells <'a> (&'a self) -> BoxThunk<'a, TuiOut> {
|
|
(move||Fixed::y(2, Map::new(||self.tracks_with_widths(), move|(_, track, x1, x2), i| {
|
|
let w = (x2 - x1) as u16;
|
|
let cell = Bsp::s("[Rec]", "[Mon]");
|
|
let color: ItemPalette = track.color().dark.into();
|
|
let last_color = Arc::new(RwLock::new(ItemPalette::from(Color::Rgb(0, 0, 0))));
|
|
map_east(x1 as u16, w, Fixed::x(w, Tui::bg(Color::Rgb(0,0,0), Fill::y(Map::new(
|
|
||self.scenes_with_heights(2),
|
|
move|(_, scene, y1, y2), i| {
|
|
let h = (y2 - y1) as u16;
|
|
let color = scene.color();
|
|
let name = format!("🭬{}", &scene.name);
|
|
//*last_color.write().unwrap() = color
|
|
map_south(y1 as u16, 2, Fill::x(Self::phat_cell_3(
|
|
TuiTheme::g(32).into(),
|
|
TuiTheme::g(32).into(),
|
|
TuiTheme::g(32).into(),
|
|
//Tui::fg(TuiTheme::g(64), " ⏺ ")
|
|
Tui::fg(TuiTheme::g(64), " ⏹ ")
|
|
)))
|
|
}
|
|
))).boxed()
|
|
))
|
|
})).boxed()).into()
|
|
}
|
|
|
|
pub fn tracks_with_widths (&self)
|
|
-> impl Iterator<Item = (usize, &ArrangerTrack, usize, usize)>
|
|
{
|
|
Self::tracks_with_widths_static(self.tracks.as_slice())
|
|
}
|
|
fn tracks_with_widths_static (tracks: &[ArrangerTrack])
|
|
-> impl Iterator<Item = (usize, &ArrangerTrack, usize, usize)>
|
|
{
|
|
let mut x = 0;
|
|
tracks.iter().enumerate().map(move |(index, track)|{
|
|
let data = (index, track, x, x + track.width);
|
|
x += track.width;
|
|
data
|
|
})
|
|
}
|
|
fn track_column_separators <'a> (&'a self) -> impl Content<TuiOut> + 'a {
|
|
let scenes_w = 16;//.max(SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16);
|
|
let fg = Color::Rgb(64,64,64);
|
|
Map::new(move||self.tracks_with_widths(), move|(_n, _track, x1, x2), _i|{
|
|
Push::x(scenes_w, map_east(x1 as u16, (x2 - x1) as u16,
|
|
Fixed::x((x2 - x1) as u16, Tui::fg(fg, RepeatV(&"·")))))
|
|
})
|
|
}
|
|
/// name and width of track
|
|
fn cell_name (track: &ArrangerTrack, _w: usize) -> impl Content<TuiOut> {
|
|
Tui::bold(true, Tui::fg(track.color.lightest.rgb, track.name().clone()))
|
|
}
|
|
/// beats until switchover
|
|
fn cell_until_next (track: &ArrangerTrack, current: &Arc<Moment>)
|
|
-> Option<impl Content<TuiOut>>
|
|
{
|
|
let timebase = ¤t.timebase;
|
|
let mut result = String::new();
|
|
if let Some((t, _)) = track.player.next_phrase().as_ref() {
|
|
let target = t.pulse.get();
|
|
let current = current.pulse.get();
|
|
if target > current {
|
|
result = format!("-{:>}", timebase.format_beats_0_short(target - current))
|
|
}
|
|
}
|
|
Some(result)
|
|
}
|
|
|
|
pub fn scenes_with_heights (&self, h: usize) -> impl Iterator<Item = (usize, &ArrangerScene, usize, usize)> {
|
|
let mut y = 0;
|
|
self.scenes.iter().enumerate().map(move|(index, scene)|{
|
|
let data = (index, scene, y, y + h);
|
|
y += h;
|
|
data
|
|
})
|
|
}
|
|
fn scene_rows (&self) -> impl Content<TuiOut> + use<'_> {
|
|
let scenes_w = 16.max(SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16);
|
|
Map::new(||self.scenes_with_heights(1), move|(_, scene, y1, y2), i| {
|
|
let h = (y2 - y1) as u16;
|
|
let color = scene.color();
|
|
let cell = Fixed::y(h, Fixed::x(scenes_w, Self::cell(color, scene.name.clone())));
|
|
map_south(y1 as u16, 1, cell)
|
|
})
|
|
}
|
|
pub fn scene_heights (scenes: &[ArrangerScene], factor: usize) -> Vec<(usize, usize)> {
|
|
let mut total = 0;
|
|
if factor == 0 {
|
|
scenes.iter().map(|scene|{
|
|
let pulses = scene.pulses().max(PPQ);
|
|
total += pulses;
|
|
(pulses, total - pulses)
|
|
}).collect()
|
|
} else {
|
|
(0..=scenes.len()).map(|i|{
|
|
(factor*PPQ, factor*PPQ*i)
|
|
}).collect()
|
|
}
|
|
}
|
|
|
|
fn cell_scene <'a> (
|
|
tracks: &'a [ArrangerTrack], scene: &'a ArrangerScene, pulses: usize
|
|
) -> impl Content<TuiOut> + use<'a> {
|
|
let height = 1.max((pulses / PPQ) as u16);
|
|
let playing = scene.is_playing(tracks);
|
|
let icon = Tui::bg(
|
|
scene.color.base.rgb, if playing { "▶ " } else { " " }
|
|
);
|
|
let name = Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb,
|
|
Expand::x(1, Tui::bold(true, scene.name.clone()))
|
|
);
|
|
let clips = Map::new(||Arranger::tracks_with_widths_static(tracks), move|(index, track, x1, x2), _|
|
|
Push::x((x2 - x1) as u16, Self::cell_clip(scene, index, track, (x2 - x1) as u16, height))
|
|
);
|
|
Fixed::y(height, Bsp::e(icon, Bsp::e(name, clips)))
|
|
}
|
|
|
|
fn cell_clip <'a> (
|
|
scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16
|
|
) -> impl Content<TuiOut> + use<'a> {
|
|
scene.clips.get(index).map(|clip|clip.as_ref().map(|phrase|{
|
|
let phrase = phrase.read().unwrap();
|
|
let mut bg = TuiTheme::border_bg();
|
|
let name = phrase.name.to_string();
|
|
let max_w = name.len().min((w as usize).saturating_sub(2));
|
|
let color = phrase.color;
|
|
bg = color.dark.rgb;
|
|
if let Some((_, Some(ref playing))) = track.player.play_phrase() {
|
|
if *playing.read().unwrap() == *phrase {
|
|
bg = color.light.rgb
|
|
}
|
|
};
|
|
Fixed::xy(w, h, &Tui::bg(bg, Push::x(1, Fixed::x(w, &name.as_str()[0..max_w]))));
|
|
}))
|
|
}
|
|
fn toolbar_view (&self) -> impl Content<TuiOut> + use<'_> {
|
|
Fill::x(Fixed::y(2, Align::x(TransportView::new(true, &self.clock))))
|
|
}
|
|
fn pool_view (&self) -> impl Content<TuiOut> + use<'_> {
|
|
let w = self.size.w();
|
|
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
|
|
let pool_w = if self.pool.visible { phrase_w } else { 0 };
|
|
let pool = Pull::y(1, Fill::y(Align::e(PoolView(self.pool.visible, &self.pool))));
|
|
Fixed::x(pool_w, Align::e(Fill::y(PoolView(self.compact, &self.pool))))
|
|
}
|
|
|
|
pub fn track_widths (tracks: &[ArrangerTrack]) -> Vec<(usize, usize)> {
|
|
let mut widths = vec![];
|
|
let mut total = 0;
|
|
for track in tracks.iter() {
|
|
let width = track.width;
|
|
widths.push((width, total));
|
|
total += width;
|
|
}
|
|
widths.push((0, total));
|
|
widths
|
|
}
|
|
|
|
fn scene_row_sep <'a> (&'a self) -> impl Content<TuiOut> + 'a {
|
|
let fg = Color::Rgb(255,255,255);
|
|
Map::new(move||self.scenes_with_heights(1), |_, _|"")
|
|
//Map(||rows.iter(), |(_n, _scene, y1, _y2), _i| {
|
|
//let y = to.area().y() + (y / PPQ) as u16 + 1;
|
|
//if y >= to.buffer.area.height { break }
|
|
//for x in to.area().x()..to.area().x2().saturating_sub(2) {
|
|
////if x < to.buffer.area.x && y < to.buffer.area.y {
|
|
//if let Some(cell) = to.buffer.cell_mut(ratatui::prelude::Position::from((x, y))) {
|
|
//cell.modifier = Modifier::UNDERLINED;
|
|
//cell.underline_color = fg;
|
|
//}
|
|
////}
|
|
//}
|
|
//})
|
|
}
|
|
|
|
fn cursor (&self) -> impl Content<TuiOut> + '_ {
|
|
let color = self.color;
|
|
let bg = color.lighter.rgb;//Color::Rgb(0, 255, 0);
|
|
let selected = self.selected();
|
|
let cols = Arranger::track_widths(&self.tracks);
|
|
let rows = Arranger::scene_heights(&self.scenes, 1);
|
|
let scenes_w = 16.max(SCENES_W_OFFSET + ArrangerScene::longest_name(&self.scenes) as u16);
|
|
let focused = true;
|
|
let reticle = Reticle(Style {
|
|
fg: Some(self.color.lighter.rgb),
|
|
bg: None,
|
|
underline_color: None,
|
|
add_modifier: Modifier::empty(),
|
|
sub_modifier: Modifier::DIM
|
|
});
|
|
RenderThunk::new(move|to: &mut TuiOut|{
|
|
let area = to.area();
|
|
let [x, y, w, h] = area.xywh();
|
|
let mut track_area: Option<[u16;4]> = match selected {
|
|
ArrangerSelection::Track(t) | ArrangerSelection::Clip(t, _) => Some([
|
|
x + scenes_w + cols[t].1 as u16, y,
|
|
cols[t].0 as u16, h,
|
|
]),
|
|
_ => None
|
|
};
|
|
let mut scene_area: Option<[u16;4]> = match selected {
|
|
ArrangerSelection::Scene(s) | ArrangerSelection::Clip(_, s) => Some([
|
|
x, y + HEADER_H + (rows[s].1 / PPQ) as u16,
|
|
w, (rows[s].0 / PPQ) as u16
|
|
]),
|
|
_ => None
|
|
};
|
|
let mut clip_area: Option<[u16;4]> = match selected {
|
|
ArrangerSelection::Clip(t, s) => Some([
|
|
(scenes_w + x + cols[t].1 as u16).saturating_sub(1),
|
|
HEADER_H + y + (rows[s].1/PPQ) as u16,
|
|
cols[t].0 as u16 + 2,
|
|
(rows[s].0 / PPQ) as u16
|
|
]),
|
|
_ => None
|
|
};
|
|
if let Some([x, y, width, height]) = track_area {
|
|
to.fill_fg([x, y, 1, height], bg);
|
|
to.fill_fg([x + width, y, 1, height], bg);
|
|
}
|
|
if let Some([_, y, _, height]) = scene_area {
|
|
to.fill_ul([x, y - 1, w, 1], bg);
|
|
to.fill_ul([x, y + height - 1, w, 1], bg);
|
|
}
|
|
if focused {
|
|
to.place(if let Some(clip_area) = clip_area {
|
|
clip_area
|
|
} else if let Some(track_area) = track_area {
|
|
track_area.clip_h(HEADER_H)
|
|
} else if let Some(scene_area) = scene_area {
|
|
scene_area.clip_w(scenes_w)
|
|
} else {
|
|
area.clip_w(scenes_w).clip_h(HEADER_H)
|
|
}, &reticle)
|
|
};
|
|
})
|
|
}
|
|
}
|
|
|
|
//pub struct ArrangerVCursor {
|
|
//cols: Vec<(usize, usize)>,
|
|
//rows: Vec<(usize, usize)>,
|
|
//color: ItemPalette,
|
|
//reticle: Reticle,
|
|
//selected: ArrangerSelection,
|
|
//scenes_w: u16,
|
|
//}
|
|
|
|
//from!(|args:(&Arranger, usize)|ArrangerVCursor = Self {
|
|
//cols: Arranger::track_widths(&args.0.tracks),
|
|
//rows: Arranger::scene_heights(&args.0.scenes, args.1),
|
|
//selected: args.0.selected(),
|
|
//scenes_w: SCENES_W_OFFSET + ArrangerScene::longest_name(&args.0.scenes) as u16,
|
|
//color: args.0.color,
|
|
//reticle: Reticle(Style {
|
|
//fg: Some(args.0.color.lighter.rgb),
|
|
//bg: None,
|
|
//underline_color: None,
|
|
//add_modifier: Modifier::empty(),
|
|
//sub_modifier: Modifier::DIM
|
|
//}),
|
|
//});
|
|
//impl Content<TuiOut> for ArrangerVCursor {
|
|
//fn render (&self, to: &mut TuiOut) {
|
|
//let area = to.area();
|
|
//let focused = true;
|
|
//let selected = self.selected;
|
|
//let get_track_area = |t: usize| [
|
|
//self.scenes_w + area.x() + self.cols[t].1 as u16, area.y(),
|
|
//self.cols[t].0 as u16, area.h(),
|
|
//];
|
|
//let get_scene_area = |s: usize| [
|
|
//area.x(), HEADER_H + area.y() + (self.rows[s].1 / PPQ) as u16,
|
|
//area.w(), (self.rows[s].0 / PPQ) as u16
|
|
//];
|
|
//let get_clip_area = |t: usize, s: usize| [
|
|
//(self.scenes_w + area.x() + self.cols[t].1 as u16).saturating_sub(1),
|
|
//HEADER_H + area.y() + (self.rows[s].1/PPQ) as u16,
|
|
//self.cols[t].0 as u16 + 2,
|
|
//(self.rows[s].0 / PPQ) as u16
|
|
//];
|
|
//let mut track_area: Option<[u16;4]> = None;
|
|
//let mut scene_area: Option<[u16;4]> = None;
|
|
//let mut clip_area: Option<[u16;4]> = None;
|
|
//let area = match selected {
|
|
//ArrangerSelection::Mix => area,
|
|
//ArrangerSelection::Track(t) => {
|
|
//track_area = Some(get_track_area(t));
|
|
//area
|
|
//},
|
|
//ArrangerSelection::Scene(s) => {
|
|
//scene_area = Some(get_scene_area(s));
|
|
//area
|
|
//},
|
|
//ArrangerSelection::Clip(t, s) => {
|
|
//track_area = Some(get_track_area(t));
|
|
//scene_area = Some(get_scene_area(s));
|
|
//clip_area = Some(get_clip_area(t, s));
|
|
//area
|
|
//},
|
|
//};
|
|
//let bg = self.color.lighter.rgb;//Color::Rgb(0, 255, 0);
|
|
//if let Some([x, y, width, height]) = track_area {
|
|
//to.fill_fg([x, y, 1, height], bg);
|
|
//to.fill_fg([x + width, y, 1, height], bg);
|
|
//}
|
|
//if let Some([_, y, _, height]) = scene_area {
|
|
//to.fill_ul([area.x(), y - 1, area.w(), 1], bg);
|
|
//to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg);
|
|
//}
|
|
//if focused {
|
|
//to.place(if let Some(clip_area) = clip_area {
|
|
//clip_area
|
|
//} else if let Some(track_area) = track_area {
|
|
//track_area.clip_h(HEADER_H)
|
|
//} else if let Some(scene_area) = scene_area {
|
|
//scene_area.clip_w(self.scenes_w)
|
|
//} else {
|
|
//area.clip_w(self.scenes_w).clip_h(HEADER_H)
|
|
//}, &self.reticle)
|
|
//};
|
|
//}
|
|
//}
|
|
//impl Arranger {
|
|
//fn render_mode (state: &Self) -> impl Content<TuiOut> + use<'_> {
|
|
//match state.mode {
|
|
//ArrangerMode::H => todo!("horizontal arranger"),
|
|
//ArrangerMode::V(factor) => Self::render_mode_v(state, factor),
|
|
//}
|
|
//}
|
|
//}
|
|
//render!(TuiOut: (self: Arranger) => {
|
|
//let pool_w = if self.pool.visible { self.splits[1] } else { 0 };
|
|
//let color = self.color;
|
|
//let layout = Bsp::a(Fill::xy(ArrangerStatus::from(self)),
|
|
//Bsp::n(Fixed::x(pool_w, PoolView(self.pool.visible, &self.pool)),
|
|
//Bsp::n(TransportView::new(true, &self.clock),
|
|
//Bsp::s(Fixed::y(1, MidiEditStatus(&self.editor)),
|
|
//Bsp::n(Fill::x(Fixed::y(20,
|
|
//Bsp::a(Fill::xy(Tui::bg(color.darkest.rgb, "background")),
|
|
//Bsp::a(
|
|
//Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))),
|
|
//Self::render_mode(self))))), Fill::y(&"fixme: self.editor"))))));
|
|
//self.size.of(layout)
|
|
//});
|
|
//Align::n(Fill::xy(lay!(
|
|
//Align::n(Fill::xy(Tui::bg(self.color.darkest.rgb, " "))),
|
|
//Align::n(Fill::xy(ArrangerVRowSep::from((self, 1)))),
|
|
//Align::n(Fill::xy(ArrangerVColSep::from(self))),
|
|
//Align::n(Fill::xy(ArrangerVClips::new(self, 1))),
|
|
//Align::n(Fill::xy(ArrangerVCursor::from((self, 1))))))))))))))));
|
|
//Align::n(Fill::xy(":")))))))))))));
|
|
//"todo:"))))))));
|
|
//Bsp::s(
|
|
//Align::n(Fixed::y(1, Fill::x(ArrangerVIns::from(self)))),
|
|
//Bsp::s(
|
|
//Fixed::y(20, Align::n(ArrangerVClips::new(self, 1))),
|
|
//Fill::x(Fixed::y(1, ArrangerVOuts::from(self)))))))))))));
|
|
//Bsp::s(
|
|
//Bsp::s(
|
|
//Bsp::s(
|
|
//Fill::xy(ArrangerVClips::new(self, 1)),
|
|
//Fill::x(ArrangerVOuts::from(self)))))
|
|
|