diff --git a/src/dialog.rs b/src/dialog.rs index f19e5639..22f68924 100644 --- a/src/dialog.rs +++ b/src/dialog.rs @@ -2,28 +2,28 @@ use crate::*; pub fn get_dialog <'a> (_: &App, src: impl Language) -> Perhaps { src.word()?.map(|word|Ok(match word { - ":dialog/none" => Dialog::None, - ":dialog/options" => Dialog::Options, - ":dialog/device" => Dialog::Device(0), - ":dialog/device/prev" => Dialog::Device(0), - ":dialog/device/next" => Dialog::Device(0), - ":dialog/help" => Dialog::Help(0), - ":dialog/save" => Dialog::Browse( + ":none" => Dialog::None, + ":options" => Dialog::Options, + ":device" => Dialog::Device(0), + ":device/prev" => Dialog::Device(0), + ":device/next" => Dialog::Device(0), + ":help" => Dialog::Help(0), + ":save" => Dialog::Browse( BrowseTarget::SaveProject, Browse::new(None).unwrap().into()), - ":dialog/load" => Dialog::Browse( + ":load" => Dialog::Browse( BrowseTarget::LoadProject, Browse::new(None).unwrap().into()), - ":dialog/import/clip" => Dialog::Browse( + ":import/clip" => Dialog::Browse( BrowseTarget::ImportClip(Default::default()), Browse::new(None).unwrap().into()), - ":dialog/export/clip" => Dialog::Browse( + ":export/clip" => Dialog::Browse( BrowseTarget::ExportClip(Default::default()), Browse::new(None).unwrap().into()), - ":dialog/import/sample" => Dialog::Browse( + ":import/sample" => Dialog::Browse( BrowseTarget::ImportSample(Default::default()), Browse::new(None).unwrap().into()), - ":dialog/export/sample" => Dialog::Browse( + ":export/sample" => Dialog::Browse( BrowseTarget::ExportSample(Default::default()), Browse::new(None).unwrap().into()), _ => return Err( @@ -89,6 +89,12 @@ impl Dialog { modes: vec![":arranger".into()] } }, + AppCommand::Tracks { + command: TracksCommand::Add + }, + AppCommand::Scenes { + command: ScenesCommand::Add + } ]), MenuItem::new(" Load session ", [ diff --git a/src/tek.edn b/src/tek.edn index 78f5a22c..c21ade5c 100644 --- a/src/tek.edn +++ b/src/tek.edn @@ -15,10 +15,11 @@ (info Mode selector.) (keys :axis/y :confirm) (view - (bar/n 2 (bsp/e :transport :status) - (align/c - (bar/s 2 (align/x (bg (g 12) :logo)) - :dialog/menu))))) + (bar/s 2 (pad/x 1 :transport) + (bar/n 2 :status + (align/c + (bar/s 2 (align/x (bg (g 12) :logo)) + :dialog/menu)))))) (keys :back (@escape cancel)) (keys :confirm (@enter confirm)) @@ -39,16 +40,28 @@ (mode :scene (keys :scene)) (mode :mix (keys :mix)) (view - (bar/n 2 (bsp/e :transport :status) - (bar/s 2 :tracks/outputs - (bar/s 2 :tracks/devices - (bar/s 2 :tracks/names - (bar/n 2 :tracks/inputs - (bar/e 16 :scenes/names :scenes/clips)))))))) + (bar/n 2 :status + (bar/s 8 + (bar/e 16 (align/nw (pad/x 1 :transport)) + (bar/w 16 (bar/s 2 (bar/w 4 :tracks/outputs/add :tracks/outputs/count) + (bar/s 2 (bar/w 4 :tracks/devices/add :tracks/devices/count) + (bar/s 2 (bar/w 4 :tracks/names/add :tracks/names/count) + (bar/w 4 :tracks/inputs/add :tracks/inputs/count)))) + (align/x (bar/s 2 :tracks/outputs/cells + (bar/s 2 :tracks/devices/cells + (bar/s 2 :tracks/names/cells + :tracks/inputs/cells)))))) + (bar/w 16 (text) + (bar/e 16 :scenes/names + :scenes/clips)))))) (keys :global (@f1 (dialog :help)) + (@f2 (project new)) + (@f3 (dialog :history)) + (@f6 (dialog :save)) (@f8 (dialog :options)) + (@f9 (dialog :load)) (@f10 (dialog :quit))) (keys :clock @@ -56,10 +69,10 @@ (@shift/space (clock/toggle 0))) (keys :color - (@c color)) + (@c (color))) (keys :launch - (@q launch)) + (@q (launch))) (keys :scenes (@shift/S (scenes add)) @@ -155,8 +168,8 @@ (@shift/R sampler/record/back)) (keys :sampler/play (@p sampler/play/sample :sample/selected) (@P sampler/stop/sample :sample/selected)) -(keys :sampler/import-export (@shift/f6 dialog :dialog/export/sample) - (@shift/f9 dialog :dialog/import/sample)) +(keys :sampler/import-export (@shift/f6 dialog :export/sample) + (@shift/f9 dialog :import/sample)) (keys :sampler/directions (@up sampler/select :sample/above) (@down sampler/select :sample/below) (@left sampler/select :sample/to/left) diff --git a/src/track.rs b/src/track.rs index 4b6c524b..3dc84d74 100644 --- a/src/track.rs +++ b/src/track.rs @@ -369,34 +369,42 @@ pub trait TracksView: HasTracks + ScenesView + HasMidiIns + HasMidiOuts + HasTra /// Draw name of each track fn view_track_names (&self, theme: ItemTheme) -> impl Draw { - let btn1t = self.view_track_count(); - let btn1s = self.view_scene_count(); - let btns1 = south(btn1t, btn1s); - let btns2 = south(self.view_track_add(), self.view_scene_add()); view_track_row_section(theme, - btns1, - btns2, - bg(theme.darker.term, - iter_east(||self.tracks_with_sizes().map(|(index, track, _x1, _x2)|{ - let b = if self.selection().track() == Some(index) { - track.color.light.term - } else { - track.color.base.term - }; - bg(b, south( - east!( - "·t", - index, - " ", - fg(Rgb(255, 255, 255), bold(true, &track.name)) - ) - .align_nw() - .full_w(), - "" - )) - .exact_w(track_width(index, track)) - .exact_h(2) - })))) + self.view_track_names_count(), + self.view_track_names_add(), + self.view_track_names_cells() + ) + } + + fn view_track_names_add (&self) -> impl Draw { + south(self.view_track_add(), self.view_scene_add()) + } + + fn view_track_names_count (&self) -> impl Draw { + south(self.view_track_count(), self.view_scene_count()) + } + + fn view_track_names_cells <'a> (&'a self) -> impl Draw { + iter_east(||self.tracks_with_sizes().map(|(index, track, _x1, _x2)|{ + let b = if self.selection().track() == Some(index) { + track.color.light.term + } else { + track.color.base.term + }; + bg(b, south( + east!( + "·t", + index, + " ", + fg(Rgb(255, 255, 255), bold(true, &track.name)) + ) + .align_nw() + .full_w(), + "" + )) + .exact_w(track_width(index, track)) + .exact_h(2) + })) } /// Draw outputs per track @@ -404,52 +412,36 @@ pub trait TracksView: HasTracks + ScenesView + HasMidiIns + HasMidiOuts + HasTra view_track_row_section(theme, self.view_track_output_count(), self.view_track_output_add(), - bg(theme.darker.term, - iter_east(move||self.tracks_with_sizes().map(move|(index, track, _x1, _x2)|{ - let f = Rgb(255, 255, 255); - let b = track.color.dark.term; - iter_south(move||track.sequencer.midi_outs.iter().map(move|port: &MidiOutput|{ - fg(f, bg(b, east!("·o", index, " ", port.port_name()).full_w().align_w()).exact_h(1)) - })) - .full_h() - .align_nw() - .exact_w(track_width(index, track)) - })))) + self.view_track_output_cells() + ) } - /// Draw inputs per track - fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw { - let mut height = 0u16; - for track in self.tracks().iter() { - height = height.max(track.sequencer.midi_ins.len() as u16); - } - view_track_row_section(theme, - self.view_track_input_count(), - self.view_track_input_add(), - bg(theme.darker.term, iter_east(move||self - .tracks_with_sizes() - .map(move|(index, track, _x1, _x2)|{ - south( - bg(track.color.base.term, - east!( - either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "), - either(track.sequencer.recording, fg(Red, "●rec "), "·rec "), - either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "), - ).align_w().full_w()), - iter_south(move||track.sequencer.midi_ins.iter().map(move|port|fg_bg( - Rgb(255, 255, 255), - track.color.dark.term, - east!("·i", index, " ", port.port_name()).align_w().full_w())))) - .align_nw() - .exact_wh(track_width(index, track), height + 1) - }))).align_w()) + fn view_track_output_cells <'a> (&'a self) -> impl Draw { + iter_east(move||self.tracks_with_sizes().map(move|(index, track, _x1, _x2)|{ + let f = Rgb(255, 255, 255); + let b = track.color.dark.term; + iter_south(move||track.sequencer.midi_outs.iter().map(move|port: &MidiOutput|{ + fg(f, bg(b, east!("·o", index, " ", port.port_name()).full_w().align_w()).exact_h(1)) + })) + .full_h() + .align_nw() + .exact_w(track_width(index, track)) + })) + } + + fn view_track_device_count (&self) -> impl Draw { + button_3("d", "evice", self.track().map(|t|t.devices.len()).unwrap_or(0), false).min_h(2) } fn view_track_devices (&self, theme: ItemTheme) -> impl Draw { let height = self.tracks_devices_height(); - let btn1 = button_3("d", "evice", self.track().map(|t|t.devices.len()).unwrap_or(0), false).min_h(2); + let btn1 = self.view_track_device_count(); let btn2 = self.view_track_device_add(); - view_track_row_section(theme, btn1, btn2, iter_east(move||self.tracks_with_sizes() + view_track_row_section(theme, btn1, btn2, self.view_track_device_cells(height)) + } + + fn view_track_device_cells (&self, height: u16) -> impl Draw { + iter_east(move||self.tracks_with_sizes() .enumerate() .map(move|(index, (_, track, _x1, _x2))|bg( track.color.dark.term, @@ -463,7 +455,7 @@ pub trait TracksView: HasTracks + ScenesView + HasMidiIns + HasMidiOuts + HasTra .exact_wh( Some(track_width(index, track)), Some(height + 1), - )))) + ))) } fn tracks_devices_height (&self) -> u16 { @@ -474,10 +466,51 @@ pub trait TracksView: HasTracks + ScenesView + HasMidiIns + HasMidiOuts + HasTra h as u16 } - fn view_inputs (&self, _theme: ItemTheme) -> impl Draw + '_ { + fn view_inputs (&self) -> impl Draw + '_ { let title_1 = button_3("i", "nput ", self.midi_ins().len(), false).align_w().exact_wh(20, 1); let title_2 = self.view_track_input_add().exact_wh(4, 1); - east(title_1, west(title_2, draw(move|to: &mut Tui|{ + east(title_1, west(title_2, self.view_input_cells())) + } + + fn tracks_inputs_height (&self) -> u16 { + let mut height = 0u16; + for track in self.tracks().iter() { + height = height.max(track.sequencer.midi_ins.len() as u16); + } + height + } + + /// Draw inputs per track + fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw { + view_track_row_section(theme, + self.view_track_input_count(), + self.view_track_input_add(), + self.view_track_input_cells(self.tracks_inputs_height()) + ) + } + + fn view_track_input_cells (&self, height: u16) -> impl Draw { + iter_east(move||self + .tracks_with_sizes() + .map(move|(index, track, _x1, _x2)|{ + south( + bg(track.color.base.term, + east!( + either(track.sequencer.monitoring, fg(Green, "●mon "), "·mon "), + either(track.sequencer.recording, fg(Red, "●rec "), "·rec "), + either(track.sequencer.overdub, fg(Yellow, "●dub "), "·dub "), + ).align_w().full_w()), + iter_south(move||track.sequencer.midi_ins.iter().map(move|port|fg_bg( + Rgb(255, 255, 255), + track.color.dark.term, + east!("·i", index, " ", port.port_name()).align_w().full_w())))) + .align_nw() + .exact_wh(track_width(index, track), height + 1) + })).align_w() + } + + fn view_input_cells (&self) -> impl Draw { + draw(move|to: &mut Tui|{ for (_index, track, x1, _x2) in self.tracks_with_sizes() { let _ = south( bg(track.color.dark.term, east!( @@ -502,12 +535,12 @@ pub trait TracksView: HasTracks + ScenesView + HasMidiIns + HasMidiOuts + HasTra ) ).push_x(index as u16 * 10).exact_h(1).draw(to)?; } - todo!() + Ok(None) }) ).draw(to)?; } Ok(Some(to.area())) - }))) + }) } fn outputs_height (&self) -> u16 { diff --git a/src/views.rs b/src/views.rs index 8a64f218..a293e47c 100644 --- a/src/views.rs +++ b/src/views.rs @@ -262,13 +262,30 @@ impl View { Some("output") => Self::boxed(move|_, to|bg(Rgb(30, 30, 30), "Output Meters".align_s().full_h()).draw(to)), _ => panic!() }, - Some(":tracks") => match word.split("/").skip(1).next() { - None => Self::boxed(move|_, to|"TODO tracks".draw(to)), - Some("names") => draw!(|app|app.project.view_track_names(app.color.clone())), - Some("inputs") => draw!(|app|app.project.view_track_inputs(app.color.clone())), - Some("devices") => draw!(|app|app.project.view_track_devices(app.color.clone())), - Some("outputs") => draw!(|app|app.project.view_track_outputs(app.color.clone(), 0)), - _ => panic!() + Some(":tracks") => match &word[(":tracks".len()+1)..] { + "" => Self::boxed(move|_, to|"TODO tracks".draw(to)), + + "names" => draw!(|app|app.project.view_track_names(app.color.clone())), + "names/count" => draw!(|app|app.project.view_track_names_count()), + "names/cells" => draw!(|app|app.project.view_track_names_cells()), + "names/add" => draw!(|app|app.project.view_track_names_add()), + + "devices" => draw!(|app|app.project.view_track_devices(app.color.clone())), + "devices/count" => draw!(|app|app.project.view_track_device_count()), + "devices/cells" => draw!(|app|app.project.view_track_device_cells(app.tracks_devices_height())), + "devices/add" => draw!(|app|app.project.view_track_device_add()), + + "inputs" => draw!(|app|app.project.view_track_inputs(app.color.clone())), + "inputs/count" => draw!(|app|app.project.view_track_input_count()), + "inputs/cells" => draw!(|app|app.project.view_track_input_cells(app.tracks_inputs_height())), + "inputs/add" => draw!(|app|app.project.view_track_input_add()), + + "outputs" => draw!(|app|app.project.view_track_outputs(app.color.clone(), 0)), + "outputs/count" => draw!(|app|app.project.view_track_output_count()), + "outputs/cells" => draw!(|app|app.project.view_track_output_cells()), + "outputs/add" => draw!(|app|app.project.view_track_output_add()), + + _ => panic!("unknown: {word}") }, Some(":scenes") => match word.split("/").skip(1).next() { Some("clips") => draw!(|app|app.view_scenes_clips()),