From 89df3cf1919c66cff72f6a0b1936c4d5b9604af6 Mon Sep 17 00:00:00 2001 From: i do not exist Date: Fri, 17 Apr 2026 04:18:25 +0300 Subject: [PATCH] argh --- src/arrange.rs | 84 +++++++++++++++++++++++++++++++++++++------------- src/browse.rs | 38 +++++++++++------------ src/device.rs | 12 ++++++++ src/editor.rs | 42 ++++++++++++------------- src/sample.rs | 4 +-- src/tek.rs | 77 +++++++++++++++++++++++++++------------------ tengri | 2 +- 7 files changed, 164 insertions(+), 95 deletions(-) diff --git a/src/arrange.rs b/src/arrange.rs index b8ac5062..31b01809 100644 --- a/src/arrange.rs +++ b/src/arrange.rs @@ -244,11 +244,12 @@ pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll { button_2("O", "+", false), bg(theme.darker.term, origin_w(thunk(|to: &mut Tui|{ for (index, track, _x1, _x2) in self.tracks_with_sizes() { + let iter = ||track.sequencer.midi_outs.iter(); + let draw = |port: &MidiOutput|fg(Rgb(255, 255, 255), + h_exact(1, bg(track.color.dark.term, w_full(origin_w( + format!("·o{index:02} {}", port.port_name())))))); to.place(&w_exact(track_width(index, track), - origin_nw(h_full(iter_south(||track.sequencer.midi_outs.iter(), - |port, index|fg(Rgb(255, 255, 255), - h_exact(1, bg(track.color.dark.term, w_full(origin_w( - format!("·o{index:02} {}", port.port_name()))))))))))); + origin_nw(h_full(iter_south(iter, draw))))); } Ok(XYWH(0, 0, 0, 0)) })))) @@ -261,16 +262,16 @@ pub trait TracksView: ScenesView + HasMidiIns + HasMidiOuts + HasTrackScroll { } let content = thunk(move|to: &mut Tui|{ for (index, track, _x1, _x2) in self.tracks_with_sizes() { - to.place(&wh_exact(track_width(index, track), h + 1, + to.place(&wh_exact(Some(track_width(index, track)), Some(h + 1), origin_nw(south( bg(track.color.base.term, w_full(origin_w(east!( - either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "), - either(track.sequencer.recording, fg(Red, "●rec "), "·rec "), + either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "), + either(track.sequencer.recording, fg(Red, "●rec "), "·rec "), either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "), )))), - iter_south(1, ||track.sequencer.midi_ins.iter(), - |port, index|fg_bg(Rgb(255, 255, 255), track.color.dark.term, + iter_south(||track.sequencer.midi_ins.iter(), + |port|fg_bg(Rgb(255, 255, 255), track.color.dark.term, w_full(origin_w(format!("·i{index:02} {}", port.port_name()))))))))); } Ok(XYWH(0, 0, 0, 0)) @@ -308,8 +309,11 @@ pub trait ScenesView: HasEditor + HasSelection + HasSceneScroll + HasClipsSize + } fn view_scenes_names (&self) -> impl Draw { - w_exact(20, thunk(|to: &mut Tui|for (index, scene, ..) in self.scenes_with_sizes() { - to.place(&self.view_scene_name(index, scene)); + w_exact(20, thunk(|to: &mut Tui|{ + for (index, scene, ..) in self.scenes_with_sizes() { + to.place(&self.view_scene_name(index, scene)); + } + Ok(XYWH(1, 1, 1, 1)) })) } @@ -319,18 +323,18 @@ pub trait ScenesView: HasEditor + HasSelection + HasSceneScroll + HasClipsSize + } else { Self::H_SCENE as u16 }; - let bg = if self.selection().scene() == Some(index) { - scene.color.light.term - } else { - scene.color.base.term - }; let a = w_full(origin_w(east(format!("·s{index:02} "), fg(g(255), bold(true, &scene.name))))); let b = when(self.selection().scene() == Some(index) && self.is_editing(), wh_full(origin_nw(south( self.editor().as_ref().map(|e|e.clip_status()), self.editor().as_ref().map(|e|e.edit_status()))))); - wh_exact(20, h, bg(bg, origin_nw(south(a, b)))) + let c = if self.selection().scene() == Some(index) { + scene.color.light.term + } else { + scene.color.base.term + }; + wh_exact(Some(20), Some(h), bg(c, origin_nw(south(a, b)))) } } @@ -577,6 +581,7 @@ pub trait HasTrack: AsRefOpt + AsMutOpt { } impl Arrangement { + /// Create a new arrangement. pub fn new ( jack: &Jack<'static>, @@ -596,27 +601,33 @@ impl Arrangement { ..Default::default() } } + /// Width of display pub fn w (&self) -> u16 { self.size.w() as u16 } + /// Width allocated for sidebar. pub fn w_sidebar (&self, is_editing: bool) -> u16 { self.w() / if is_editing { 16 } else { 8 } as u16 } + /// Width available to display tracks. pub fn w_tracks_area (&self, is_editing: bool) -> u16 { self.w().saturating_sub(self.w_sidebar(is_editing)) } + /// Height of display pub fn h (&self) -> u16 { self.size.h() as u16 } + /// Height taken by visible device slots. pub fn h_devices (&self) -> u16 { 2 //1 + self.devices_with_sizes().last().map(|(_, _, _, _, y)|y as u16).unwrap_or(0) } + /// Add multiple tracks #[cfg(feature = "track")] pub fn tracks_add ( &mut self, @@ -634,6 +645,7 @@ impl Arrangement { } Ok(()) } + /// Add a track #[cfg(feature = "track")] pub fn track_add ( &mut self, @@ -669,6 +681,7 @@ impl Arrangement { } Ok((index, &mut self.tracks_mut()[index])) } + #[cfg(feature = "track")] pub fn view_inputs (&self, _theme: ItemTheme) -> impl Draw + '_ { south( h_exact(1, self.view_inputs_header()), @@ -679,6 +692,7 @@ impl Arrangement { }) ) } + #[cfg(feature = "track")] fn view_inputs_header (&self) -> impl Draw + '_ { east(w_exact(20, origin_w(button_3("i", "nput ", format!("{}", self.midi_ins.len()), false))), west(w_exact(4, button_2("I", "+", false)), thunk(move|to: &mut Tui|for (_index, track, x1, _x2) in self.tracks_with_sizes() { @@ -690,6 +704,7 @@ impl Arrangement { )))))) }))) } + #[cfg(feature = "track")] fn view_inputs_row (&self, port: &MidiInput) -> impl Draw { east(w_exact(20, origin_w(east(" ● ", bold(true, fg(Rgb(255,255,255), port.port_name()))))), west(w_exact(4, ()), thunk(move|to: &mut Tui|for (_index, track, _x1, _x2) in self.tracks_with_sizes() { @@ -701,14 +716,20 @@ impl Arrangement { ))))) }))) } + #[cfg(feature = "track")] pub fn view_outputs (&self, theme: ItemTheme) -> impl Draw { let mut h = 1; + for output in self.midi_outs().iter() { h += 1 + output.connections.len(); } + let h = h as u16; + let list = south( - h_exact(1, w_full(origin_w(button_3("o", "utput", format!("{}", self.midi_outs.len()), false)))), + h_exact(1, w_full(origin_w(button_3( + "o", "utput", format!("{}", self.midi_outs.len()), false + )))), h_exact(h - 1, wh_full(origin_nw(thunk(|to: &mut Tui|{ for (_index, port) in self.midi_outs().iter().enumerate() { to.place(&h_exact(1,w_full(east( @@ -720,7 +741,9 @@ impl Arrangement { to.place(&h_exact(1, w_full(origin_w(format!(" c{index:02}{}", conn.info()))))); } } - }))))); + })))) + ); + h_exact(h, view_track_row_section(theme, list, button_2("O", "+", false), bg(theme.darker.term, origin_w(w_full( thunk(|to: &mut Tui|{ @@ -739,7 +762,13 @@ impl Arrangement { for (_index, _conn) in port.connections.iter().enumerate() { to.place(&h_exact(1, w_full(""))); } - }})))}})))))) + } + }) + )) + } + }) + ))) + )) } #[cfg(feature = "track")] pub fn view_track_devices (&self, theme: ItemTheme) -> impl Draw { let mut h = 2u16; @@ -756,9 +785,15 @@ impl Arrangement { fg_bg( ItemTheme::G[32].lightest.term, ItemTheme::G[32].dark.term, - origin_nw(format!(" · {}", "--"))))))))); - })) + origin_nw(format!(" · {}", "--")) + ) + ))) + ) + )); + }) + ) } + /// Put a clip in a slot #[cfg(feature = "clip")] pub fn clip_put ( &mut self, track: usize, scene: usize, clip: Option>> @@ -767,6 +802,7 @@ impl Arrangement { self.scenes[scene].clips[track] = clip; old } + /// Change the color of a clip, returning the previous one #[cfg(feature = "clip")] pub fn clip_set_color (&self, track: usize, scene: usize, color: ItemTheme) -> Option @@ -779,20 +815,24 @@ impl Arrangement { //old }) } + /// Toggle looping for the active clip #[cfg(feature = "clip")] pub fn toggle_loop (&mut self) { if let Some(clip) = self.selected_clip() { clip.write().unwrap().toggle_loop() } } + /// Get the first sampler of the active track #[cfg(feature = "sampler")] pub fn sampler (&self) -> Option<&Sampler> { self.selected_track()?.sampler(0) } + /// Get the first sampler of the active track #[cfg(feature = "sampler")] pub fn sampler_mut (&mut self) -> Option<&mut Sampler> { self.selected_track_mut()?.sampler_mut(0) } + } impl ScenesView for Arrangement { fn h_scenes (&self) -> u16 { diff --git a/src/browse.rs b/src/browse.rs index 71ae746c..658f32ba 100644 --- a/src/browse.rs +++ b/src/browse.rs @@ -245,28 +245,28 @@ impl Pool { impl<'a> PoolView<'a> { fn tui (&self) -> impl Draw { let Self(pool) = self; - //let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||Tui::g(32).into()); - //let on_bg = |x|x;//below(Repeat(" "), Tui::bg(color.darkest.term, x)); + //let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||g(32).into()); + //let on_bg = |x|x;//below(Repeat(" "), bg(color.darkest.term, x)); //let border = |x|x;//Outer(Style::default().fg(color.dark.term).bg(color.darkest.term)).enclose(x); //let height = pool.clips.read().unwrap().len() as u16; w_exact(20, h_full(origin_n(iter( ||pool.clips().clone().into_iter(), move|clip: Arc>, i: usize|{ - let item_height = 1; - let item_offset = i as u16 * item_height; - let selected = i == pool.clip_index(); - let MidiClip { ref name, color, length, .. } = *clip.read().unwrap(); - let bg = if selected { color.light.term } else { color.base.term }; - let fg = color.lightest.term; - let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") }; - let length = if false { String::default() } else { format!("{length} ") }; - h_exact(1, iter_south(item_offset, item_height, Tui::bg(bg, below!( - w_full(origin_w(Tui::fg(fg, Tui::bold(selected, name)))), - w_full(origin_e(Tui::fg(fg, Tui::bold(selected, length)))), - w_full(origin_w(When::new(selected, Tui::bold(true, Tui::fg(Tui::g(255), "▶"))))), - w_full(origin_e(When::new(selected, Tui::bold(true, Tui::fg(Tui::g(255), "◀"))))), - )))) - })))) + let MidiClip { ref name, color, length, .. } = *clip.read().unwrap(); + let item_height = 1; + let item_offset = i as u16 * item_height; + let selected = i == pool.clip_index(); + let b = if selected { color.light.term } else { color.base.term }; + let f = color.lightest.term; + let name = if false { format!(" {i:>3}") } else { format!(" {i:>3} {name}") }; + let length = if false { String::default() } else { format!("{length} ") }; + h_exact(1, iter_south(item_offset, item_height, bg(b, below!( + w_full(origin_w(fg(fg, bold(selected, name)))), + w_full(origin_e(fg(fg, bold(selected, length)))), + w_full(origin_w(When::new(selected, bold(true, fg(g(255), "▶"))))), + w_full(origin_e(When::new(selected, bold(true, fg(g(255), "◀"))))), + )))) + })))) } } impl ClipLength { @@ -337,10 +337,10 @@ impl<'a> Iterator for EntriesIterator<'a> { let index = self.index; if self.index < dirs { self.index += 1; - Some(Tui::bold(true, self.browser.dirs[index].1.as_str())) + Some(bold(true, self.browser.dirs[index].1.as_str())) } else if self.index < dirs + files { self.index += 1; - Some(Tui::bold(false, self.browser.files[index - dirs].1.as_str())) + Some(bold(false, self.browser.files[index - dirs].1.as_str())) } else { None } diff --git a/src/device.rs b/src/device.rs index c87f7c2a..c3ea587d 100644 --- a/src/device.rs +++ b/src/device.rs @@ -460,6 +460,18 @@ impl JackPort for MidiOutput { } } +impl View for MidiInput { + fn view (&self) -> impl Draw { + "TODO: MIDI IN" + } +} + +impl View for MidiOutput { + fn view (&self) -> impl Draw { + "TODO: MIDI OUT" + } +} + impl MidiOutput { /// Clear the section of the output buffer that we will be using, /// emitting "all notes off" at start of buffer if requested. diff --git a/src/editor.rs b/src/editor.rs index 82187504..c792c39f 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -167,19 +167,19 @@ pub trait MidiViewer: MidiRange + MidiPoint + Debug + Send + Sync { let note_lo = self.get_note_lo(); let note_hi = self.get_note_hi(); if note_pos < note_lo { - self.note_lo().set(note_pos); + self.note_lo().store(note_pos, Relaxed); } else if note_pos > note_hi { - self.note_lo().set((note_lo + note_pos).saturating_sub(note_hi)); + self.note_lo().store((note_lo + note_pos).saturating_sub(note_hi), Relaxed); } } /// Make sure time range is within display fn autozoom (&self) { - if self.time_lock().get() { + if self.time_lock().load(Relaxed) { let time_len = self.get_time_len(); let time_axis = self.get_time_axis(); let time_zoom = self.get_time_zoom(); loop { - let time_zoom = self.time_zoom().get(); + let time_zoom = self.time_zoom().load(Relaxed); let time_area = time_axis * time_zoom; if time_area > time_len { let next_time_zoom = note_duration_prev(time_zoom); @@ -205,7 +205,7 @@ pub trait MidiViewer: MidiRange + MidiPoint + Debug + Send + Sync { } } } - if time_zoom != self.time_zoom().get() { + if time_zoom != self.time_zoom().load(Relaxed) { self.redraw() } } @@ -289,7 +289,7 @@ pub trait TimeRange { self.time_axis().load(Relaxed) } fn get_time_end (&self) -> usize { - self.time_start().get() + self.time_axis().get() * self.time_zoom().get() + self.time_start().load(Relaxed) + self.time_axis().load(Relaxed) * self.time_zoom().load(Relaxed) } } @@ -419,13 +419,13 @@ impl MidiEditor { w_exact(20, south!( w_full(origin_w(east( button_2("f2", "name ", false), - w_full(origin_e(Tui::fg(Rgb(255, 255, 255), format!("{name} "))))))), + w_full(origin_e(fg(Rgb(255, 255, 255), format!("{name} "))))))), w_full(origin_w(east( button_2("l", "ength ", false), - w_full(origin_e(Tui::fg(Rgb(255, 255, 255), format!("{length} "))))))), + w_full(origin_e(fg(Rgb(255, 255, 255), format!("{length} "))))))), w_full(origin_w(east( button_2("r", "epeat ", false), - w_full(origin_e(Tui::fg(Rgb(255, 255, 255), format!("{looped} "))))))), + w_full(origin_e(fg(Rgb(255, 255, 255), format!("{looped} "))))))), )) } pub fn edit_status (&self) -> impl Draw + '_ { @@ -442,15 +442,15 @@ impl MidiEditor { w_exact(20, south!( w_full(origin_w(east( button_2("t", "ime ", false), - w_full(origin_e(Tui::fg(Rgb(255, 255, 255), + w_full(origin_e(fg(Rgb(255, 255, 255), format!("{length} /{time_zoom} +{time_pos} "))))))), w_full(origin_w(east( button_2("z", "lock ", false), - w_full(origin_e(Tui::fg(Rgb(255, 255, 255), + w_full(origin_e(fg(Rgb(255, 255, 255), format!("{time_lock}"))))))), w_full(origin_w(east( button_2("x", "note ", false), - w_full(origin_e(Tui::fg(Rgb(255, 255, 255), + w_full(origin_e(fg(Rgb(255, 255, 255), format!("{note_name} {note_pos} {note_len}"))))))), )) } @@ -665,7 +665,7 @@ impl PianoHorizontal { let note_hi = state.get_note_hi(); let note_pos = state.get_note_pos(); let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0))); - let off_style = Some(Style::default().fg(Tui::g(255))); + let off_style = Some(Style::default().fg(g(255))); let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.term).bold()); h_full(w_exact(self.keys_width, Thunk::new(move|to: &mut Tui|{ let XYWH(x, y0, _w, _h) = to.area(); @@ -688,7 +688,7 @@ impl PianoHorizontal { let style = Some(Style::default().dim()); let length = self.clip.as_ref().map(|p|p.read().unwrap().length).unwrap_or(1); for (area_x, screen_x) in (0..w).map(|d|(d, d+x)) { - let t = area_x as usize * self.time_zoom().get(); + let t = area_x as usize * self.time_zoom().load(Relaxed); if t < length { to.blit(&"|", screen_x, y, style); } @@ -724,7 +724,7 @@ impl MidiViewer for PianoHorizontal { fn clip_mut (&mut self) -> &mut Option>> { &mut self.clip } /// Determine the required space to render the clip. fn buffer_size (&self, clip: &MidiClip) -> (usize, usize) { - (clip.length / self.range.time_zoom().get(), 128) + (clip.length / self.range.time_zoom().load(Relaxed), 128) } fn redraw (&self) { *self.buffer.write().unwrap() = if let Some(clip) = self.clip.as_ref() { @@ -765,12 +765,12 @@ impl OctaveVertical { impl OctaveVertical { fn tui (&self) -> impl Draw { east!( - Tui::fg_bg(self.color(0), self.color(1), "▙"), - Tui::fg_bg(self.color(2), self.color(3), "▙"), - Tui::fg_bg(self.color(4), self.color(5), "▌"), - Tui::fg_bg(self.color(6), self.color(7), "▟"), - Tui::fg_bg(self.color(8), self.color(9), "▟"), - Tui::fg_bg(self.color(10), self.color(11), "▟"), + fg_bg(self.color(0), self.color(1), "▙"), + fg_bg(self.color(2), self.color(3), "▙"), + fg_bg(self.color(4), self.color(5), "▌"), + fg_bg(self.color(6), self.color(7), "▟"), + fg_bg(self.color(8), self.color(9), "▟"), + fg_bg(self.color(10), self.color(11), "▟"), ) } } diff --git a/src/sample.rs b/src/sample.rs index 09b238ff..43763aa3 100644 --- a/src/sample.rs +++ b/src/sample.rs @@ -631,7 +631,7 @@ fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_ //height as f64 / 2.0, //text.red() //); - }).render(area, &mut to.buffer); + }).render(area, &mut to.1); } else { Canvas::default() .x_bounds([0.0, width as f64]) @@ -644,7 +644,7 @@ fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_ //text.red() //); }) - .render(area, &mut to.buffer); + .render(area, &mut to.1); } }) } diff --git a/src/tek.rs b/src/tek.rs index 2c6476cf..90955b66 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -426,11 +426,11 @@ pub fn button_play_pause (playing: bool) -> impl Draw { let compact = true;//self.is_editing(); bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) }, either(compact, - Thunk::new(move|to: &mut Tui|to.place(&w_exact(9, either(playing, + thunk(move|to: &mut Tui|to.place(&w_exact(9, either(playing, fg(Rgb(0, 255, 0), " PLAYING "), fg(Rgb(255, 128, 0), " STOPPED "))) )), - Thunk::new(move|to: &mut Tui|to.place(&w_exact(5, either(playing, + thunk(move|to: &mut Tui|to.place(&w_exact(5, either(playing, fg(Rgb(0, 255, 0), south(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)), fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",)))) )) @@ -466,19 +466,19 @@ pub fn view_wrap (bg: Color, fg: Color, content: impl Draw) -> impl Draw (label: &'a str, value: f32) -> impl Draw + 'a { south!( field_h(ItemTheme::G[128], label, format!("{:>+9.3}", value)), - wh_exact(if value >= 0.0 { 13 } - else if value >= -1.0 { 12 } - else if value >= -2.0 { 11 } - else if value >= -3.0 { 10 } - else if value >= -4.0 { 9 } - else if value >= -6.0 { 8 } - else if value >= -9.0 { 7 } - else if value >= -12.0 { 6 } - else if value >= -15.0 { 5 } - else if value >= -20.0 { 4 } - else if value >= -25.0 { 3 } - else if value >= -30.0 { 2 } - else if value >= -40.0 { 1 } + wh_exact(if value >= 0.0 { &"13" } + else if value >= -1.0 { &"12" } + else if value >= -2.0 { &"11" } + else if value >= -3.0 { &"10" } + else if value >= -4.0 { &"9" } + else if value >= -6.0 { &"8" } + else if value >= -9.0 { &"7" } + else if value >= -12.0 { &"6" } + else if value >= -15.0 { &"5" } + else if value >= -20.0 { &"4" } + else if value >= -25.0 { &"3" } + else if value >= -30.0 { &"2" } + else if value >= -40.0 { &"1" } else { 0 }, 1, bg(if value >= 0.0 { Red } else if value >= -3.0 { Yellow } else { Green }, ()))) @@ -491,7 +491,7 @@ pub fn view_meters (values: &[f32;2]) -> impl Draw + use<'_> { } pub fn draw_info (sample: Option<&Arc>>) -> impl Draw + use<'_> { - when(sample.is_some(), Thunk::new(move|to: &mut Tui|{ + when(sample.is_some(), thunk(move|to: &mut Tui|{ let sample = sample.unwrap().read().unwrap(); let theme = sample.color; to.place(&east!( @@ -506,7 +506,7 @@ pub fn draw_info (sample: Option<&Arc>>) -> impl Draw + use< } pub fn draw_info_v (sample: Option<&Arc>>) -> impl Draw + use<'_> { - either(sample.is_some(), Thunk::new(move|to: &mut Tui|{ + either(sample.is_some(), thunk(move|to: &mut Tui|{ let sample = sample.unwrap().read().unwrap(); let theme = sample.color; to.place(&w_exact(20, south!( @@ -517,7 +517,7 @@ pub fn draw_info_v (sample: Option<&Arc>>) -> impl Draw + us w_full(origin_w(field_h(theme, "Trans ", "0"))), w_full(origin_w(field_h(theme, "Gain ", format!("{}", sample.gain)))), ))) - }), Thunk::new(|to: &mut Tui|to.place(&fg(Red, south!( + }), thunk(|to: &mut Tui|to.place(&fg(Red, south!( bold(true, "× No sample."), "[r] record", "[Shift-F9] import", @@ -543,9 +543,9 @@ pub fn view_ports_status <'a, T: JackPort> (theme: ItemTheme, title: &'a str, po let ins = ports.len() as u16; let frame = Outer(true, Style::default().fg(g(96))); let iter = move||ports.iter(); - let names = iter_south(1, iter, move|port, index|h_full(origin_w(format!(" {index} {}", port.port_name())))); + let names = iter_south(iter, move|port, index|h_full(origin_w(format!(" {index} {}", port.port_name())))); let field = field_v(theme, title, names); - wh_exact(20, 1 + ins, frame.enclose(wh_exact(20, 1 + ins, field))) + wh_exact(Some(20), Some(1 + ins), frame.enclose(wh_exact(Some(20), Some(1 + ins), field))) } pub fn io_ports <'a, T: PortsSizes<'a>> ( @@ -554,11 +554,22 @@ pub fn io_ports <'a, T: PortsSizes<'a>> ( iter(items, move|( _index, name, connections, y, y2 ): (usize, &'a Arc, &'a [Connect], usize, usize), _| - iter_south(y as u16, (y2-y) as u16, south( - h_full(bold(true, fg_bg(fg, bg, origin_w(east(&" 󰣲 ", name))))), - iter(||connections.iter(), move|connect: &'a Connect, index|iter_south(index as u16, 1, - h_full(origin_w(bold(false, fg_bg(fg, bg, - &connect.info))))))))) + iter_south( + y as u16, + (y2-y) as u16, + south( + h_full(bold(true, fg_bg(fg, bg, origin_w(east(" 󰣲 ", name))))), + iter( + ||connections.iter(), + move|connect: &'a Connect, index|iter_south( + index as u16, + 1, + h_full(origin_w(bold(false, fg_bg(fg, bg, &connect.info)))) + ) + ) + ) + ) + ) } /// CLI banner. @@ -758,7 +769,7 @@ fn app_understand_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usu Some("menu") => to.place(&if let Dialog::Menu(selected, items) = &state.dialog { let items = items.clone(); let selected = selected; - Some(wh_full(Thunk::new(move|to: &mut Tui|{ + Some(wh_full(thunk(move|to: &mut Tui|{ for (index, MenuItem(item, _)) in items.0.iter().enumerate() { to.place(&y_push((2 * index) as u16, fg_bg( @@ -776,7 +787,7 @@ fn app_understand_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usu Some(":templates") => to.place(&{ let modes = state.config.modes.clone(); let height = (modes.read().unwrap().len() * 2) as u16; - h_exact(height, w_min(30, Thunk::new(move |to: &mut Tui|{ + h_exact(height, w_min(30, thunk(move |to: &mut Tui|{ for (index, (id, profile)) in modes.read().unwrap().iter().enumerate() { let bg = if index == 0 { Rgb(70,70,70) } else { Rgb(50,50,50) }; let name = profile.name.get(0).map(|x|x.as_ref()).unwrap_or(""); @@ -792,7 +803,7 @@ fn app_understand_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usu } }))) }), - Some(":sessions") => to.place(&h_exact(6, w_min(30, Thunk::new(|to: &mut Tui|{ + Some(":sessions") => to.place(&h_exact(6, w_min(30, thunk(|to: &mut Tui|{ let fg = Rgb(224, 192, 128); for (index, name) in ["session1", "session2", "session3"].iter().enumerate() { let bg = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) }; @@ -811,7 +822,7 @@ fn app_understand_word (state: &App, to: &mut Tui, dsl: &impl Expression) -> Usu }, w_shrink(3, h_exact(1, fg(g(96), x_repeat("🭻")))))))), Some(":device") => { let selected = state.dialog.device_kind().unwrap(); - to.place(&south(bold(true, "Add device"), iter_south(1, + to.place(&south(bold(true, "Add device"), iter_south( move||device_kinds().iter(), move|_label: &&'static str, i|{ let bg = if i == selected { Rgb(64,128,32) } else { Rgb(0,0,0) }; @@ -957,7 +968,7 @@ impl App { impl Draw for App { fn draw (self, to: &mut Tui) -> Usually> { if let Some(e) = self.error.read().unwrap().as_ref() { - to.place_at(to.area(), e); + to.place_at(to.area().into(), e.as_ref()); } for (index, dsl) in self.mode.view.iter().enumerate() { if let Err(e) = self.understand(to, dsl) { @@ -974,3 +985,9 @@ primitive!(u8: try_to_u8); primitive!(u16: try_to_u16); primitive!(usize: try_to_usize); primitive!(isize: try_to_isize); + +fn field_h (theme: ItemTheme, head: impl Draw, body: impl Draw) -> impl Draw { +} + +fn field_v (theme: ItemTheme, head: impl Draw, body: impl Draw) -> impl Draw { +} diff --git a/tengri b/tengri index a93fe92a..c9b9ff15 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit a93fe92a596b8a9bcec898e228fca909c0e2e9f4 +Subproject commit c9b9ff15191ec3a37e8da35f382ce0d4af74d0d8