down to 28e, sane ones

This commit is contained in:
🪞👃🪞 2024-12-31 15:50:53 +01:00
parent 46609855eb
commit 16e6a0397c
15 changed files with 91 additions and 87 deletions

View file

@ -1,4 +1,5 @@
use crate::*;
use std::marker::PhantomData;
//use std::sync::{Arc, Mutex, RwLock};
/// Rendering target
@ -42,54 +43,52 @@ impl<E: Engine, T: Content<E>> Content<E> for Option<T> {}
impl<E: Engine, T: Content<E>> Content<E> for Vec<T> {}
pub struct Thunk<E: Engine, T: Content<E>, F: Fn()->T + Send + Sync>(F, PhantomData<E>);
impl<E: Engine, T: Content<E>, F: Fn()->T + Send + Sync> Thunk<E, T, F> {
pub fn new (thunk: F) -> Self {
Self(thunk, Default::default())
}
}
impl<E: Engine, T: Content<E>, F: Fn()->T + Send + Sync> Content<E> for Thunk<E, T, F> {
fn content (&self) -> impl Content<E> {
(self.0)()
}
}
#[macro_export] macro_rules! render {
(($self:ident:$Struct:ty) => $content:expr) => {
impl <E: Engine> Content<E> for $Struct {
fn content (&$self) -> Option<impl Content<E>> {
Some($content)
}
fn content (&$self) -> impl Content<E> { Some($content) }
}
};
(|$self:ident:$Struct:ident $(<
$($L:lifetime),*
$($T:ident $(:$Trait:path)?),*
$($L:lifetime),* $($T:ident $(:$Trait:path)?),*
>)?, $to:ident | $render:expr) => {
impl <$($($L),*)? E: Engine, $($T$(:$Trait)?),*> Content<E>
for $Struct $(<$($L),* $($T),*>>)? {
fn render (&$self, $to: &mut E::Output) {
Some($render)
}
fn render (&$self, $to: &mut E::Output) { $render }
}
};
($Engine:ty:
($self:ident:$Struct:ident $(<$(
$($L:lifetime)?
$($T:ident)?
$(:$Trait:path)?
$($L:lifetime)? $($T:ident)? $(:$Trait:path)?
),+>)?) => $content:expr
) => {
impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Content<$Engine>
for $Struct $(<$($($L)? $($T)?),+>)?
{
fn content (&$self) -> Option<impl Content<$Engine>> {
Some($content)
}
for $Struct $(<$($($L)? $($T)?),+>)? {
fn content (&$self) -> impl Content<$Engine> { $content }
}
};
($Engine:ty:
|$self:ident : $Struct:ident $(<$(
$($L:lifetime)?
$($T:ident)?
$(:$Trait:path)?
$($L:lifetime)? $($T:ident)? $(:$Trait:path)?
),+>)?, $to:ident| $render:expr
) => {
impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Content<$Engine>
for $Struct $(<$($($L)? $($T)?),+>)?
{
fn render (&$self, $to: &mut <$Engine as Engine>::Output) {
Some($render)
}
for $Struct $(<$($($L)? $($T)?),+>)? {
fn render (&$self, $to: &mut <$Engine as Engine>::Output) { $render }
}
};
}

View file

@ -121,8 +121,8 @@ impl<E: Engine, X: Content<E>, Y: Content<E>> Default for Bsp<E, X, Y> {
impl<E: Engine, X: Content<E>, Y: Content<E>> Content<E> for Bsp<E, X, Y> {
fn render (&self, to: &mut E::Output) {
let n = E::Size::zero();
let s = to.wh();
let _n = E::Size::zero();
let _s = to.wh();
match self {
Self::Null(_) => {},
//Self::S(p, a, b) => {

View file

@ -25,13 +25,13 @@ macro_rules! transform_xy {
pub fn xy (item: T) -> Self { Self::XY(item) }
}
impl<E: Engine, T: Content<E>> Content<E> for $Enum<E, T> {
fn content (&self) -> Option<impl Content<E>> {
Some(match self {
fn content (&self) -> impl Content<E> {
match self {
Self::X(item) => item,
Self::Y(item) => item,
Self::XY(item) => item,
_ => unreachable!()
})
}
}
fn area (&$self, $to: <E as Engine>::Area) -> <E as Engine>::Area {
$area
@ -42,7 +42,7 @@ macro_rules! transform_xy {
transform_xy!(self: Fill |to|{
let [x0, y0, wmax, hmax] = to.xywh();
let [x, y, w, h] = self.content().unwrap().area(to).xywh();
let [x, y, w, h] = self.content().area(to).xywh();
return match self {
Self::X(_) => [x0, y, wmax, h],
Self::Y(_) => [x, y0, w, hmax],
@ -78,7 +78,7 @@ macro_rules! transform_xy_unit {
}
}
impl<E: Engine, T: Content<E>> Content<E> for $Enum<E, T> {
fn content (&self) -> Option<impl Content<E>> {
fn content (&self) -> impl Content<E> {
Some(match self {
Self::X(_, content) => content,
Self::Y(_, content) => content,

View file

@ -72,11 +72,16 @@ impl Content<Tui> for ArrangerVCursor {
to.fill_ul([area.x(), y - 1, area.w(), 1], bg);
to.fill_ul([area.x(), y + height - 1, area.w(), 1], bg);
}
Ok(if focused {
to.render_in(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)?
})
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)
};
}
}

View file

@ -24,7 +24,6 @@ render!(Tui: |self: Border<S: BorderStyle>, to| {
to.blit(&self.0.e(), area.x() + area.w() - 1, y, self.0.style());
}
}
Ok(())
});
pub trait BorderStyle: Send + Sync + Copy {
@ -130,7 +129,7 @@ macro_rules! border {
#[derive(Copy, Clone)]
pub struct $T(pub Style);
impl Content<Tui> for $T {
fn render (&self, to: &mut TuiOutput) { self.draw(to) }
fn render (&self, to: &mut TuiOutput) { self.draw(to); }
}
)+}
}

View file

@ -149,13 +149,14 @@ render!(Tui: (self: Groovebox) => {
struct EditStatus<'a, T: Content<Tui>>(&'a Sampler, &'a MidiEditor, usize, T);
impl<'a, T: Content<Tui>> Content<Tui> for EditStatus<'a, T> {
fn content (&self) -> Option<impl Content<Tui>> {
Some(Split::n(false, 9, col!(
fn content (&self) -> impl Content<Tui> {
Split::n(false, 9, col!(
row!(
Cond::opt(
&self.0.mapped[self.2],
|sample|format!("Sample {}", sample.read().unwrap().end)
),
self.0.mapped[self.2].as_ref().map(|sample|format!(
"Sample {}-{}",
sample.read().unwrap().start,
sample.read().unwrap().end,
)),
MidiEditStatus(&self.1),
),
lay!(
@ -168,7 +169,7 @@ impl<'a, T: Content<Tui>> Content<Tui> for EditStatus<'a, T> {
SampleViewer(None)
})),
),
), &self.3))
), &self.3)
}
}
@ -177,7 +178,7 @@ render!(Tui: (self: GrooveboxSamples<'a>) => {
let note_lo = self.0.editor.note_lo().load(Relaxed);
let note_pt = self.0.editor.note_point();
let note_hi = self.0.editor.note_hi();
Fill::xy(Coll::map((note_lo..=note_hi).rev(), |note, i| {
Fill::xy(Coll::map((note_lo..=note_hi).rev(), move|note, i| {
let mut bg = if note == note_pt { TuiTheme::g(64) } else { Color::Reset };
let mut fg = TuiTheme::g(160);
if let Some((index, _)) = self.0.sampler.recording {
@ -188,7 +189,7 @@ render!(Tui: (self: GrooveboxSamples<'a>) => {
} else if self.0.sampler.mapped[note].is_some() {
fg = TuiTheme::g(224);
}
Push::y(i, Tui::bg(bg, if let Some(sample) = &self.0.sampler.mapped[note] {
Push::y(i as u16, Tui::bg(bg, if let Some(sample) = &self.0.sampler.mapped[note] {
Tui::fg(fg, format!("{note:3} ?????? "))
} else {
Tui::fg(fg, format!("{note:3} (none) "))

View file

@ -9,7 +9,7 @@ pub(crate) use ::tek_layout::{
tek_engine::{
Usually, Perhaps,
Engine, Size, Area,
Output, Content, render,
Output, Content, Thunk, render,
Input, Handle, handle,
kexp, key_pat, key_event_pat, key_event_expr,
tui::{

View file

@ -3,6 +3,6 @@ use crate::*;
pub struct Meters<'a>(pub &'a[f32]);
render!(Tui: (self: Meters<'a>) => col!(
&format!("L/{:>+9.3}", self.0[0]),
&format!("R/{:>+9.3}", self.0[1]),
format!("L/{:>+9.3}", self.0[0]),
format!("R/{:>+9.3}", self.0[1]),
));

View file

@ -97,7 +97,7 @@ pub struct TrackView<'a> {
}
impl<'a> Content<Tui> for TrackView<'a> {
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
fn render (&self, to: &mut TuiOutput) {
todo!();
//let mut area = to.area();
//if let Some(chain) = self.chain {

View file

@ -5,14 +5,14 @@ pub struct PianoHorizontalKeys<'a>(pub(crate) &'a PianoHorizontal);
render!(Tui: |self: PianoHorizontalKeys<'a>, to|{
let state = self.0;
let color = state.color();
let color = state.color;
let note_lo = state.note_lo().get();
let note_hi = state.note_hi();
let note_point = state.note_point();
let [x, y0, w, h] = to.area().xywh();
let key_style = Some(Style::default().fg(Color::Rgb(192, 192, 192)).bg(Color::Rgb(0, 0, 0)));
let off_style = Some(Style::default().fg(TuiTheme::g(160)));
let on_style = Some(Style::default().fg(TuiTheme::g(255)).bg(color.rgb).bold());
let on_style = Some(Style::default().fg(TuiTheme::g(255)).bg(color.base.rgb).bold());
for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
to.blit(&to_key(note), x, screen_y, key_style);
if note > 127 {

View file

@ -171,7 +171,7 @@ fn draw_sample (
}
impl Content<Tui> for AddSampleModal {
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
fn render (&self, to: &mut TuiOutput) {
todo!()
//let area = to.area();
//to.make_dim();

View file

@ -52,6 +52,4 @@ render!(Tui: |self: SampleViewer, to|{
.y_bounds(y_bounds)
.paint(|ctx| { for line in lines.iter() { ctx.draw(line) } })
.render(area, &mut to.buffer);
Ok(())
});

View file

@ -82,7 +82,7 @@ render!(Tui: |self: SamplesTui, render|{
let note = self.note_hi - y as usize;
let bg = if note == self.note_pt { bg_selected } else { bg_base };
let style = Some(style_empty.bg(bg));
render.blit(&" (no sample) ", x, render.area.y() + y as u16, style)
render.blit(&" (no sample) ", x, render.area.y() + y as u16, style);
}
});

View file

@ -23,7 +23,7 @@ impl TuiStyle for Tui {}
pub struct Bold<W: Content<Tui>>(pub bool, W);
impl<W: Content<Tui>> Content<Tui> for Bold<W> {
fn content (&self) -> Option<impl Content<Tui>> {
fn content (&self) -> impl Content<Tui> {
Some(&self.1)
}
fn render (&self, to: &mut TuiOutput) {
@ -35,7 +35,7 @@ impl<W: Content<Tui>> Content<Tui> for Bold<W> {
pub struct Foreground<W: Content<Tui>>(pub Color, W);
impl<W: Content<Tui>> Content<Tui> for Foreground<W> {
fn content (&self) -> Option<impl Content<Tui>> {
fn content (&self) -> impl Content<Tui> {
Some(&self.1)
}
fn render (&self, to: &mut TuiOutput) {
@ -47,7 +47,7 @@ impl<W: Content<Tui>> Content<Tui> for Foreground<W> {
pub struct Background<W: Content<Tui>>(pub Color, W);
impl<W: Content<Tui>> Content<Tui> for Background<W> {
fn content (&self) -> Option<impl Content<Tui>> {
fn content (&self) -> impl Content<Tui> {
Some(&self.1)
}
fn render (&self, to: &mut TuiOutput) {
@ -59,14 +59,14 @@ impl<W: Content<Tui>> Content<Tui> for Background<W> {
pub struct Styled<T: Content<Tui>>(pub Option<Style>, pub T);
impl Content<Tui> for Styled<&str> {
fn content (&self) -> Option<impl Content<Tui>> {
fn content (&self) -> impl Content<Tui> {
Some(&self.1)
}
fn render (&self, to: &mut TuiOutput) {
// FIXME
let [x, y, ..] = to.area();
//let [w, h] = self.min_size(to.area().wh())?.unwrap();
Ok(to.blit(&self.1, x, y, None))
to.blit(&self.1, x, y, None)
}
}

View file

@ -89,23 +89,29 @@ impl TransportView {
}
render!(Tui: (self: TransportView) => {
let color = self.color;
let transport_field = move|label, value|row!(
Tui::fg_bg(color.lightest.rgb, color.base.rgb, Tui::bold(true, label)),
Tui::fg_bg(color.base.rgb, color.darkest.rgb, ""),
Tui::fg_bg(color.lightest.rgb, color.darkest.rgb, format!("{:>10}", value)),
Tui::fg_bg(color.darkest.rgb, color.base.rgb, ""),
);
Fixed::y(3, Tui::bg(color.base.rgb, Fill::x(row!(
col!(
TransportField(" Beat", self.beat.as_str(), &color),
TransportField(" Time", format!("{:.1}s", self.current_second).as_str(), &color),
TransportField(" BPM", self.bpm.as_str(), &color),
),
col!(
TransportField(" Rate", format!("{}", self.sr).as_str(), &color),
TransportField(" Chunk", format!("{}", self.chunk).as_str(), &color),
TransportField(" Lag", format!("{:.3}ms", self.latency).as_str(), &color),
),
Thunk::new(move||col!(
transport_field(" Beat", self.beat.as_str()),
transport_field(" Time", format!("{:.1}s", self.current_second).as_str()),
transport_field(" BPM", self.bpm.as_str()),
)),
Thunk::new(move||col!(
transport_field(" Rate", format!("{}", self.sr).as_str()),
transport_field(" Chunk", format!("{}", self.chunk).as_str()),
transport_field(" Lag", format!("{:.3}ms", self.latency).as_str()),
)),
col!(
//Field(" CPU%", format!("{:.1}ms", self.perf).as_str(), &color),
),
))))
});
struct TransportField<'a>(&'a str, &'a str, &'a ItemPalette);
struct TransportField<'a>(&'a str, &'a str, ItemPalette);
render!(Tui: (self: TransportField<'a>) => row!(
Tui::fg_bg(self.2.lightest.rgb, self.2.base.rgb, Tui::bold(true, self.0)),
Tui::fg_bg(self.2.base.rgb, self.2.darkest.rgb, ""),
@ -115,17 +121,13 @@ render!(Tui: (self: TransportField<'a>) => row!(
pub struct PlayPause(pub bool);
render!(Tui: (self: PlayPause) => Tui::bg(
if self.0{Color::Rgb(0,128,0)}else{Color::Rgb(128,64,0)},
Fixed::x(5, col!(|add|if self.0 {
add(&Tui::fg(Color::Rgb(0, 255, 0), col!(
" 🭍🭑🬽 ",
" 🭞🭜🭘 ",
)))
} else {
add(&Tui::fg(Color::Rgb(255, 128, 0), col!(
" ▗▄▖ ",
" ▝▀▘ ",
)))
}))
Fixed::x(5, Cond::either(self.0, Tui::fg(Color::Rgb(0, 255, 0), col!(
" 🭍🭑🬽 ",
" 🭞🭜🭘 ",
)), Tui::fg(Color::Rgb(255, 128, 0), col!(
" ▗▄▖ ",
" ▝▀▘ ",
))))
));
impl HasFocus for TransportTui {
type Item = TransportFocus;
@ -152,7 +154,7 @@ impl FocusWrap<TransportFocus> for TransportFocus {
let focused = focus == self;
let corners = focused.then_some(CORNERS);
//let highlight = focused.then_some(Tui::bg(Color::Rgb(60, 70, 50)));
lay!(corners, /*highlight,*/ *content)
lay!(corners, /*highlight,*/ content)
}
}
impl FocusWrap<TransportFocus> for Option<TransportFocus> {
@ -162,7 +164,7 @@ impl FocusWrap<TransportFocus> for Option<TransportFocus> {
let focused = Some(focus) == self;
let corners = focused.then_some(CORNERS);
//let highlight = focused.then_some(Background(Color::Rgb(60, 70, 50)));
lay!(corners, /*highlight,*/ *content)
lay!(corners, /*highlight,*/ content)
}
}
pub trait TransportControl<T>: HasClock + {