mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
fix track title and corners overlap
This commit is contained in:
parent
db5a96a7e4
commit
0f6c09cf2b
4 changed files with 80 additions and 68 deletions
|
|
@ -158,6 +158,20 @@ impl<E: Engine> Arranger<E> {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// Update status bar
|
||||||
|
pub fn update_status (&mut self) {
|
||||||
|
self.status = match self.focused() {
|
||||||
|
ArrangerFocus::Transport => ArrangerStatusBar::Transport,
|
||||||
|
ArrangerFocus::Arrangement => match self.arrangement.selected {
|
||||||
|
ArrangementFocus::Mix => ArrangerStatusBar::ArrangementMix,
|
||||||
|
ArrangementFocus::Track(_) => ArrangerStatusBar::ArrangementTrack,
|
||||||
|
ArrangementFocus::Scene(_) => ArrangerStatusBar::ArrangementScene,
|
||||||
|
ArrangementFocus::Clip(_, _) => ArrangerStatusBar::ArrangementClip,
|
||||||
|
},
|
||||||
|
ArrangerFocus::PhrasePool => ArrangerStatusBar::PhrasePool,
|
||||||
|
ArrangerFocus::PhraseEditor => ArrangerStatusBar::PhraseEditor,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/// Focus layout of arranger app
|
/// Focus layout of arranger app
|
||||||
impl<E: Engine> FocusGrid<ArrangerFocus> for Arranger<E> {
|
impl<E: Engine> FocusGrid<ArrangerFocus> for Arranger<E> {
|
||||||
|
|
@ -180,12 +194,7 @@ impl<E: Engine> FocusGrid<ArrangerFocus> for Arranger<E> {
|
||||||
focused == ArrangerFocus::PhrasePool;
|
focused == ArrangerFocus::PhrasePool;
|
||||||
self.editor.focused =
|
self.editor.focused =
|
||||||
focused == ArrangerFocus::PhraseEditor;
|
focused == ArrangerFocus::PhraseEditor;
|
||||||
self.status = match focused {
|
self.update_status();
|
||||||
ArrangerFocus::Transport => ArrangerStatusBar::Transport,
|
|
||||||
ArrangerFocus::Arrangement => ArrangerStatusBar::ArrangementMix,
|
|
||||||
ArrangerFocus::PhrasePool => ArrangerStatusBar::PhrasePool,
|
|
||||||
ArrangerFocus::PhraseEditor => ArrangerStatusBar::PhraseEditor,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// General methods for arrangement
|
/// General methods for arrangement
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ impl Handle<Tui> for Arranger<Tui> {
|
||||||
_ => return Ok(None)
|
_ => return Ok(None)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
self.update_status();
|
||||||
Ok(Some(true))
|
Ok(Some(true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -40,7 +41,7 @@ impl Arranger<Tui> {
|
||||||
key!(KeyCode::Char('>')) => {
|
key!(KeyCode::Char('>')) => {
|
||||||
self.phrases_split = self.phrases_split + 1;
|
self.phrases_split = self.phrases_split + 1;
|
||||||
},
|
},
|
||||||
_ => return self.arrangement.handle(from)
|
_ => return self.phrases.handle(from)
|
||||||
}
|
}
|
||||||
Ok(Some(true))
|
Ok(Some(true))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
/// The standalone arranger consists of transport, clip grid, and sequencer.
|
/// Layout for standalone arranger app.
|
||||||
impl Content for Arranger<Tui> {
|
impl Content for Arranger<Tui> {
|
||||||
type Engine = Tui;
|
type Engine = Tui;
|
||||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||||
|
|
@ -19,7 +19,7 @@ impl Content for Arranger<Tui> {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
).fill_xy()
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Content for ArrangerStatusBar {
|
impl Content for ArrangerStatusBar {
|
||||||
|
|
@ -38,8 +38,8 @@ impl Content for ArrangerStatusBar {
|
||||||
.fg(Color::Rgb(0, 0, 0))
|
.fg(Color::Rgb(0, 0, 0))
|
||||||
.bold(true);
|
.bold(true);
|
||||||
row!(label, " ", match self {
|
row!(label, " ", match self {
|
||||||
Self::ArrangementMix =>
|
Self::ArrangementClip =>
|
||||||
"[G]et [S]et [A]dd [I]nsert [D]uplicate [E]dit [C]olor",
|
"[G]et [S]et [A]dd [I]nsert [D]uplicate [E]dit [C]olor [,.]Choose",
|
||||||
Self::PhrasePool =>
|
Self::PhrasePool =>
|
||||||
"[A]ppend [I]nsert [D]uplicate [C]olor re[N]ame leng[T]h [,.]Move [<>]Resize",
|
"[A]ppend [I]nsert [D]uplicate [C]olor re[N]ame leng[T]h [,.]Move [<>]Resize",
|
||||||
_ => ""
|
_ => ""
|
||||||
|
|
@ -120,6 +120,55 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
|
// track titles
|
||||||
|
let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{
|
||||||
|
let name = track.name.read().unwrap();
|
||||||
|
let max_w = w.saturating_sub(1).min(name.len());
|
||||||
|
(&format!("▎{}", &name[0..max_w]).as_str())
|
||||||
|
.min_xy(w as u16, 2)
|
||||||
|
.bg(track.color)
|
||||||
|
.push_x(offset - 1)
|
||||||
|
});
|
||||||
|
|
||||||
|
// scene titles
|
||||||
|
let scene_name = |scene, playing: bool, height|row!(
|
||||||
|
if playing { "▶ " } else { " " },
|
||||||
|
(scene as &Scene).name.read().unwrap().as_str(),
|
||||||
|
).fixed_xy(offset.saturating_sub(1), height);
|
||||||
|
|
||||||
|
// scene clips
|
||||||
|
let scene_clip = |scene, track: usize, w: u16, h: u16|Layers::new(move |add|{
|
||||||
|
let mut color = clip_bg;
|
||||||
|
match (tracks.get(track), (scene as &Scene).clips.get(track)) {
|
||||||
|
(Some(_), Some(Some(phrase))) => {
|
||||||
|
let name = &(phrase as &Arc<RwLock<Phrase>>).read().unwrap().name;
|
||||||
|
let name = format!("{}", name);
|
||||||
|
let max_w = name.len().min((w as usize).saturating_sub(2));
|
||||||
|
add(&name.as_str()[0..max_w].push_x(1).fixed_x(w))?;
|
||||||
|
color = (phrase as &Arc<RwLock<Phrase>>).read().unwrap().color;
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
add(&Background(color))
|
||||||
|
}).fixed_xy(w, h);
|
||||||
|
|
||||||
|
add(&col!(track_titles, col!(
|
||||||
|
// scenes:
|
||||||
|
(scene, pulses) in scenes.iter().zip(rows.iter().map(|row|row.0)) => {
|
||||||
|
let height = 1.max((pulses / PPQ) as u16);
|
||||||
|
let playing = scene.is_playing(tracks);
|
||||||
|
Stack::right(move |add| {
|
||||||
|
// scene title:
|
||||||
|
add(&scene_name(scene, playing, height).bg(scene.color))?;
|
||||||
|
// clip per track:
|
||||||
|
for (track, w) in cols.iter().map(|col|col.0).enumerate() {
|
||||||
|
add(&scene_clip(scene, track, w as u16, height))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}).fixed_y(height)
|
||||||
|
}
|
||||||
|
)))?;
|
||||||
|
|
||||||
// cursor
|
// cursor
|
||||||
add(&CustomWidget::new(|_|Ok(Some([0,0])), move|to: &mut TuiOutput|{
|
add(&CustomWidget::new(|_|Ok(Some([0,0])), move|to: &mut TuiOutput|{
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
|
|
@ -165,63 +214,19 @@ impl<'a> Content for VerticalArranger<'a, Tui> {
|
||||||
if focused {
|
if focused {
|
||||||
if let Some(clip_area) = clip_area {
|
if let Some(clip_area) = clip_area {
|
||||||
to.render_in(clip_area, &CORNERS)?;
|
to.render_in(clip_area, &CORNERS)?;
|
||||||
to.fill_bg(clip_area, Color::Rgb(40, 50, 30));
|
//to.fill_bg(clip_area, Color::Rgb(40, 50, 30));
|
||||||
} else if let Some(track_area) = track_area {
|
} else if let Some(track_area) = track_area {
|
||||||
to.render_in(track_area.clip_h(2), &CORNERS)?;
|
to.render_in(track_area.clip_h(2), &CORNERS)?;
|
||||||
to.fill_bg(track_area, Color::Rgb(40, 50, 30));
|
//to.fill_bg(track_area, Color::Rgb(40, 50, 30));
|
||||||
} else if let Some(scene_area) = scene_area {
|
} else if let Some(scene_area) = scene_area {
|
||||||
to.render_in(scene_area.clip_w(offset-1), &CORNERS)?;
|
to.render_in(scene_area.clip_w(offset-1), &CORNERS)?;
|
||||||
to.fill_bg(scene_area, Color::Rgb(40, 50, 30));
|
//to.fill_bg(scene_area, Color::Rgb(40, 50, 30));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}))?;
|
}))?;
|
||||||
|
|
||||||
let track_titles = row!((track, w) in tracks.iter().zip(cols.iter().map(|col|col.0))=>{
|
Ok(())
|
||||||
let name = track.name.read().unwrap();
|
|
||||||
let max_w = w.min(name.len());
|
|
||||||
(&format!("▎{}", &name[0..max_w]).as_str())
|
|
||||||
.min_xy(w as u16, 2)
|
|
||||||
.bg(track.color)
|
|
||||||
.push_x(offset - 1)
|
|
||||||
});
|
|
||||||
|
|
||||||
let scene_name = |scene, playing: bool, height|row!(
|
|
||||||
if playing { "▶ " } else { " " },
|
|
||||||
(scene as &Scene).name.read().unwrap().as_str(),
|
|
||||||
).fixed_xy(offset.saturating_sub(1), height);
|
|
||||||
|
|
||||||
let scene_clip = |scene, track: usize, w: u16, h: u16|Layers::new(move |add|{
|
|
||||||
let mut color = clip_bg;
|
|
||||||
match (tracks.get(track), (scene as &Scene).clips.get(track)) {
|
|
||||||
(Some(_), Some(Some(phrase))) => {
|
|
||||||
let name = &(phrase as &Arc<RwLock<Phrase>>).read().unwrap().name;
|
|
||||||
let name = format!("{}", name);
|
|
||||||
let max_w = name.len().min((w as usize).saturating_sub(2));
|
|
||||||
add(&name.as_str()[0..max_w].push_x(1).fixed_x(w))?;
|
|
||||||
color = (phrase as &Arc<RwLock<Phrase>>).read().unwrap().color;
|
|
||||||
},
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
add(&Background(color))
|
|
||||||
}).fixed_xy(w, h);
|
|
||||||
|
|
||||||
add(&col!(track_titles, col!(
|
|
||||||
// scenes:
|
|
||||||
(scene, pulses) in scenes.iter().zip(rows.iter().map(|row|row.0)) => {
|
|
||||||
let height = 1.max((pulses / PPQ) as u16);
|
|
||||||
let playing = scene.is_playing(tracks);
|
|
||||||
Stack::right(move |add| {
|
|
||||||
// scene title:
|
|
||||||
add(&scene_name(scene, playing, height).bg(scene.color))?;
|
|
||||||
// clip per track:
|
|
||||||
for (track, w) in cols.iter().map(|col|col.0).enumerate() {
|
|
||||||
add(&scene_clip(scene, track, w as u16, height))?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}).fixed_y(height)
|
|
||||||
}
|
|
||||||
)))
|
|
||||||
}).bg(bg).border(border)
|
}).bg(bg).border(border)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,21 +17,18 @@ submod! {
|
||||||
|
|
||||||
pub const PPQ: usize = 96;
|
pub const PPQ: usize = 96;
|
||||||
|
|
||||||
pub const CORNERS: CornersTall = CornersTall(NOT_DIM_GREEN);
|
pub const CORNERS: CornersTall = CornersTall(CORNERS_STYLE);
|
||||||
|
tui_style!(CORNERS_STYLE =
|
||||||
|
Some(Color::Rgb(96, 255, 32)), None, None, Modifier::empty(), Modifier::DIM);
|
||||||
|
|
||||||
/// Octave number (from -1 to 9)
|
/// Octave number (from -1 to 9)
|
||||||
pub const NTH_OCTAVE: [&'static str;11] = [
|
pub const NTH_OCTAVE: [&'static str;11] = [
|
||||||
"-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
"-1", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
|
||||||
];
|
];
|
||||||
|
|
||||||
tui_style!(GRAY_DIM =
|
tui_style!(GRAY_DIM = Some(Color::Gray), None, None, Modifier::DIM, Modifier::empty());
|
||||||
Some(Color::Gray), None, None, Modifier::DIM, Modifier::empty());
|
tui_style!(GRAY_NOT_DIM_BOLD = Some(Color::Gray), None, None, Modifier::BOLD, Modifier::DIM);
|
||||||
tui_style!(GRAY_NOT_DIM_BOLD =
|
tui_style!(WHITE_NOT_DIM_BOLD = Some(Color::White), None, None, Modifier::BOLD, Modifier::DIM);
|
||||||
Some(Color::Gray), None, None, Modifier::BOLD, Modifier::DIM);
|
|
||||||
tui_style!(NOT_DIM_GREEN =
|
|
||||||
Some(Color::Rgb(96, 255, 32)), Some(COLOR_BG1), None, Modifier::empty(), Modifier::DIM);
|
|
||||||
tui_style!(WHITE_NOT_DIM_BOLD =
|
|
||||||
Some(Color::White), None, None, Modifier::BOLD, Modifier::DIM);
|
|
||||||
|
|
||||||
pub fn random_okhsl () -> Okhsl<f32> {
|
pub fn random_okhsl () -> Okhsl<f32> {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue