From 60406e1d32475c43b7625f1ca4da774b9966a5a1 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Tue, 10 Sep 2024 23:12:02 +0300 Subject: [PATCH] replace old Split component --- crates/tek_core/src/engine/layout.rs | 61 +++++-------- crates/tek_core/src/tui/tui_layout.rs | 95 +++++++++++++------- crates/tek_mixer/src/mixer.rs | 11 +-- crates/tek_sequencer/src/arranger_main.rs | 10 ++- crates/tek_sequencer/src/arranger_view_h.rs | 18 ++-- crates/tek_sequencer/src/arranger_view_v.rs | 7 +- crates/tek_sequencer/src/sequencer_view_h.rs | 13 +-- crates/tek_sequencer/src/transport_view.rs | 14 +-- crates/tek_test/src/main.rs | 19 +++- 9 files changed, 141 insertions(+), 107 deletions(-) diff --git a/crates/tek_core/src/engine/layout.rs b/crates/tek_core/src/engine/layout.rs index 2a08fd33..1a906efe 100644 --- a/crates/tek_core/src/engine/layout.rs +++ b/crates/tek_core/src/engine/layout.rs @@ -52,6 +52,29 @@ impl<'a, E: Engine> Collect<'a, E> for Collection<'a, E> { } } +pub struct Split< + E: Engine, + F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()> +>(pub F, pub Direction, PhantomData); + +impl< + E: Engine, + F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()> +> Split { + #[inline] + pub fn new (direction: Direction, build: F) -> Self { + Self(build, direction, Default::default()) + } + #[inline] + pub fn right (build: F) -> Self { + Self::new(Direction::Right, build) + } + #[inline] + pub fn down (build: F) -> Self { + Self::new(Direction::Down, build) + } +} + pub struct Layers< E: Engine, F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()> @@ -61,6 +84,7 @@ impl< E: Engine, F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()> > Layers { + #[inline] pub fn new (build: F) -> Self { Self(build, Default::default()) } @@ -83,43 +107,6 @@ impl Direction { } } -pub struct Split<'a, E: Engine> { - pub items: Collection<'a, E>, - pub direction: Direction, - pub focus: Option -} - -impl<'a, E: Engine> Split<'a, E> { - pub fn new (direction: Direction) -> Self { - Self { - items: Collection::new(), - direction, - focus: None - } - } - pub fn down () -> Self { - Self::new(Direction::Down) - } - pub fn right () -> Self { - Self::new(Direction::Right) - } - pub fn focus (mut self, focus: Option) -> Self { - self.focus = focus; - self - } -} - -impl<'a, E: Engine> Collect<'a, E> for Split<'a, E> { - fn add_box (mut self, item: Box + 'a>) -> Self { - self.items = self.items.add_box(item); - self - } - fn add_ref (mut self, item: &'a dyn Widget) -> Self { - self.items = self.items.add_ref(item); - self - } -} - /// Override X and Y coordinates, aligning to corner, side, or center of area pub enum Align { Center(L), diff --git a/crates/tek_core/src/tui/tui_layout.rs b/crates/tek_core/src/tui/tui_layout.rs index ec21215e..801f43d6 100644 --- a/crates/tek_core/src/tui/tui_layout.rs +++ b/crates/tek_core/src/tui/tui_layout.rs @@ -1,55 +1,82 @@ use crate::*; -impl<'a> Widget for Split<'a, Tui> { +impl Widget for Split +where + F: Send + Sync + Fn(&mut dyn FnMut(&dyn Widget)->Usually<()>)->Usually<()> +{ type Engine = Tui; - fn layout (&self, area: [u16;4]) -> Perhaps<[u16;4]> { - todo!() - } - fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { - Ok(Some(self.render_areas(to)?.0)) - } -} - -// TODO -impl<'a> Split<'a, Tui> { - pub fn render_areas (&self, to: &mut Tui) -> Usually<([u16;4], Vec>)> { - let area = to.area(); + fn layout (&self, to: [u16;4]) -> Perhaps<[u16;4]> { let mut w = 0; let mut h = 0; - let mut areas = vec![]; - Ok((match self.direction { + match self.1 { Direction::Down => { - for component in self.items.0.iter() { - if h >= area.h() { - break + (self.0)(&mut |component| { + if h >= to.h() { + return Ok(()) } - let offset = Offset::Y(h, component as &dyn Widget); - let result = offset.render(to)?; - areas.push(result); - if let Some([_, _, width, height]) = result { + if let Some([_, _, width, height]) = Offset::Y( + h, component as &dyn Widget + ).layout(to)? { h += height; w = w.max(width) } - } - [area.x(), area.y(), w, h] + Ok(()) + })?; }, Direction::Right => { - for component in self.items.0.iter() { - if w >= area.x() { - break + (self.0)(&mut |component| { + if w >= to.w() { + return Ok(()) } - let offset = Offset::X(w, component as &dyn Widget); - let result = offset.render(to)?; - areas.push(result); - if let Some([_, _, width, height]) = result { + if let Some([_, _, width, height]) = Offset::X( + w, component as &dyn Widget + ).layout(to)? { w += width; h = h.max(height) } - } - [area.x(), area.y(), w, h] + Ok(()) + })?; }, _ => todo!() - }, areas)) + }; + Ok(Some([to.x(), to.y(), w, h])) + } + fn render (&self, to: &mut Tui) -> Perhaps<[u16;4]> { + let area = to.area(); + let mut w = 0; + let mut h = 0; + match self.1 { + Direction::Down => { + (self.0)(&mut |component| { + if h >= area.h() { + return Ok(()) + } + if let Some([_, _, width, height]) = Offset::Y( + h, component as &dyn Widget + ).render(to)? { + h += height; + w = w.max(width) + }; + Ok(()) + })?; + }, + Direction::Right => { + (self.0)(&mut |component| { + if w >= area.w() { + return Ok(()) + } + if let Some([_, _, width, height]) = Offset::X( + w, component as &dyn Widget + ).render(to)? { + w += width; + h = h.max(height) + }; + Ok(()) + })?; + }, + _ => todo!() + }; + Ok(Some([area.x(), area.y(), w, h])) } } diff --git a/crates/tek_mixer/src/mixer.rs b/crates/tek_mixer/src/mixer.rs index 1875b790..ec0f6d30 100644 --- a/crates/tek_mixer/src/mixer.rs +++ b/crates/tek_mixer/src/mixer.rs @@ -33,10 +33,11 @@ impl Audio for Mixer { impl Content for Mixer { type Engine = Tui; fn content (&self) -> impl Widget { - let mut tracks = Split::right(); - for channel in self.tracks.iter() { - tracks = tracks.add_ref(channel) - } - tracks + Split::right(|add| { + for channel in self.tracks.iter() { + add(channel)?; + } + Ok(()) + }) } } diff --git a/crates/tek_sequencer/src/arranger_main.rs b/crates/tek_sequencer/src/arranger_main.rs index b87a5a76..0119aa13 100644 --- a/crates/tek_sequencer/src/arranger_main.rs +++ b/crates/tek_sequencer/src/arranger_main.rs @@ -82,10 +82,12 @@ impl Widget for ArrangerStandalone { let area = to.area(); let sequencer = self.arranger.sequencer() .map(|t|t as &dyn Widget); - let result = Split::down() - .add_ref(&self.transport) - .add_ref(&self.arranger) - .add_ref(&sequencer) + let result = Split::down(|add|{ + add(&self.transport)?; + add(&self.arranger)?; + add(&sequencer)?; + Ok(()) + }) //.focus(Some(self.focus)) .render(to)?; if let Some(ref modal) = self.arranger.modal { diff --git a/crates/tek_sequencer/src/arranger_view_h.rs b/crates/tek_sequencer/src/arranger_view_h.rs index 589bcb81..11649f56 100644 --- a/crates/tek_sequencer/src/arranger_view_h.rs +++ b/crates/tek_sequencer/src/arranger_view_h.rs @@ -6,14 +6,16 @@ pub fn draw (state: &Arranger, to: &mut Tui) -> Perhaps<[u16;4]> { let tracks = state.tracks.as_slice(); Layers::new(|add|{ add(&state.focused.then_some(FillBg(COLOR_BG0)))?; - add(&Split::right() - .add(TrackNameColumn(tracks, state.selected)) - .add(TrackMonitorColumn(tracks)) - .add(TrackRecordColumn(tracks)) - .add(TrackOverdubColumn(tracks)) - .add(TrackEraseColumn(tracks)) - .add(TrackGainColumn(tracks)) - .add(TrackScenesColumn(tracks, state.scenes.as_slice(), state.selected))) + add(&Split::right(|add|{ + add(&TrackNameColumn(tracks, state.selected))?; + add(&TrackMonitorColumn(tracks))?; + add(&TrackRecordColumn(tracks))?; + add(&TrackOverdubColumn(tracks))?; + add(&TrackEraseColumn(tracks))?; + add(&TrackGainColumn(tracks))?; + add(&TrackScenesColumn(tracks, state.scenes.as_slice(), state.selected))?; + Ok(()) + })) }).render(to.with_rect(area)) } diff --git a/crates/tek_sequencer/src/arranger_view_v.rs b/crates/tek_sequencer/src/arranger_view_v.rs index dd079028..9a537e95 100644 --- a/crates/tek_sequencer/src/arranger_view_v.rs +++ b/crates/tek_sequencer/src/arranger_view_v.rs @@ -43,9 +43,10 @@ pub fn draw <'a, 'b> ( add(&ColumnSeparators(offset, cols))?; add(&RowSeparators(rows))?; add(&CursorFocus(state.selected, offset, cols, rows))?; - add(&Split::down() - .add_ref(&TracksHeader(offset, cols, tracks)) - .add_ref(&SceneRows(offset, cols, rows, tracks, scenes))) + add(&Split::right(|add|{ + add(&TracksHeader(offset, cols, tracks))?; + add(&SceneRows(offset, cols, rows, tracks, scenes)) + })) }).render(to.with_rect(area)) } diff --git a/crates/tek_sequencer/src/sequencer_view_h.rs b/crates/tek_sequencer/src/sequencer_view_h.rs index 3ef2c683..77c70aad 100644 --- a/crates/tek_sequencer/src/sequencer_view_h.rs +++ b/crates/tek_sequencer/src/sequencer_view_h.rs @@ -6,12 +6,13 @@ impl Sequencer { pub(crate) fn horizontal_draw <'a> (&self, to: &mut Tui) -> Usually<()> { let area = to.area(); - Split::down() - .add_ref(&SequenceName(&self)) - .add_ref(&SequenceRange) - .add_ref(&SequenceLoopRange) - .add_ref(&SequenceNoteRange) - .render(to.with_area(area.x(), area.y(), 10, area.h()))?; + Split::down(|add|{ + add(&SequenceName(&self))?; + add(&SequenceRange)?; + add(&SequenceLoopRange)?; + add(&SequenceNoteRange)?; + Ok(()) + }).render(to.with_area(area.x(), area.y(), 10, area.h()))?; let area = [area.x() + 10, area.y(), area.w().saturating_sub(10), area.h().min(66)]; Lozenge(Style::default().fg(Nord::BG2)).draw(to.with_rect(area))?; let area = [area.x() + 1, area.y(), area.w().saturating_sub(1), area.h()]; diff --git a/crates/tek_sequencer/src/transport_view.rs b/crates/tek_sequencer/src/transport_view.rs index bcf3146d..504d71f9 100644 --- a/crates/tek_sequencer/src/transport_view.rs +++ b/crates/tek_sequencer/src/transport_view.rs @@ -5,12 +5,14 @@ const CORNERS: Corners = Corners(NOT_DIM_GREEN); impl Content for TransportToolbar { type Engine = Tui; fn content (&self) -> impl Widget { - Split::right() - .add_ref(&self.playing) - .add_ref(&self.bpm) - .add_ref(&self.quant) - .add_ref(&self.sync) - .add_ref(&self.clock) + Split::right(|add|{ + add(&self.playing)?; + add(&self.bpm)?; + add(&self.quant)?; + add(&self.sync)?; + add(&self.clock)?; + Ok(()) + }) } } diff --git a/crates/tek_test/src/main.rs b/crates/tek_test/src/main.rs index de5ef263..da9bf25f 100644 --- a/crates/tek_test/src/main.rs +++ b/crates/tek_test/src/main.rs @@ -40,10 +40,21 @@ impl Content for Demo { //Align::Center(&self.items[self.index] as &dyn Widget) Align::Center(Layers::new(|add|{ add(&Outset::WH(1, 1, FillBg(Color::Rgb(0,128,128))))?; - add(&Layers::new(|add|{ - add(&Align::Center("....."))?; - add(&Align::Center("FOO"))?; - Ok(()) + add(&Split::down(|add|{ + add(&Layers::new(|add|{ + add(&Outset::WH(1, 1, FillBg(Color::Rgb(0,128,0))))?; + add(&Align::Center("55555"))?; + add(&Align::Center("FOO"))?; + //add(&FillBg(Color::Rgb(0,128,0)))?; + Ok(()) + }))?; + add(&Layers::new(|add|{ + add(&Outset::WH(1, 1, FillBg(Color::Rgb(0,0,128))))?; + add(&Align::Center("7777777"))?; + add(&Align::Center("BAR"))?; + //add(&FillBg(Color::Rgb(0,0,128)))?; + Ok(()) + })) })) })) }