diff --git a/src/device/arrange.rs b/src/device/arrange.rs index 5f871a38..e86227c6 100644 --- a/src/device/arrange.rs +++ b/src/device/arrange.rs @@ -609,9 +609,15 @@ impl Track { pub fn per <'a, T: Draw + 'a, U: TracksSizes<'a>> ( tracks: impl Fn() -> U + Send + Sync + 'a, - callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a + callback: &'a (impl Fn(usize, &'a Track)->T + Send + Sync + 'a) ) -> impl Draw + 'a { - view_track_per(tracks, callback) + iter_east(move||tracks().map(|(index, track, x1, x2): (usize, &Track, usize, usize)|{ + fg_bg( + track.color.lightest.term, + track.color.base.term, + callback(index, track) + ).exact_w((x2 - x1) as u16) + })) } } @@ -948,10 +954,11 @@ impl Arrangement { pub fn view_track_devices (&self, theme: ItemTheme) -> impl Draw { let height = self.devices_height(); - view_track_row_section(theme, - button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false), - button_2("D", "+", false), - iter_once(self.tracks_with_sizes(), move|(_, track, _x1, _x2), index|bg( + let btn1 = button_3("d", "evice", format!("{}", self.track().map(|t|t.devices.len()).unwrap_or(0)), false); + let btn2 = button_2("D", "+", false); + view_track_row_section(theme, btn1, btn2, iter_east(move||self.tracks_with_sizes() + .enumerate() + .map(move|(index, (_, track, _x1, _x2))|bg( track.color.dark.term, iter_south(move||(0..height).map(|_|fg_bg( ItemTheme::G[32].lightest.term, @@ -963,7 +970,7 @@ impl Arrangement { .exact_wh( Some(track_width(index, track)), Some(height + 1), - ))) + )))) } fn devices_height (&self) -> u16 { diff --git a/src/tek.edn b/src/tek.edn index 7dac49a6..ef4b6566 100644 --- a/src/tek.edn +++ b/src/tek.edn @@ -1,7 +1,7 @@ -(view :logo (bsp/s (text ~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) - (bsp/s (text ~~~~ ║ ~ ╟─╌ ~╟─< ~~ heatwave is the new darkwave ~~ ) - (bsp/s (text ~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ) - (text))))) +(view :logo (bsp/s (bg (rgb 100 70 40) (text ~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ )) + (bsp/s (bg (rgb 90 70 50) (text ~~~~ ║ ~ ╟─╌ ~╟─< ~~ heatwave is the new darkwave ~~ )) + (bsp/s (bg (rgb 80 70 60) (text ~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ )) + (align/x (text .)))))) (view :browse (bsp/s (padding 3 1 :browse-title) @@ -15,51 +15,8 @@ (mode :menu (name Menu) (info Mode selector.) (keys :axis/y :confirm) (view (bsp/s - (align/s (bsp/e :ports/out - (bsp/e :transport - :ports/in))) - (align/c (bsp/s (align/x (bg (g 36) :logo)) - (bg (g 24) :dialog/menu)))))) - -(view :ports/out - (bsp/s (align/w (text L-AUDIO-OUT)) - (bsp/e (text MIDI-OUT) - (align/e (text AUDIO-OUT-R))))) - -(view :ports/in - (bsp/s (align/w (text L-AUDIO-IN)) - (bsp/e (text MIDI-IN) - (align/e (text AUDIO-IN-R))))) - -(mode :sequencer (name Sequencer) (info MIDI sequencer.) - (keys :editor :clock :global) - (mode browse (keys :browse)) - (mode rename (keys :pool/rename)) - (mode length (keys :pool/length)) - (bsp/s (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) - (fill (bsp/a (fill/xy (align/e :pool)) :editor))))) - -(mode :sampler (name Sampler) (info Sample player.) - (keys :sampler/directions :sampler/record :sampler/play) - (bsp/s (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) - (fill :samples/grid)))) - -(mode :groovebox (name Groovebox) (info Sequencer with sampler.) - (keys :clock :editor :sampler :global) - (mode browse (keys :browse)) - (mode rename (keys :pool-rename)) - (mode length (keys :pool-length)) - (bsp/w :meters/output (bsp/e :meters/input (bsp/w :groove/meta :groove/editor)))) - -(view :groove/meta (fill/y (align/n (stack/s :midi-ins/status :midi-outs/status :audio-ins/status :audio-outs/status :pool)))) - -(view :groove/editor (bsp/n :groove/sample :groove/sequence)) - -(view :groove/sample (fixed/y :h-sample-detail (bsp/e (fill/y (fixed/x 20 (align/nw :sample-status))) :sample-viewer))) - -(view :groove/sequence (bsp/e (fill/y (align/n (bsp/s :status/v :editor-status))) (bsp/e :samples/keys :editor))) + (align/s (bsp/e :ports/out (bsp/e :transport :ports/in))) + (align/c (bsp/s (align/x (bg (g 36) :logo)) (bg (g 24) :dialog/menu)))))) (mode :arranger (name Arranger) (info Launch grid.) (keys (see :clock :color :launch :scenes :tracks :global) @@ -76,7 +33,58 @@ (mode :track (keys :track)) (mode :scene (keys :scene)) (mode :mix (keys :mix)) - (view (bg (g 64) (bsp/n :status (text test))))) + (view + (bsp/n (bg (g 10) (bsp/e :transport :status)) + (bsp/w (bg (g 20) (exact/x 4 (align/ne :meters/output))) + (bsp/e (bg (g 30) (exact/x 4 (align/nw :meters/input))) + (full/xy (align/c (max/xy 80 80 + (bsp/s (bg (g 40) (exact/y 4 :tracks/outputs)) + (bsp/s (bg (g 50) (exact/y 2 :tracks/names)) + (bsp/s (bg (g 60) (exact/y 4 :tracks/devices)) + (bsp/s (bg (g 70) (exact/y 4 :tracks/inputs)) + (either :mode/editor + (bg (g 80) (bsp/s :scenes/names :editor)) + (bg (g 90) :scenes)))))))))))))) + +(view :ports/out + (bsp/s (align/w (text L-AUDIO-OUT)) + (bsp/e (text MIDI-OUT) + (align/e (text AUDIO-OUT-R))))) + +(view :ports/in + (bsp/s (align/w (text L-AUDIO-IN)) + (bsp/e (text MIDI-IN) + (align/e (text AUDIO-IN-R))))) + +(mode :sequencer (name Sequencer) (info MIDI sequencer.) + (keys :editor :clock :global) + (mode browse (keys :browse)) + (mode rename (keys :pool/rename)) + (mode length (keys :pool/length)) + (bsp/s (exact/y 1 :transport) + (bsp/n (exact/y 1 :status) + (fill (bsp/a (fill/xy (align/e :pool)) :editor))))) + +(mode :sampler (name Sampler) (info Sample player.) + (keys :sampler/directions :sampler/record :sampler/play) + (bsp/s (exact/y 1 :transport) + (bsp/n (exact/y 1 :status) + (fill :samples/grid)))) + +(mode :groovebox (name Groovebox) (info Sequencer with sampler.) + (keys :clock :editor :sampler :global) + (mode browse (keys :browse)) + (mode rename (keys :pool-rename)) + (mode length (keys :pool-length)) + (bsp/w :meters/output (bsp/e :meters/input (bsp/w :groove/meta :groove/editor)))) + +(view :groove/meta (fill/y (align/n (stack/s :midi-ins/status :midi-outs/status :audio-ins/status :audio-outs/status :pool)))) + +(view :groove/editor (bsp/n :groove/sample :groove/sequence)) + +(view :groove/sample (exact/y :h-sample-detail (bsp/e (fill/y (exact/x 20 (align/nw :sample-status))) :sample-viewer))) + +(view :groove/sequence (bsp/e (fill/y (align/n (bsp/s :status/v :editor-status))) (bsp/e :samples/keys :editor))) (keys :back (@escape back)) (keys :confirm (@enter confirm)) diff --git a/src/tek.rs b/src/tek.rs index 85efad6a..520197a9 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -1380,9 +1380,7 @@ mod draw { /// Load custom view definition. pub(crate) fn load_view ( - views: &Views, - name: &impl AsRef, - body: &impl Language, + views: &Views, name: &impl AsRef, body: &impl Language, ) -> Usually<()> { views.write().unwrap().insert( name.as_ref().into(), @@ -1393,7 +1391,7 @@ mod draw { impl Keywords> for App { fn keywords () -> impl Iterator Perhaps>> { - [kw_when, kw_either, kw_split, kw_align, kw_exact, kw_min, kw_max, kw_push, + [kw_when, kw_either, kw_split, kw_align, kw_exact, kw_min, kw_max, kw_push, kw_full, kw_tui_text, kw_tui_fg, kw_tui_bg] .into_iter() } @@ -1467,11 +1465,26 @@ mod draw { let mut frags = lang.src()?.unwrap().split("/"); match frags.next() { //Some(":logo") => view_logo().draw(to), - Some(":meters") => draw_meter_section(to, frags), - Some(":tracks") => draw_tracks(to, frags, self), - Some(":scenes") => draw_scenes(to, frags), + Some(":meters") => match frags.next() { + Some("input") => bg(Rgb(30, 30, 30), "Input Meters".align_s().full_h()).draw(to), + Some("output") => bg(Rgb(30, 30, 30), "Output Meters".align_s().full_h()).draw(to), + _ => panic!() + }, + Some(":tracks") => match frags.next() { + None => "TODO tracks".draw(to), + Some("names") => self.project.view_track_names(self.color.clone()).draw(to),//bg(Rgb(40, 40, 40), full_w(align_w("Track Names")))), + Some("inputs") => self.project.view_track_inputs(self.color.clone()).draw(to),//bg(Rgb(40, 40, 40), "Track Inputs".align_w().full_w()).draw(to), + Some("devices") => self.project.view_track_devices(self.color.clone()).draw(to),//bg(Rgb(40, 40, 40), "Track Devices".align_w().full_w()).draw(to), + Some("outputs") => self.project.view_track_outputs(self.color.clone(), 0).draw(to), + _ => panic!() + }, + Some(":scenes") => match frags.next() { + None => "TODO Scenes".draw(to), + Some(":scenes/names") => "TODO Scene Names".draw(to), + _ => panic!() + }, Some(":dialog") => draw_dialog(to, frags, self, lang), - Some(":templates") => draw_templates(to, frags, self), + Some(":templates") => view_templates(frags, self).draw(to), Some(":sessions") => view_sessions().draw(to), Some(":browse/title") => view_browse_title(self).draw(to), Some(":device") => view_device(self).draw(to), @@ -1486,7 +1499,7 @@ mod draw { std::mem::drop(views); self.interpret(to, &lang) } else { - unimplemented!("{lang:?}"); + fg(Color::Rgb(128, 32, 32), format!("undefined: {lang:?}")).draw(to) } }, _ => unreachable!() @@ -1504,34 +1517,7 @@ mod draw { fn width_dec (&mut self); } - pub fn draw_meter_section (to: &mut Tui, mut frags: std::str::Split<&str>) -> Drawn { - match frags.next() { - Some("input") => bg(Rgb(30, 30, 30), "Input Meters".align_s().full_h()).draw(to), - Some("output") => bg(Rgb(30, 30, 30), "Output Meters".align_s().full_h()).draw(to), - _ => panic!() - } - } - - pub fn draw_tracks (to: &mut Tui, mut frags: std::str::Split<&str>, state: &App) -> Drawn { - match frags.next() { - None => "TODO tracks".draw(to), - Some("names") => state.project.view_track_names(state.color.clone()).draw(to),//bg(Rgb(40, 40, 40), full_w(align_w("Track Names")))), - Some("inputs") => bg(Rgb(40, 40, 40), "Track Inputs".align_w().full_w()).draw(to), - Some("devices") => bg(Rgb(40, 40, 40), "Track Devices".align_w().full_w()).draw(to), - Some("outputs") => bg(Rgb(40, 40, 40), "Track Outputs".align_w().full_w()).draw(to), - _ => panic!() - } - } - - pub fn draw_scenes (to: &mut Tui, mut frags: std::str::Split<&str>) -> Drawn { - match frags.next() { - None => "TODO Scenes".draw(to), - Some(":scenes/names") => "TODO Scene Names".draw(to), - _ => panic!() - } - } - - pub fn draw_templates (to: &mut Tui, _frags: std::str::Split<&str>, state: &App) -> Drawn { + pub fn view_templates (_frags: std::str::Split<&str>, state: &App) -> impl Draw { let height = (state.config.modes.len() * 2) as u16; draw(move |to: &mut Tui|{ let mut index = 0; @@ -1549,29 +1535,29 @@ mod draw { index += 1; }); Ok(Some(to.area().into())) - }).min_w(30).exact_h(height).draw(to) + }).min_w(30).exact_h(height) } - pub fn per_track <'a, T: Draw + 'a, U: TracksSizes<'a>> ( - tracks: impl Fn() -> U + Send + Sync + 'a, - callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a - ) -> impl Draw + 'a { - per_track_top(tracks, move|index, track|callback(index, track).full_h().align_y()) - } + //pub fn per_track <'a, T: Draw + 'a, U: TracksSizes<'a>> ( + //tracks: impl Fn() -> U + Send + Sync + 'a, + //callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a + //) -> impl Draw + 'a { + //per_track_top(tracks, move|index, track|callback(index, track).full_h().align_y()) + //} - pub fn per_track_top <'a, T: Draw + 'a, U: TracksSizes<'a>> ( - tracks: impl Fn() -> U + Send + Sync + 'a, - callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a - ) -> impl Draw + 'a { - bg(Reset, iter_east(tracks, - move|(index, track, x1, x2): (usize, &'a Track, usize, usize), _|{ - fg_bg( - track.color.lightest.term, - track.color.base.term, - callback(index, track) - ).exact_w((x2 - x1) as u16) - }).align_x()) - } + //pub fn per_track_top <'a, T: Draw + 'a, U: TracksSizes<'a>> ( + //tracks: impl Fn() -> U + Send + Sync + 'a, + //callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a + //) -> impl Draw + 'a { + //bg(Reset, iter_east(||tracks() + //.map(move|(index, track, x1, x2): (usize, &'a Track, usize, usize)|{ + //fg_bg( + //track.color.lightest.term, + //track.color.base.term, + //callback(index, track) + //).exact_w((x2 - x1) as u16) + //})).align_x()) + //} pub fn field_h ( _theme: ItemTheme, _head: impl Draw, _body: impl Draw @@ -1932,17 +1918,43 @@ mod draw { track.map(move|track|view_ports_status(theme, "Audio outs:", &track.audio_outs())) } - pub fn view_track_per <'a, T: Draw + 'a, U: TracksSizes<'a>> ( - tracks: impl Fn() -> U + Send + Sync + 'a, - callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a + //pub fn view_track_per <'a, T: Draw + 'a, U: TracksSizes<'a>> ( + //tracks: impl Fn() -> U + Send + Sync + 'a, + //callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a + //) -> impl Draw { + //} + + /// ``` + /// let _ = tek::button_2("", "", true); + /// let _ = tek::button_2("", "", false); + /// ``` + pub fn button_2 <'a> (key: impl Draw, label: impl Draw, hide: bool) -> impl Draw { + let c1 = tui_orange(); + let c2 = tui_g(0); + let c3 = tui_g(96); + let c4 = tui_g(255); + bold(true, fg_bg(c1, c2, + east!(fg(c2, "▐"), key, fg(c3, "▐"), when(!hide, fg_bg(c4, c3, label))))) + } + + /// ``` + /// let _ = tek::button_3("", "", "", true); + /// let _ = tek::button_3("", "", "", false); + /// ``` + pub fn button_3 <'a> ( + key: impl Draw, label: impl Draw, value: impl Draw, editing: bool, ) -> impl Draw { - iter_east(tracks, move|(index, track, x1, x2): (usize, &Track, usize, usize), _|{ - fg_bg( - track.color.lightest.term, - track.color.base.term, - callback(index, track) - ).exact_w((x2 - x1) as u16) - }) + let c1 = tui_orange(); + let c2 = tui_g(0); + let c3 = tui_g(96); + let c4 = tui_g(255); + let c5 = tui_g(128); + bold(true, east( + fg_bg(c1, c2, + east(fg(c2, "▐"), east(key, fg(if editing { c5 } else { c3 }, "▐")))), + east( + when(!editing, east(fg_bg(c4, c3, label), fg_bg(c5, c3, "▐"),)), + east(fg_bg(tui_g(224), c5, value), fg_bg(c5, Reset, "▌"), )))) } } diff --git a/tengri b/tengri index 799e4976..8a6eb19e 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit 799e49762250f48778dadd92874a29495114a6af +Subproject commit 8a6eb19e279afefc126008c27b38cc66645e1c96