wip: add TuiStyle, unifying Modal

This commit is contained in:
🪞👃🪞 2024-09-24 18:32:42 +03:00
parent 7c555848e4
commit 29f11b5977
6 changed files with 467 additions and 434 deletions

View file

@ -48,13 +48,12 @@ impl ArrangerCli {
//}
}
transport.set_focused(true);
let state = Arc::new(RwLock::new(ArrangerStandalone {
Tui::run(Arc::new(RwLock::new(ArrangerStandalone {
transport,
show_sequencer: Some(tek_core::Direction::Down),
arranger,
focus: 0
}));
Tui::run(state)?;
})))?;
Ok(())
}
}
@ -73,26 +72,27 @@ struct ArrangerStandalone<E: Engine> {
impl Content for ArrangerStandalone<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Split::down(|add|{
add(&self.transport)?;
let show = self.arranger.modal.is_some();
let modal = self.arranger.modal.as_ref().map(|x|x as &dyn Content<Engine = Tui>);
ModalHost(show, modal, Split::down(move|add|{
add(&(&self.transport as &dyn Widget<Engine = Tui>).debug())?;
if let (Some(direction), Some(sequencer)) = (
self.show_sequencer,
self.arranger.sequencer(),
) {
add(&Split::new(direction, |add|{
add(&Shrink::Y(20, &self.arranger as &dyn Widget<Engine = Tui>))?;
add(&Min::Y(20, sequencer as &dyn Widget<Engine = Tui>))?;
add(&Split::new(direction, move|add|{
add(&(&self.arranger as &dyn Widget<Engine = Tui>)
.shrink_y(30)
.debug())?;
add(&(sequencer as &dyn Widget<Engine = Tui>)
.min_y(20)
.debug())?;
Ok(())
}))
} else {
add(&self.arranger)
}
})
//if let Some(ref modal) = self.arranger.modal {
//to.fill_bg(area, Nord::bg_lo(false, false));
//to.fill_fg(area, Nord::bg_hi(false, false));
//modal.render(to)?;
//}
}))
}
}

View file

@ -482,6 +482,7 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
(0..=state.scenes.len()).map(|i|(factor*ppq, factor*ppq*i)).collect::<Vec<_>>(),
),
};
//let height = rows.last().map(|(w,y)|(y+w)/ppq).unwrap_or(16);
let tracks: &[Sequencer<Tui>] = state.tracks.as_ref();
let scenes = state.scenes.as_ref();
let offset = 4 + scene_name_max_len(scenes) as u16;
@ -491,48 +492,48 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
add(&VerticalArrangerGrid(offset, &rows, &cols))?;
add(&VerticalArrangerCursor(state.focused, state.selected, offset, &cols, &rows))?;
add(&Split::down(|add|{
add(&Push::X(offset, Split::right(move |add|{
add(&Split::right(move |add|{
for (track, (w, _)) in tracks.iter().zip(cols) {
add(&Min::XY(*w as u16, 2, Layers::new(|add|{
add(&Layers::new(|add|{
add(&Background(COLOR_BG1))?;
add(&track.name.read().unwrap().as_str())
})))?;
}).min_xy(*w as u16, 2))?;
}
Ok(())
})))?;
}).push_x(offset))?;
add(&Split::down(move |add| {
for (scene, (pulses, _)) in scenes.iter().zip(rows) {
let height = 1.max((pulses / 96) as u16);
let playing = scene.is_playing(tracks);
add(&Fixed::Y(height, Split::right(move |add| {
add(&Fixed::XY(offset.saturating_sub(1), height, Split::right(|add|{
add(&Split::right(move |add| {
add(&Split::right(|add|{
add(&if playing { "" } else { " " })?;
add(&scene.name.read().unwrap().as_str())
})))?;
}).fixed_xy(offset.saturating_sub(1), height))?;
for (track, (w, _x)) in cols.iter().enumerate() {
add(&Fixed::XY(*w as u16, height, Layers::new(move |add|{
add(&Layers::new(move |add|{
let mut color = COLOR_BG0;
if let (Some(track), Some(Some(clip))) = (
tracks.get(track),
scene.clips.get(track),
) {
if let Some(phrase) = track.phrases.get(*clip) {
add(&Push::X(1, format!(
add(&format!(
"{clip:02} {}",
phrase.read().unwrap().name.read().unwrap()
).as_str()))?;
).as_str().push_x(1))?;
color = if track.sequence == Some(*clip) {
Nord::PLAYING
COLOR_PLAYING
} else {
COLOR_BG1
};
}
}
add(&Background(color))
})))?;
}).fixed_xy(*w as u16, height))?;
}
Ok(())
})))?;
}).fixed_y(height))?;
}
Ok(())
}))
@ -556,7 +557,7 @@ impl<'a> Widget for VerticalArrangerGrid<'a> {
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
let Self(offset, rows, cols) = self;
let style = Some(Style::default().fg(Nord::SEPARATOR));
let style = Some(Style::default().fg(COLOR_SEPARATOR));
for (_, x) in cols.iter() {
let x = offset + area.x() + *x as u16 - 1;
for y in area.y()..area.y2() {
@ -572,7 +573,7 @@ impl<'a> Widget for VerticalArrangerGrid<'a> {
if x < to.buffer.area.x && y < to.buffer.area.y {
let cell = to.buffer.get_mut(x, y);
cell.modifier = Modifier::UNDERLINED;
cell.underline_color = Nord::SEPARATOR;
cell.underline_color = COLOR_SEPARATOR;
}
}
}
@ -982,7 +983,7 @@ impl Widget for ArrangerRenameModal<Tui> {
let area = to.area();
let y = area.y() + area.h() / 2;
let bg_area = [1, y - 1, area.w() - 2, 3];
to.fill_bg(bg_area, Nord::BG0);
to.fill_bg(bg_area, COLOR_BG1);
Lozenge(Style::default().bold().white().dim()).draw(to.with_rect(bg_area));
let label = match self.target {
ArrangerFocus::Mix => "Rename project:",
@ -1333,22 +1334,23 @@ impl Sequencer<Tui> {
impl Content for Sequencer<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Split::right(move |add|{
add(&Split::down(|add|{
add(&SequenceName(&self))?;
add(&SequenceRange)?;
add(&SequenceLoopRange)?;
add(&SequenceNoteRange)?;
Ok(())
}))?;
add(&Layers::new(|add|{
add(&SequenceKeys(&self))?;
add(&self.phrase.as_ref().map(|phrase|SequenceTimer(&self, phrase.clone())))?;
add(&SequenceNotes(&self))?;
add(&SequenceCursor(&self))?;
add(&SequenceZoom(&self))
}))
})
let toolbar = col!(
SequenceName(&self),
SequenceRange,
SequenceLoopRange,
SequenceNoteRange,
);
let content = lay!(
SequenceKeys(&self),
self.phrase.as_ref().map(|phrase|SequenceTimer(&self, phrase.clone())),
SequenceNotes(&self),
SequenceCursor(&self),
SequenceZoom(&self),
);
row!(toolbar, content)
.min_y(10)
.inset_x(1)
.background(Color::Red)
}
}
@ -1544,13 +1546,7 @@ struct SequenceName<'a>(&'a Sequencer<Tui>);
impl<'a> Content for SequenceName<'a> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Min::XY(10, 4, Split::down(|add|{
let name: &str = &*self.0.name.read().unwrap();
add(&"Name")?;
add(&name)?;
//Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(frame))?;
Ok(())
}))
col! { "Name", self.0.name.read().unwrap().as_str(), }.min_xy(10, 4)
}
}
@ -1560,14 +1556,8 @@ struct SequenceRange;
impl Content for SequenceRange {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Min::XY(10, 6, Split::down(|add|{
add(&"Start: ")?;//Some(STYLE_LABEL));
add(&" 1.1.1")?;//Some(STYLE_VALUE));
add(&"End: ")?;//Some(STYLE_LABEL));
add(&" 2.1.1")?;//Some(STYLE_VALUE));
//Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(frame))?;
Ok(())
}))
col! { "Start: ", " 1.1.1"
, "End: ", " 2.1.1", }.min_xy(10, 6)
}
}
@ -1577,15 +1567,9 @@ struct SequenceLoopRange;
impl Content for SequenceLoopRange {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Min::XY(10, 7, Split::down(|add|{
//Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(range))?;
add(&"Loop [ ]")?;//Some(STYLE_LABEL));
add(&"From: ")?;//Some(STYLE_LABEL));
add(&" 1.1.1")?;//Some(STYLE_VALUE));
add(&"Length: ")?;//Some(STYLE_LABEL));
add(&" 1.0.0")?;//Some(STYLE_VALUE));
Ok(())
}))
col! { "Loop [ ]"
, "From: ", " 1.1.1"
, "Length: ", " 1.0.0", }.min_xy(10, 7)
}
}
@ -1595,7 +1579,7 @@ struct SequenceNoteRange;
impl Content for SequenceNoteRange {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Min::XY(10, 9, Split::down(|add|{
Split::down(|add|{
//Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(range))?;
add(&"Notes: ")?;//Some(STYLE_LABEL));
add(&"C#0-C#9 ")?;//Some(STYLE_VALUE));
@ -1605,7 +1589,7 @@ impl Content for SequenceNoteRange {
add(&"[ Inv ]")?;//Some(STYLE_LABEL));
add(&"[ Dup ]")?;//Some(STYLE_LABEL));
Ok(())
}))
}).min_xy(10, 9)
}
}
@ -2202,7 +2186,7 @@ impl Content for TransportPlayPauseButton<Tui> {
type Engine = Tui;
fn content (&self) -> impl Widget<Engine = Tui> {
Layers::new(|add|{
add(&Push::X(1, Min::XY(11, 2, Styled(match self.value {
add(&Styled(match self.value {
Some(TransportState::Stopped) => Some(GRAY_DIM.bold()),
Some(TransportState::Starting) => Some(GRAY_NOT_DIM_BOLD),
Some(TransportState::Rolling) => Some(WHITE_NOT_DIM_BOLD),
@ -2212,7 +2196,7 @@ impl Content for TransportPlayPauseButton<Tui> {
Some(TransportState::Starting) => "READY ...",
Some(TransportState::Stopped) => "⏹ STOPPED",
_ => unreachable!(),
}))))?;
}).min_xy(11, 2).push_x(1))?;
Ok(())
})
}