mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
deduplicate scene cell rendering
This commit is contained in:
parent
4eff4316c6
commit
a66a6a9669
4 changed files with 225 additions and 182 deletions
|
|
@ -55,4 +55,3 @@ impl<E: Output, A: Render<E>, B: Render<E>> Content<E> for Either<A, B> {
|
||||||
if *cond { a.render(to) } else { b.render(to) }
|
if *cond { a.render(to) } else { b.render(to) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ impl Tek {
|
||||||
midi_ins: {
|
midi_ins: {
|
||||||
let mut midi_ins = vec![];
|
let mut midi_ins = vec![];
|
||||||
for (index, connect) in midi_froms.iter().enumerate() {
|
for (index, connect) in midi_froms.iter().enumerate() {
|
||||||
let port = JackMidiIn::new(jack, &format!("m/{index}"), &[connect.clone()])?;
|
let port = JackMidiIn::new(jack, &format!("M/{index}"), &[connect.clone()])?;
|
||||||
midi_ins.push(port);
|
midi_ins.push(port);
|
||||||
}
|
}
|
||||||
midi_ins
|
midi_ins
|
||||||
|
|
@ -115,7 +115,7 @@ impl Tek {
|
||||||
midi_outs: {
|
midi_outs: {
|
||||||
let mut midi_outs = vec![];
|
let mut midi_outs = vec![];
|
||||||
for (index, connect) in midi_tos.iter().enumerate() {
|
for (index, connect) in midi_tos.iter().enumerate() {
|
||||||
let port = JackMidiOut::new(jack, &format!("{index}/m"), &[connect.clone()])?;
|
let port = JackMidiOut::new(jack, &format!("{index}/M"), &[connect.clone()])?;
|
||||||
midi_outs.push(port);
|
midi_outs.push(port);
|
||||||
}
|
}
|
||||||
midi_outs
|
midi_outs
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ use crate::*;
|
||||||
pub perf: PerfModel,
|
pub perf: PerfModel,
|
||||||
pub editing: AtomicBool,
|
pub editing: AtomicBool,
|
||||||
pub history: Vec<TekCommand>,
|
pub history: Vec<TekCommand>,
|
||||||
|
pub ports: std::collections::BTreeMap<u32, Port<Unowned>>,
|
||||||
|
|
||||||
/// View definition
|
/// View definition
|
||||||
pub view: SourceIter<'static>,
|
pub view: SourceIter<'static>,
|
||||||
|
|
@ -331,22 +332,6 @@ pub trait HasScenes: HasSelection + HasEditor + Send + Sync {
|
||||||
fn scene_longest (&self) -> usize {
|
fn scene_longest (&self) -> usize {
|
||||||
self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max)
|
self.scenes().iter().map(|s|s.name.len()).fold(0, usize::max)
|
||||||
}
|
}
|
||||||
fn scenes_sizes (&self, editing: bool, height: usize, larger: usize,)
|
|
||||||
-> impl Iterator<Item = (usize, &Scene, usize, usize)> + Send + Sync
|
|
||||||
{
|
|
||||||
let mut y = 0;
|
|
||||||
let (selected_track, selected_scene) = match self.selected() {
|
|
||||||
Selection::Clip(t, s) => (Some(t.saturating_sub(1)), Some(s.saturating_sub(1))),
|
|
||||||
_ => (None, None)
|
|
||||||
};
|
|
||||||
self.scenes().iter().enumerate().map(move|(s, scene)|{
|
|
||||||
let active = editing && selected_track.is_some() && selected_scene == Some(s);
|
|
||||||
let height = if active { larger } else { height };
|
|
||||||
let data = (s, scene, y, y + height);
|
|
||||||
y += height;
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
fn scene (&self) -> Option<&Scene> {
|
fn scene (&self) -> Option<&Scene> {
|
||||||
self.selected().scene().and_then(|s|self.scenes().get(s))
|
self.selected().scene().and_then(|s|self.scenes().get(s))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
385
tek/src/view.rs
385
tek/src/view.rs
|
|
@ -50,42 +50,28 @@ impl Default for ViewCache {
|
||||||
}
|
}
|
||||||
view!(TuiOut: |self: Tek| self.size.of(View(self, self.view)); {
|
view!(TuiOut: |self: Tek| self.size.of(View(self, self.view)); {
|
||||||
":editor" => (&self.editor).boxed(),
|
":editor" => (&self.editor).boxed(),
|
||||||
|
":inputs" => self.view_inputs().boxed(),
|
||||||
|
":outputs" => self.view_outputs().boxed(),
|
||||||
":pool" => self.view_pool().boxed(),
|
":pool" => self.view_pool().boxed(),
|
||||||
":sample" => ().boxed(),//self.view_sample(self.is_editing()).boxed(),
|
":sample" => ().boxed(),//self.view_sample(self.is_editing()).boxed(),
|
||||||
":sampler" => ().boxed(),//self.view_sampler(self.is_editing(), &self.editor).boxed(),
|
":sampler" => ().boxed(),//self.view_sampler(self.is_editing(), &self.editor).boxed(),
|
||||||
|
":scene-add" => self.view_scene_add().boxed(),
|
||||||
|
":scenes" => self.view_scenes().boxed(),
|
||||||
":status" => self.view_editor().boxed(),
|
":status" => self.view_editor().boxed(),
|
||||||
":toolbar" => self.view_clock().boxed(),
|
":toolbar" => self.view_clock().boxed(),
|
||||||
":tracks" => self.view_tracks().boxed(),
|
|
||||||
":track-add" => self.view_track_add().boxed(),
|
":track-add" => self.view_track_add().boxed(),
|
||||||
":inputs" => self.view_inputs().boxed(),
|
":tracks" => self.view_tracks().boxed(),
|
||||||
":outputs" => self.view_outputs().boxed(),
|
|
||||||
":scenes" => self.view_scenes().boxed(),
|
|
||||||
":scene-add" => self.view_scene_add().boxed(),
|
|
||||||
});
|
});
|
||||||
provide_num!(u16: |self: Tek| {
|
provide_num!(u16: |self: Tek| {
|
||||||
":w-sidebar-w" => self.w_sidebar(),
|
":h-ins" => self.h_inputs(),
|
||||||
":h-sample-h" => if self.is_editing() { 0 } else { 5 },
|
":h-outs" => self.h_outputs(),
|
||||||
":w-samples-w" => if self.is_editing() { 4 } else { 11 },
|
":h-sample" => if self.is_editing() { 0 } else { 5 },
|
||||||
":y-samples-y" => if self.is_editing() { 1 } else { 0 },
|
":w-samples" => if self.is_editing() { 4 } else { 11 },
|
||||||
":h-ins" => self.h_inputs(),
|
":w-sidebar" => self.w_sidebar(),
|
||||||
":h-outs" => self.h_outputs(),
|
":y-ins" => (self.size.h() as u16).saturating_sub(self.h_inputs() + 1),
|
||||||
":y-ins" => (self.size.h() as u16).saturating_sub(self.h_inputs()),
|
":y-outs" => (self.size.h() as u16).saturating_sub(self.h_outputs() + 1),
|
||||||
":y-outs" => (self.size.h() as u16).saturating_sub(self.h_outputs()),
|
":y-samples" => if self.is_editing() { 1 } else { 0 },
|
||||||
});
|
});
|
||||||
macro_rules! per_track {
|
|
||||||
($area:expr;|$self:ident,$track:ident,$index:ident|$content:expr) => {{
|
|
||||||
let tracks = ||$self.tracks_sizes($self.is_editing(), $self.editor_w());
|
|
||||||
Box::new(move||Align::x(Map::new(tracks, move|(_, $track, x1, x2), $index| {
|
|
||||||
let width = (x2 - x1) as u16;
|
|
||||||
let content = Fixed::y(1, $content);
|
|
||||||
let styled = Tui::fg_bg($track.color.lightest.rgb, $track.color.base.rgb, content);
|
|
||||||
Either(x2 >= $area, (),
|
|
||||||
map_east(x1 as u16, width, Align::y(Fixed::x(width, styled)))) }))).into() }} }
|
|
||||||
macro_rules! io_header {
|
|
||||||
($self:ident, $key:expr, $label:expr, $count:expr, $content:expr) => {
|
|
||||||
(move||{
|
|
||||||
let button = $self.button($key, format!("{:10} ({})", $label, $count));
|
|
||||||
Bsp::s(Fill::x(Align::w(button)), $content).boxed() }).into() } }
|
|
||||||
macro_rules! rewrite {
|
macro_rules! rewrite {
|
||||||
($buf:ident, $($rest:tt)*) => { |$buf,_,_|{$buf.clear();write!($buf, $($rest)*)} } }
|
($buf:ident, $($rest:tt)*) => { |$buf,_,_|{$buf.clear();write!($buf, $($rest)*)} } }
|
||||||
impl Tek {
|
impl Tek {
|
||||||
|
|
@ -189,69 +175,51 @@ impl Tek {
|
||||||
Fill::xy(Align::c(Fixed::x(w, b)))
|
Fill::xy(Align::c(Fixed::x(w, b)))
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
fn view_inputs (&self) -> impl Content<TuiOut> + use<'_> {
|
}
|
||||||
let fg = Tui::g(224);
|
macro_rules! per_track {
|
||||||
let bg = Tui::g(64);
|
($area:expr;|$self:ident,$track:ident,$index:ident|$content:expr) => {{
|
||||||
let conn = move|conn: &PortConnect|Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, conn.info()))));
|
let tracks = ||$self.tracks_sizes($self.is_editing(), $self.editor_w())
|
||||||
let header: ThunkBox<_> = io_header!(self, " I ", " midi ins", self.midi_ins.len(),
|
.map_while(|(t, track, x1, x2)|if x2 >= $area {
|
||||||
Map::new(||self.midi_ins.iter(), move|input, index|map_south(index as u16, 1, Bsp::s(
|
None } else { Some((t, track, x1, x2)) });
|
||||||
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(input.name())))),
|
Box::new(move||Align::x(Map::new(tracks, move|(_, $track, x1, x2), $index| {
|
||||||
Map::new(||input.conn().iter(), move|connect, index|map_south(index as u16, 0,
|
let width = (x2 - x1) as u16;
|
||||||
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))));
|
let content = Fixed::y(1, $content);
|
||||||
let cells: ThunkBox<_> = per_track!(self.size.w();|self, track, t|{
|
let styled = Tui::fg_bg($track.color.lightest.rgb, $track.color.base.rgb, content);
|
||||||
let rec = track.player.recording;
|
map_east(x1 as u16, width, Align::y(Fixed::x(width, styled))) }))).into() }} }
|
||||||
let mon = track.player.monitoring;
|
macro_rules! io_header {
|
||||||
let bg = if self.selected().track() == Some(t+1) { track.color.light.rgb } else { track.color.base.rgb };
|
($self:ident, $key:expr, $label:expr, $count:expr, $content:expr) => {
|
||||||
let bg2 = if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
(move||Fill::xy(Align::nw({
|
||||||
Bsp::s(
|
let button = $self.button($key, format!("{:10} ({})", $label, $count));
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Bsp::e(
|
Bsp::s(button, $content)
|
||||||
Tui::fg_bg(if rec { White } else { track.color.darkest.rgb }, bg, "Recrd"),
|
})).boxed()).into() } }
|
||||||
Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "Monit"),
|
macro_rules! per_track_top {
|
||||||
))),
|
($area:expr;|$self:ident,$track:ident,$index:ident|$content:expr) => {{
|
||||||
Map::new(||self.midi_ins.iter(), move|input, index|map_south(index as u16, 1,
|
let tracks = ||$self.tracks_sizes($self.is_editing(), $self.editor_w())
|
||||||
Self::wrap(bg, fg, Bsp::e(
|
.map_while(|(t, track, x1, x2)|if x2 >= $area {
|
||||||
Tui::fg_bg(if rec { White } else { track.color.darkest.rgb }, bg, "R▞▞▞▞"),
|
None } else { Some((t, track, x1, x2)) });
|
||||||
Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "M▞▞▞▞"),
|
(move||Fill::xy(Align::nw(Map::new(tracks, move|(_, $track, x1, x2), $index| {
|
||||||
)))))});
|
let width = (x2 - x1) as u16;
|
||||||
Tui::bg(Black, self.view_row(self.w(), self.h_inputs(), header, cells))
|
let content = Fixed::y(1, $content);
|
||||||
}
|
let styled = Tui::fg_bg($track.color.lightest.rgb, $track.color.base.rgb, content);
|
||||||
fn h_inputs (&self) -> u16 {
|
map_east(x1 as u16, width, Fixed::x(width, Align::n(styled))) }))).boxed()).into() }} }
|
||||||
let mut h = 1;
|
impl Tek {
|
||||||
for midi_in in self.midi_ins.iter() { h += 1 + midi_in.conn().len() as u16 }
|
|
||||||
h
|
fn view_row_top <'a> (
|
||||||
}
|
&'a self, w: u16, h: u16, a: impl Content<TuiOut> + 'a, b: impl Content<TuiOut> + 'a
|
||||||
fn view_outputs (&self) -> impl Content<TuiOut> + use<'_> {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
let fg = Tui::g(224);
|
Fixed::y(h, Bsp::a(
|
||||||
let bg = Tui::g(64);
|
Fill::xy(Align::nw(Fixed::xy(self.w_sidebar() as u16, h, a))),
|
||||||
let conn = move|conn: &PortConnect|Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, conn.info()))));
|
Fill::xy(Align::n(Fixed::xy(w, h, b)))
|
||||||
let header: ThunkBox<_> = io_header!(self, " O ", " midi outs", self.midi_outs.len(),
|
))
|
||||||
Map::new(||self.midi_outs.iter(), move|output, index|map_south(index as u16, 0, Bsp::s(
|
|
||||||
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(output.name())))),
|
|
||||||
Map::new(||output.conn().iter(), move|connect, index|map_south(index as u16, 0,
|
|
||||||
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))));
|
|
||||||
let mute = false;
|
|
||||||
let solo = false;
|
|
||||||
let cells: ThunkBox<_> = per_track!(self.size.w();|self, track, t|{
|
|
||||||
let bg = if self.selected().track() == Some(t+1) { track.color.light.rgb } else { track.color.base.rgb };
|
|
||||||
let bg2 = if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
|
||||||
Bsp::s(
|
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Bsp::e(
|
|
||||||
Tui::fg_bg(if mute { White } else { track.color.darkest.rgb }, bg, "Play "),
|
|
||||||
Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "Solo "),))),
|
|
||||||
Map::new(||self.midi_outs.iter(), move|output, index|map_south(index as u16, 1u16,
|
|
||||||
Self::wrap(bg, fg, Bsp::e(
|
|
||||||
Tui::fg_bg(if mute { White } else { track.color.darkest.rgb }, bg, "P▞▞▞▞"),
|
|
||||||
Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "S▞▞▞▞"))))))});
|
|
||||||
Tui::bg(Black, self.view_row(self.w(), self.h_outputs(), header, cells))
|
|
||||||
}
|
|
||||||
fn h_outputs (&self) -> u16 {
|
|
||||||
let mut h = 1;
|
|
||||||
for midi_out in self.midi_outs.iter() { h += 1 + midi_out.conn().len() as u16 }
|
|
||||||
h
|
|
||||||
}
|
}
|
||||||
fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
fn wrap (bg: Color, fg: Color, content: impl Content<TuiOut>) -> impl Content<TuiOut> {
|
||||||
Bsp::e(Tui::fg_bg(bg, Reset, "▐"), Bsp::w(Tui::fg_bg(bg, Reset, "▌"), Tui::fg_bg(fg, bg, content)))
|
Bsp::e(Tui::fg_bg(bg, Reset, "▐"), Bsp::w(Tui::fg_bg(bg, Reset, "▌"), Tui::fg_bg(fg, bg, content)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TRACKS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
fn w_tracks (&self, editing: bool, bigger: usize) -> u16 {
|
||||||
|
self.tracks_sizes(editing, bigger).last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize)
|
fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize)
|
||||||
-> impl Iterator<Item=(usize, &'a Track, usize, usize)> + Send + Sync + 'a
|
-> impl Iterator<Item=(usize, &'a Track, usize, usize)> + Send + Sync + 'a
|
||||||
{
|
{
|
||||||
|
|
@ -268,11 +236,8 @@ impl Tek {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn w_tracks (&self, editing: bool, bigger: usize) -> u16 {
|
|
||||||
self.tracks_sizes(editing, bigger).last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
|
|
||||||
}
|
|
||||||
fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
|
fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
let height = 1;
|
let height = 3;
|
||||||
let header: ThunkBox<_> =
|
let header: ThunkBox<_> =
|
||||||
(move||Tui::bg(Tui::g(32), Fill::x(Align::w(self.view_track_add()))).boxed()).into();
|
(move||Tui::bg(Tui::g(32), Fill::x(Align::w(self.view_track_add()))).boxed()).into();
|
||||||
let content: ThunkBox<_> = per_track!(self.size.w();|self, track, t|{
|
let content: ThunkBox<_> = per_track!(self.size.w();|self, track, t|{
|
||||||
|
|
@ -287,7 +252,101 @@ impl Tek {
|
||||||
});
|
});
|
||||||
self.view_row(self.w(), height, header, content)
|
self.view_row(self.w(), height, header, content)
|
||||||
}
|
}
|
||||||
fn scenes_sizes (&self, editing: bool, height: usize, larger: usize,)
|
|
||||||
|
// INPUTS /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
fn inputs_sizes (&self) -> impl Iterator<Item = (usize, &JackMidiIn, usize, usize)> + Send + Sync {
|
||||||
|
let mut y = 0;
|
||||||
|
self.midi_ins.iter().enumerate().map(move|(i, input)|{
|
||||||
|
let height = 1 + input.conn().len();
|
||||||
|
let data = (i, input, y, y + height);
|
||||||
|
y += height;
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn h_inputs (&self) -> u16 {
|
||||||
|
1 + self.inputs_sizes().last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
fn view_inputs (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let fg = Tui::g(224);
|
||||||
|
let bg = Tui::g(64);
|
||||||
|
let header: ThunkBox<_> = io_header!(self, " I ", " midi ins", self.midi_ins.len(),
|
||||||
|
Map::new(||self.inputs_sizes(),
|
||||||
|
move|(index, input, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
|
||||||
|
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(input.name())))),
|
||||||
|
Map::new(||input.conn().iter(), move|connect, index|map_south(index as u16, 1,
|
||||||
|
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))));
|
||||||
|
|
||||||
|
let cells: ThunkBox<_> = per_track_top!(self.size.w();|self, track, t|{
|
||||||
|
let rec = track.player.recording;
|
||||||
|
let mon = track.player.monitoring;
|
||||||
|
let bg = if self.selected().track() == Some(t+1) { track.color.light.rgb } else { track.color.base.rgb };
|
||||||
|
let bg2 = if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
||||||
|
Bsp::s(
|
||||||
|
Fixed::y(1, Align::n(Self::wrap(bg, fg, Tui::bold(true, Bsp::e(
|
||||||
|
Tui::fg_bg(if rec { White } else { track.color.darkest.rgb }, bg, "Rec "),
|
||||||
|
Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "Mon ")))))),
|
||||||
|
Fill::y(Tui::bg(Green, Map::new(
|
||||||
|
||self.inputs_sizes(),
|
||||||
|
move|(index, input, y, y2), _|map_south(y as u16, (y2-y) as u16,
|
||||||
|
Self::wrap(bg, fg, Bsp::e(
|
||||||
|
Tui::fg_bg(if rec { White } else { track.color.darkest.rgb }, bg, "R▞▞▞▞"),
|
||||||
|
Tui::fg_bg(if mon { White } else { track.color.darkest.rgb }, bg, "M▞▞▞▞"))))))))});
|
||||||
|
|
||||||
|
Bsp::<_, Push<u16, ThunkBox<_>>>::s(
|
||||||
|
Tui::bg(Black, self.view_row_top(self.w(), self.h_inputs(), header, Tui::bg(Red, cells))),
|
||||||
|
Push::xy(self.w_sidebar(), 1, per_track_top!(self.size.w();|self, track, t|"kyp"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OUTPUTS ////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
fn h_outputs (&self) -> u16 {
|
||||||
|
1 + self.outputs_sizes().last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
fn outputs_sizes (&self) -> impl Iterator<Item = (usize, &JackMidiOut, usize, usize)> + Send + Sync {
|
||||||
|
let mut y = 0;
|
||||||
|
self.midi_outs.iter().enumerate().map(move|(i, output)|{
|
||||||
|
let height = 1 + output.conn().len();
|
||||||
|
let data = (i, output, y, y + height);
|
||||||
|
y += height;
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn view_outputs (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let fg = Tui::g(224);
|
||||||
|
let bg = Tui::g(64);
|
||||||
|
let header: ThunkBox<_> = io_header!(self, " O ", " midi outs", self.midi_outs.len(),
|
||||||
|
Map::new(||self.outputs_sizes(),
|
||||||
|
move|(index, output, y, y2), _|map_south(y as u16, (y2-y) as u16, Bsp::s(
|
||||||
|
Fill::x(Tui::bold(true, Tui::fg_bg(fg, bg, Align::w(output.name())))),
|
||||||
|
Map::new(||output.conn().iter(), move|connect, index|map_south(index as u16, 1,
|
||||||
|
Fill::x(Align::w(Tui::bold(false, Tui::fg_bg(fg, bg, connect.info()))))))))));
|
||||||
|
|
||||||
|
let mute = false;
|
||||||
|
let solo = false;
|
||||||
|
let cells: ThunkBox<_> = per_track_top!(self.size.w();|self, track, t|{
|
||||||
|
let bg = if self.selected().track() == Some(t+1) { track.color.light.rgb } else { track.color.base.rgb };
|
||||||
|
let bg2 = if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
||||||
|
Bsp::s(
|
||||||
|
Fixed::y(1, Self::wrap(bg, fg, Tui::bold(true, Bsp::e(
|
||||||
|
Tui::fg_bg(if mute { White } else { track.color.darkest.rgb }, bg, "Play "),
|
||||||
|
Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "Solo "),)))),
|
||||||
|
Fill::y(Map::new(
|
||||||
|
||self.outputs_sizes(),
|
||||||
|
move|(index, output, y, y2), _|map_south(y as u16, (y2-y) as u16,
|
||||||
|
Self::wrap(bg, fg, Bsp::e(
|
||||||
|
Tui::fg_bg(if mute { White } else { track.color.darkest.rgb }, bg, "P▞▞▞▞"),
|
||||||
|
Tui::fg_bg(if solo { White } else { track.color.darkest.rgb }, bg, "S▞▞▞▞")))))))});
|
||||||
|
|
||||||
|
Tui::bg(Black, self.view_row_top(self.w(), self.h_outputs(),
|
||||||
|
Tui::bg(Yellow, header),
|
||||||
|
Tui::bg(Blue, cells)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCENES /////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
fn h_scenes (&self, editing: bool, height: usize, larger: usize) -> u16 {
|
||||||
|
self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
fn scenes_sizes (&self, editing: bool, height: usize, larger: usize)
|
||||||
-> impl Iterator<Item = (usize, &Scene, usize, usize)> + Send + Sync
|
-> impl Iterator<Item = (usize, &Scene, usize, usize)> + Send + Sync
|
||||||
{
|
{
|
||||||
let mut y = 0;
|
let mut y = 0;
|
||||||
|
|
@ -303,91 +362,91 @@ impl Tek {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn h_scenes (&self, editing: bool, height: usize, larger: usize) -> u16 {
|
|
||||||
self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
|
||||||
}
|
|
||||||
fn view_scenes (&self) -> impl Content<TuiOut> + use<'_> {
|
fn view_scenes (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
let bstyle = Style::default().fg(Tui::g(0));
|
let w = self.size.w() as u16;
|
||||||
let size_w = self.size.w();
|
let h = self.size.h() as u16;
|
||||||
let size_h = self.size.h();
|
|
||||||
let editing = self.is_editing();
|
let editing = self.is_editing();
|
||||||
let tracks = move||self.tracks_sizes(editing, self.editor_w());
|
let tracks = move||self.tracks_sizes(editing, self.editor_w());
|
||||||
|
let header = move||self.view_scenes_header(editing);
|
||||||
|
let content = move||self.view_scenes_content(editing, h);
|
||||||
|
self.view_row(w, h,
|
||||||
|
<_ as Into<ThunkBox<_>>>::into(header),
|
||||||
|
<_ as Into<ThunkBox<_>>>::into(content))
|
||||||
|
}
|
||||||
|
fn view_scenes_header (&self, editing: bool) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let size_h = self.size.h();
|
||||||
|
Align::y(Map::new(
|
||||||
|
move||self.scenes_sizes(editing, 2, 15).map_while(
|
||||||
|
move|(s, scene, y1, y2)|if y2 > size_h {
|
||||||
|
None
|
||||||
|
} else { Some((s, scene, y1, y2, if s == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.scenes[s-1].color)
|
||||||
|
})) }),
|
||||||
|
move|(_, scene, y1, y2, prev), s| {
|
||||||
|
let height = (1 + y2 - y1) as u16;
|
||||||
|
let bg = scene.color;
|
||||||
|
let fg = scene.color.lightest.rgb;
|
||||||
|
let name = Some(scene.name.clone());
|
||||||
|
map_south(y1 as u16, height, Fixed::y(height, self.view_clip_cell(
|
||||||
|
true, s, &bg, prev, name, " ⯈ ", fg)))
|
||||||
|
})).boxed()
|
||||||
|
}
|
||||||
|
fn view_scenes_content (&self, editing: bool, height: u16) -> ThunkBox<TuiOut> {
|
||||||
let selected_track = self.selected().track();
|
let selected_track = self.selected().track();
|
||||||
let selected_scene = self.selected().scene();
|
let selected_scene = self.selected().scene();
|
||||||
let header_cell = move|t, s, bg: &ItemPalette, last: Option<ItemPalette>, name: Arc<str>|{
|
per_track!(self.size.w(); |self, track, t|{
|
||||||
let selected = t && self.selected().scene() == Some(s+1);
|
|
||||||
let neighbor = t && self.selected().scene() == Some(s);
|
|
||||||
Phat {
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
selected,
|
|
||||||
content: Tui::bold(true, Bsp::e("🭬", name.clone())),
|
|
||||||
colors: colors(
|
|
||||||
bg, last, selected, neighbor, s == self.scenes.len().saturating_sub(1)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let header = move||{
|
|
||||||
Align::y(Map::new(
|
|
||||||
move||self.scenes_sizes(editing, 2, 15).map_while(
|
|
||||||
move|(s, scene, y1, y2)|if y2 > size_h { None } else { Some((s, scene, y1, y2, if s == 0 {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(self.scenes[s-1].color)
|
|
||||||
})) }),
|
|
||||||
move|(_, scene, y1, y2, last), s| {
|
|
||||||
let height = (1 + y2 - y1) as u16;
|
|
||||||
map_south(y1 as u16, height, Fixed::y(height,
|
|
||||||
header_cell(true, s, &scene.color, last, scene.name.clone()))) })).boxed()
|
|
||||||
};
|
|
||||||
let content: ThunkBox<_> = per_track!(self.size.w(); |self, track, t|{
|
|
||||||
let tab = " Tab ";
|
let tab = " Tab ";
|
||||||
let same_track = selected_track == Some(t+1);
|
let same_track = selected_track == Some(t+1);
|
||||||
Map::new(
|
Map::new(
|
||||||
move||self.scenes_sizes(editing, 2, 15).map_while(
|
move||self.scenes_sizes(editing, 2, 15).map_while(
|
||||||
move|(s, scene, y1, y2)|if y2 > size_h { None } else { Some((s, scene, y1, y2, if s == 0 {
|
move|(s, scene, y1, y2)|if y2 as u16 > height { None } else { Some((s, scene, y1, y2, if s == 0 {
|
||||||
None
|
None } else { Some(self.scenes[s-1].clips[t].as_ref()
|
||||||
} else {
|
|
||||||
Some(self.scenes[s-1].clips[t].as_ref()
|
|
||||||
.map(|c|c.read().unwrap().color)
|
.map(|c|c.read().unwrap().color)
|
||||||
.unwrap_or(ItemPalette::G[32])) })) }),
|
.unwrap_or(ItemPalette::G[32])) })) }),
|
||||||
move|(_, scene, y1, y2, last), s| {
|
move|(_, scene, y1, y2, prev), s| {
|
||||||
let height = (1 + y2 - y1) as u16;
|
let height = (1 + y2 - y1) as u16;
|
||||||
let (fg, bg) = if let Some(clip) = &scene.clips[t] {
|
let (name, fg, bg) = if let Some(clip) = &scene.clips[t] {
|
||||||
let clip = clip.read().unwrap();
|
let clip = clip.read().unwrap();
|
||||||
(clip.color.lightest.rgb, clip.color)
|
(Some(clip.name.clone()), clip.color.lightest.rgb, clip.color)
|
||||||
} else {
|
} else {
|
||||||
(Tui::g(96), ItemPalette::G[32])
|
(None, Tui::g(96), ItemPalette::G[32])
|
||||||
};
|
};
|
||||||
let selected = same_track && selected_scene == Some(s+1);
|
let active = editing && same_track && selected_scene == Some(s+1);
|
||||||
let neighbor = same_track && selected_scene == Some(s);
|
let edit = |x|Bsp::b(x, When(active, &self.editor));
|
||||||
let active = editing && selected;
|
map_south(y1 as u16, height, edit(Fixed::y(height, self.view_clip_cell(
|
||||||
map_south(y1 as u16, height, Fixed::y(height, Phat {
|
same_track, s, &bg, prev, name, " ⏹ ", fg))))})
|
||||||
width: 0,
|
})
|
||||||
height: 0,
|
}
|
||||||
selected,
|
fn view_clip_cell <'a> (
|
||||||
content: {
|
&self,
|
||||||
let clip = scene.clips[t].clone();
|
same_track: bool,
|
||||||
let icon = " ⏹ ";
|
scene: usize,
|
||||||
let name = clip.map(|c|c.read().unwrap().name.clone());
|
color: &ItemPalette,
|
||||||
Bsp::a(
|
prev: Option<ItemPalette>,
|
||||||
Fill::xy(Align::nw(Tui::fg(fg, Bsp::e(icon, Bsp::e(Tui::bold(true, name), " "))))),
|
name: Option<Arc<str>>,
|
||||||
When(active, &self.editor)
|
icon: &'a str,
|
||||||
)
|
fg: Color,
|
||||||
},
|
) -> impl Content<TuiOut> + use<'a> {
|
||||||
colors: colors(
|
let selected_scene = self.selected().scene();
|
||||||
&bg, last, selected, neighbor, s == self.scenes.len().saturating_sub(1)
|
let selected = same_track && selected_scene == Some(scene+1);
|
||||||
),
|
let neighbor = same_track && selected_scene == Some(scene);
|
||||||
}))
|
self.view_cell(scene, color, prev, selected, neighbor,
|
||||||
})
|
Fill::x(Align::w(Tui::fg(fg, Tui::bold(true, Bsp::e(icon, name))))))
|
||||||
});
|
}
|
||||||
//let border = move|x|Outer(false, bstyle).enclose_bg(x);
|
fn view_cell <T: Content<TuiOut>> (
|
||||||
self.view_row(
|
&self,
|
||||||
self.w(),
|
scene: usize,
|
||||||
size_h as u16,
|
color: &ItemPalette,
|
||||||
<_ as Into<ThunkBox<_>>>::into(header),
|
prev: Option<ItemPalette>,
|
||||||
<_ as Into<ThunkBox<_>>>::into(content),
|
selected: bool,
|
||||||
)
|
neighbor: bool,
|
||||||
|
content: T,
|
||||||
|
) -> Phat<T> {
|
||||||
|
let is_last = scene == self.scenes.len().saturating_sub(1);
|
||||||
|
let colors = colors(color, prev, selected, neighbor, is_last);
|
||||||
|
Phat { width: 0, height: 0, selected, content, colors, }
|
||||||
}
|
}
|
||||||
fn w (&self) -> u16 {
|
fn w (&self) -> u16 {
|
||||||
self.tracks_sizes(self.is_editing(), self.editor_w())
|
self.tracks_sizes(self.is_editing(), self.editor_w())
|
||||||
|
|
@ -431,8 +490,8 @@ fn button <'a> (
|
||||||
label: impl Content<TuiOut> + 'a
|
label: impl Content<TuiOut> + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
Tui::bold(true, Bsp::e(
|
Tui::bold(true, Bsp::e(
|
||||||
Margin::x(1, Tui::fg_bg(Tui::g(0), Tui::orange(), key)),
|
Tui::fg_bg(Tui::g(0), Tui::orange(), key),
|
||||||
Margin::x(1, Tui::fg_bg(Tui::g(255), Tui::g(96), label)),
|
Tui::fg_bg(Tui::g(255), Tui::g(96), label),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
fn colors (
|
fn colors (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue