mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
piano roll full block cursor (1 off)
This commit is contained in:
parent
d2a9e0b722
commit
aef0213a2b
1 changed files with 77 additions and 60 deletions
|
|
@ -34,7 +34,7 @@ impl<'a, T: HasEditor> From<&'a T> for PhraseView<'a> {
|
||||||
editor.note_lo.store(note_lo, Ordering::Relaxed);
|
editor.note_lo.store(note_lo, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut note_hi = 127.min(note_lo + height * 2 + 1);
|
let mut note_hi = 127.min(note_lo + height + 1);
|
||||||
if note_point > note_hi {
|
if note_point > note_hi {
|
||||||
note_lo += note_point - note_hi;
|
note_lo += note_point - note_hi;
|
||||||
note_hi = note_point;
|
note_hi = note_point;
|
||||||
|
|
@ -84,34 +84,43 @@ impl<'a> Content for PhraseView<'a> {
|
||||||
now,
|
now,
|
||||||
..
|
..
|
||||||
} = self;
|
} = self;
|
||||||
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 upper_left = format!(
|
||||||
let border = Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(border_color));
|
"{note_hi} {note_hi_name} {}",
|
||||||
let playhead_inactive = Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(40,50,30));
|
phrase.as_ref().map(|p|p.read().unwrap().name.clone()).unwrap_or(String::new())
|
||||||
let playhead_active = playhead_inactive.clone().yellow().bold().not_dim();
|
);
|
||||||
let mut name = "".to_string();
|
|
||||||
if let Some(phrase) = phrase {
|
let lower_left = format!(
|
||||||
name = phrase.read().unwrap().name.clone();
|
"{note_lo} {note_lo_name}"
|
||||||
}
|
|
||||||
let upper_left = format!("{note_hi} {note_hi_name} {name}");
|
);
|
||||||
let lower_left = format!("{note_lo} {note_lo_name}");
|
|
||||||
let mut lower_right = format!("┤{}├", size.format());
|
let mut lower_right = format!(
|
||||||
|
"┤{}├", size.format()
|
||||||
|
);
|
||||||
if *focused && *entered {
|
if *focused && *entered {
|
||||||
lower_right = format!("┤Note: {} ({}) {}├─{lower_right}",
|
lower_right = format!("┤Note: {} ({}) {}├─{lower_right}",
|
||||||
note_point, to_note_name(*note_point), pulses_to_name(*note_len)
|
note_point, to_note_name(*note_point), pulses_to_name(*note_len)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let mut upper_right = format!("[{}]", if *entered {"■"} else {" "});
|
|
||||||
|
let mut upper_right = format!(
|
||||||
|
"[{}]",
|
||||||
|
if *entered {"■"} else {" "}
|
||||||
|
);
|
||||||
if let Some(phrase) = phrase {
|
if let Some(phrase) = phrase {
|
||||||
upper_right = format!("┤Time: {}/{} {}├{upper_right}",
|
upper_right = format!("┤Time: {}/{} {}├{upper_right}",
|
||||||
time_point, phrase.read().unwrap().length, pulses_to_name(*time_scale),
|
time_point, phrase.read().unwrap().length, pulses_to_name(*time_scale),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let title_color = if *focused{Color::Rgb(150, 160, 90)}else{Color::Rgb(120, 130, 100)};
|
||||||
|
|
||||||
lay!(
|
lay!(
|
||||||
row!(
|
row!(
|
||||||
CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_w(2))), move|to: &mut TuiOutput|{
|
CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_w(2))), move|to: &mut TuiOutput|{
|
||||||
Ok(if to.area().h() >= 2 {
|
Ok(if to.area().h() >= 2 {
|
||||||
view_mode.blit_keys(to, *note_hi)
|
view_mode.blit_keys(to, *note_hi, *note_lo)
|
||||||
})
|
})
|
||||||
}).fill_y(),
|
}).fill_y(),
|
||||||
lay!(
|
lay!(
|
||||||
|
|
@ -128,14 +137,20 @@ impl<'a> Content for PhraseView<'a> {
|
||||||
Ok(if *focused && *entered {
|
Ok(if *focused && *entered {
|
||||||
view_mode.blit_cursor(
|
view_mode.blit_cursor(
|
||||||
to,
|
to,
|
||||||
*time_point, *time_scale,
|
*time_point, *time_start, *time_scale,
|
||||||
*note_len, *note_hi, *note_lo, *note_point
|
*note_point, *note_len, *note_hi, *note_lo,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
).fill_x()
|
).fill_x()
|
||||||
).fill_x().bg(Color::Rgb(40, 50, 30)).border(border),
|
).fill_x().bg(Color::Rgb(40, 50, 30)).border(Lozenge(Style::default().bg(Color::Rgb(40, 50, 30)).fg(if *focused{
|
||||||
|
Color::Rgb(100, 110, 40)
|
||||||
|
} else {
|
||||||
|
Color::Rgb(70, 80, 50)
|
||||||
|
}))),
|
||||||
CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_h(1))), move|to: &mut TuiOutput|{
|
CustomWidget::new(|to:[u16;2]|Ok(Some(to.clip_h(1))), move|to: &mut TuiOutput|{
|
||||||
|
let playhead_inactive = Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(40,50,30));
|
||||||
|
let playhead_active = playhead_inactive.clone().yellow().bold().not_dim();
|
||||||
if let Some(_) = phrase {
|
if let Some(_) = phrase {
|
||||||
let now = now.get() as usize; // TODO FIXME: self.now % phrase.read().unwrap().length;
|
let now = now.get() as usize; // TODO FIXME: self.now % phrase.read().unwrap().length;
|
||||||
let time_clamp = time_clamp;
|
let time_clamp = time_clamp;
|
||||||
|
|
@ -226,59 +241,61 @@ impl PhraseViewMode {
|
||||||
_ => unimplemented!()
|
_ => unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn blit_keys (&self, to: &mut TuiOutput, note_hi: usize) {
|
fn blit_keys (&self, to: &mut TuiOutput, note_hi: usize, note_lo: usize) {
|
||||||
for y in to.area.y()..to.area.y2() {
|
let style = Some(Style::default().fg(Color::White).bg(Color::Rgb(0, 0, 0)));
|
||||||
let n = y - to.area.y();
|
match self {
|
||||||
let m = note_hi.saturating_sub(n as usize*2);
|
Self::PianoHorizontal { .. } => {
|
||||||
//let c = format!("{m:>03} {n}");
|
let [x0, y0, _, h] = to.area().xywh();
|
||||||
//to.blit(&c, to.area.x(), y, None);
|
for (y, note) in (note_lo..note_hi).rev().enumerate() {
|
||||||
let x = to.area.x();
|
to.blit(&match note % 12 {
|
||||||
let s = Some(Style::default().fg(Color::Rgb(255,255,255)).bg(Color::Rgb(0,0,0)));
|
11 => "██",
|
||||||
match m % 2 {
|
10 => " ",
|
||||||
1 => match (m / 2) % 6 {
|
9 => "██",
|
||||||
5 => to.blit(&"▀", x, y, s),
|
8 => " ",
|
||||||
4 => to.blit(&"▀", x, y, s),
|
7 => "██",
|
||||||
3 => to.blit(&"▀", x, y, s),
|
6 => " ",
|
||||||
2 => to.blit(&"█", x, y, s),
|
5 => "██",
|
||||||
1 => to.blit(&"▄", x, y, s),
|
4 => "██",
|
||||||
0 => to.blit(&"▄", x, y, s),
|
3 => " ",
|
||||||
_ => unreachable!(),
|
2 => "██",
|
||||||
},
|
1 => " ",
|
||||||
0 => match (m / 2) % 6 {
|
0 => "██",
|
||||||
5 => to.blit(&"▄", x, y, s),
|
_ => unreachable!(),
|
||||||
4 => to.blit(&"▄", x, y, s),
|
}, x0, y0 + y as u16, style)
|
||||||
3 => to.blit(&"▄", x, y, s),
|
}
|
||||||
2 => to.blit(&"▀", x, y, s),
|
},
|
||||||
1 => to.blit(&"▀", x, y, s),
|
_ => unimplemented!()
|
||||||
0 => to.blit(&"█", x, y, s),
|
|
||||||
_ => unreachable!(),
|
|
||||||
},
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn blit_cursor (
|
fn blit_cursor (
|
||||||
&self,
|
&self,
|
||||||
to: &mut TuiOutput,
|
to: &mut TuiOutput,
|
||||||
time_point: usize,
|
time_point: usize,
|
||||||
|
time_start: usize,
|
||||||
time_scale: usize,
|
time_scale: usize,
|
||||||
|
note_point: usize,
|
||||||
note_len: usize,
|
note_len: usize,
|
||||||
note_hi: usize,
|
note_hi: usize,
|
||||||
note_lo: usize,
|
note_lo: usize,
|
||||||
note_point: usize,
|
|
||||||
) {
|
) {
|
||||||
let area = to.area();
|
match self {
|
||||||
let x1 = area.x() + (time_point / time_scale) as u16;
|
Self::PianoHorizontal { .. } => {
|
||||||
let x2 = x1 + (note_len / time_scale) as u16;
|
let [x0, y0, w, h] = to.area().xywh();
|
||||||
let y = area.y() + (note_hi - note_point) as u16 / 2;
|
for (y, note) in (note_lo..note_hi).rev().enumerate() {
|
||||||
let c = if note_lo % 2 == 0 {
|
if note == note_point {
|
||||||
if note_point % 2 == 0 { "▄" } else { "▀" }
|
for x in 0..w {
|
||||||
} else {
|
let time_1 = time_start + x as usize * time_scale;
|
||||||
if note_point % 2 == 0 { "▀" } else { "▄" }
|
let time_2 = time_1 + time_scale;
|
||||||
};
|
if time_1 <= time_point && time_point < time_2 {
|
||||||
let style = Some(Style::default().fg(Color::Rgb(0,255,0)));
|
to.blit(&"█", x0 + x as u16, y0 + y as u16, None);
|
||||||
for x in x1..x2 {
|
break
|
||||||
to.blit(&c, x, y, style);
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Determine the required width to render the phrase.
|
/// Determine the required width to render the phrase.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue