use crate::*; /// Draw arranger with 1 row per scene. pub fn draw_compact_1 (state: &Arranger, buf: &mut Buffer, area: Rect) -> Usually { let track_cols = track_clip_name_lengths(state.tracks.as_slice()); let scene_rows = (0..=state.scenes.len()).map(|i|(96, 96*i)).collect::>(); draw(state, buf, area, track_cols.as_slice(), scene_rows.as_slice()) } /// Draw arranger with 2 rows per scene. pub fn draw_compact_2 (state: &Arranger, buf: &mut Buffer, area: Rect) -> Usually { let track_cols = track_clip_name_lengths(state.tracks.as_slice()); let scene_rows = (0..=state.scenes.len()).map(|i|(192, 192*i)).collect::>(); draw(state, buf, area, track_cols.as_slice(), scene_rows.as_slice()) } /// Draw arranger with number of rows per scene corresponding to duration of scene. pub fn draw_expanded (state: &Arranger, buf: &mut Buffer, area: Rect) -> Usually { let track_cols = track_clip_name_lengths(state.tracks.as_slice()); let scene_rows = scene_ppqs(state.tracks.as_slice(), state.scenes.as_slice()); draw(state, buf, area, track_cols.as_slice(), scene_rows.as_slice()) } pub fn draw ( state: &Arranger, buf: &mut Buffer, mut area: Rect, cols: &[(usize, usize)], rows: &[(usize, usize)], ) -> Usually { area.height = 2 + (rows[rows.len() - 1].1 / 96) as u16; let offset = 3 + scene_name_max_len(state.scenes.as_ref()) as u16; let Arranger { focus_sequencer, focused, entered, selected, .. } = *state; let tracks = state.tracks.as_ref(); let scenes = state.scenes.as_ref(); Layered::new() .add(FillBg(Nord::bg_lo(state.focused, state.entered))) .add(ColumnSeparators(offset, cols)) .add(CursorFocus(focus_sequencer, focused, entered, selected, offset, cols, rows)) .add(Split::down() .add(TracksHeader(offset, cols, tracks)) .add(SceneRows(offset, cols, rows, tracks, scenes))) .add(RowSeparators(rows)) .render(buf, area) } struct ColumnSeparators<'a>(u16, &'a [(usize, usize)]); impl<'a> Render for ColumnSeparators<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Self(offset, cols) = self; let style = Some(Style::default().fg(Nord::SEPARATOR)); for (_, x) in cols.iter() { let x = offset + area.x + *x as u16 - 1; for y in area.y..area.height+area.y { "▎".blit(buf, x, y, style)?; } } Ok(area) } } struct RowSeparators<'a>(&'a [(usize, usize)]); impl<'a> Render for RowSeparators<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Self(rows) = self; for (_, y) in rows.iter() { let y = area.y + (*y / 96) as u16 + 1; if y >= buf.area.height { break } for x in area.x..area.width+area.y-2 { let cell = buf.get_mut(x, y); cell.modifier = Modifier::UNDERLINED; cell.underline_color = Nord::SEPARATOR; } } Ok(area) } } struct CursorFocus<'a>( bool, bool, bool, ArrangerFocus, u16, &'a [(usize, usize)], &'a [(usize, usize)] ); impl<'a> Render for CursorFocus<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Self(focus_sequencer, focused, entered, selected, offset, cols, rows) = *self; let area = match selected { ArrangerFocus::Mix => if focused && entered && selected == ArrangerFocus::Mix { fill_bg(buf, area, Nord::bg_hi(focused, entered)); area } else { area }, ArrangerFocus::Track(t) => { let area = Rect { x: offset + area.x + cols[t].1 as u16 - 1, y: area.y, width: cols[t].0 as u16, height: area.height }; fill_bg(buf, area, Nord::bg_hi(focused, entered)); area }, ArrangerFocus::Scene(s) => { let area = Rect { x: area.x, y: 2 + area.y + (rows[s].1 / 96) as u16, width: area.width, height: (rows[s].0 / 96) as u16 }; fill_bg(buf, area, Nord::bg_hi(focused, entered)); area }, ArrangerFocus::Clip(t, s) => { let track_area = Rect { x: offset + area.x + cols[t].1 as u16 - 1, y: area.y, width: cols[t].0 as u16, height: area.height }; let scene_area = Rect { x: area.x, y: 2 + area.y + (rows[s].1 / 96) as u16, width: area.width, height: (rows[s].0 / 96) as u16 }; let area = Rect { x: offset + area.x + cols[t].1 as u16 - 1, y: 2 + area.y + (rows[s].1 / 96) as u16, width: cols[t].0 as u16, height: (rows[s].0 / 96) as u16 }; let lo = Nord::bg_hi(focused, entered); let hi = Nord::bg_hier(focused, entered); fill_bg(buf, track_area, lo); fill_bg(buf, scene_area, lo); fill_bg(buf, area, hi); area }, }; if !focus_sequencer { Corners(Style::default().green().not_dim()).draw(buf, area)?; } Ok(area) } } struct TracksHeader<'a>(u16, &'a[(usize, usize)], &'a [Sequencer]); impl<'a> Render for TracksHeader<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Self(offset, track_cols, tracks) = *self; let Rect { y, width, .. } = area; for (track, (_, x)) in tracks.iter().zip(track_cols) { let x = *x as u16; if x > width { break } track.name.blit(buf, offset + x + 1, y, Some(Style::default()))?; } Ok(Rect { x: area.x, y, width, height: 2 }) } } struct SceneRows<'a>(u16, &'a[(usize, usize)], &'a[(usize, usize)], &'a[Sequencer], &'a[Scene]); impl<'a> Render for SceneRows<'a> { fn render (&self, buf: &mut Buffer, area: Rect) -> Usually { let Self(offset, track_cols, scene_rows, tracks, scenes) = *self; let black = Some(Style::default().fg(Nord::SEPARATOR)); let Rect { mut y, height, .. } = area; for (_, x) in track_cols.iter() { let x = *x as u16; if x > 0 { for y in area.y-2..y-2 { "▎".blit(buf, x - 1, y, black)?; } } } for (scene, (pulses, _)) in scenes.iter().zip(scene_rows) { if y > height { break } let h = 1.max((pulses / 96) as u16); scene_row(tracks, buf, Rect { x: area.x, y, width: area.width, height: h,//.min(area.height - y) }, scene, track_cols, offset)?; y = y + h } Ok(area) } } fn scene_row <'a> ( tracks: &'a[Sequencer], buf: &mut Buffer, area: Rect, scene: &Scene, track_cols: &[(usize, usize)], offset: u16 ) -> Usually { let Rect { y, width, .. } = area; let playing = scene.is_playing(tracks); (if playing { "▶" } else { " " }).blit(buf, area.x, y, None)?; scene.name.blit(buf, area.x + 1, y, None)?; let style = Some(Style::default().white()); for (track, (w, x)) in track_cols.iter().enumerate() { let x = *x as u16 + offset; if x > width { break } if let (Some(track), Some(Some(clip))) = ( tracks.get(track), scene.clips.get(track) ) { if let Some(phrase) = track.phrases.get(*clip) { let phrase = phrase.read().unwrap(); phrase.name.blit(buf, x + 1, y, style)?; if track.sequence == Some(*clip) { fill_bg(buf, Rect { x: x - 1, y, width: *w as u16, height: area.height, }, Nord::PLAYING); } } } } Ok((scene.pulses(tracks) / 96) as u16) }