mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
shrink and grow track widths
This commit is contained in:
parent
5282dab918
commit
333e8bf98a
2 changed files with 60 additions and 24 deletions
|
|
@ -47,6 +47,8 @@ pub struct ArrangementTrack<E: Engine> {
|
||||||
pub player: PhrasePlayer<E>,
|
pub player: PhrasePlayer<E>,
|
||||||
/// Outputs
|
/// Outputs
|
||||||
pub outputs: Vec<()>,
|
pub outputs: Vec<()>,
|
||||||
|
/// Preferred width of track column
|
||||||
|
pub width: usize,
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
|
|
@ -143,6 +145,33 @@ impl<E: Engine> Arrangement<E> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn delete (&mut self) {
|
||||||
|
match self.selected {
|
||||||
|
ArrangementFocus::Track(t) => self.track_del(),
|
||||||
|
ArrangementFocus::Scene(s) => self.scene_del(),
|
||||||
|
ArrangementFocus::Clip(t, s) => self.phrase_del(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.show_phrase()
|
||||||
|
}
|
||||||
|
pub fn increment (&mut self) {
|
||||||
|
match self.selected {
|
||||||
|
ArrangementFocus::Track(t) => self.track_width_inc(),
|
||||||
|
ArrangementFocus::Scene(s) => self.scene_next(),
|
||||||
|
ArrangementFocus::Clip(t, s) => self.phrase_next(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.show_phrase()
|
||||||
|
}
|
||||||
|
pub fn decrement (&mut self) {
|
||||||
|
match self.selected {
|
||||||
|
ArrangementFocus::Track(t) => self.track_width_dec(),
|
||||||
|
ArrangementFocus::Scene(s) => self.scene_prev(),
|
||||||
|
ArrangementFocus::Clip(t, s) => self.phrase_prev(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
self.show_phrase()
|
||||||
|
}
|
||||||
pub fn is_first_row (&self) -> bool {
|
pub fn is_first_row (&self) -> bool {
|
||||||
let selected = self.selected;
|
let selected = self.selected;
|
||||||
selected.is_mix() || selected.is_track()
|
selected.is_mix() || selected.is_track()
|
||||||
|
|
@ -166,6 +195,12 @@ impl<E: Engine> Arrangement<E> {
|
||||||
pub fn track_mut (&mut self) -> Option<&mut ArrangementTrack<E>> {
|
pub fn track_mut (&mut self) -> Option<&mut ArrangementTrack<E>> {
|
||||||
self.selected.track().map(|t|self.tracks.get_mut(t)).flatten()
|
self.selected.track().map(|t|self.tracks.get_mut(t)).flatten()
|
||||||
}
|
}
|
||||||
|
pub fn track_width_inc (&mut self) {
|
||||||
|
self.track_mut().map(|t|t.width_inc());
|
||||||
|
}
|
||||||
|
pub fn track_width_dec (&mut self) {
|
||||||
|
self.track_mut().map(|t|t.width_dec());
|
||||||
|
}
|
||||||
pub fn track_next (&mut self) {
|
pub fn track_next (&mut self) {
|
||||||
self.selected.track_next(self.tracks.len() - 1)
|
self.selected.track_next(self.tracks.len() - 1)
|
||||||
}
|
}
|
||||||
|
|
@ -187,21 +222,15 @@ impl<E: Engine> Arrangement<E> {
|
||||||
format!("Track {}", self.tracks.len() + 1)
|
format!("Track {}", self.tracks.len() + 1)
|
||||||
}
|
}
|
||||||
pub fn track_widths (&self) -> Vec<(usize, usize)> {
|
pub fn track_widths (&self) -> Vec<(usize, usize)> {
|
||||||
let to_len = |track: &ArrangementTrack<E>|track.name.read().unwrap().len();
|
let mut widths = vec![];
|
||||||
let mut lens: Vec<usize> = self.tracks.iter().map(to_len).collect();
|
|
||||||
for scene in self.scenes.iter() {
|
|
||||||
for track_index in 0..self.tracks.len() {
|
|
||||||
if let Some(phrase) = scene.clip(track_index) {
|
|
||||||
let len = phrase.read().unwrap().name.read().unwrap().len();
|
|
||||||
lens[track_index] = lens[track_index].max(len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
let to_x_and_w = |len: &usize|{ total = total + *len; (*len, total - *len) };
|
for track in self.tracks.iter() {
|
||||||
let mut lens: Vec<(usize, usize)> = lens.iter().map(to_x_and_w).collect();
|
let width = track.width;
|
||||||
lens.push((0, total));
|
widths.push((width, total));
|
||||||
lens
|
total += width;
|
||||||
|
}
|
||||||
|
widths.push((0, total));
|
||||||
|
widths
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Methods for scenes in arrangement
|
/// Methods for scenes in arrangement
|
||||||
|
|
@ -326,6 +355,7 @@ impl<E: Engine> ArrangementTrack<E> {
|
||||||
inputs: vec![],
|
inputs: vec![],
|
||||||
player: PhrasePlayer::new(name),
|
player: PhrasePlayer::new(name),
|
||||||
outputs: vec![],
|
outputs: vec![],
|
||||||
|
width: name.len() + 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn longest_name (tracks: &[Self]) -> usize {
|
pub fn longest_name (tracks: &[Self]) -> usize {
|
||||||
|
|
@ -333,6 +363,14 @@ impl<E: Engine> ArrangementTrack<E> {
|
||||||
.map(|s|s.name.read().unwrap().len())
|
.map(|s|s.name.read().unwrap().len())
|
||||||
.fold(0, usize::max)
|
.fold(0, usize::max)
|
||||||
}
|
}
|
||||||
|
pub fn width_inc (&mut self) {
|
||||||
|
self.width += 1;
|
||||||
|
}
|
||||||
|
pub fn width_dec (&mut self) {
|
||||||
|
if self.width > 1 {
|
||||||
|
self.width -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Focus identification methods
|
/// Focus identification methods
|
||||||
impl ArrangementFocus {
|
impl ArrangementFocus {
|
||||||
|
|
|
||||||
|
|
@ -80,15 +80,15 @@ impl Arranger<Tui> {
|
||||||
impl Handle<Tui> for Arrangement<Tui> {
|
impl Handle<Tui> for Arrangement<Tui> {
|
||||||
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
fn handle (&mut self, from: &TuiInput) -> Perhaps<bool> {
|
||||||
match from.event() {
|
match from.event() {
|
||||||
key!(KeyCode::Char('`')) => { self.mode.to_next(); },
|
key!(KeyCode::Char('`')) => { self.mode.to_next(); },
|
||||||
key!(KeyCode::Delete) => { self.phrase_del(); self.show_phrase(); },
|
key!(KeyCode::Delete) => { self.delete(); },
|
||||||
key!(KeyCode::Char('.')) => { self.phrase_next(); self.show_phrase(); },
|
key!(KeyCode::Char('.')) => { self.increment(); },
|
||||||
key!(KeyCode::Char(',')) => { self.phrase_prev(); self.show_phrase(); },
|
key!(KeyCode::Char(',')) => { self.decrement(); },
|
||||||
// TODO: next/prev scene
|
// TODO: next/prev scene
|
||||||
key!(KeyCode::Enter) => { self.activate(); },
|
key!(KeyCode::Enter) => { self.activate(); },
|
||||||
key!(Ctrl-KeyCode::Char('a')) => { self.scene_add(None)?; },
|
key!(Ctrl-KeyCode::Char('a')) => { self.scene_add(None)?; },
|
||||||
key!(Ctrl-KeyCode::Char('t')) => { self.track_add(None)?; },
|
key!(Ctrl-KeyCode::Char('t')) => { self.track_add(None)?; },
|
||||||
key!(KeyCode::Char('n')) => { todo!("rename selected"); },
|
key!(KeyCode::Char('n')) => { todo!("rename selected"); },
|
||||||
key!(KeyCode::Char('c')) => { todo!("recolor selected"); },
|
key!(KeyCode::Char('c')) => { todo!("recolor selected"); },
|
||||||
key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() {
|
key!(KeyCode::Char('l')) => if let Some(phrase) = self.phrase() {
|
||||||
phrase.write().unwrap().toggle_loop()
|
phrase.write().unwrap().toggle_loop()
|
||||||
|
|
@ -147,11 +147,9 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
let Self(state, factor) = self;
|
let Self(state, factor) = self;
|
||||||
let (cols, rows) = if *factor == 0 {(
|
let (cols, rows) = if *factor == 0 {(
|
||||||
state.track_widths(),
|
state.track_widths(),
|
||||||
//ArrangementTrack::clip_name_lengths(state.tracks.as_slice()),
|
|
||||||
Scene::ppqs(state.tracks.as_slice(), state.scenes.as_slice()),
|
Scene::ppqs(state.tracks.as_slice(), state.scenes.as_slice()),
|
||||||
)} else {(
|
)} else {(
|
||||||
state.track_widths(),
|
state.track_widths(),
|
||||||
//ArrangementTrack::clip_name_lengths(state.tracks.as_slice()),
|
|
||||||
(0..=state.scenes.len()).map(|i|(factor*PPQ, factor*PPQ*i)).collect::<Vec<_>>(),
|
(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 height = rows.last().map(|(w,y)|(y+w)/PPQ).unwrap_or(16);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue