From 3a6202464c21246731c5f682f44996281bcfad49 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 16 Jan 2025 20:26:34 +0100 Subject: [PATCH] why do the borders think they are enabled --- sampler/src/sampler_tui.rs | 4 +- tek/src/lib.rs | 173 +++++++++++++++++-------------------- tui/src/tui_border.rs | 114 +++++++++++------------- tui/src/tui_content.rs | 3 +- tui/src/tui_style.rs | 8 +- 5 files changed, 135 insertions(+), 167 deletions(-) diff --git a/sampler/src/sampler_tui.rs b/sampler/src/sampler_tui.rs index 9f97b8c3..c37d9b06 100644 --- a/sampler/src/sampler_tui.rs +++ b/sampler/src/sampler_tui.rs @@ -32,7 +32,7 @@ content!(TuiOut: |self: SamplerTui| { let keys = move||"";//SamplerKeys(self); let fg = self.color.base.rgb; let bg = self.color.darkest.rgb; - let border = Fill::xy(Outer(Style::default().fg(fg).bg(bg))); + let border = Fill::xy(Outer(true, Style::default().fg(fg).bg(bg))); let with_border = |x|lay!(border, Fill::xy(x)); let with_size = |x|lay!(self.size.clone(), x); Tui::bg(bg, Fill::xy(with_border(Bsp::s( @@ -83,7 +83,7 @@ impl Sampler { let note_lo = editor.note_lo().load(Relaxed); let note_pt = editor.note_pos(); let note_hi = editor.note_hi(); - Outer(Style::default().fg(TuiTheme::g(96))).enclose(Map::new(move||(note_lo..=note_hi).rev(), move|note, i| { + Outer(true, Style::default().fg(TuiTheme::g(96))).enclose(Map::new(move||(note_lo..=note_hi).rev(), move|note, i| { let offset = |a|Push::y(i as u16, Align::n(Fixed::y(1, Fill::x(a)))); let mut bg = if note == note_pt { TuiTheme::g(64) } else { Color::Reset }; let mut fg = TuiTheme::g(160); diff --git a/tek/src/lib.rs b/tek/src/lib.rs index 03e41672..9be02611 100644 --- a/tek/src/lib.rs +++ b/tek/src/lib.rs @@ -200,23 +200,68 @@ edn_view!(TuiOut: |self: Tek| self.size.of(EdnView::from_source(self, self.edn.a ":tracks" => self.view_row(self.w(), 3, self.track_header(), self.track_cells()).boxed(), ":inputs" => self.view_row(self.w(), 3, self.input_header(), self.input_cells()).boxed(), ":outputs" => self.view_row(self.w(), 3, self.output_header(), self.output_cells()).boxed(), - ":scenes" => Outer(Style::default().fg(TuiTheme::g(0))).enclose_bg(self.view_row( + ":scenes" => Outer(false, Style::default().fg(TuiTheme::g(0))).enclose_bg(self.view_row( self.w(), self.size.h().saturating_sub(12) as u16, self.scene_header(), self.clip_columns() )).boxed() }}); impl Tek { + fn new_clock ( + jack: &Arc>, + bpm: Option, sync_lead: bool, sync_follow: bool, + midi_froms: &[PortConnection], midi_tos: &[PortConnection], + ) -> Usually { + let tek = Self { + edn: include_str!("./view_transport.edn").to_string(), + jack: jack.clone(), + color: ItemPalette::random(), + clock: Clock::new(jack, bpm), + midi_ins: vec![JackPort::::new(jack, "GlobalI", midi_froms)?], + midi_outs: vec![JackPort::::new(jack, "GlobalO", midi_tos)?], + ..Default::default() + }; + tek.sync_lead(sync_lead); + tek.sync_follow(sync_follow); + Ok(tek) + } + fn new_sequencer ( + jack: &Arc>, + bpm: Option, sync_lead: bool, sync_follow: bool, + midi_froms: &[PortConnection], midi_tos: &[PortConnection], + ) -> Usually { + let clip = MidiClip::new("Clip", true, 384usize, None, Some(ItemColor::random().into())); + let clip = Arc::new(RwLock::new(clip)); + Ok(Self { + edn: include_str!("./view_sequencer.edn").to_string(), + pool: Some((&clip).into()), + editor: Some((&clip).into()), + editing: false.into(), + midi_buf: vec![vec![];65536], + player: Some(MidiPlayer::new(&jack, "sequencer", Some(&clip), &midi_froms, &midi_tos)?), + ..Self::new_clock(jack, bpm, sync_lead, sync_follow, midi_froms, midi_tos)? + }) + } + fn new_groovebox ( + jack: &Arc>, + bpm: Option, sync_lead: bool, sync_follow: bool, + midi_froms: &[PortConnection], midi_tos: &[PortConnection], + audio_froms: &[&[PortConnection];2], audio_tos: &[&[PortConnection];2], + ) -> Usually { + let app = Self { + edn: include_str!("./view_groovebox.edn").to_string(), + sampler: Some(Sampler::new(jack, &"sampler", midi_froms, audio_froms, audio_tos)?), + ..Self::new_sequencer(jack, bpm, sync_lead, sync_follow, midi_froms, midi_tos)? + }; + if let Some(sampler) = app.sampler.as_ref().unwrap().midi_in.as_ref() { + jack.connect_ports(&app.player.as_ref().unwrap().midi_outs[0].port, &sampler.port)?; + } + Ok(app) + } fn new_arranger ( - jack: &Arc>, - bpm: Option, - sync_lead: bool, - sync_follow: bool, - midi_froms: &[PortConnection], - midi_tos: &[PortConnection], - audio_froms: &[&[PortConnection];2], - audio_tos: &[&[PortConnection];2], - scenes: usize, - tracks: usize, - track_width: usize, + jack: &Arc>, + bpm: Option, sync_lead: bool, sync_follow: bool, + midi_froms: &[PortConnection], midi_tos: &[PortConnection], + audio_froms: &[&[PortConnection];2], audio_tos: &[&[PortConnection];2], + scenes: usize, tracks: usize, track_width: usize, ) -> Usually { let mut arranger = Self { edn: include_str!("./view_arranger.edn").to_string(), @@ -240,6 +285,21 @@ impl Tek { } Ok(()) } + fn scene_add (&mut self, name: Option<&str>, color: Option) + -> Usually<(usize, &mut Scene)> + { + let scene = Scene { + name: name.map_or_else(||self.scene_default_name(), |x|x.to_string().into()), + clips: vec![None;self.tracks().len()], + color: color.unwrap_or_else(ItemPalette::random), + }; + self.scenes_mut().push(scene); + let index = self.scenes().len() - 1; + Ok((index, &mut self.scenes_mut()[index])) + } + fn scene_default_name (&self) -> Arc { + format!("Sc{:3>}", self.scenes().len() + 1).into() + } fn tracks_add ( &mut self, count: usize, width: usize, midi_from: &[PortConnection], midi_to: &[PortConnection], @@ -282,71 +342,6 @@ impl Tek { } Ok((index, &mut self.tracks_mut()[index])) } - fn new_groovebox ( - jack: &Arc>, - bpm: Option, - sync_lead: bool, - sync_follow: bool, - midi_froms: &[PortConnection], - midi_tos: &[PortConnection], - audio_froms: &[&[PortConnection];2], - audio_tos: &[&[PortConnection];2], - ) -> Usually { - let app = Self { - edn: include_str!("./view_groovebox.edn").to_string(), - sampler: Some(Sampler::new(jack, &"sampler", midi_froms, audio_froms, audio_tos)?), - ..Self::new_sequencer(jack, bpm, sync_lead, sync_follow, midi_froms, midi_tos)? - }; - if let Some(sampler) = app.sampler.as_ref().unwrap().midi_in.as_ref() { - jack.connect_ports(&app.player.as_ref().unwrap().midi_outs[0].port, &sampler.port)?; - } - Ok(app) - } - fn new_sequencer ( - jack: &Arc>, - bpm: Option, - sync_lead: bool, - sync_follow: bool, - midi_froms: &[PortConnection], - midi_tos: &[PortConnection], - ) -> Usually { - let clip = MidiClip::new("Clip", true, 384usize, None, Some(ItemColor::random().into())); - let clip = Arc::new(RwLock::new(clip)); - Ok(Self { - edn: include_str!("./view_sequencer.edn").to_string(), - pool: Some((&clip).into()), - editor: Some((&clip).into()), - editing: false.into(), - midi_buf: vec![vec![];65536], - player: Some(MidiPlayer::new(&jack, "sequencer", Some(&clip), &midi_froms, &midi_tos)?), - ..Self::new_clock(jack, bpm, sync_lead, sync_follow, midi_froms, midi_tos)? - }) - } - fn new_clock ( - jack: &Arc>, - bpm: Option, - sync_lead: bool, - sync_follow: bool, - midi_froms: &[PortConnection], - midi_tos: &[PortConnection], - ) -> Usually { - let tek = Self { - edn: include_str!("./view_transport.edn").to_string(), - jack: jack.clone(), - color: ItemPalette::random(), - clock: Clock::new(jack, bpm), - midi_ins: vec![ - JackPort::::new(jack, "GlobalI", midi_froms)? - ], - midi_outs: vec![ - JackPort::::new(jack, "GlobalO", midi_tos)? - ], - ..Default::default() - }; - tek.sync_lead(sync_lead); - tek.sync_follow(sync_follow); - Ok(tek) - } fn sync_lead (&self, enable: bool) -> Usually<()> { if enable { self.jack.read().unwrap().client().register_timebase_callback(false, |mut state|{ @@ -363,7 +358,7 @@ impl Tek { Ok(()) } fn view_clock (&self) -> impl Content + use<'_> { - Outer(Style::default().fg(TuiTheme::g(0))).enclose(row!( + Outer(false, Style::default().fg(TuiTheme::g(0))).enclose(row!( self.view_engine_stats(), " ", self.view_play_pause(), " ", self.view_beat_stats(), @@ -485,25 +480,13 @@ impl Tek { scene.clips.remove(index); } } - fn scene_add (&mut self, name: Option<&str>, color: Option) - -> Usually<(usize, &mut Scene)> - { - let scene = Scene { - name: name.map_or_else(||self.scene_default_name(), |x|x.to_string().into()), - clips: vec![None;self.tracks().len()], - color: color.unwrap_or_else(ItemPalette::random), - }; - self.scenes_mut().push(scene); - let index = self.scenes().len() - 1; - Ok((index, &mut self.scenes_mut()[index])) - } fn clip_columns <'a> (&'a self) -> BoxThunk<'a, TuiOut> { let editing = self.is_editing(); let tracks = move||self.tracks_sizes(editing, self.editor_w()); let scenes = move||self.scenes_sizes(editing, 2, 15); let selected_track = self.selected().track(); let selected_scene = self.selected().scene(); - let border = |x|Outer(Style::default().fg(TuiTheme::g(0))).enclose(x); + let border = |x|Outer(false, Style::default().fg(TuiTheme::g(0))).enclose(x); (move||Align::c(Map::new(tracks, move|(_, track, x1, x2), t| { let w = (x2 - x1) as u16; let color: ItemPalette = track.color.dark.into(); @@ -955,7 +938,8 @@ trait HasTracks: HasSelection + HasClock + HasJack + HasEditor + Send + Sync { let bfg = if active { Color::Rgb(255,255,255) } else { Color::Rgb(0,0,0) }; let border = Style::default().fg(bfg).bg(bg); Tui::bg(bg, map_east(x1 as u16, (x2 - x1) as u16, - Outer(border).enclose(Tui::fg_bg(fg, bg, Tui::bold(true, Fill::x(Align::x(name))))) + Outer(false, border) + .enclose(Tui::fg_bg(fg, bg, Tui::bold(true, Fill::x(Align::x(name))))) )) })).boxed()).into() } @@ -1107,9 +1091,6 @@ trait HasScenes: HasSelection + HasEditor + Send + Sync { data }) } - fn scene_default_name (&self) -> Arc { - format!("Sc{:3>}", self.scenes().len() + 1).into() - } fn scene (&self) -> Option<&Scene> { self.selected().scene().and_then(|s|self.scenes().get(s)) } @@ -1142,7 +1123,7 @@ trait HasScenes: HasSelection + HasEditor + Send + Sync { ); *last_color.write().unwrap() = color; map_south(y1 as u16, h, Push::y(1, Fixed::y(h, - Outer(Style::default().fg(TuiTheme::g(0))).enclose(cell)))) + Outer(false, Style::default().fg(TuiTheme::g(0))).enclose(cell)))) }).boxed() }).into() } diff --git a/tui/src/tui_border.rs b/tui/src/tui_border.rs index b3c60744..c0ff7617 100644 --- a/tui/src/tui_border.rs +++ b/tui/src/tui_border.rs @@ -1,44 +1,42 @@ use crate::*; -pub struct Bordered>(pub S, pub W); +pub struct Bordered>(pub bool, pub S, pub W); content!(TuiOut: |self: Bordered>|Fill::xy( - lay!(Border(self.0), Padding::xy(1, 1, &self.1)) + lay!(When::new(self.0, Border(self.0, self.1)), Padding::xy(1, 1, &self.2)) )); -pub struct Border(pub S); +pub struct Border(pub bool, pub S); render!(TuiOut: |self: Border, to| { - let area = to.area(); - if area.w() > 0 && area.y() > 0 { - to.blit(&self.0.nw(), area.x(), area.y(), self.0.style()); - to.blit(&self.0.ne(), area.x() + area.w() - 1, area.y(), self.0.style()); - to.blit(&self.0.sw(), area.x(), area.y() + area.h() - 1, self.0.style()); - to.blit(&self.0.se(), area.x() + area.w() - 1, area.y() + area.h() - 1, self.0.style()); - for x in area.x()+1..area.x()+area.w()-1 { - to.blit(&self.0.n(), x, area.y(), self.0.style()); - to.blit(&self.0.s(), x, area.y() + area.h() - 1, self.0.style()); - } - for y in area.y()+1..area.y()+area.h()-1 { - to.blit(&self.0.w(), area.x(), y, self.0.style()); - to.blit(&self.0.e(), area.x() + area.w() - 1, y, self.0.style()); + if self.0 { + let area = to.area(); + if area.w() > 0 && area.y() > 0 { + to.blit(&self.1.nw(), area.x(), area.y(), self.1.style()); + to.blit(&self.1.ne(), area.x() + area.w() - 1, area.y(), self.1.style()); + to.blit(&self.1.sw(), area.x(), area.y() + area.h() - 1, self.1.style()); + to.blit(&self.1.se(), area.x() + area.w() - 1, area.y() + area.h() - 1, self.1.style()); + for x in area.x()+1..area.x()+area.w()-1 { + to.blit(&self.1.n(), x, area.y(), self.1.style()); + to.blit(&self.1.s(), x, area.y() + area.h() - 1, self.1.style()); + } + for y in area.y()+1..area.y()+area.h()-1 { + to.blit(&self.1.w(), area.x(), y, self.1.style()); + to.blit(&self.1.e(), area.x() + area.w() - 1, y, self.1.style()); + } } } }); pub trait BorderStyle: Send + Sync + Copy { - fn wrap > (self, w: W) -> Bordered { - Bordered(self, w) - } + fn enabled (&self) -> bool; fn enclose > (self, w: W) -> impl Content { - lay!(Fill::xy(Border(self)), w) + Bsp::b(Fill::xy(Border(self.enabled(), self)), w) } fn enclose2 > (self, w: W) -> impl Content { - Bsp::b(Margin::xy(1, 1, Fill::xy(Border(self))), w) + Bsp::b(Margin::xy(1, 1, Fill::xy(Border(self.enabled(), self))), w) } fn enclose_bg > (self, w: W) -> impl Content { - Tui::bg(self.style().unwrap().bg.unwrap_or(Color::Reset), lay!( - Fill::xy(Border(self)), - w - )) + Tui::bg(self.style().unwrap().bg.unwrap_or(Color::Reset), + Bsp::b(Fill::xy(Border(self.enabled(), self)), w)) } const NW: &'static str = ""; const N: &'static str = ""; @@ -65,9 +63,11 @@ pub trait BorderStyle: Send + Sync + Copy { #[inline] fn draw <'a> ( &self, to: &mut TuiOut ) -> Usually<()> { - self.draw_horizontal(to, None)?; - self.draw_vertical(to, None)?; - self.draw_corners(to, None)?; + if self.enabled() { + self.draw_horizontal(to, None)?; + self.draw_vertical(to, None)?; + self.draw_corners(to, None)?; + } Ok(()) } #[inline] fn draw_horizontal ( @@ -135,11 +135,13 @@ macro_rules! border { const S: &'static str = $s; const SE: &'static str = $se; $($x)* + fn enabled (&self) -> bool { self.0 } } - #[derive(Copy, Clone)] - pub struct $T(pub Style); + #[derive(Copy, Clone)] pub struct $T(pub bool, pub Style); impl Content for $T { - fn render (&self, to: &mut TuiOut) { let _ = self.draw(to); } + fn render (&self, to: &mut TuiOut) { + if self.enabled() { let _ = self.draw(to); } + } } )+} } @@ -148,57 +150,57 @@ border! { Square { "┌" "─" "┐" "│" "│" - "└" "─" "┘" fn style (&self) -> Option