mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
remove H_KEYS_OFFSET, just use row macro
This commit is contained in:
parent
ee94df78f6
commit
c56758b616
4 changed files with 50 additions and 52 deletions
|
|
@ -47,6 +47,8 @@ pub trait Size<N: Number> {
|
|||
#[inline] fn w (&self) -> N { self.x() }
|
||||
#[inline] fn h (&self) -> N { self.y() }
|
||||
#[inline] fn wh (&self) -> [N;2] { [self.x(), self.y()] }
|
||||
#[inline] fn clip_w (&self, w: N) -> [N;2] { [self.w().min(w.into()), self.h()] }
|
||||
#[inline] fn clip_h (&self, h: N) -> [N;2] { [self.w(), self.h().min(h.into())] }
|
||||
#[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
|
||||
if self.w() < w || self.h() < h {
|
||||
Err(format!("min {w}x{h}").into())
|
||||
|
|
@ -67,20 +69,29 @@ impl<N: Number> Size<N> for [N;2] {
|
|||
}
|
||||
|
||||
pub trait Area<N: Number>: Copy {
|
||||
fn x (&self) -> N;
|
||||
fn y (&self) -> N;
|
||||
fn w (&self) -> N;
|
||||
fn h (&self) -> N;
|
||||
fn x (&self) -> N;
|
||||
fn y (&self) -> N;
|
||||
fn w (&self) -> N;
|
||||
fn h (&self) -> N;
|
||||
fn x2 (&self) -> N { self.x() + self.w() }
|
||||
fn y2 (&self) -> N { self.y() + self.h() }
|
||||
#[inline] fn wh (&self) -> [N;2] {
|
||||
[self.w(), self.h()]
|
||||
#[inline] fn wh (&self) -> [N;2] { [self.w(), self.h()] }
|
||||
#[inline] fn xywh (&self) -> [N;4] { [self.x(), self.y(), self.w(), self.h()] }
|
||||
#[inline] fn lrtb (&self) -> [N;4] { [self.x(), self.x2(), self.y(), self.y2()] }
|
||||
#[inline] fn push_x (&self, x: N) -> [N;4] { [self.x() + x, self.y(), self.w(), self.h()] }
|
||||
#[inline] fn push_y (&self, y: N) -> [N;4] { [self.x(), self.y() + y, self.w(), self.h()] }
|
||||
#[inline] fn shrink_x (&self, x: N) -> [N;4] { [self.x(), self.y(), self.w() - x, self.h()] }
|
||||
#[inline] fn shrink_y (&self, y: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h() - y] }
|
||||
#[inline] fn set_w (&self, w: N) -> [N;4] { [self.x(), self.y(), w, self.h()] }
|
||||
#[inline] fn set_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), h] }
|
||||
#[inline] fn clip_h (&self, h: N) -> [N;4] {
|
||||
[self.x(), self.y(), self.w(), self.h().min(h.into())]
|
||||
}
|
||||
#[inline] fn xywh (&self) -> [N;4] {
|
||||
[self.x(), self.y(), self.w(), self.h()]
|
||||
#[inline] fn clip_w (&self, w: N) -> [N;4] {
|
||||
[self.x(), self.y(), self.w().min(w.into()), self.h()]
|
||||
}
|
||||
#[inline] fn lrtb (&self) -> [N;4] {
|
||||
[self.x(), self.x2(), self.y(), self.y2()]
|
||||
#[inline] fn clip (&self, wh: impl Size<N>) -> [N;4] {
|
||||
[self.x(), self.y(), wh.w(), wh.h()]
|
||||
}
|
||||
#[inline] fn expect_min (&self, w: N, h: N) -> Usually<&Self> {
|
||||
if self.w() < w || self.h() < h {
|
||||
|
|
@ -89,9 +100,6 @@ pub trait Area<N: Number>: Copy {
|
|||
Ok(self)
|
||||
}
|
||||
}
|
||||
#[inline] fn clip (&self, wh: impl Size<N>) -> [N;4] {
|
||||
[self.x(), self.y(), wh.w(), wh.h()]
|
||||
}
|
||||
#[inline] fn split_fixed (&self, direction: Direction, a: N) -> ([N;4],[N;4]) {
|
||||
match direction {
|
||||
Direction::Up => (
|
||||
|
|
@ -109,14 +117,6 @@ pub trait Area<N: Number>: Copy {
|
|||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
#[inline] fn push_x (&self, x: N) -> [N;4] { [self.x() + x, self.y(), self.w(), self.h()] }
|
||||
#[inline] fn push_y (&self, y: N) -> [N;4] { [self.x(), self.y() + y, self.w(), self.h()] }
|
||||
#[inline] fn shrink_x (&self, x: N) -> [N;4] { [self.x(), self.y(), self.w() - x, self.h()] }
|
||||
#[inline] fn shrink_y (&self, y: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h() - y] }
|
||||
#[inline] fn set_w (&self, w: N) -> [N;4] { [self.x(), self.y(), w, self.h()] }
|
||||
#[inline] fn set_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), h] }
|
||||
#[inline] fn clip_h (&self, h: N) -> [N;4] { [self.x(), self.y(), self.w(), self.h().min(h)] }
|
||||
#[inline] fn clip_w (&self, w: N) -> [N;4] { [self.x(), self.y(), self.w().min(w), self.h()] }
|
||||
}
|
||||
|
||||
impl<N: Number> Area<N> for (N, N, N, N) {
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ impl<E: Engine> Arranger<E> {
|
|||
transport,
|
||||
arrangement,
|
||||
phrases,
|
||||
phrases_split: 20,
|
||||
phrases_split: 20,
|
||||
arrangement_split: 20,
|
||||
};
|
||||
app.update_focus();
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ impl Content for ArrangerStatusBar {
|
|||
Self::ArrangementScene => "SCENE",
|
||||
Self::ArrangementClip => "CLIP",
|
||||
Self::PhrasePool => "SEQ LIST",
|
||||
Self::PhraseView => "SEQ VIEW",
|
||||
Self::PhraseEdit => "SEQ EDIT",
|
||||
Self::PhraseView => "VIEW SEQ",
|
||||
Self::PhraseEdit => "EDIT SEQ",
|
||||
};
|
||||
let mode = TuiStyle::bg(format!(" {label} "), Color::Rgb(150, 160, 90))
|
||||
.fg(Color::Rgb(0, 0, 0))
|
||||
|
|
@ -259,13 +259,13 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
|||
to.render_in(clip_area, &CORNERS)?;
|
||||
//to.fill_bg(clip_area, Color::Rgb(40, 50, 30));
|
||||
} else if let Some(track_area) = track_area {
|
||||
to.render_in(track_area.clip_h(2), &CORNERS)?;
|
||||
to.render_in(track_area.clip_h(2u16), &CORNERS)?;
|
||||
//to.fill_bg(track_area, Color::Rgb(40, 50, 30));
|
||||
} else if let Some(scene_area) = scene_area {
|
||||
to.render_in(scene_area.clip_w(offset-1), &CORNERS)?;
|
||||
//to.fill_bg(scene_area, Color::Rgb(40, 50, 30));
|
||||
} else {
|
||||
to.render_in(area.clip_w(offset-1).clip_h(2), &CORNERS)?;
|
||||
to.render_in(area.clip_w(offset-1).clip_h(2u16), &CORNERS)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -52,10 +52,9 @@ impl Content for PhraseEditor<Tui> {
|
|||
let Self {
|
||||
focused, entered, time_axis, note_axis, keys, phrase, buffer, note_len, ..
|
||||
} = self;
|
||||
let offset = Self::H_KEYS_OFFSET as u16;
|
||||
let color = Color::Rgb(0,255,0);
|
||||
let color = phrase.as_ref().map(|p|p.read().unwrap().color).unwrap_or(color);
|
||||
let keys = CustomWidget::new(|_|Ok(Some([32u16,0u16])), move|to: &mut TuiOutput|{
|
||||
let keys = CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_w(5))), move|to: &mut TuiOutput|{
|
||||
if to.area().h() >= 2 {
|
||||
to.buffer_update(to.area().set_w(5), &|cell, x, y|{
|
||||
let y = y + note_axis.start as u16;
|
||||
|
|
@ -66,11 +65,12 @@ impl Content for PhraseEditor<Tui> {
|
|||
}
|
||||
Ok(())
|
||||
}).fill_y();
|
||||
let notes = CustomWidget::new(|_|Ok(Some([32u16,4u16])), move|to: &mut TuiOutput|{
|
||||
if to.area().h() >= 2 && to.area().w() >= offset {
|
||||
let area = to.area().push_x(offset).shrink_x(offset);
|
||||
let notes_bg_null = Color::Rgb(28, 35, 25);
|
||||
let notes = CustomWidget::new(|to|Ok(Some(to)), move|to: &mut TuiOutput|{
|
||||
if to.area().h() >= 2 {
|
||||
let area = to.area();
|
||||
to.buffer_update(area, &move |cell, x, y|{
|
||||
cell.set_bg(Color::Rgb(20, 20, 20));
|
||||
cell.set_bg(notes_bg_null);
|
||||
let src_x = ((x as usize + time_axis.start) * time_axis.scale) as usize;
|
||||
let src_y = (y as usize + note_axis.start) as usize;
|
||||
if src_x < buffer.width && src_y < buffer.height - 1 {
|
||||
|
|
@ -83,11 +83,11 @@ impl Content for PhraseEditor<Tui> {
|
|||
}
|
||||
Ok(())
|
||||
}).fill_x();
|
||||
let cursor = CustomWidget::new(|_|Ok(Some([1u16,1u16])), move|to: &mut TuiOutput|{
|
||||
let cursor = CustomWidget::new(|to|Ok(Some(to)), move|to: &mut TuiOutput|{
|
||||
if *entered {
|
||||
let area = to.area();
|
||||
if let (Some(time), Some(note)) = (time_axis.point, note_axis.point) {
|
||||
let x = area.x() + Self::H_KEYS_OFFSET as u16 + time as u16;
|
||||
let x = area.x() + time as u16;
|
||||
let y = area.y() + 1 + note as u16 / 2;
|
||||
let c = if note % 2 == 0 { "▀" } else { "▄" };
|
||||
to.blit(&c, x, y, Some(Style::default().fg(color)));
|
||||
|
|
@ -95,22 +95,21 @@ impl Content for PhraseEditor<Tui> {
|
|||
}
|
||||
Ok(())
|
||||
});
|
||||
let playhead = CustomWidget::new(|_|Ok(Some([32u16,2u16])), move|to: &mut TuiOutput|{
|
||||
let playhead_inactive = Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(0,0,0));
|
||||
let playhead_active = playhead_inactive.yellow().bold().not_dim();
|
||||
let playhead = CustomWidget::new(|to|Ok(Some(to)), move|to: &mut TuiOutput|{
|
||||
if let Some(_) = phrase {
|
||||
let time_0 = time_axis.start;
|
||||
let time_z = time_axis.scale;
|
||||
let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length;
|
||||
let [x, y, width, _] = to.area();
|
||||
let x2 = x as usize + Self::H_KEYS_OFFSET;
|
||||
let x3 = x as usize + width as usize;
|
||||
for x in x2..x3 {
|
||||
let step = (time_0 + x2) * time_z;
|
||||
let next_step = (time_0 + x2 + 1) * time_z;
|
||||
let mut style = Style::default().fg(Color::Rgb(255,255,255));
|
||||
if step <= now && now < next_step {
|
||||
style = style.yellow().bold().not_dim()
|
||||
}
|
||||
to.blit(&"-", x as u16, y, Some(style));
|
||||
let now = 0; // TODO FIXME: self.now % phrase.read().unwrap().length;
|
||||
let ScaledAxis { start: first_beat, scale: time_zoom, .. } = time_axis;
|
||||
for x in 0..10 {
|
||||
let this_step = (first_beat + 0) * time_zoom;
|
||||
let next_step = (first_beat + 1) * time_zoom;
|
||||
let x = to.area().x() + x;
|
||||
to.blit(&"-", x, to.area.y(), Some(if this_step <= now && now < next_step {
|
||||
playhead_active
|
||||
} else {
|
||||
playhead_active
|
||||
}));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -118,7 +117,8 @@ impl Content for PhraseEditor<Tui> {
|
|||
let border_color = if *focused{Color::Rgb(100, 110, 40)}else{Color::Rgb(70, 80, 50)};
|
||||
let title_color = if *focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)};
|
||||
let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color));
|
||||
let piano_roll = lay!(keys, notes, cursor).fill_x();
|
||||
let note_area = lay!(notes, cursor, playhead).fill_x();
|
||||
let piano_roll = row!(keys, note_area).fill_x();
|
||||
let content_bg = Color::Rgb(40, 50, 30);
|
||||
let content = piano_roll.bg(content_bg).border(border);
|
||||
let mut upper_left = String::from("Sequencer");
|
||||
|
|
@ -131,14 +131,12 @@ impl Content for PhraseEditor<Tui> {
|
|||
}
|
||||
lay!(
|
||||
content,
|
||||
playhead,
|
||||
TuiStyle::fg(upper_left.to_string(), title_color).push_x(1).align_nw().fill_xy(),
|
||||
TuiStyle::fg(upper_right.to_string(), title_color).pull_x(1).align_ne().fill_xy(),
|
||||
)
|
||||
}
|
||||
}
|
||||
impl<E: Engine> PhraseEditor<E> {
|
||||
const H_KEYS_OFFSET: usize = 5;
|
||||
pub fn put (&mut self) {
|
||||
if let (Some(phrase), Some(time), Some(note)) = (
|
||||
&self.phrase,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue