mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
add CustomWidget and use it to remove more one-time components
This commit is contained in:
parent
47fd9de549
commit
418e662aaf
2 changed files with 99 additions and 103 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>>);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue