mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
view refactors; remove view_sizes
This commit is contained in:
parent
93a64833e9
commit
39ab736cbe
8 changed files with 239 additions and 208 deletions
|
|
@ -3,7 +3,6 @@ mod view_clock; pub use self::view_clock::*;
|
||||||
mod view_color; pub use self::view_color::*;
|
mod view_color; pub use self::view_color::*;
|
||||||
mod view_memo; pub use self::view_memo::*;
|
mod view_memo; pub use self::view_memo::*;
|
||||||
mod view_meter; pub use self::view_meter::*;
|
mod view_meter; pub use self::view_meter::*;
|
||||||
mod view_sizes; pub use self::view_sizes::*;
|
|
||||||
mod view_track; pub use self::view_track::*;
|
mod view_track; pub use self::view_track::*;
|
||||||
mod view_ports; pub use self::view_ports::*;
|
mod view_ports; pub use self::view_ports::*;
|
||||||
mod view_layout; pub use self::view_layout::*;
|
mod view_layout; pub use self::view_layout::*;
|
||||||
|
|
@ -134,6 +133,55 @@ impl<'a> ArrangerView<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Tek {
|
impl Tek {
|
||||||
|
/// Spacing between tracks.
|
||||||
|
pub(crate) const TRACK_SPACING: usize = 0;
|
||||||
|
/// Default scene height.
|
||||||
|
pub(crate) const H_SCENE: usize = 2;
|
||||||
|
/// Default editor height.
|
||||||
|
pub(crate) const H_EDITOR: usize = 15;
|
||||||
|
|
||||||
|
/// Width of display
|
||||||
|
pub(crate) fn w (&self) -> u16 {
|
||||||
|
self.size.w() as u16
|
||||||
|
}
|
||||||
|
pub(crate) fn w_sidebar (&self) -> u16 {
|
||||||
|
self.w() / if self.is_editing() { 16 } else { 8 } as u16
|
||||||
|
}
|
||||||
|
/// Width taken by all tracks.
|
||||||
|
pub(crate) fn w_tracks (&self) -> u16 {
|
||||||
|
self.tracks_with_sizes().last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
/// Width available to display tracks.
|
||||||
|
pub(crate) fn w_tracks_area (&self) -> u16 {
|
||||||
|
self.w().saturating_sub(2 * self.w_sidebar())
|
||||||
|
}
|
||||||
|
/// Height of display
|
||||||
|
pub(crate) fn h (&self) -> u16 {
|
||||||
|
self.size.h() as u16
|
||||||
|
}
|
||||||
|
/// Height available to display track headers.
|
||||||
|
pub(crate) fn h_tracks_area (&self) -> u16 {
|
||||||
|
5
|
||||||
|
//self.h().saturating_sub(self.h_inputs() + self.h_outputs())
|
||||||
|
}
|
||||||
|
/// Height available to display tracks.
|
||||||
|
pub(crate) fn h_scenes_area (&self) -> u16 {
|
||||||
|
//15
|
||||||
|
self.h().saturating_sub(self.h_inputs() + self.h_outputs() + 11)
|
||||||
|
}
|
||||||
|
/// Height taken by all inputs.
|
||||||
|
pub(crate) fn h_inputs (&self) -> u16 {
|
||||||
|
1 + self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
/// Height taken by all outputs.
|
||||||
|
pub(crate) fn h_outputs (&self) -> u16 {
|
||||||
|
1 + self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
/// Height taken by all scenes.
|
||||||
|
pub(crate) fn h_scenes (&self) -> u16 {
|
||||||
|
self.scenes_with_sizes(self.is_editing(), Self::H_SCENE, Self::H_EDITOR).last()
|
||||||
|
.map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn inputs_with_sizes (&self)
|
pub(crate) fn inputs_with_sizes (&self)
|
||||||
-> impl PortsSizes<'_>
|
-> impl PortsSizes<'_>
|
||||||
|
|
@ -199,6 +247,18 @@ impl Tek {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Define a type alias for iterators of sized items (columns).
|
||||||
|
macro_rules! def_sizes_iter {
|
||||||
|
($Type:ident => $($Item:ty),+) => {
|
||||||
|
pub(crate) trait $Type<'a> =
|
||||||
|
Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a;}}
|
||||||
|
|
||||||
|
def_sizes_iter!(ScenesSizes => Scene);
|
||||||
|
def_sizes_iter!(TracksSizes => Track);
|
||||||
|
def_sizes_iter!(InputsSizes => JackMidiIn);
|
||||||
|
def_sizes_iter!(OutputsSizes => JackMidiOut);
|
||||||
|
def_sizes_iter!(PortsSizes => Arc<str>, [PortConnect]);
|
||||||
|
|
||||||
#[cfg(test)] #[test] fn test_view_iter () {
|
#[cfg(test)] #[test] fn test_view_iter () {
|
||||||
let mut tek = Tek::default();
|
let mut tek = Tek::default();
|
||||||
tek.editor = Some(Default::default());
|
tek.editor = Some(Default::default());
|
||||||
|
|
@ -209,3 +269,14 @@ impl Tek {
|
||||||
//let _: Vec<_> = tek.scenes_with_colors(true, 10).collect();
|
//let _: Vec<_> = tek.scenes_with_colors(true, 10).collect();
|
||||||
//let _: Vec<_> = tek.scenes_with_track_colors(true, 10, 10).collect();
|
//let _: Vec<_> = tek.scenes_with_track_colors(true, 10, 10).collect();
|
||||||
}
|
}
|
||||||
|
#[cfg(test)] #[test] fn test_view_sizes () {
|
||||||
|
let app = Tek::default();
|
||||||
|
let _ = app.w();
|
||||||
|
let _ = app.w_sidebar();
|
||||||
|
let _ = app.w_tracks_area();
|
||||||
|
let _ = app.h();
|
||||||
|
let _ = app.h_tracks_area();
|
||||||
|
let _ = app.h_inputs();
|
||||||
|
let _ = app.h_outputs();
|
||||||
|
let _ = app.h_scenes();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,64 +1,64 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
impl Tek {
|
impl Tek {
|
||||||
fn update_clock (&self) {
|
fn update_clock (&self) {
|
||||||
let compact = self.size.w() > 80;
|
ViewCache::update_clock(&self.view_cache, self.clock(), self.size.w() > 80)
|
||||||
let clock = self.clock();
|
|
||||||
let rate = clock.timebase.sr.get();
|
|
||||||
let chunk = clock.chunk.load(Relaxed) as f64;
|
|
||||||
let lat = chunk / rate * 1000.;
|
|
||||||
let delta = |start: &Moment|clock.global.usec.get() - start.usec.get();
|
|
||||||
let mut view_cache = self.view_cache.write().unwrap();
|
|
||||||
view_cache.buf.update(Some(chunk), rewrite!(buf, "{chunk}"));
|
|
||||||
view_cache.lat.update(Some(lat), rewrite!(buf, "{lat:.1}ms"));
|
|
||||||
view_cache.sr.update(Some((compact, rate)), |buf,_,_|if compact {
|
|
||||||
buf.clear(); write!(buf, "{:.1}kHz", rate / 1000.)
|
|
||||||
} else {
|
|
||||||
buf.clear(); write!(buf, "{:.0}Hz", rate)
|
|
||||||
});
|
|
||||||
if let Some(now) = clock.started.read().unwrap().as_ref().map(delta) {
|
|
||||||
let pulse = clock.timebase.usecs_to_pulse(now);
|
|
||||||
let time = now/1000000.;
|
|
||||||
let bpm = clock.timebase.bpm.get();
|
|
||||||
view_cache.beat.update(Some(pulse),
|
|
||||||
|buf, _, _|{buf.clear();clock.timebase.format_beats_1_to(buf, pulse)});
|
|
||||||
view_cache.time.update(Some(time), rewrite!(buf, "{:.3}s", time));
|
|
||||||
view_cache.bpm.update(Some(bpm), rewrite!(buf, "{:.3}", bpm));
|
|
||||||
} else {
|
|
||||||
view_cache.beat.update(None, rewrite!(buf, "{}", ViewCache::BEAT_EMPTY));
|
|
||||||
view_cache.time.update(None, rewrite!(buf, "{}", ViewCache::TIME_EMPTY));
|
|
||||||
view_cache.bpm.update(None, rewrite!(buf, "{}", ViewCache::BPM_EMPTY));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub(crate) fn view_transport (&self) -> impl Content<TuiOut> + use<'_> {
|
pub(crate) fn view_transport (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.update_clock();
|
self.update_clock();
|
||||||
let theme = ItemPalette::G[96];
|
let cache = self.view_cache.read().unwrap();
|
||||||
let view_cache = self.view_cache.read().unwrap();
|
view_transport(
|
||||||
Fixed::y(1, Tui::bg(Black, row!(Bsp::a(
|
self.clock.is_rolling(),
|
||||||
Fill::xy(Align::w(button_play_pause(self.clock.is_rolling()))),
|
cache.bpm.view.clone(),
|
||||||
Fill::xy(Align::e(row!(
|
cache.beat.view.clone(),
|
||||||
FieldH(theme, "BPM", view_cache.bpm.view.clone()),
|
cache.time.view.clone(),
|
||||||
FieldH(theme, "Beat", view_cache.beat.view.clone()),
|
)
|
||||||
FieldH(theme, "Time", view_cache.time.view.clone())
|
|
||||||
)))
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
pub(crate) fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
pub(crate) fn view_status (&self) -> impl Content<TuiOut> + use<'_> {
|
||||||
self.update_clock();
|
self.update_clock();
|
||||||
let theme = ItemPalette::G[96];
|
let cache = self.view_cache.read().unwrap();
|
||||||
let view_cache = self.view_cache.read().unwrap();
|
view_status(
|
||||||
Tui::bg(Black, row!(Bsp::a(
|
self.selected.describe(&self.tracks, &self.scenes),
|
||||||
Fill::xy(Align::w(
|
cache.sr.view.clone(),
|
||||||
FieldH(theme, "Selected", self.selected.describe(&self.tracks, &self.scenes))
|
cache.buf.view.clone(),
|
||||||
)),
|
cache.lat.view.clone(),
|
||||||
Fill::xy(Align::e(row!(
|
)
|
||||||
FieldH(theme, "SR", view_cache.sr.view.clone()),
|
|
||||||
FieldH(theme, "Buf", view_cache.buf.view.clone()),
|
|
||||||
FieldH(theme, "Lat", view_cache.lat.view.clone()),
|
|
||||||
)))
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn view_transport (
|
||||||
|
play: bool,
|
||||||
|
bpm: Arc<RwLock<String>>,
|
||||||
|
beat: Arc<RwLock<String>>,
|
||||||
|
time: Arc<RwLock<String>>,
|
||||||
|
) -> impl Content<TuiOut> {
|
||||||
|
let theme = ItemPalette::G[96];
|
||||||
|
Tui::bg(Black, row!(Bsp::a(
|
||||||
|
Fill::xy(Align::w(button_play_pause(play))),
|
||||||
|
Fill::xy(Align::e(row!(
|
||||||
|
FieldH(theme, "BPM", bpm),
|
||||||
|
FieldH(theme, "Beat", beat),
|
||||||
|
FieldH(theme, "Time", time),
|
||||||
|
)))
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view_status (
|
||||||
|
sel: Arc<str>,
|
||||||
|
sr: Arc<RwLock<String>>,
|
||||||
|
buf: Arc<RwLock<String>>,
|
||||||
|
lat: Arc<RwLock<String>>,
|
||||||
|
) -> impl Content<TuiOut> {
|
||||||
|
let theme = ItemPalette::G[96];
|
||||||
|
Tui::bg(Black, row!(Bsp::a(
|
||||||
|
Fill::xy(Align::w(FieldH(theme, "Selected", sel))),
|
||||||
|
Fill::xy(Align::e(row!(
|
||||||
|
FieldH(theme, "SR", sr),
|
||||||
|
FieldH(theme, "Buf", buf),
|
||||||
|
FieldH(theme, "Lat", lat),
|
||||||
|
)))
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
|
fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
|
||||||
let compact = true;//self.is_editing();
|
let compact = true;//self.is_editing();
|
||||||
Tui::bg(
|
Tui::bg(
|
||||||
|
|
@ -66,10 +66,14 @@ fn button_play_pause (playing: bool) -> impl Content<TuiOut> {
|
||||||
Either::new(compact,
|
Either::new(compact,
|
||||||
Thunk::new(move||Fixed::x(9, Either::new(playing,
|
Thunk::new(move||Fixed::x(9, Either::new(playing,
|
||||||
Tui::fg(Rgb(0, 255, 0), " PLAYING "),
|
Tui::fg(Rgb(0, 255, 0), " PLAYING "),
|
||||||
Tui::fg(Rgb(255, 128, 0), " STOPPED ")))),
|
Tui::fg(Rgb(255, 128, 0), " STOPPED ")))
|
||||||
|
),
|
||||||
Thunk::new(move||Fixed::x(5, Either::new(playing,
|
Thunk::new(move||Fixed::x(5, Either::new(playing,
|
||||||
Tui::fg(Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
Tui::fg(Rgb(0, 255, 0), Bsp::s(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)),
|
||||||
Tui::fg(Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",)))))))
|
Tui::fg(Rgb(255, 128, 0), Bsp::s(" ▗▄▖ ", " ▝▀▘ ",))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] mod test {
|
#[cfg(test)] mod test {
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,19 @@ impl Tek {
|
||||||
[fg, bg, hi, lo]
|
[fg, bg, hi, lo]
|
||||||
}
|
}
|
||||||
pub(crate) fn color_hi (prev: Option<ItemPalette>, neighbor: bool) -> Color {
|
pub(crate) fn color_hi (prev: Option<ItemPalette>, neighbor: bool) -> Color {
|
||||||
prev.map(|prev|if neighbor { prev.light.rgb } else { prev.base.rgb }).unwrap_or(Reset)
|
prev.map(|prev|if neighbor {
|
||||||
|
prev.light.rgb
|
||||||
|
} else {
|
||||||
|
prev.base.rgb
|
||||||
|
}).unwrap_or(Reset)
|
||||||
}
|
}
|
||||||
pub(crate) fn color_lo (theme: &ItemPalette, is_last: bool, selected: bool) -> Color {
|
pub(crate) fn color_lo (theme: &ItemPalette, is_last: bool, selected: bool) -> Color {
|
||||||
if is_last { Reset } else if selected { theme.light.rgb } else { theme.base.rgb }
|
if is_last {
|
||||||
|
Reset
|
||||||
|
} else if selected {
|
||||||
|
theme.light.rgb
|
||||||
|
} else {
|
||||||
|
theme.base.rgb
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,7 @@ use crate::*;
|
||||||
|
|
||||||
/// Clear a pre-allocated buffer, then write into it.
|
/// Clear a pre-allocated buffer, then write into it.
|
||||||
#[macro_export] macro_rules! rewrite {
|
#[macro_export] macro_rules! rewrite {
|
||||||
($buf:ident, $($rest:tt)*) => {
|
($buf:ident, $($rest:tt)*) => { |$buf,_,_|{ $buf.clear(); write!($buf, $($rest)*) } }
|
||||||
|$buf,_,_|{
|
|
||||||
$buf.clear();
|
|
||||||
write!($buf, $($rest)*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)] pub(crate) struct ViewMemo<T, U> {
|
#[derive(Debug, Default)] pub(crate) struct ViewMemo<T, U> {
|
||||||
|
|
@ -33,7 +28,7 @@ impl<T: PartialEq, U> ViewMemo<T, U> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)] pub(crate) struct ViewCache {
|
#[derive(Debug)] pub struct ViewCache {
|
||||||
pub(crate) sr: ViewMemo<Option<(bool, f64)>, String>,
|
pub(crate) sr: ViewMemo<Option<(bool, f64)>, String>,
|
||||||
pub(crate) buf: ViewMemo<Option<f64>, String>,
|
pub(crate) buf: ViewMemo<Option<f64>, String>,
|
||||||
pub(crate) lat: ViewMemo<Option<f64>, String>,
|
pub(crate) lat: ViewMemo<Option<f64>, String>,
|
||||||
|
|
@ -46,12 +41,6 @@ impl<T: PartialEq, U> ViewMemo<T, U> {
|
||||||
pub(crate) edit: Arc<str>,
|
pub(crate) edit: Arc<str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ViewCache {
|
|
||||||
pub const BEAT_EMPTY: &'static str = "-.-.--";
|
|
||||||
pub const TIME_EMPTY: &'static str = "-.---s";
|
|
||||||
pub const BPM_EMPTY: &'static str = "---.---";
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ViewCache {
|
impl Default for ViewCache {
|
||||||
fn default () -> Self {
|
fn default () -> Self {
|
||||||
let mut beat = String::with_capacity(16);
|
let mut beat = String::with_capacity(16);
|
||||||
|
|
@ -74,3 +63,58 @@ impl Default for ViewCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ViewCache {
|
||||||
|
pub const BEAT_EMPTY: &'static str = "-.-.--";
|
||||||
|
pub const TIME_EMPTY: &'static str = "-.---s";
|
||||||
|
pub const BPM_EMPTY: &'static str = "---.---";
|
||||||
|
|
||||||
|
pub(crate) fn track_counter (cache: &Arc<RwLock<Self>>, track: usize, tracks: usize)
|
||||||
|
-> Arc<RwLock<String>>
|
||||||
|
{
|
||||||
|
let data = (track, tracks);
|
||||||
|
cache.write().unwrap().trks.update(Some(data), rewrite!(buf, "{}/{}", data.0, data.1));
|
||||||
|
cache.read().unwrap().trks.view.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn scene_add (cache: &Arc<RwLock<Self>>, scene: usize, scenes: usize, is_editing: bool)
|
||||||
|
-> impl Content<TuiOut>
|
||||||
|
{
|
||||||
|
let data = (scene, scenes);
|
||||||
|
cache.write().unwrap().scns.update(Some(data), rewrite!(buf, "({}/{})", data.0, data.1));
|
||||||
|
button_3("S", "add scene", cache.read().unwrap().scns.view.clone(), is_editing)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn update_clock (cache: &Arc<RwLock<Self>>, clock: &Clock, compact: bool) {
|
||||||
|
let rate = clock.timebase.sr.get();
|
||||||
|
let chunk = clock.chunk.load(Relaxed) as f64;
|
||||||
|
let lat = chunk / rate * 1000.;
|
||||||
|
let delta = |start: &Moment|clock.global.usec.get() - start.usec.get();
|
||||||
|
let mut cache = cache.write().unwrap();
|
||||||
|
cache.buf.update(Some(chunk), rewrite!(buf, "{chunk}"));
|
||||||
|
cache.lat.update(Some(lat), rewrite!(buf, "{lat:.1}ms"));
|
||||||
|
cache.sr.update(Some((compact, rate)), |buf,_,_|{
|
||||||
|
buf.clear();
|
||||||
|
if compact {
|
||||||
|
write!(buf, "{:.1}kHz", rate / 1000.)
|
||||||
|
} else {
|
||||||
|
write!(buf, "{:.0}Hz", rate)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if let Some(now) = clock.started.read().unwrap().as_ref().map(delta) {
|
||||||
|
let pulse = clock.timebase.usecs_to_pulse(now);
|
||||||
|
let time = now/1000000.;
|
||||||
|
let bpm = clock.timebase.bpm.get();
|
||||||
|
cache.beat.update(Some(pulse), |buf, _, _|{
|
||||||
|
buf.clear();
|
||||||
|
clock.timebase.format_beats_1_to(buf, pulse)
|
||||||
|
});
|
||||||
|
cache.time.update(Some(time), rewrite!(buf, "{:.3}s", time));
|
||||||
|
cache.bpm.update(Some(bpm), rewrite!(buf, "{:.3}", bpm));
|
||||||
|
} else {
|
||||||
|
cache.beat.update(None, rewrite!(buf, "{}", ViewCache::BEAT_EMPTY));
|
||||||
|
cache.time.update(None, rewrite!(buf, "{}", ViewCache::TIME_EMPTY));
|
||||||
|
cache.bpm.update(None, rewrite!(buf, "{}", ViewCache::BPM_EMPTY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// Define a type alias for iterators of sized items (columns).
|
|
||||||
macro_rules! def_sizes_iter {
|
|
||||||
($Type:ident => $($Item:ty),+) => {
|
|
||||||
pub(crate) trait $Type<'a> =
|
|
||||||
Iterator<Item=(usize, $(&'a $Item,)+ usize, usize)> + Send + Sync + 'a;}}
|
|
||||||
|
|
||||||
def_sizes_iter!(ScenesSizes => Scene);
|
|
||||||
def_sizes_iter!(TracksSizes => Track);
|
|
||||||
def_sizes_iter!(InputsSizes => JackMidiIn);
|
|
||||||
def_sizes_iter!(OutputsSizes => JackMidiOut);
|
|
||||||
def_sizes_iter!(PortsSizes => Arc<str>, [PortConnect]);
|
|
||||||
|
|
||||||
impl Tek {
|
|
||||||
/// Spacing between tracks.
|
|
||||||
pub(crate) const TRACK_SPACING: usize = 0;
|
|
||||||
/// Default scene height.
|
|
||||||
pub(crate) const H_SCENE: usize = 2;
|
|
||||||
/// Default editor height.
|
|
||||||
pub(crate) const H_EDITOR: usize = 15;
|
|
||||||
|
|
||||||
/// Width of display
|
|
||||||
pub(crate) fn w (&self) -> u16 {
|
|
||||||
self.size.w() as u16
|
|
||||||
}
|
|
||||||
pub(crate) fn w_sidebar (&self) -> u16 {
|
|
||||||
self.w() / if self.is_editing() { 16 } else { 8 } as u16
|
|
||||||
}
|
|
||||||
/// Width taken by all tracks.
|
|
||||||
pub(crate) fn w_tracks (&self) -> u16 {
|
|
||||||
self.tracks_with_sizes().last().map(|(_, _, _, x)|x as u16).unwrap_or(0)
|
|
||||||
}
|
|
||||||
/// Width available to display tracks.
|
|
||||||
pub(crate) fn w_tracks_area (&self) -> u16 {
|
|
||||||
self.w().saturating_sub(2 * self.w_sidebar())
|
|
||||||
}
|
|
||||||
/// Height of display
|
|
||||||
pub(crate) fn h (&self) -> u16 {
|
|
||||||
self.size.h() as u16
|
|
||||||
}
|
|
||||||
/// Height available to display track headers.
|
|
||||||
pub(crate) fn h_tracks_area (&self) -> u16 {
|
|
||||||
5
|
|
||||||
//self.h().saturating_sub(self.h_inputs() + self.h_outputs())
|
|
||||||
}
|
|
||||||
/// Height available to display tracks.
|
|
||||||
pub(crate) fn h_scenes_area (&self) -> u16 {
|
|
||||||
//15
|
|
||||||
self.h().saturating_sub(self.h_inputs() + self.h_outputs() + 11)
|
|
||||||
}
|
|
||||||
/// Height taken by all inputs.
|
|
||||||
pub(crate) fn h_inputs (&self) -> u16 {
|
|
||||||
1 + self.inputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
|
||||||
}
|
|
||||||
/// Height taken by all outputs.
|
|
||||||
pub(crate) fn h_outputs (&self) -> u16 {
|
|
||||||
1 + self.outputs_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0)
|
|
||||||
}
|
|
||||||
/// Height taken by all scenes.
|
|
||||||
pub(crate) fn h_scenes (&self) -> u16 {
|
|
||||||
self.scenes_with_sizes(self.is_editing(), Self::H_SCENE, Self::H_EDITOR).last()
|
|
||||||
.map(|(_, _, _, y)|y as u16).unwrap_or(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(test)] #[test] fn test_view_sizes () {
|
|
||||||
let app = Tek::default();
|
|
||||||
let _ = app.w();
|
|
||||||
let _ = app.w_sidebar();
|
|
||||||
let _ = app.w_tracks_area();
|
|
||||||
let _ = app.h();
|
|
||||||
let _ = app.h_tracks_area();
|
|
||||||
let _ = app.h_inputs();
|
|
||||||
let _ = app.h_outputs();
|
|
||||||
let _ = app.h_scenes();
|
|
||||||
}
|
|
||||||
|
|
@ -18,7 +18,7 @@ impl<'a> ArrangerView<'a> {
|
||||||
let Self {
|
let Self {
|
||||||
width, width_side, width_mid,
|
width, width_side, width_mid,
|
||||||
scenes_height, scene_last, scene_selected,
|
scenes_height, scene_last, scene_selected,
|
||||||
track_selected, is_editing, ..
|
track_selected, is_editing, app: Tek { editor, .. }, ..
|
||||||
} = self;
|
} = self;
|
||||||
Tryptich::center(*scenes_height)
|
Tryptich::center(*scenes_height)
|
||||||
.left(*width_side, Map::new(||self.scenes_with_scene_colors(),
|
.left(*width_side, Map::new(||self.scenes_with_scene_colors(),
|
||||||
|
|
@ -47,28 +47,25 @@ impl<'a> ArrangerView<'a> {
|
||||||
*track_selected == Some(track_index),
|
*track_selected == Some(track_index),
|
||||||
*scene_selected,
|
*scene_selected,
|
||||||
*scene_last == scene_index,
|
*scene_last == scene_index,
|
||||||
&self.app.editor
|
editor
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scene_add (&'a self) -> impl Content<TuiOut> + 'a {
|
fn scene_add (&'a self) -> impl Content<TuiOut> + 'a {
|
||||||
let Self {
|
ViewCache::scene_add(
|
||||||
scene_selected, scene_count, is_editing, app: Tek { view_cache, .. }, ..
|
&self.app.view_cache,
|
||||||
} = self;
|
self.scene_selected.unwrap_or(0),
|
||||||
let data = (scene_selected.unwrap_or(0), *scene_count);
|
self.scene_count,
|
||||||
view_cache.write().unwrap()
|
self.is_editing,
|
||||||
.scns.update(Some(data), rewrite!(buf, "({}/{})", data.0, data.1));
|
)
|
||||||
button_3("S", "add scene", view_cache.read().unwrap().scns.view.clone(), *is_editing)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn track_counter (&'a self) -> Arc<RwLock<String>> {
|
fn track_counter (&'a self) -> Arc<RwLock<String>> {
|
||||||
let Self {
|
ViewCache::track_counter(
|
||||||
track_selected, track_count, app: Tek { view_cache, .. }, ..
|
&self.app.view_cache,
|
||||||
} = self;
|
self.track_selected.unwrap_or(0),
|
||||||
let data = (track_selected.unwrap_or(0), *track_count);
|
self.track_count,
|
||||||
view_cache.write().unwrap()
|
)
|
||||||
.trks.update(Some(data), rewrite!(buf, "{}/{}", data.0, data.1));
|
|
||||||
view_cache.read().unwrap().trks.view.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -93,15 +90,7 @@ pub(crate) fn view_scene_name (
|
||||||
select: Option<usize>,
|
select: Option<usize>,
|
||||||
) -> impl Content<TuiOut> {
|
) -> impl Content<TuiOut> {
|
||||||
Fill::x(map_south(offset, height, Fixed::y(height, view_scene_cell(
|
Fill::x(map_south(offset, height, Fixed::y(height, view_scene_cell(
|
||||||
" ⯈ ",
|
" ⯈ ", Some(scene.name.clone()), &scene.color, prev, last, select, true, index,
|
||||||
Some(scene.name.clone()),
|
|
||||||
last,
|
|
||||||
select,
|
|
||||||
true,
|
|
||||||
index,
|
|
||||||
&scene.color,
|
|
||||||
prev,
|
|
||||||
scene.color.lightest.rgb
|
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,7 +99,7 @@ pub(crate) fn view_scene_clip <'a> (
|
||||||
height: u16,
|
height: u16,
|
||||||
offset: u16,
|
offset: u16,
|
||||||
scene: &'a Scene,
|
scene: &'a Scene,
|
||||||
prev: Option<ItemPalette>,
|
prev_bg: Option<ItemPalette>,
|
||||||
scene_index: usize,
|
scene_index: usize,
|
||||||
track_index: usize,
|
track_index: usize,
|
||||||
editing: bool,
|
editing: bool,
|
||||||
|
|
@ -119,37 +108,29 @@ pub(crate) fn view_scene_clip <'a> (
|
||||||
scene_is_last: bool,
|
scene_is_last: bool,
|
||||||
editor: &'a Option<MidiEditor>,
|
editor: &'a Option<MidiEditor>,
|
||||||
) -> impl Content<TuiOut> + use<'a> {
|
) -> impl Content<TuiOut> + use<'a> {
|
||||||
let (name, fg, bg) = if let Some(clip) = &scene.clips[track_index] {
|
let (name, _fg, bg) = if let Some(clip) = &scene.clips[track_index] {
|
||||||
let clip = clip.read().unwrap();
|
let clip = clip.read().unwrap();
|
||||||
(Some(clip.name.clone()), clip.color.lightest.rgb, clip.color)
|
(Some(clip.name.clone()), clip.color.lightest.rgb, clip.color)
|
||||||
} else {
|
} else {
|
||||||
(None, Tui::g(96), ItemPalette::G[32])
|
(None, Tui::g(96), ItemPalette::G[32])
|
||||||
};
|
};
|
||||||
let active = editing && same_track && scene_selected == Some(scene_index);
|
let active = editing && same_track && scene_selected == Some(scene_index);
|
||||||
let edit = |x|Bsp::b(x, When(active, editor));
|
let with_editor = |x|Bsp::b(x, When(active, editor));
|
||||||
map_south(offset, height, edit(Fixed::y(height, view_scene_cell(
|
map_south(offset, height, with_editor(Fixed::y(height, view_scene_cell(
|
||||||
" ⏹ ",
|
" ⏹ ", name, &bg, prev_bg,
|
||||||
name,
|
scene_is_last, scene_selected, same_track, scene_index,
|
||||||
scene_is_last,
|
|
||||||
scene_selected,
|
|
||||||
same_track,
|
|
||||||
scene_index,
|
|
||||||
&bg,
|
|
||||||
prev,
|
|
||||||
fg
|
|
||||||
))))
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn view_scene_cell <'a> (
|
pub(crate) fn view_scene_cell <'a> (
|
||||||
icon: &'a str,
|
icon: &'a str,
|
||||||
name: Option<Arc<str>>,
|
name: Option<Arc<str>>,
|
||||||
|
color: &ItemPalette,
|
||||||
|
prev_color: Option<ItemPalette>,
|
||||||
is_last: bool,
|
is_last: bool,
|
||||||
selected: Option<usize>,
|
selected: Option<usize>,
|
||||||
same_track: bool,
|
same_track: bool,
|
||||||
scene: usize,
|
scene: usize,
|
||||||
color: &ItemPalette,
|
|
||||||
prev_color: Option<ItemPalette>,
|
|
||||||
fg: Color,
|
|
||||||
) -> impl Content<TuiOut> + use<'a> {
|
) -> impl Content<TuiOut> + use<'a> {
|
||||||
Phat {
|
Phat {
|
||||||
width: 0,
|
width: 0,
|
||||||
|
|
|
||||||
|
|
@ -395,30 +395,27 @@ atom_command!(ClipRenameCommand: |state: MidiPool| {
|
||||||
("confirm" [] Some(Self::Confirm))
|
("confirm" [] Some(Self::Confirm))
|
||||||
("set" [n: Arc<str>] Some(Self::Set(n.expect("no name"))))
|
("set" [n: Arc<str>] Some(Self::Set(n.expect("no name"))))
|
||||||
});
|
});
|
||||||
command!(|self: ClipRenameCommand, state: MidiPool|{
|
command!(|self: ClipRenameCommand, state: MidiPool|if let Some(
|
||||||
use ClipRenameCommand::*;
|
PoolMode::Rename(clip, ref mut old_name)
|
||||||
if let Some(
|
) = state.mode_mut().clone() {
|
||||||
PoolMode::Rename(clip, ref mut old_name)
|
match self {
|
||||||
) = state.mode_mut().clone() {
|
Self::Set(s) => {
|
||||||
match self {
|
state.clips()[clip].write().unwrap().name = s;
|
||||||
Set(s) => {
|
return Ok(Some(Self::Set(old_name.clone().into())))
|
||||||
state.clips()[clip].write().unwrap().name = s;
|
},
|
||||||
return Ok(Some(Self::Set(old_name.clone().into())))
|
Self::Confirm => {
|
||||||
},
|
let old_name = old_name.clone();
|
||||||
Confirm => {
|
*state.mode_mut() = None;
|
||||||
let old_name = old_name.clone();
|
return Ok(Some(Self::Set(old_name)))
|
||||||
*state.mode_mut() = None;
|
},
|
||||||
return Ok(Some(Self::Set(old_name)))
|
Self::Cancel => {
|
||||||
},
|
state.clips()[clip].write().unwrap().name = old_name.clone().into();
|
||||||
Cancel => {
|
return Ok(None)
|
||||||
state.clips()[clip].write().unwrap().name = old_name.clone().into();
|
},
|
||||||
return Ok(None)
|
_ => unreachable!()
|
||||||
},
|
|
||||||
_ => unreachable!()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
unreachable!()
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
});
|
});
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)] pub enum ClipLengthCommand {
|
#[derive(Copy, Clone, Debug, PartialEq)] pub enum ClipLengthCommand {
|
||||||
Begin,
|
Begin,
|
||||||
|
|
|
||||||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9809c4642883b4dba896bdc92709f6d0b1513f8b
|
Subproject commit 1daca5ea7b286d95ffb1c9c14b513e0cbe641965
|
||||||
Loading…
Add table
Add a link
Reference in a new issue