mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
down to 28e, sane ones
This commit is contained in:
parent
46609855eb
commit
16e6a0397c
15 changed files with 91 additions and 87 deletions
|
|
@ -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 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
}
|
||||
)+}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) "))
|
||||
|
|
|
|||
|
|
@ -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::{
|
||||
|
|
|
|||
|
|
@ -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]),
|
||||
));
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
10
src/style.rs
10
src/style.rs
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 + {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue