add CustomWidget and use it to remove more one-time components

This commit is contained in:
🪞👃🪞 2024-09-29 01:15:19 +03:00
parent 47fd9de549
commit 418e662aaf
2 changed files with 99 additions and 103 deletions

View file

@ -183,6 +183,36 @@ pub trait ContentComponent<E: Engine>: Widget<Engine = E> + Handle<E> {}
/// Everything that implements [Render] and [Handle] is a [Component].
impl<E: Engine, C: Content<Engine = E> + Handle<E>> ContentComponent<E> for C {}
pub struct CustomWidget<
E: Engine,
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
>(L, R, PhantomData<E>);
impl<
E: Engine,
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
> CustomWidget<E, L, R> {
pub fn new (layout: L, render: R) -> Self {
Self(layout, render, Default::default())
}
}
impl<
E: Engine,
L: Send + Sync + Fn(E::Size)->Perhaps<E::Size>,
R: Send + Sync + Fn(&mut E::Output)->Usually<()>
> Widget for CustomWidget<E, L, R> {
type Engine = E;
fn layout (&self, to: E::Size) -> Perhaps<E::Size> {
self.0(to)
}
fn render (&self, to: &mut E::Output) -> Usually<()> {
self.1(to)
}
}
pub trait Exit: Send {
fn exited (&self) -> bool;
fn exit (&mut self);

View file

@ -1357,11 +1357,76 @@ impl Content for Sequencer<Tui> {
}.min_xy(10, 9),
);
let content = lay!(
SequenceKeys(&self).fill_y(),
// keys
CustomWidget::new(|to|Ok(Some([32,4])), |to: &mut TuiOutput|{
let area = to.area();
if area.h() < 2 {
return Ok(())
}
let area = [area.x(), area.y(), 5, area.h() - 2];
to.buffer_update(area, &|cell, x, y|{
let y = y + self.note_axis.start as u16;
if x < self.keys.area.width && y < self.keys.area.height {
*cell = self.keys.get(x, y).clone()
}
});
Ok(())
}).fill_y(),
self.phrase.as_ref().map(|phrase|SequenceTimer(&self, phrase.clone()).fill_x()),
SequenceNotes(&self).fill_x(),
SequenceCursor(&self),
SequenceZoom(&self),
// notes
CustomWidget::new(|to|Ok(Some([32,4])), |to: &mut TuiOutput|{
let area = to.area();
if area.h() < 2 {
return Ok(())//Some(area))
}
let area = [
area.x() + Sequencer::H_KEYS_OFFSET as u16,
area.y() + 1,
area.w().saturating_sub(Sequencer::H_KEYS_OFFSET as u16),
area.h().saturating_sub(2),
];
to.buffer_update(area, &move |cell, x, y|{
let src_x = ((x as usize + self.time_axis.start) * self.time_axis.scale) as usize;
let src_y = (y as usize + self.note_axis.start) as usize;
if src_x < self.buffer.width && src_y < self.buffer.height - 1 {
let src = self.buffer.get(src_x, self.buffer.height - src_y);
src.map(|src|{
cell.set_symbol(src.symbol());
cell.set_fg(src.fg);
});
}
});
Ok(())//Some(area))
}).fill_x(),
// cursor
CustomWidget::new(|to|Ok(Some([1,1])), |to: &mut TuiOutput|{
let area = to.area();
if let (Some(time), Some(note)) = (self.time_axis.point, self.note_axis.point) {
let x = area.x() + Sequencer::H_KEYS_OFFSET as u16 + time as u16;
let y = area.y() + 1 + note as u16 / 2;
let c = if note % 2 == 0 { "" } else { "" };
to.blit(&c, x, y, self.style_focus());
Ok(())
} else {
//Ok(Some([0,0,0,0]))
Ok(())
}
}),
//zoom
CustomWidget::new(|to|Ok(Some([10,1])), |to: &mut TuiOutput|{
let area = to.area();
let quant = ppq_to_name(self.time_axis.scale);
let quant_x = area.x() + area.w() - 1 - quant.len() as u16;
let quant_y = area.y() + area.h() - 2;
to.blit(&quant, quant_x, quant_y, self.style_focus());
Ok(())
}),
);
row!(toolbar, content)
.fill_x()
@ -1556,105 +1621,6 @@ pub(crate) fn keys_vert () -> Buffer {
buffer
}
///////////////////////////////////////////////////////////////////////////////////////////////////
struct SequenceKeys<'a>(&'a Sequencer<Tui>);
impl<'a> Widget for SequenceKeys<'a> {
type Engine = Tui;
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([32,4]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
if area.h() < 2 {
return Ok(())
}
let area = [area.x(), area.y(), 5, area.h() - 2];
to.buffer_update(area, &|cell, x, y|{
let y = y + self.0.note_axis.start as u16;
if x < self.0.keys.area.width && y < self.0.keys.area.height {
*cell = self.0.keys.get(x, y).clone()
}
});
Ok(())
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
struct SequenceNotes<'a>(&'a Sequencer<Tui>);
impl<'a> Widget for SequenceNotes<'a> {
type Engine = Tui;
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([32,4]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
if area.h() < 2 {
return Ok(())//Some(area))
}
let area = [
area.x() + Sequencer::H_KEYS_OFFSET as u16,
area.y() + 1,
area.w().saturating_sub(Sequencer::H_KEYS_OFFSET as u16),
area.h().saturating_sub(2),
];
to.buffer_update(area, &move |cell, x, y|{
let src_x = ((x as usize + self.0.time_axis.start) * self.0.time_axis.scale) as usize;
let src_y = (y as usize + self.0.note_axis.start) as usize;
if src_x < self.0.buffer.width && src_y < self.0.buffer.height - 1 {
let src = self.0.buffer.get(src_x, self.0.buffer.height - src_y);
src.map(|src|{
cell.set_symbol(src.symbol());
cell.set_fg(src.fg);
});
}
});
Ok(())//Some(area))
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
struct SequenceCursor<'a>(&'a Sequencer<Tui>);
impl<'a> Widget for SequenceCursor<'a> {
type Engine = Tui;
fn layout (&self, to: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([1,1]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
if let (Some(time), Some(note)) = (self.0.time_axis.point, self.0.note_axis.point) {
let x = area.x() + Sequencer::H_KEYS_OFFSET as u16 + time as u16;
let y = area.y() + 1 + note as u16 / 2;
let c = if note % 2 == 0 { "" } else { "" };
to.blit(&c, x, y, self.0.style_focus());
Ok(())
} else {
//Ok(Some([0,0,0,0]))
Ok(())
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
struct SequenceZoom<'a>(&'a Sequencer<Tui>);
impl<'a> Widget for SequenceZoom<'a> {
type Engine = Tui;
fn layout (&self, _to: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([10,1]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
let quant = ppq_to_name(self.0.time_axis.scale);
let quant_x = area.x() + area.w() - 1 - quant.len() as u16;
let quant_y = area.y() + area.h() - 2;
to.blit(&quant, quant_x, quant_y, self.0.style_focus());
Ok(())
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
struct SequenceTimer<'a>(&'a Sequencer<Tui>, Arc<RwLock<Phrase>>);