wip6 (60e):

This commit is contained in:
🪞👃🪞 2024-12-09 18:31:53 +01:00
parent 7d78811f68
commit 3b73da86e0
25 changed files with 212 additions and 227 deletions

View file

@ -1,3 +1,5 @@
// manja s grozde; ikebana s chiaroscuro
use crate::*;
submod! {
@ -18,7 +20,3 @@ submod! {
split
stack
}
#[macro_export] macro_rules! lay {
($($expr:expr),* $(,)?) => { Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) }
}

View file

@ -1 +0,0 @@
manja s grozde i ikebana s chiaroscuro

View file

@ -1,6 +1,6 @@
use crate::*;
impl<E: Engine, W: Render<E>> LayoutFixed<E> for W {}
impl<E: Engine> LayoutFixed<E> for E {}
pub trait LayoutFixed<E: Engine> {
fn fixed_x <W: Render<E>> (x: E::Unit, w: W) -> Fixed<E, W> {

View file

@ -25,7 +25,6 @@ pub trait LayoutInsetOutset<E: Engine>: LayoutPushPull<E> + LayoutShrinkGrow<E>
/// Shrink from each side
pub enum Inset<E: Engine, T> {
_Unused(PhantomData<E>),
/// Decrease width
X(E::Unit, T),
/// Decrease height
@ -40,7 +39,6 @@ impl<E: Engine, T: Render<E>> Inset<E, T> {
Self::X(_, i) => i,
Self::Y(_, i) => i,
Self::XY(_, _, i) => i,
_ => unreachable!(),
}
}
}
@ -51,14 +49,12 @@ impl<E: Engine, T: Render<E>> Render<E> for Inset<E, T> {
Self::X(x, inner) => E::push_x(*x, E::shrink_x(*x, inner)),
Self::Y(y, inner) => E::push_y(*y, E::shrink_y(*y, inner)),
Self::XY(x, y, inner) => E::push_xy(*x, *y, E::shrink_xy(*x, *y, inner)),
_ => unreachable!(),
}.render(to)
}
}
/// Grow on each side
pub enum Outset<E: Engine, T: Render<E>> {
_Unused(PhantomData<E>),
/// Increase width
X(E::Unit, T),
/// Increase height
@ -74,7 +70,6 @@ impl<E: Engine, T: Render<E>> Outset<E, T> {
Self::X(_, i) => i,
Self::Y(_, i) => i,
Self::XY(_, _, i) => i,
_ => unreachable!(),
}
}
}
@ -85,7 +80,6 @@ impl<E: Engine, T: Render<E>> Render<E> for Outset<E, T> {
Self::X(x, ref inner) => E::grow_x(x + x, inner),
Self::Y(y, ref inner) => E::grow_y(y + y, inner),
Self::XY(x, y, ref inner) => E::grow_xy(x + x, y + y, inner),
_ => unreachable!(),
}.min_size(to)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
@ -93,7 +87,6 @@ impl<E: Engine, T: Render<E>> Render<E> for Outset<E, T> {
Self::X(x, ref inner) => E::push_x(x, inner),
Self::Y(y, ref inner) => E::push_y(y, inner),
Self::XY(x, y, ref inner) => E::push_xy(x, y, inner),
_ => unreachable!(),
}.render(to)
}
}

View file

@ -1,5 +1,10 @@
use crate::*;
#[macro_export] macro_rules! lay {
($(move)*|$add:ident|$expr:expr) => { Layers::new($(move)*|$add|$expr) };
($($expr:expr),* $(,)?) => { Layers::new(move|add|{ $(add(&$expr)?;)* Ok(()) }) }
}
pub struct Layers<
E: Engine,
F: Send + Sync + Fn(&mut dyn FnMut(&dyn Render<E>)->Usually<()>)->Usually<()>

View file

@ -3,41 +3,57 @@ use crate::*;
impl<E: Engine> LayoutMinMax<E> for E {}
pub trait LayoutMinMax<E: Engine> {
fn min_x <W: Render<E>> (x: E::Unit, w: W) -> Min<E::Unit, W> {
fn min_x <W: Render<E>> (x: E::Unit, w: W) -> Min<E, W> {
Min::X(x, w)
}
fn min_y <W: Render<E>> (y: E::Unit, w: W) -> Min<E::Unit, W> {
fn min_y <W: Render<E>> (y: E::Unit, w: W) -> Min<E, W> {
Min::Y(y, w)
}
fn min_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Min<E::Unit, W> {
fn min_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Min<E, W> {
Min::XY(x, y, w)
}
fn max_x <W: Render<E>> (x: E::Unit, w: W) -> Max<E::Unit, W> {
fn max_x <W: Render<E>> (x: E::Unit, w: W) -> Max<E, W> {
Max::X(x, w)
}
fn max_y <W: Render<E>> (y: E::Unit, w: W) -> Max<E::Unit, W> {
fn max_y <W: Render<E>> (y: E::Unit, w: W) -> Max<E, W> {
Max::Y(y, w)
}
fn max_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Max<E::Unit, W> {
fn max_xy <W: Render<E>> (x: E::Unit, y: E::Unit, w: W) -> Max<E, W> {
Max::XY(x, y, w)
}
}
/// Enforce minimum size of drawing area
pub enum Min<U: Coordinate, T> {
pub enum Min<E: Engine, T: Render<E>> {
/// Enforce minimum width
X(U, T),
X(E::Unit, T),
/// Enforce minimum height
Y(U, T),
Y(E::Unit, T),
/// Enforce minimum width and height
XY(U, U, T),
XY(E::Unit, E::Unit, T),
}
impl<N: Coordinate, T> Min<N, T> {
/// Enforce maximum size of drawing area
pub enum Max<E: Engine, T: Render<E>> {
/// Enforce maximum width
X(E::Unit, T),
/// Enforce maximum height
Y(E::Unit, T),
/// Enforce maximum width and height
XY(E::Unit, E::Unit, T),
}
impl<E: Engine, T: Render<E>> Min<E, T> {
pub fn inner (&self) -> &T {
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
match self {
Self::X(_, i) => i,
Self::Y(_, i) => i,
Self::XY(_, _, i) => i,
}
}
}
impl<E: Engine, T: Render<E>> Render<E> for Min<E::Unit, T> {
impl<E: Engine, T: Render<E>> Render<E> for Min<E, T> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
Ok(self.inner().min_size(to)?.map(|to|match *self {
Self::X(w, _) => [to.w().max(w), to.h()],
@ -53,23 +69,17 @@ impl<E: Engine, T: Render<E>> Render<E> for Min<E::Unit, T> {
}
}
/// Enforce maximum size of drawing area
pub enum Max<U: Coordinate, T> {
/// Enforce maximum width
X(U, T),
/// Enforce maximum height
Y(U, T),
/// Enforce maximum width and height
XY(U, U, T),
}
impl<N: Coordinate, T> Max<N, T> {
impl<E: Engine, T: Render<E>> Max<E, T> {
fn inner (&self) -> &T {
match self { Self::X(_, i) => i, Self::Y(_, i) => i, Self::XY(_, _, i) => i, }
match self {
Self::X(_, i) => i,
Self::Y(_, i) => i,
Self::XY(_, _, i) => i,
}
}
}
impl<E: Engine, T: Render<E>> Render<E> for Max<E:: Unit, T> {
impl<E: Engine, T: Render<E>> Render<E> for Max<E, T> {
fn min_size (&self, to: E::Size) -> Perhaps<E::Size> {
Ok(self.inner().min_size(to)?.map(|to|match *self {
Self::X(w, _) => [to.w().min(w), to.h()],

View file

@ -39,7 +39,6 @@ impl<E: Engine, T: Render<E>> Push<E, T> {
Self::X(_, i) => i,
Self::Y(_, i) => i,
Self::XY(_, _, i) => i,
_ => unreachable!(),
}
}
pub fn x (&self) -> E::Unit {
@ -47,7 +46,6 @@ impl<E: Engine, T: Render<E>> Push<E, T> {
Self::X(x, _) => *x,
Self::Y(_, _) => E::Unit::default(),
Self::XY(x, _, _) => *x,
_ => unreachable!(),
}
}
pub fn y (&self) -> E::Unit {
@ -55,7 +53,6 @@ impl<E: Engine, T: Render<E>> Push<E, T> {
Self::X(_, _) => E::Unit::default(),
Self::Y(y, _) => *y,
Self::XY(_, y, _) => *y,
_ => unreachable!(),
}
}
}

View file

@ -1,31 +1,35 @@
use crate::*;
#[macro_export] macro_rules! col {
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
($(move)?|$add:ident|$expr:expr) => { Stack::down($(move)?|$add|$expr) };
($pat:pat in $collection:expr => $item:expr) => {
Stack::down(move |add|{
for $pat in $collection { add(&$item)?; }
Ok(())
})
}
};
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
}
#[macro_export] macro_rules! col_up {
($($expr:expr),* $(,)?) => { Stack::down(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
($(move)?|$add:ident|$expr:expr) => { Stack::up($(move)?|$add|$expr) };
($pat:pat in $collection:expr => $item:expr) => {
Stack::up(move |add|{
for $pat in $collection { add(&$item)?; }
Ok(())
})
}
};
($($expr:expr),* $(,)?) => { Stack::up(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
}
#[macro_export] macro_rules! row {
($($expr:expr),* $(,)?) => { Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) }) };
($(move)?|$add:ident|$expr:expr) => {
Stack::right($(move)?|$add|$expr)
};
($pat:pat in $collection:expr => $item:expr) => {
Stack::right(move |add|{
for $pat in $collection { add(&$item)?; }
Ok(())
})
}
Stack::right(move |add|{ for $pat in $collection { add(&$item)?; } Ok(()) })
};
($($expr:expr),* $(,)?) => {
Stack::right(move|add|{ $(add(&$expr)?;)* Ok(()) })
};
}
pub struct Stack<
@ -100,7 +104,7 @@ where
(self.0)(&mut |component: &dyn Render<E>| {
let max = to.h().minus(h);
if max > E::Unit::ZERO() {
let item = component.max_y(to.h() - h);
let item = Tui::max_y(to.h() - h, component);
let size = item.min_size(to)?.map(|size|size.wh());
if let Some([width, height]) = size {
h = h + height.into();
@ -134,7 +138,7 @@ where
Direction::Down => {
(self.0)(&mut |item| {
if h < area.h() {
let item = item.push_y(h).max_y(area.h() - h);
let item = Tui::max_y(area.h() - h, Tui::push_y(h, item));
let show = item.min_size(area.wh().into())?.map(|s|s.wh());
if let Some([width, height]) = show {
item.render(to)?;
@ -148,7 +152,7 @@ where
Direction::Right => {
(self.0)(&mut |item| {
if w < area.w() {
let item = item.push_x(w).max_x(area.w() - w);
let item = Tui::max_x(area.w() - w, Tui::push_x(w, item));
let show = item.min_size(area.wh().into())?.map(|s|s.wh());
if let Some([width, height]) = show {
item.render(to)?;

View file

@ -3,7 +3,6 @@ use crate::*;
submod! {
engine_focus
engine_input
engine_layout
engine_output
engine_style

View file

@ -128,7 +128,7 @@ impl StatusBar for SequencerStatusBar {
fn hotkey_fg () -> Color {
TuiTheme::hotkey_fg()
}
fn update (&mut self, state: &SequencerTui) {
fn update (&mut self, _: &SequencerTui) {
todo!()
}
}

View file

@ -90,12 +90,11 @@ impl StatusBar for TransportStatusBar {
fn hotkey_fg () -> Color {
TuiTheme::hotkey_fg()
}
fn update (&mut self, state: &()) {
fn update (&mut self, _: &()) {
todo!()
}
}
render!(|self: TransportStatusBar|{
todo!();
""
"todo"
});

View file

@ -34,7 +34,7 @@ impl Command<ArrangerTui> for ArrangerCommand {
Phrases(cmd) => cmd.execute(&mut state.phrases)?.map(Phrases),
Editor(cmd) => cmd.execute(&mut state.editor)?.map(Editor),
Clock(cmd) => cmd.execute(state)?.map(Clock),
Zoom(zoom) => { todo!(); },
Zoom(_) => { todo!(); },
Select(selected) => {
*state.selected_mut() = selected;
None
@ -45,22 +45,22 @@ impl Command<ArrangerTui> for ArrangerCommand {
}
impl Command<ArrangerTui> for ArrangerSceneCommand {
fn execute (self, state: &mut ArrangerTui) -> Perhaps<Self> {
todo!();
fn execute (self, _state: &mut ArrangerTui) -> Perhaps<Self> {
//todo!();
Ok(None)
}
}
impl Command<ArrangerTui> for ArrangerTrackCommand {
fn execute (self, state: &mut ArrangerTui) -> Perhaps<Self> {
todo!();
fn execute (self, _state: &mut ArrangerTui) -> Perhaps<Self> {
//todo!();
Ok(None)
}
}
impl Command<ArrangerTui> for ArrangerClipCommand {
fn execute (self, state: &mut ArrangerTui) -> Perhaps<Self> {
todo!();
fn execute (self, _state: &mut ArrangerTui) -> Perhaps<Self> {
//todo!();
Ok(None)
}
}

View file

@ -38,7 +38,6 @@ impl Command<PhraseListModel> for FileBrowserCommand {
}
},
_ => todo!(),
_ => unreachable!()
},
Some(PhrasesMode::Export(index, ref mut browser)) => match self {
Cancel => {
@ -62,7 +61,7 @@ impl InputToCommand<Tui, PhraseListModel> for FileBrowserCommand {
fn input_to_command (state: &PhraseListModel, from: &TuiInput) -> Option<Self> {
use KeyCode::{Up, Down, Right, Left, Enter, Esc, Char, Backspace};
use FileBrowserCommand::*;
if let Some(PhrasesMode::Import(index, browser)) = state.phrases_mode() {
if let Some(PhrasesMode::Import(_index, browser)) = state.phrases_mode() {
Some(match from.event() {
key!(Up) => Select(
browser.index.overflowing_sub(1).0.min(browser.len().saturating_sub(1))
@ -73,19 +72,19 @@ impl InputToCommand<Tui, PhraseListModel> for FileBrowserCommand {
key!(Right) => Chdir(browser.cwd.clone()),
key!(Left) => Chdir(browser.cwd.clone()),
key!(Enter) => Confirm,
key!(Char(c)) => { todo!() },
key!(Char(_)) => { todo!() },
key!(Backspace) => { todo!() },
key!(Esc) => Self::Cancel,
_ => return None
})
} else if let Some(PhrasesMode::Export(index, browser)) = state.phrases_mode() {
} else if let Some(PhrasesMode::Export(_index, browser)) = state.phrases_mode() {
Some(match from.event() {
key!(Up) => Select(browser.index.overflowing_sub(1).0.min(browser.len())),
key!(Down) => Select(browser.index.saturating_add(1) % browser.len()),
key!(Right) => Chdir(browser.cwd.clone()),
key!(Left) => Chdir(browser.cwd.clone()),
key!(Enter) => Confirm,
key!(Char(c)) => { todo!() },
key!(Char(_)) => { todo!() },
key!(Backspace) => { todo!() },
key!(Esc) => Self::Cancel,
_ => return None

View file

@ -60,7 +60,6 @@ impl InputToCommand<Tui, PhraseEditorModel> for PhraseCommand {
_ => return None
},
}
_ => return None
})
}
}
@ -119,7 +118,6 @@ impl Command<PhraseEditorModel> for PhraseCommand {
}
None
},
_ => unreachable!()
})
}
}

View file

@ -14,16 +14,9 @@ pub enum TransportCommand {
impl<T: TransportControl> Command<T> for TransportCommand {
fn execute (self, state: &mut T) -> Perhaps<Self> {
use TransportCommand::{Focus, Clock};
use FocusCommand::{Next, Prev};
use ClockCommand::{SetBpm, SetQuant, SetSync};
Ok(match self {
Focus(cmd) => cmd.execute(state)?.map(Focus),
Clock(cmd) => cmd.execute(state)?.map(Clock),
//Clock(SetBpm(bpm)) => Some(Clock(SetBpm(state.bpm().set(bpm)))),
//Clock(SetQuant(quant)) => Some(Clock(SetQuant(state.quant().set(quant)))),
//Clock(SetSync(sync)) => Some(Clock(SetSync(state.sync().set(sync)))),
_ => return Ok(None)
Self::Focus(cmd) => cmd.execute(state)?.map(Self::Focus),
Self::Clock(cmd) => cmd.execute(state)?.map(Self::Clock),
})
}
}

View file

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

View file

@ -105,9 +105,7 @@ pub fn arranger_content_vertical (
let any_size = |_|Ok(Some([0,0]));
// track titles
let header = Tui::reduce(
tracks.iter().zip(cols.iter().map(|col|col.0)),
|prev, (track, w)|{
let header = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0)) => {
// name and width of track
let name = track.name().read().unwrap();
let max_w = w.saturating_sub(1).min(name.len()).max(2);
@ -146,17 +144,15 @@ pub fn arranger_content_vertical (
.map(|port|port.short_name())
.transpose()?
.unwrap_or("(none)".into()));
//Tui::to_east(prev, Tui::push_x(scenes_w,
//Tui::bg(track.color().rgb,
//Tui::min_xy(w as u16, header_h,
//Tui::to_south(name, timer)))))
prev
}
);
Tui::push_x(scenes_w,
Tui::bg(track.color().rgb,
Tui::min_xy(w as u16, header_h,
Tui::to_south(name, timer))))
});
let height = (view.size.h() as u16).saturating_sub(header_h);
let scene_rows = scenes.iter().zip(rows.iter().map(|row|row.0));
let content = Tui::fixed_y(height, Tui::reduce(scene_rows, |prev, (scene, pulses)| {
let content = Tui::fixed_y(
(view.size.h() as u16).saturating_sub(header_h),
col!((scene, pulses) in scenes.iter().zip(rows.iter().map(|row|row.0)) => {
let height = 1.max((pulses / PPQ) as u16);
let playing = scene.is_playing(tracks);
Tui::fixed_y(
@ -166,9 +162,8 @@ pub fn arranger_content_vertical (
if playing { "" } else { " " },
Tui::bold(true, scene.name.read().unwrap().as_str())
),
Tui::iter(
cols.iter().map(|col|col.0).enumerate(),
|(track, w)|Tui::fixed_xy(w as u16, height, Layers::new(move |add|{
row!((track, w) in cols.iter().map(|col|col.0).enumerate() => {
Tui::fixed_xy(w as u16, height, Layers::new(move |add|{
let mut bg = clip_bg;
match (tracks.get(track), scene.clips.get(track)) {
(Some(track), Some(Some(phrase))) => {
@ -176,24 +171,25 @@ pub fn arranger_content_vertical (
let name = format!("{}", name);
let max_w = name.len().min((w as usize).saturating_sub(2));
let color = phrase.read().unwrap().color;
add(&name.as_str()[0..max_w].push_x(1).fixed_x(w as u16))?;
bg = color.dark.rgb;
if let Some((_, Some(ref playing))) = track.player.play_phrase() {
if *playing.read().unwrap() == *phrase.read().unwrap() {
bg = color.light.rgb
}
};
add(&Tui::fixed_x(w as u16, Tui::push_x(1, &name.as_str()[0..max_w])))?;
},
_ => {}
};
add(&Background(bg))
//add(&Background(bg))
Ok(())
}))
)
})
)
)
}));
let arrangement = Layers::new(move |add|{
let arrangement = Tui::bg(bg.rgb, lay!(move|add|{
// column separators
add(&Widget::new(any_size, move|to: &mut TuiOutput|{
let style = Some(Style::default().fg(sep_fg));
@ -273,7 +269,7 @@ pub fn arranger_content_vertical (
else { area.clip_w(scenes_w).clip_h(header_h) }, &CORNERS)?
})
}))
}).bg(bg.rgb);
}));
let color = TuiTheme::title_fg(view.arranger_focused());
let size = format!("{}x{}", view.size.w(), view.size.h());
let lower_right = Tui::at_se(Tui::fill_xy(Tui::pull_x(1, Tui::fg(color, size))));

View file

@ -6,13 +6,13 @@ impl Content<Tui> for FileBrowser {
let mut i = 0;
for (_, name) in self.dirs.iter() {
if i >= self.scroll {
add(&TuiStyle::bold(name.as_str(), i == self.index))?;
add(&Tui::bold(i == self.index, name.as_str()))?;
}
i += 1;
}
for (_, name) in self.files.iter() {
if i >= self.scroll {
add(&TuiStyle::bold(name.as_str(), i == self.index))?;
add(&Tui::bold(i == self.index, name.as_str()))?;
}
i += 1;
}

View file

@ -229,7 +229,7 @@ impl PhraseViewMode {
let style = Some(Style::default().fg(Color::Rgb(192, 192, 192)).bg(Color::Rgb(0, 0, 0)));
match self {
Self::PianoHorizontal { .. } => {
let [x0, y0, _, h] = to.area().xywh();
let [x0, y0, _, _] = to.area().xywh();
for (y, note) in (note_lo..=note_hi).rev().enumerate() {
to.blit(&match note % 12 {
11 => "██",

View file

@ -1,19 +1,19 @@
use crate::*;
render!(|self:PhraseLength|{
let bars = self.bars_string().as_str();
let beats = self.beats_string().as_str();
let ticks = self.ticks_string().as_str();
Tui::reduce(match self.focus {
let bars = ||self.bars_string();
let beats = ||self.beats_string();
let ticks = ||self.ticks_string();
row!(|add|(match self.focus {
None =>
[" ", bars, "B", beats, "b", ticks, "T"],
add(&row!(" ", bars(), "B", beats(), "b", ticks(), "T")),
Some(PhraseLengthFocus::Bar) =>
["[", bars, "]", beats, "b", ticks, "T"],
add(&row!("[", bars(), "]", beats(), "b", ticks(), "T")),
Some(PhraseLengthFocus::Beat) =>
[" ", bars, "[", beats, "]", ticks, "T"],
add(&row!(" ", bars(), "[", beats(), "]", ticks(), "T")),
Some(PhraseLengthFocus::Tick) =>
[" ", bars, "B", beats, "[", ticks, "]"],
}.iter(), Tui::to_east)
add(&row!(" ", bars(), "B", beats(), "[", ticks(), "]")),
}))
//Layers::new(move|add|{
//match self.focus {
//None => add(&row!(

View file

@ -18,7 +18,7 @@ render!(|self: SequencerTui|{
TransportView::from(self),
Tui::min_y(
20,
Tui::split_right(
Tui::to_east(
20,
Tui::to_south(
Tui::fixed_y(4, play),
@ -35,46 +35,39 @@ render!(|self: SequencerTui|{
});
render!(|self: SequencerStatusBar|{
let orange = Color::Rgb(255,128,0);
let yellow = Color::Rgb(255,255,0);
let modeline = {
let light = Color::Rgb(100,100,100);
let dark = Color::Rgb(100,100,100);
let yellow = Color::Rgb(255,255,0);
let black = Color::Rgb(0,0,0);
let modeline = Tui::to_east(
Tui::bg(
orange,
Tui::fg(
black,
Tui::bold(
true,
Tui::text(self.mode)))),
Tui::bg(
light,
Tui::reduce(
self.help.iter(),
|(prefix, hotkey, suffix)|Tui::reduce(
Tui::to_east,
[widget(&" "), widget(*prefix), widget(Tui::fg(yellow, *hotkey)), widget(*suffix)]
),
Tui::to_east(
Tui::bg(orange, Tui::fg(black, Tui::bold(true, self.mode))),
Tui::bg(light, row!((prefix, hotkey, suffix) in self.help.iter() => {
row!(" ", prefix, Tui::fg(yellow, *hotkey), suffix)
}))
)
)
);
let statusbar = Tui::bg(
dark,
Tui::reduce(
Tui::to_east,
[
Tui::fg(orange, widget(&self.cpu)),
Tui::fg(orange, widget(&self.res)),
Tui::fg(orange, widget(&self.size)),
]
)
);
if self.width > 60 {
return Stack::Right(modeline, statusbar);
}
if self.width > 0 {
return Stack::Down(modeline, statusbar);
}
return Stack::None
};
let statusbar = {
let dark = Color::Rgb(100,100,100);
let cpu = &self.cpu;
let res = &self.res;
let size = &self.size;
Tui::bg(dark, row!(
Tui::fg(orange, cpu),
Tui::fg(orange, res),
Tui::fg(orange, size),
))
};
lay!(|add|if self.width > 60 {
add(&row!(modeline, statusbar))
} else if self.width > 0 {
add(&col!(modeline, statusbar))
} else {
Ok(())
})
});

View file

@ -10,11 +10,14 @@ pub trait StatusBar: Render<Tui> {
Self: Sized
{
let hotkey_fg = Self::hotkey_fg();
Tui::reduce(commands.iter(), |prev, [a, b, c]|
Tui::to_east(prev,
Tui::to_east(a,
Tui::to_east(Tui::fg(hotkey_fg, Tui::bold(true, b)),
c))))
row!([a, b, c] in commands.iter() => {
row!(a, Tui::fg(hotkey_fg, Tui::bold(true, b)), c)
})
//Tui::reduce(commands.iter(), |prev, [a, b, c]|
//Tui::to_east(prev,
//Tui::to_east(a,
//Tui::to_east(Tui::fg(hotkey_fg, Tui::bold(true, b)),
//c))))
}
fn with <'a> (state: &'a Self::State, content: impl Render<Tui>) -> impl Render<Tui>

View file

@ -21,7 +21,7 @@ pub struct TransportView {
}
render!(|self: TransportView|{
let Self { state, selected, focused, bpm, sync, quant, beat, msu, } = self;
let Self { state, .. } = self;// selected, focused, bpm, sync, quant, beat, msu, } = self;
let world = Tui::to_east("│World ", Tui::to_east(format!("│0 (0)"), //sample(chunk)
Tui::to_east(format!("│00m00s000u"), /*msu*/ format!("│00B 0b 00/00"), /*bbt*/)));
let timer = Tui::either(