mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
further reducing whatever is causing the wrong centering
along 1 axis anyway, along the other i just saw it increase
This commit is contained in:
parent
30f43eac79
commit
cdbcea0a8f
4 changed files with 208 additions and 228 deletions
239
tek/src/view.rs
239
tek/src/view.rs
|
|
@ -1,5 +1,8 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use std::fmt::Write;
|
pub(crate) use std::fmt::Write;
|
||||||
|
mod clip; pub use self::clip::*;
|
||||||
|
mod input; pub use self::input::*;
|
||||||
|
mod output; pub use self::output::*;
|
||||||
macro_rules! def_sizes_iter {
|
macro_rules! def_sizes_iter {
|
||||||
($Type:ident => $($Item:ty),+) => {
|
($Type:ident => $($Item:ty),+) => {
|
||||||
trait $Type<'a> = Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a;
|
trait $Type<'a> = Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a;
|
||||||
|
|
@ -79,7 +82,7 @@ provide_num!(u16: |self: Tek| {
|
||||||
":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() + 1),
|
||||||
":y-samples" => if self.is_editing() { 1 } else { 0 },
|
":y-samples" => if self.is_editing() { 1 } else { 0 },
|
||||||
});
|
});
|
||||||
macro_rules! rewrite {
|
#[macro_export] 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 {
|
||||||
fn update_clock (&self) {
|
fn update_clock (&self) {
|
||||||
|
|
@ -175,18 +178,7 @@ impl Tek {
|
||||||
.map(|pool|Fixed::x(self.w_sidebar(), PoolView(self.is_editing(), pool)))
|
.map(|pool|Fixed::x(self.w_sidebar(), PoolView(self.is_editing(), pool)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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())
|
|
||||||
.map_while(|(t, track, x1, x2)|if x2 >= $area {
|
|
||||||
None } else { Some((t, track, x1, x2)) });
|
|
||||||
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);
|
|
||||||
map_east(x1 as u16, width, Align::y(Fixed::x(width, styled))) }))).into() }} }
|
|
||||||
impl Tek {
|
impl Tek {
|
||||||
|
|
||||||
// SIZES //////////////////////////////////////////////////////////////////////////////////////
|
// SIZES //////////////////////////////////////////////////////////////////////////////////////
|
||||||
fn w (&self) -> u16 { self.size.w() as u16 }
|
fn w (&self) -> u16 { self.size.w() as u16 }
|
||||||
fn h (&self) -> u16 { self.size.h() as u16 }
|
fn h (&self) -> u16 { self.size.h() as u16 }
|
||||||
|
|
@ -205,7 +197,6 @@ impl Tek {
|
||||||
fn h_scenes (&self, editing: bool, height: usize, larger: usize) -> u16 {
|
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)
|
self.scenes_sizes(editing, height, larger).last().map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// THINGS WITH SIZES //////////////////////////////////////////////////////////////////////////
|
// THINGS WITH SIZES //////////////////////////////////////////////////////////////////////////
|
||||||
const TRACK_SPACING: usize = 0;
|
const TRACK_SPACING: usize = 0;
|
||||||
fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize) -> impl TracksSizes<'a> {
|
fn tracks_sizes <'a> (&'a self, editing: bool, bigger: usize) -> impl TracksSizes<'a> {
|
||||||
|
|
@ -254,42 +245,41 @@ impl Tek {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// COMPONENTS ////////////////////////////////////////////////////////////////////////////////
|
/// COMPONENTS ////////////////////////////////////////////////////////////////////////////////
|
||||||
fn row <'a> (
|
fn row <'a> (
|
||||||
&'a self, w: u16, h: u16, a: impl Content<TuiOut> + 'a, b: impl Content<TuiOut> + 'a
|
&'a self, w: u16, h: u16, a: impl Content<TuiOut> + 'a, b: impl Content<TuiOut> + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
Fixed::y(h, Bsp::a(
|
Fixed::y(h, Bsp::a(
|
||||||
Fill::xy(Align::w(Fixed::x(self.w_sidebar() as u16, a))),
|
Fill::xy(Align::w(Fixed::x(self.w_sidebar() as u16, a))),
|
||||||
Fill::xy(Align::c(Fixed::x(w, b)))))}
|
Fill::xy(Align::c(Fixed::x(w, Align::x(b))))))}
|
||||||
fn row_top <'a> (
|
fn row_top <'a> (
|
||||||
&'a self, w: u16, h: u16, a: impl Content<TuiOut> + 'a, b: impl Content<TuiOut> + 'a
|
&'a self, w: u16, h: u16, a: impl Content<TuiOut> + 'a, b: impl Content<TuiOut> + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
Fixed::y(h, Bsp::a(
|
Fixed::y(h, Bsp::a(
|
||||||
Fill::xy(Align::nw(Fixed::xy(self.w_sidebar() as u16, h, a))),
|
Fill::xy(Align::nw(Fixed::xy(self.w_sidebar() as u16, h, a))),
|
||||||
Fill::xy(Align::n(Fixed::xy(w, h, b)))))}
|
Fill::xy(Align::n(Fixed::xy(w, h, Align::x(b))))))}
|
||||||
fn per_track <'a, T: Content<TuiOut> + 'a> (
|
fn per_track <'a, T: Content<TuiOut> + 'a> (
|
||||||
&'a self, f: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
&'a self, f: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
let width = self.size.w();
|
let width = self.size.w();
|
||||||
let filter = move|(t, track, x1, x2)|if x2 >= width {None} else {Some((t, track, x1, x2))};
|
let filter = move|(t, track, x1, x2)|if x2 >= width {None} else {Some((t, track, x1, x2))};
|
||||||
let tracks = move||self.tracks_sizes(self.is_editing(), self.editor_w()).map_while(filter);
|
let tracks = move||self.tracks_sizes(self.is_editing(), self.editor_w()).map_while(filter);
|
||||||
Map::new(tracks, move|(index, track, x1, x2), _|{
|
Align::x(Tui::bg(Yellow, Map::new(tracks, move|(index, track, x1, x2), _|{
|
||||||
let width = (x2 - x1) as u16;
|
let width = (x2 - x1) as u16;
|
||||||
let content = Fixed::y(1, f(index, track));
|
let content = Fixed::y(1, f(index, track));
|
||||||
let styled = Tui::fg_bg(track.color.lightest.rgb, track.color.base.rgb, content);
|
let styled = Tui::fg_bg(track.color.lightest.rgb, track.color.base.rgb, content);
|
||||||
map_east(x1 as u16, width, Align::y(Fixed::x(width, styled))) }) }
|
map_east(x1 as u16, width, Align::y(Fixed::x(width, styled))) }))) }
|
||||||
fn per_track_top <'a, T: Content<TuiOut> + 'a> (
|
fn per_track_top <'a, T: Content<TuiOut> + 'a> (
|
||||||
&'a self, f: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
&'a self, f: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
let width = self.size.w();
|
let width = self.size.w();
|
||||||
let filter = move|(t, track, x1, x2)|if x2 >= width {None} else {Some((t, track, x1, x2))};
|
let filter = move|(t, track, x1, x2)|if x2 >= width {None} else {Some((t, track, x1, x2))};
|
||||||
let tracks = move||self.tracks_sizes(self.is_editing(), self.editor_w()).map_while(filter);
|
let tracks = move||self.tracks_sizes(self.is_editing(), self.editor_w()).map_while(filter);
|
||||||
Map::new(tracks, move|(index, track, x1, x2), _|{
|
Align::x(Tui::bg(Green, Map::new(tracks, move|(index, track, x1, x2), _|{
|
||||||
let width = (x2 - x1) as u16;
|
let width = (x2 - x1) as u16;
|
||||||
let content = Fixed::y(1, f(index, track));
|
let content = Fixed::y(1, f(index, track));
|
||||||
let styled = Tui::fg_bg(track.color.lightest.rgb, track.color.base.rgb, content);
|
let styled = Tui::fg_bg(track.color.lightest.rgb, track.color.base.rgb, content);
|
||||||
map_east(x1 as u16, width, Fixed::x(width, styled)) }) }
|
map_east(x1 as u16, width, Fixed::x(width, styled)) }))) }
|
||||||
fn io_ports <'a, T: PortsSizes<'a>> (
|
fn io_ports <'a, T: PortsSizes<'a>> (
|
||||||
&'a self, fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
&'a self, fg: Color, bg: Color, iter: impl Fn()->T + Send + Sync + 'a
|
||||||
) -> impl Content<TuiOut> + 'a {
|
) -> impl Content<TuiOut> + 'a {
|
||||||
|
|
@ -341,211 +331,4 @@ impl Tek {
|
||||||
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, "▌"),
|
Bsp::e(Tui::fg_bg(bg, Reset, "▐"), Bsp::w(Tui::fg_bg(bg, Reset, "▌"),
|
||||||
Tui::fg_bg(fg, bg, content))) }
|
Tui::fg_bg(fg, bg, content))) }
|
||||||
|
|
||||||
// TRACKS /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
self.row(self.w(), 3, Tui::bg(Tui::g(32), Fill::x(Align::w({
|
|
||||||
let data = (self.selected.track().unwrap_or(0), self.tracks().len());
|
|
||||||
self.fmtd.write().unwrap().trks.update(Some(data),
|
|
||||||
rewrite!(buf, "({}/{})", data.0, data.1));
|
|
||||||
Bsp::e(
|
|
||||||
self.button3(" t", "track", self.fmtd.read().unwrap().trks.view.clone()),
|
|
||||||
self.button2(" T", "add track"),
|
|
||||||
)
|
|
||||||
}))), self.per_track(|t, track|{
|
|
||||||
let active = self.selected().track() == Some(t+1);
|
|
||||||
let name = &track.name;
|
|
||||||
let fg = track.color.lightest.rgb;
|
|
||||||
let bg = if active { track.color.light.rgb } else { track.color.base.rgb };
|
|
||||||
let bg2 = Reset;//if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
|
||||||
let bfg = if active { Rgb(255,255,255) } else { Rgb(0,0,0) };
|
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Align::nw(name))))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// ACTIVE CLIPS ///////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn view_clips_into (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let heading = Align::e("Into:");
|
|
||||||
let content = self.per_track_top(|_, _|Tui::bg(Reset, " --- "));
|
|
||||||
self.row_top(self.w(), 1, heading, content)
|
|
||||||
}
|
|
||||||
fn view_clips_from (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let heading = Align::e("From:");
|
|
||||||
let content = self.per_track_top(|_, _|Tui::bg(Reset, " --- "));
|
|
||||||
self.row_top(self.w(), 1, heading, content)
|
|
||||||
}
|
|
||||||
fn view_clips_next (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let heading = Align::e("Next:");
|
|
||||||
let content = self.per_track_top(|_, _|Tui::bg(Reset, " --- "));
|
|
||||||
self.row_top(self.w(), 1, heading, content)
|
|
||||||
}
|
|
||||||
|
|
||||||
// INPUTS /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn view_inputs (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let fg = Tui::g(224);
|
|
||||||
let key = " i";
|
|
||||||
let label = "midi ins";
|
|
||||||
let count = self.midi_ins.len();
|
|
||||||
Bsp::s(
|
|
||||||
Bsp::s(
|
|
||||||
self.row_top(self.w(), 1,
|
|
||||||
Fill::x(Align::w(Bsp::e(
|
|
||||||
self.button3(" i", "midi ins", format!("{count}")),
|
|
||||||
self.button2(" I", "add midi in"),
|
|
||||||
))),
|
|
||||||
self.per_track_top(move|t, track|{
|
|
||||||
let rec = track.player.recording;
|
|
||||||
let mon = track.player.monitoring;
|
|
||||||
let rec = if rec { White } else { track.color.darkest.rgb };
|
|
||||||
let mon = if mon { White } else { track.color.darkest.rgb };
|
|
||||||
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 };
|
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Bsp::e(
|
|
||||||
Tui::fg_bg(rec, bg, "Rec "),
|
|
||||||
Tui::fg_bg(mon, bg, "Mon ")))))})),
|
|
||||||
self.row_top(self.w(), self.h_inputs() - 1,
|
|
||||||
self.io_ports(fg, Tui::g(32), ||self.inputs_sizes()),
|
|
||||||
self.per_track_top(move|t, track|self.io_connections(
|
|
||||||
track.color.dark.rgb,
|
|
||||||
track.color.darker.rgb,
|
|
||||||
||self.inputs_sizes()
|
|
||||||
))),
|
|
||||||
),
|
|
||||||
self.view_clips_into()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// OUTPUTS ////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn view_outputs (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let fg = Tui::g(224);
|
|
||||||
let key = " o";
|
|
||||||
let label = "midi outs";
|
|
||||||
let count = self.midi_outs.len();
|
|
||||||
Align::n(Bsp::s(
|
|
||||||
Bsp::s(
|
|
||||||
self.view_clips_next(),
|
|
||||||
self.view_clips_from(),
|
|
||||||
),
|
|
||||||
Bsp::s(
|
|
||||||
self.row_top(self.w(), 1,
|
|
||||||
Fill::x(Align::w(Bsp::e(
|
|
||||||
self.button3(" o", "midi outs", format!("{count}")),
|
|
||||||
self.button2(" O", "add midi out"),
|
|
||||||
))),
|
|
||||||
self.per_track_top(move|t, track|{
|
|
||||||
let mute = false;
|
|
||||||
let solo = false;
|
|
||||||
let mute = if mute { White } else { track.color.darkest.rgb };
|
|
||||||
let solo = if solo { White } else { track.color.darkest.rgb };
|
|
||||||
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 };
|
|
||||||
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Bsp::e(
|
|
||||||
Tui::fg_bg(mute, bg, "Play "),
|
|
||||||
Tui::fg_bg(solo, bg, "Solo ")))))})),
|
|
||||||
self.row_top(self.w(), self.h_outputs() - 1,
|
|
||||||
self.io_ports(fg, Tui::g(32), ||self.outputs_sizes()),
|
|
||||||
self.per_track_top(move|t, track|self.io_connections(
|
|
||||||
track.color.dark.rgb, track.color.darker.rgb, ||self.outputs_sizes()))),
|
|
||||||
)
|
|
||||||
))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SCENES /////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
fn view_scenes (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let w = self.size.w() as u16;
|
|
||||||
let h = self.size.h() as u16;
|
|
||||||
let editing = self.is_editing();
|
|
||||||
let selected_track = self.selected().track();
|
|
||||||
let selected_scene = self.selected().scene();
|
|
||||||
self.row(w, h,
|
|
||||||
Align::y(Map::new(
|
|
||||||
move||self.scenes_sizes(editing, 2, 15).map_while(
|
|
||||||
move|(s, scene, y1, y2)|if y2 as u16 > 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(),
|
|
||||||
self.per_track(move|t, track|{
|
|
||||||
let same_track = selected_track == Some(t+1);
|
|
||||||
Map::new(
|
|
||||||
move||self.scenes_sizes(editing, 2, 15).map_while(
|
|
||||||
move|(s, scene, y1, y2)|if y2 as u16 > h { None } else { Some((s, scene, y1, y2, if s == 0 {
|
|
||||||
None } else { Some(self.scenes[s-1].clips[t].as_ref()
|
|
||||||
.map(|c|c.read().unwrap().color)
|
|
||||||
.unwrap_or(ItemPalette::G[32])) })) }),
|
|
||||||
move|(_, scene, y1, y2, prev), s| {
|
|
||||||
let height = (1 + y2 - y1) as u16;
|
|
||||||
let (name, fg, bg) = if let Some(clip) = &scene.clips[t] {
|
|
||||||
let clip = clip.read().unwrap();
|
|
||||||
(Some(clip.name.clone()), clip.color.lightest.rgb, clip.color)
|
|
||||||
} else {
|
|
||||||
(None, Tui::g(96), ItemPalette::G[32])
|
|
||||||
};
|
|
||||||
let active = editing && same_track && selected_scene == Some(s+1);
|
|
||||||
let edit = |x|Bsp::b(x, When(active, &self.editor));
|
|
||||||
map_south(y1 as u16, height, edit(Fixed::y(height, self.view_clip_cell(
|
|
||||||
same_track, s, &bg, prev, name, " ⏹ ", fg))))})
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
const TAB: &str = " Tab";
|
|
||||||
fn view_clip_cell <'a> (
|
|
||||||
&self,
|
|
||||||
same_track: bool,
|
|
||||||
scene: usize,
|
|
||||||
color: &ItemPalette,
|
|
||||||
prev: Option<ItemPalette>,
|
|
||||||
name: Option<Arc<str>>,
|
|
||||||
icon: &'a str,
|
|
||||||
fg: Color,
|
|
||||||
) -> impl Content<TuiOut> + use<'a> {
|
|
||||||
let selected_scene = self.selected().scene();
|
|
||||||
let selected = same_track && selected_scene == Some(scene+1);
|
|
||||||
let neighbor = same_track && selected_scene == Some(scene);
|
|
||||||
let is_last = scene == self.scenes.len().saturating_sub(1);
|
|
||||||
let colors = colors(color, prev, selected, neighbor, is_last);
|
|
||||||
let content = Fill::x(Align::w(Tui::fg(fg, Tui::bold(true, Bsp::e(icon, name)))));
|
|
||||||
Phat { width: 0, height: 0, selected, content, colors, }
|
|
||||||
}
|
|
||||||
fn view_scene_add (&self) -> impl Content<TuiOut> + use<'_> {
|
|
||||||
let data = (self.selected().scene().unwrap_or(0), self.scenes().len());
|
|
||||||
self.fmtd.write().unwrap().scns.update(Some(data), rewrite!(buf, "({}/{})", data.0, data.1));
|
|
||||||
self.button3(" S", "add scene", self.fmtd.read().unwrap().scns.view.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn colors (
|
|
||||||
this: &ItemPalette,
|
|
||||||
prev: Option<ItemPalette>,
|
|
||||||
selected: bool,
|
|
||||||
neighbor: bool,
|
|
||||||
is_last: bool,
|
|
||||||
) -> [Color;4] {
|
|
||||||
let fg = this.lightest.rgb;
|
|
||||||
let bg = if selected { this.light } else { this.base }.rgb;
|
|
||||||
let hi = if neighbor {
|
|
||||||
prev.map(|prev|prev.light.rgb)
|
|
||||||
} else {
|
|
||||||
prev.map(|prev|prev.base.rgb)
|
|
||||||
}.unwrap_or(Reset);
|
|
||||||
let lo = if is_last {
|
|
||||||
Reset
|
|
||||||
} else if selected {
|
|
||||||
this.light.rgb
|
|
||||||
} else {
|
|
||||||
this.base.rgb
|
|
||||||
};
|
|
||||||
[fg, bg, hi, lo]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
112
tek/src/view/clip.rs
Normal file
112
tek/src/view/clip.rs
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
use crate::*;
|
||||||
|
impl Tek {
|
||||||
|
pub fn view_tracks (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let data = (self.selected.track().unwrap_or(0), self.tracks().len());
|
||||||
|
self.fmtd.write().unwrap().trks.update(Some(data), rewrite!(buf, "({}/{})", data.0, data.1));
|
||||||
|
self.row(self.w(), 3, Align::w(Bsp::e(
|
||||||
|
self.button3(" t", "track", self.fmtd.read().unwrap().trks.view.clone()),
|
||||||
|
self.button2(" T", "add track"),
|
||||||
|
)), self.per_track(|t, track|{
|
||||||
|
let active = self.selected().track() == Some(t+1);
|
||||||
|
let name = &track.name;
|
||||||
|
let fg = track.color.lightest.rgb;
|
||||||
|
let bg = if active { track.color.light.rgb } else { track.color.base.rgb };
|
||||||
|
let bg2 = Reset;//if t > 0 { self.tracks()[t - 1].color.base.rgb } else { Reset };
|
||||||
|
let bfg = if active { Rgb(255,255,255) } else { Rgb(0,0,0) };
|
||||||
|
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Align::nw(name))))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
pub fn view_scenes (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let w = self.size.w() as u16;
|
||||||
|
let h = self.size.h() as u16;
|
||||||
|
let editing = self.is_editing();
|
||||||
|
let selected_track = self.selected().track();
|
||||||
|
let selected_scene = self.selected().scene();
|
||||||
|
self.row(w, h,
|
||||||
|
Align::y(Map::new(
|
||||||
|
move||self.scenes_sizes(editing, 2, 15).map_while(
|
||||||
|
move|(s, scene, y1, y2)|if y2 as u16 > 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(),
|
||||||
|
self.per_track(move|t, track|{
|
||||||
|
let same_track = selected_track == Some(t+1);
|
||||||
|
Map::new(
|
||||||
|
move||self.scenes_sizes(editing, 2, 15).map_while(
|
||||||
|
move|(s, scene, y1, y2)|if y2 as u16 > h { None } else { Some((s, scene, y1, y2, if s == 0 {
|
||||||
|
None } else { Some(self.scenes[s-1].clips[t].as_ref()
|
||||||
|
.map(|c|c.read().unwrap().color)
|
||||||
|
.unwrap_or(ItemPalette::G[32])) })) }),
|
||||||
|
move|(_, scene, y1, y2, prev), s| {
|
||||||
|
let height = (1 + y2 - y1) as u16;
|
||||||
|
let (name, fg, bg) = if let Some(clip) = &scene.clips[t] {
|
||||||
|
let clip = clip.read().unwrap();
|
||||||
|
(Some(clip.name.clone()), clip.color.lightest.rgb, clip.color)
|
||||||
|
} else {
|
||||||
|
(None, Tui::g(96), ItemPalette::G[32])
|
||||||
|
};
|
||||||
|
let active = editing && same_track && selected_scene == Some(s+1);
|
||||||
|
let edit = |x|Bsp::b(x, When(active, &self.editor));
|
||||||
|
map_south(y1 as u16, height, edit(Fixed::y(height, self.view_clip_cell(
|
||||||
|
same_track, s, &bg, prev, name, " ⏹ ", fg))))})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
const TAB: &str = " Tab";
|
||||||
|
fn view_clip_cell <'a> (
|
||||||
|
&self,
|
||||||
|
same_track: bool,
|
||||||
|
scene: usize,
|
||||||
|
color: &ItemPalette,
|
||||||
|
prev: Option<ItemPalette>,
|
||||||
|
name: Option<Arc<str>>,
|
||||||
|
icon: &'a str,
|
||||||
|
fg: Color,
|
||||||
|
) -> impl Content<TuiOut> + use<'a> {
|
||||||
|
let selected_scene = self.selected().scene();
|
||||||
|
let selected = same_track && selected_scene == Some(scene+1);
|
||||||
|
let neighbor = same_track && selected_scene == Some(scene);
|
||||||
|
let is_last = scene == self.scenes.len().saturating_sub(1);
|
||||||
|
let colors = Self::colors(color, prev, selected, neighbor, is_last);
|
||||||
|
let content = Fill::x(Align::w(Tui::fg(fg, Tui::bold(true, Bsp::e(icon, name)))));
|
||||||
|
Phat { width: 0, height: 0, selected, content, colors, }
|
||||||
|
}
|
||||||
|
pub fn view_scene_add (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let data = (self.selected().scene().unwrap_or(0), self.scenes().len());
|
||||||
|
self.fmtd.write().unwrap().scns.update(Some(data), rewrite!(buf, "({}/{})", data.0, data.1));
|
||||||
|
self.button3(" S", "add scene", self.fmtd.read().unwrap().scns.view.clone())
|
||||||
|
}
|
||||||
|
fn colors (
|
||||||
|
this: &ItemPalette,
|
||||||
|
prev: Option<ItemPalette>,
|
||||||
|
selected: bool,
|
||||||
|
neighbor: bool,
|
||||||
|
is_last: bool,
|
||||||
|
) -> [Color;4] {
|
||||||
|
let fg = this.lightest.rgb;
|
||||||
|
let bg = if selected { this.light } else { this.base }.rgb;
|
||||||
|
let hi = if neighbor {
|
||||||
|
prev.map(|prev|prev.light.rgb)
|
||||||
|
} else {
|
||||||
|
prev.map(|prev|prev.base.rgb)
|
||||||
|
}.unwrap_or(Reset);
|
||||||
|
let lo = if is_last {
|
||||||
|
Reset
|
||||||
|
} else if selected {
|
||||||
|
this.light.rgb
|
||||||
|
} else {
|
||||||
|
this.base.rgb
|
||||||
|
};
|
||||||
|
[fg, bg, hi, lo]
|
||||||
|
}
|
||||||
|
}
|
||||||
42
tek/src/view/input.rs
Normal file
42
tek/src/view/input.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
use crate::*;
|
||||||
|
impl Tek {
|
||||||
|
pub fn view_inputs (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let fg = Tui::g(224);
|
||||||
|
Bsp::s(
|
||||||
|
Bsp::s(
|
||||||
|
self.row_top(self.w(), 1,
|
||||||
|
Fill::x(Align::w(Bsp::e(
|
||||||
|
self.button3(" i", "midi ins", format!("{}", self.midi_ins.len())),
|
||||||
|
self.button2(" I", "add midi in"),
|
||||||
|
))),
|
||||||
|
self.per_track_top(move|t, track|{
|
||||||
|
let rec = track.player.recording;
|
||||||
|
let mon = track.player.monitoring;
|
||||||
|
let rec = if rec { White } else { track.color.darkest.rgb };
|
||||||
|
let mon = if mon { White } else { track.color.darkest.rgb };
|
||||||
|
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 };
|
||||||
|
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Bsp::e(
|
||||||
|
Tui::fg_bg(rec, bg, "Rec "),
|
||||||
|
Tui::fg_bg(mon, bg, "Mon ")))))})),
|
||||||
|
self.row_top(self.w(), self.h_inputs() - 1,
|
||||||
|
self.io_ports(fg, Tui::g(32), ||self.inputs_sizes()),
|
||||||
|
self.per_track_top(move|t, track|self.io_connections(
|
||||||
|
track.color.dark.rgb,
|
||||||
|
track.color.darker.rgb,
|
||||||
|
||self.inputs_sizes()
|
||||||
|
))),
|
||||||
|
),
|
||||||
|
self.view_clips_into()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
fn view_clips_into (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let heading = Align::e("Into:");
|
||||||
|
let content = self.per_track_top(|_, _|Tui::bg(Reset, " --- "));
|
||||||
|
self.row_top(self.w(), 1, heading, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
43
tek/src/view/output.rs
Normal file
43
tek/src/view/output.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
use crate::*;
|
||||||
|
impl Tek {
|
||||||
|
pub fn view_outputs (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let fg = Tui::g(224);
|
||||||
|
Align::n(Bsp::s(
|
||||||
|
Bsp::s(
|
||||||
|
self.view_clips_next(),
|
||||||
|
self.view_clips_from(),
|
||||||
|
),
|
||||||
|
Bsp::s(
|
||||||
|
self.row_top(self.w(), 1,
|
||||||
|
Fill::x(Align::w(Bsp::e(
|
||||||
|
self.button3(" o", "midi outs", format!("{}", self.midi_outs.len())),
|
||||||
|
self.button2(" O", "add midi out"),
|
||||||
|
))),
|
||||||
|
self.per_track_top(move|t, track|{
|
||||||
|
let mute = false;
|
||||||
|
let solo = false;
|
||||||
|
let mute = if mute { White } else { track.color.darkest.rgb };
|
||||||
|
let solo = if solo { White } else { track.color.darkest.rgb };
|
||||||
|
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 };
|
||||||
|
Self::wrap(bg, fg, Tui::bold(true, Fill::x(Bsp::e(
|
||||||
|
Tui::fg_bg(mute, bg, "Play "),
|
||||||
|
Tui::fg_bg(solo, bg, "Solo ")))))})),
|
||||||
|
self.row_top(self.w(), self.h_outputs() - 1,
|
||||||
|
self.io_ports(fg, Tui::g(32), ||self.outputs_sizes()),
|
||||||
|
self.per_track_top(move|t, track|self.io_connections(
|
||||||
|
track.color.dark.rgb, track.color.darker.rgb, ||self.outputs_sizes()))),
|
||||||
|
)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
fn view_clips_from (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let heading = Align::e("From:");
|
||||||
|
let content = self.per_track_top(|_, _|Tui::bg(Reset, " --- "));
|
||||||
|
self.row_top(self.w(), 1, heading, content)
|
||||||
|
}
|
||||||
|
fn view_clips_next (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
|
let heading = Align::e("Next:");
|
||||||
|
let content = self.per_track_top(|_, _|Tui::bg(Reset, " --- "));
|
||||||
|
self.row_top(self.w(), 1, heading, content)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue