wip: big flat pt.8: wh -> xy

This commit is contained in:
🪞👃🪞 2024-12-30 20:32:55 +01:00
parent da25b28ebf
commit e958b4a2d2
27 changed files with 117 additions and 117 deletions

17
Cargo.lock generated
View file

@ -1263,10 +1263,8 @@ version = "0.2.0"
dependencies = [
"atomic_float",
"backtrace",
"better-panic",
"clap",
"clojure-reader",
"crossterm",
"jack",
"livi",
"midly",
@ -1274,9 +1272,8 @@ dependencies = [
"palette",
"quanta",
"rand",
"ratatui",
"symphonia",
"tek_engine",
"tek_layout",
"toml",
"uuid",
"wavers",
@ -1285,6 +1282,18 @@ dependencies = [
[[package]]
name = "tek_engine"
version = "0.2.0"
dependencies = [
"better-panic",
"crossterm",
"ratatui",
]
[[package]]
name = "tek_layout"
version = "0.2.0"
dependencies = [
"tek_engine",
]
[[package]]
name = "thiserror"

View file

@ -4,7 +4,6 @@ edition = "2021"
version = "0.2.0"
[dependencies]
tek_engine = { path = "./engine" }
tek_layout = { path = "./layout" }
atomic_float = "1.0.0"

View file

@ -1,5 +1,5 @@
use crate::*;
use std::sync::{Arc, Mutex, RwLock};
//use std::sync::{Arc, Mutex, RwLock};
/// Rendering target
pub trait Output<E: Engine> {

View file

@ -10,7 +10,6 @@ pub(crate) use better_panic::{Settings, Verbosity};
pub use ::crossterm;
pub(crate) use crossterm::{
ExecutableCommand,
event::*,
terminal::{EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode},
event::{KeyCode, KeyModifiers, KeyEvent, KeyEventKind, KeyEventState},
};
@ -115,7 +114,7 @@ impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tu
break
}
if ::crossterm::event::poll(poll).is_ok() {
let event = TuiEvent::Input(::crossterm::event::read().unwrap());
let event = ::crossterm::event::read().unwrap();
match event {
key_pat!(Ctrl-KeyCode::Char('c')) => {
exited.store(true, Relaxed);
@ -161,20 +160,15 @@ impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tu
}
}
#[derive(Debug, Clone)]
pub struct TuiInput {
pub(crate) exited: Arc<AtomicBool>,
pub(crate) event: TuiEvent,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TuiEvent {
/// Terminal input
Input(Event),
pub(crate) event: crossterm::event::Event,
}
impl Input<Tui> for TuiInput {
type Event = TuiEvent;
fn event (&self) -> &TuiEvent {
type Event = crossterm::event::Event;
fn event (&self) -> &crossterm::event::Event {
&self.event
}
fn is_done (&self) -> bool {
@ -190,30 +184,30 @@ impl Input<Tui> for TuiInput {
(Ctrl-$code:pat) => { key_event_pat!($code, KeyModifiers::CONTROL) };
(Alt-$code:pat) => { key_event_pat!($code, KeyModifiers::ALT) };
(Shift-$code:pat) => { key_event_pat!($code, KeyModifiers::SHIFT) };
($code:pat) => { TuiEvent::Input(crossterm::event::Event::Key(KeyEvent {
($code:pat) => { crossterm::event::Event::Key(KeyEvent {
code: $code,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: KeyEventState::NONE
})) };
}) };
}
#[macro_export] macro_rules! key_event_pat {
($code:pat) => {
TuiEvent::Input(crossterm::event::Event::Key(KeyEvent {
crossterm::event::Event::Key(KeyEvent {
code: $code,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: KeyEventState::NONE
}))
})
};
($code:pat, $modifiers: pat) => {
TuiEvent::Input(crossterm::event::Event::Key(KeyEvent {
crossterm::event::Event::Key(KeyEvent {
code: $code,
modifiers: $modifiers,
kind: KeyEventKind::Press,
state: KeyEventState::NONE
}))
})
};
}
@ -236,20 +230,20 @@ impl Input<Tui> for TuiInput {
#[macro_export] macro_rules! key_event_expr {
($code:expr, $modifiers: expr) => {
TuiEvent::Input(crossterm::event::Event::Key(KeyEvent {
crossterm::event::Event::Key(KeyEvent {
code: $code,
modifiers: $modifiers,
kind: KeyEventKind::Press,
state: KeyEventState::NONE
}))
})
};
($code:expr) => {
TuiEvent::Input(crossterm::event::Event::Key(KeyEvent {
crossterm::event::Event::Key(KeyEvent {
code: $code,
modifiers: KeyModifiers::NONE,
kind: KeyEventKind::Press,
state: KeyEventState::NONE
}))
})
};
}

View file

@ -8,7 +8,7 @@ fn main () -> Usually<()> {
pub struct BspDemo<E: Engine>(std::marker::PhantomData<E>);
render!(<Tui>|self:BspDemo<Tui>|Fill::wh(Align::c(
render!(<Tui>|self:BspDemo<Tui>|Fill::xy(Align::c(
Bsp::n(Bsp::s(Bsp::e(Bsp::w("00", "11"), "22"), "33"), "44")
)));

View file

@ -1 +0,0 @@
use crate::*;

View file

@ -1,14 +1,11 @@
pub use ::tek_engine;
pub(crate) use ::tek_engine::*;
pub(crate) use std::ops::{Add, Sub, Mul, Div};
pub(crate) use std::fmt::{Display, Debug};
pub(crate) use std::marker::PhantomData;
pub(crate) use std::sync::atomic::Ordering::*;
mod collection; pub use self::collection::*;
mod direction; pub use self::direction::*;
mod layers; pub use self::layers::*;
mod logic; pub use self::logic::*;
mod space; pub use self::space::*;
mod transform; pub use self::transform::*;

View file

@ -111,13 +111,13 @@ render!(<Tui>|self: ArrangerTui|{
let with_size = |x|lay!([&self.size, x]);
let arranger = ||lay!(|add|{
let color = self.color;
add(&Fill::wh(Tui::bg(color.darkest.rgb, "")))?;
add(&Fill::wh(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))))?;
add(&Fill::xy(Tui::bg(color.darkest.rgb, "")))?;
add(&Fill::xy(Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb))))?;
add(&Self::render_mode(self))
});
Some(with_size(with_status(with_editbar(with_pool(with_transport(col!([
Fill::w(Fixed::h(20, arranger())),
Fill::wh(&self.editor),
Fill::x(Fixed::y(20, arranger())),
Fill::xy(&self.editor),
])))))))
});
audio!(|self: ArrangerTui, client, scope|{

View file

@ -1,6 +1,5 @@
use crate::*;
use ClockCommand::{Play, Pause};
use KeyCode::{Char, Delete, Tab, Up, Down, Left, Right};
#[derive(Clone, Debug)] pub enum ArrangerCommand {
History(isize),

View file

@ -15,7 +15,7 @@ from!(<'a>|args:(&'a ArrangerTui, usize)|ArrangerVClips<'a> = Self {
rows: ArrangerScene::ppqs(&args.0.scenes, args.1),
});
render!(<Tui>|self: ArrangerVClips<'a>|Fill::wh(
render!(<Tui>|self: ArrangerVClips<'a>|Fill::xy(
col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => {
Self::format_scene(self.tracks, scene, pulses)
})
@ -27,7 +27,7 @@ impl<'a> ArrangerVClips<'a> {
) -> impl Render<Tui> + use<'a> {
let height = 1.max((pulses / PPQ) as u16);
let playing = scene.is_playing(tracks);
Fixed::h(height, row!([
Fixed::y(height, row!([
Tui::bg(scene.color.base.rgb,
if playing { "" } else { " " }),
Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb,
@ -40,7 +40,7 @@ impl<'a> ArrangerVClips<'a> {
fn format_clip (
scene: &'a ArrangerScene, index: usize, track: &'a ArrangerTrack, w: u16, h: u16
) -> impl Render<Tui> + use<'a> {
Fixed::wh(w, h, Layers::new(move |add|{
Fixed::xy(w, h, Layers::new(move |add|{
if let Some(Some(phrase)) = scene.clips.get(index) {
let mut bg = TuiTheme::border_bg();
let name = &(phrase as &Arc<RwLock<MidiClip>>).read().unwrap().name.to_string();
@ -53,7 +53,7 @@ impl<'a> ArrangerVClips<'a> {
}
};
add(&Tui::bg(bg,
Push::x(1, Fixed::w(w, &name.as_str()[0..max_w])))
Push::x(1, Fixed::x(w, &name.as_str()[0..max_w])))
)?;
}
Ok(())

View file

@ -25,7 +25,7 @@ render!(<Tui>|self: ArrangerVHead<'a>|Push::x(self.scenes_w, row!(
Tui::fg(color.lightest.rgb, field)
])
}
Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::wh(w as u16, 5, col!([
Tui::bg(color.base.rgb, Min::xy(w as u16, h, Fixed::xy(w as u16, 5, col!([
row(color, &Self::format_name(track, w)),
row(color, &Self::format_input(track)?),
row(color, &Self::format_output(track)?),

View file

@ -3,7 +3,7 @@ use crate::*;
pub struct Bordered<S: BorderStyle, W: Render<Tui>>(pub S, pub W);
render!(<Tui>|self: Bordered<S: BorderStyle, W: Render<Tui>>|{
Fill::wh(lay!([Border(self.0), Padding::xy(1, 1, &self.1)]))
Fill::xy(lay!([Border(self.0), Padding::xy(1, 1, &self.1)]))
});
pub struct Border<S: BorderStyle>(pub S);

View file

@ -1,6 +1,5 @@
use crate::*;
use rand::{thread_rng, distributions::uniform::UniformSampler};
pub use ratatui::prelude::Color;
pub trait HasColor {
fn color (&self) -> ItemColor;

View file

@ -1,5 +0,0 @@
use crate::*;
mod content; pub use self::content::*;
mod render; pub use self::render::*;
mod handle; pub use self::handle::*;

View file

@ -40,17 +40,16 @@ pub enum FocusCommand<T: Send + Sync> {
impl<F: HasFocus + HasEnter + FocusGrid + FocusOrder> Command<F> for FocusCommand<F::Item> {
fn execute (self, state: &mut F) -> Perhaps<FocusCommand<F::Item>> {
use FocusCommand::*;
match self {
Next => { state.focus_next(); },
Prev => { state.focus_prev(); },
Up => { state.focus_up(); },
Down => { state.focus_down(); },
Left => { state.focus_left(); },
Right => { state.focus_right(); },
Enter => { state.focus_enter(); },
Exit => { state.focus_exit(); },
Set(to) => { state.set_focused(to); },
Self::Next => { state.focus_next(); },
Self::Prev => { state.focus_prev(); },
Self::Up => { state.focus_up(); },
Self::Down => { state.focus_down(); },
Self::Left => { state.focus_left(); },
Self::Right => { state.focus_right(); },
Self::Enter => { state.focus_enter(); },
Self::Exit => { state.focus_exit(); },
Self::Set(to) => { state.set_focused(to); },
}
Ok(None)
}
@ -248,7 +247,6 @@ pub trait FocusWrap<T> {
}
pub fn to_focus_command <T: Send + Sync> (input: &TuiInput) -> Option<FocusCommand<T>> {
use KeyCode::{Tab, BackTab, Up, Down, Left, Right, Enter, Esc};
Some(match input.event() {
key_pat!(Tab) => FocusCommand::Next,
key_pat!(Shift-Tab) => FocusCommand::Prev,

View file

@ -120,23 +120,23 @@ render!(<Tui>|self:Groovebox|{
let color = self.player.play_phrase().as_ref()
.and_then(|(_,p)|p.as_ref().map(|p|p.read().unwrap().color))
.clone();
let transport = Fixed::h(3, row!([
let transport = Fixed::y(3, row!([
PlayPause(self.clock().is_rolling()),
TransportView::new(self, color, true),
]));
let selector = Push::x(sampler_w, Fixed::h(1, row!(![
let selector = Push::x(sampler_w, Fixed::y(1, row!(![
PhraseSelector::play_phrase(&self.player),
PhraseSelector::next_phrase(&self.player),
])));
let pool = move|x|Split::w(false, pool_w, Pull::y(1, Fill::h(Align::e(PoolView(&self.pool)))), x);
let sampler = move|x|Split::e(false, sampler_w, Fill::wh(col!([
let pool = move|x|Split::w(false, pool_w, Pull::y(1, Fill::y(Align::e(PoolView(&self.pool)))), x);
let sampler = move|x|Split::e(false, sampler_w, Fill::xy(col!([
Meters(self.sampler.input_meter.as_ref()),
GrooveboxSamples(self)
])), x);
let status = EditStatus(&self.sampler, &self.editor, note_pt, pool(sampler(&self.editor)));
Fill::wh(lay!([
Fill::xy(lay!([
&self.size,
Fill::wh(Align::s(Fixed::h(2, GrooveboxStatus::from(self)))),
Fill::xy(Align::s(Fixed::y(2, GrooveboxStatus::from(self)))),
Shrink::y(2, col!(![transport, selector, status]))
]))
});
@ -154,7 +154,7 @@ impl<'a, T: Render<Tui>> Content<Tui> for EditStatus<'a, T> {
}),
lay!([
Outer(Style::default().fg(TuiTheme::g(128))),
Fill::w(Fixed::h(8, if let Some((_, sample)) = &self.0.recording {
Fill::x(Fixed::y(8, if let Some((_, sample)) = &self.0.recording {
SampleViewer(Some(sample.clone()))
} else if let Some(sample) = &self.0.mapped[self.2] {
SampleViewer(Some(sample.clone()))
@ -171,7 +171,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::wh(col!(note in (note_lo..=note_hi).rev() => {
Fill::xy(col!(note in (note_lo..=note_hi).rev() => {
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 {

View file

@ -1,18 +1,30 @@
#![allow(unused)]
#![allow(clippy::unit_arg)]
pub use ::tek_engine::*;
pub(crate) use ::tek_engine::{
pub use ::tek_layout;
pub use ::tek_layout::tek_engine;
pub(crate) use ::tek_layout::{
*,
tek_engine::{
Usually, Perhaps,
Engine, Size, Area,
Content, Render, render,
Handle, handle, kexp, key_pat, key_event_pat, key_event_expr,
Tui, TuiInput, TuiOutput,
crossterm::{
ExecutableCommand,
EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode};
KeyCode, KeyModifiers, KeyEvent, KeyEventKind, KeyEventState
self,
event::{
KeyEvent, KeyEventKind, KeyEventState, KeyModifiers,
KeyCode::{self, *},
}
},
ratatui::{
prelude::{Style, Buffer},
style::{Stylize, Modifier},
backend::{Backend, CrosstermBackend, ClearType}
},
self,
prelude::{Color, Style, Buffer, Modifier},
buffer::Cell,
}
}
};
pub(crate) use std::cmp::{Ord, Eq, PartialEq};
@ -33,7 +45,6 @@ pub mod arranger; pub use self::arranger::*;
pub mod border; pub use self::border::*;
pub mod color; pub use self::color::*;
pub mod command; pub use self::command::*;
pub mod engine; pub use self::engine::*;
pub mod event; pub use self::event::*;
pub mod file; pub use self::file::*;
pub mod focus; pub use self::focus::*;

View file

@ -76,7 +76,7 @@ render!(<Tui>|self: PianoHorizontal|{
let cursor = move||PianoHorizontalCursor(self);
let border = Fill::wh(Outer(Style::default().fg(self.color.dark.rgb).bg(self.color.darkest.rgb)));
let border = Fill::xy(Outer(Style::default().fg(self.color.dark.rgb).bg(self.color.darkest.rgb)));
let with_border = |x|lay!([border, Padding::xy(0, 0, &x)]);
with_border(lay!([
@ -86,18 +86,18 @@ render!(<Tui>|self: PianoHorizontal|{
field("Length:", length.to_string()), " ",
field("Loop:", looped.to_string())
])),
Padding::xy(0, 1, Fill::wh(Bsp::s(
Fixed::h(1, Bsp::e(
Fixed::w(self.keys_width, ""),
Padding::xy(0, 1, Fill::xy(Bsp::s(
Fixed::y(1, Bsp::e(
Fixed::x(self.keys_width, ""),
Fill::w(timeline()),
)),
Bsp::e(
Fixed::w(self.keys_width, keys()),
Fill::wh(lay!([
Fixed::x(self.keys_width, keys()),
Fill::xy(lay!([
&self.size,
Fill::wh(lay!([
Fill::wh(notes()),
Fill::wh(cursor()),
Fill::xy(lay!([
Fill::xy(notes()),
Fill::xy(cursor()),
]))
])),
),

View file

@ -208,9 +208,9 @@ render!(<Tui>|self: PoolView<'a>|{
let upper_right = format!("({})", phrases.len());
let color = self.0.phrase().read().unwrap().color;
Tui::bg(bg, lay!(move|add|{
add(&Fill::wh(Outer(Style::default().fg(color.base.rgb).bg(bg))))?;
add(&Fill::xy(Outer(Style::default().fg(color.base.rgb).bg(bg))))?;
//add(&Lozenge(Style::default().bg(border_bg).fg(border_color)))?;
add(&Padding::xy(0, 1, Fill::wh(col!(move|add|match mode {
add(&Padding::xy(0, 1, Fill::xy(col!(move|add|match mode {
Some(PoolMode::Import(_, ref file_picker)) => add(file_picker),
Some(PoolMode::Export(_, ref file_picker)) => add(file_picker),
_ => Ok(for (i, phrase) in phrases.iter().enumerate() {
@ -223,10 +223,10 @@ render!(<Tui>|self: PoolView<'a>|{
length.focus = Some(*focus);
}
}
add(&Tui::bg(color.base.rgb, Fill::w(col!([
Fill::w(lay!(|add|{
add(&Fill::w(Align::w(format!(" {i}"))))?;
add(&Fill::w(Align::e(Pull::x(1, length.clone()))))
add(&Tui::bg(color.base.rgb, Fill::x(col!([
Fill::x(lay!(|add|{
add(&Fill::x(Align::w(format!(" {i}"))))?;
add(&Fill::x(Align::e(Pull::x(1, length.clone()))))
})),
Tui::bold(true, {
let mut row2 = format!(" {name}");
@ -245,8 +245,8 @@ render!(<Tui>|self: PoolView<'a>|{
}))?;
})
}))))?;
add(&Fill::w(Align::nw(Push::x(1, Tui::fg(title_color, upper_left.to_string())))))?;
add(&Fill::w(Align::ne(Pull::x(1, Tui::fg(title_color, upper_right.to_string())))))?;
add(&Fill::x(Align::nw(Push::x(1, Tui::fg(title_color, upper_left.to_string())))))?;
add(&Fill::x(Align::ne(Pull::x(1, Tui::fg(title_color, upper_right.to_string())))))?;
add(&self.0.size)
}))
});

View file

@ -8,7 +8,7 @@ pub struct PhraseSelector {
}
// TODO: Display phrases always in order of appearance
render!(<Tui>|self: PhraseSelector|Fixed::wh(24, 1, row!([
render!(<Tui>|self: PhraseSelector|Fixed::xy(24, 1, row!([
Tui::fg(self.color.lightest.rgb, Tui::bold(true, &self.title)),
Tui::fg_bg(self.color.lighter.rgb, self.color.base.rgb, row!([
format!("{:8}", &self.name[0..8.min(self.name.len())]),

View file

@ -49,14 +49,14 @@ render!(<Tui>|self: SamplerTui|{
let keys = move||"";//SamplerKeys(self);
let fg = self.color.base.rgb;
let bg = self.color.darkest.rgb;
let border = Fill::wh(Outer(Style::default().fg(fg).bg(bg)));
let with_border = |x|lay!([border, Fill::wh(&x)]);
let border = Fill::xy(Outer(Style::default().fg(fg).bg(bg)));
let with_border = |x|lay!([border, Fill::xy(&x)]);
let with_size = |x|lay!([self.size, x]);
Tui::bg(bg, Fill::wh(with_border(Bsp::s(
Tui::bg(bg, Fill::xy(with_border(Bsp::s(
Tui::fg(self.color.light.rgb, Tui::bold(true, "Sampler")),
with_size(Shrink::y(1, Bsp::e(
Fixed::w(keys_width, keys()),
Fill::wh(render(|to: &mut TuiOutput|Ok({
Fixed::x(keys_width, keys()),
Fill::xy(render(|to: &mut TuiOutput|Ok({
let x = to.area.x();
let bg_base = self.color.darkest.rgb;
let bg_selected = self.color.darker.rgb;

View file

@ -44,13 +44,13 @@ render!(<Tui>|self: SequencerTui|{
let w = self.size.w();
let phrase_w = if w > 60 { 20 } else if w > 40 { 15 } else { 10 };
let pool_w = if self.phrases.visible { phrase_w } else { 0 };
let pool = Pull::y(1, Fill::h(Align::e(PoolView(&self.phrases))));
let pool = Pull::y(1, Fill::y(Align::e(PoolView(&self.phrases))));
let with_pool = move|x|Split::w(false, pool_w, pool, x);
let status = SequencerStatus::from(self);
let with_status = |x|Split::n(false, if self.status { 2 } else { 0 }, status, x);
let with_editbar = |x|Split::n(false, 1, MidiEditStatus(&self.editor), x);
let with_size = |x|lay!([self.size, x]);
let editor = with_editbar(with_pool(Fill::wh(&self.editor)));
let editor = with_editbar(with_pool(Fill::xy(&self.editor)));
let color = self.player.play_phrase().as_ref().map(|(_,p)|
p.as_ref().map(|p|p.read().unwrap().color)

View file

@ -20,9 +20,9 @@ from!(|state:&ArrangerTui|ArrangerStatus = {
size: format!("{}x{}│", width, state.size.h()),
}
});
render!(<Tui>|self: ArrangerStatus|Fixed::h(2, lay!([
render!(<Tui>|self: ArrangerStatus|Fixed::y(2, lay!([
Self::help(),
Fill::wh(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
])));
impl ArrangerStatus {
fn help () -> impl Render<Tui> {

View file

@ -17,7 +17,7 @@ render!(<Tui>|self:MidiEditStatus<'a>|{
let bg = color.darkest.rgb;
let fg = color.lightest.rgb;
Tui::bg(bg, Fill::w(Tui::fg(fg, row!([
Tui::bg(bg, Fill::x(Tui::fg(fg, row!([
field(" Time", format!("{}/{}-{} ({}*{}) {}",
self.0.time_point(), self.0.time_start().get(), self.0.time_end(),
self.0.time_axis().get(), self.0.time_zoom().get(),

View file

@ -20,9 +20,9 @@ from!(|state: &Groovebox|GrooveboxStatus = {
size: format!("{}x{}│", width, state.size.h()),
}
});
render!(<Tui>|self: GrooveboxStatus|Fixed::h(2, lay!([
render!(<Tui>|self: GrooveboxStatus|Fixed::y(2, lay!([
Self::help(),
Fill::wh(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
])));
impl GrooveboxStatus {
fn help () -> impl Render<Tui> {

View file

@ -20,9 +20,9 @@ from!(|state:&SequencerTui|SequencerStatus = {
size: format!("{}x{}│", width, state.size.h()),
}
});
render!(<Tui>|self: SequencerStatus|Fixed::h(2, lay!([
render!(<Tui>|self: SequencerStatus|Fixed::y(2, lay!([
Self::help(),
Fill::wh(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
Fill::xy(Align::se(Tui::fg_bg(TuiTheme::orange(), TuiTheme::g(25), self.stats()))),
])));
impl SequencerStatus {
fn help () -> impl Render<Tui> {

View file

@ -22,8 +22,8 @@ has_clock!(|self: TransportTui|&self.clock);
audio!(|self: TransportTui, client, scope|ClockAudio(self).process(client, scope));
handle!(<Tui>|self: TransportTui, from|TransportCommand::execute_with_state(self, from));
render!(<Tui>|self: TransportTui|row!([
Fixed::wh(5, 3, PlayPause(false)),
Fixed::h(3, TransportView::new(self, None, true))
Fixed::xy(5, 3, PlayPause(false)),
Fixed::y(3, TransportView::new(self, None, true))
]));
impl std::fmt::Debug for TransportTui {
fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
@ -87,7 +87,7 @@ impl TransportView {
}
render!(<Tui>|self: TransportView|{
let color = self.color;
Fixed::h(3, Tui::bg(color.base.rgb, Fill::w(row!([
Fixed::y(3, Tui::bg(color.base.rgb, Fill::x(row!([
//PlayPause(self.started), " ",
col!([
TransportField(" Beat", self.beat.as_str(), &color),
@ -114,7 +114,7 @@ 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::w(5, col!(|add|if self.0 {
Fixed::x(5, col!(|add|if self.0 {
add(&Tui::fg(Color::Rgb(0, 255, 0), col!([
" 🭍🭑🬽 ",
" 🭞🭜🭘 ",