multidispatch; mode/select status

This commit is contained in:
i do not exist 2026-09-23 11:14:24 +03:00
parent 6aff4e55a6
commit 0a89fab28a
3 changed files with 104 additions and 173 deletions

View file

@ -1,11 +1,11 @@
(mode Menu (name Main Menu) (info Welcome to Tek!) (keys Y Confirm)
(view (bar/s 2 Transport (bar/n 2 Status (align/c (bar/s 2 (align/x (bg (g 12) Logo)) Menu))))))
(view (bar/s 2 Transport (bar/n 2 StatusBar (align/c (bar/s 2 (align/x (bg (g 12) Logo)) Menu))))))
(mode Transport (name Transport) (info JACK transport controller.)
(keys Clock Global)
(view Transport))
(mode Arranger (name Arranger) (info Launch grid.)
(keys Global Clock Tracks Scenes Clip Launch Color History)
(view (bar/n 2 Status (bar/s 8 (bar/e 16 (align/nw Transport)
(view (bar/n 2 StatusBar (bar/s 8 (bar/e 16 (align/nw Transport)
(bar/w 20 (bar/s 2 (bar/w 4 TracksOutputsAdd TracksOutputsCount)
(bar/s 2 (bar/w 4 TracksDevicesAdd TracksDevicesCount)
(bar/s 2 (bar/w 4 TracksNamesAdd TracksNamesCount)
@ -16,10 +16,10 @@
(bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips))))))
(mode Sequencer (info MIDI sequencer.)
(keys Global Clock I IFine Y Page EditorView EditorAdd EditorDel)
(view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 Status) (fill/xy (bsp/a (fill/xy (align/e Pool)) Editor))))))
(view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 StatusBar) (fill/xy (bsp/a (fill/xy (align/e Pool)) Editor))))))
(mode Sampler (info Sample player.)
(keys SamplerDirs SamplerRec SamplerPlay)
(view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 Status) (fill/xy SampleGrid)))))
(view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 StatusBar) (fill/xy SampleGrid)))))
(mode Groovebox (info Sequencer with sampler.)
(keys Global Clock Sampler I IFine Y Page EditorView EditorAdd EditorDel)
(view (bsp/w MetersOut (bsp/e MetersIn (bsp/w GrooveMeta GrooveEditor)))))
@ -32,7 +32,8 @@
(view GrooveEditor (bsp/n GrooveSample GrooveSequence))
(view GrooveSample (exact/h SampleHeight (bsp/e (fill/y (exact/w 20 (align/nw SampleStatus))) SampleViewer)))
(view GrooveSequence (bsp/e (fill/y (align/n (bsp/s Status/v EditorStatus))) (bsp/e SamplesKeys Editor)))
(view Status (bar/s 1 (text Mode) ModeList))
(view StatusBar (bar/e 40 (bg (g 10) (full/x (pad/x 1 (bar/s 1 (text Selected) Selected))))
(bg (g 20) (full/x (pad/x 1 (bar/s 1 (text Mode) ModeList))))))
(view Transport (bg (g 0) (pad/x 1 (bar/e 4 PlayPause (bar/e 16 Bpm (bar/e 16 Beat Time))))))
(keys Global (@f1 (dialog Help))

View file

@ -2,7 +2,6 @@
mod deps; pub use self::deps::*;
mod midi_octave; pub use self::midi_octave::*;
mod midi_piano; pub use self::midi_piano::*;
mod midi_point; pub use self::midi_point::*;
@ -358,6 +357,10 @@ fn get_vec_arc_str <'a> (_: &App, _: impl Language) -> Perhaps<Vec<Arc<str>>> {
todo!()
}
primitive!(u8: try_to_u8);
primitive!(u16: try_to_u16);
primitive!(usize: try_to_usize);
primitive!(isize: try_to_isize);
impl_has!(Clock: |self: App|self.project.clock);
impl_has!(Dialog: |self: App|self.dialog);
impl_has!(Jack<'static>: |self: App|self.jack);
@ -369,17 +372,13 @@ impl_as_ref!(Option<Project>: |self: App|todo!());
impl_as_mut!(Option<Project>: |self: App|todo!());
impl_as_ref!(Option<MidiEditor>: |self: App|self.project.as_ref());
impl_as_mut!(Option<MidiEditor>: |self: App|self.project.as_mut());
impl HasClip for App {
fn clip_slot (&self) -> Option<Slot<MidiClip>> {
self.project.clip_slot()
}
}
primitive!(u8: try_to_u8);
primitive!(u16: try_to_u16);
primitive!(usize: try_to_usize);
primitive!(isize: try_to_isize);
tui_keys!(self: App, input {
#[cfg(feature = "prof2")] profiling::scope!("App::tui_keys!");
Self::input_cmd(self, input)
@ -388,13 +387,13 @@ tui_keys!(self: App, input {
impl App {
fn input_cmd (state: &mut Self, input: &TuiEvent) -> Usually<()> {
if let Some(bindings) = Self::input_cmd_find(state, input) {
return Self::input_cmd_exec(state, bindings)
if let Some(bindings) = Self::input_cmds_find(state, input) {
return Self::input_cmds_exec(state, bindings)
}
Ok(())
}
fn input_cmd_find (state: &mut Self, input: &TuiEvent) -> Option<Arc<[Binding<Arc<str>>]>> {
fn input_cmds_find (state: &mut Self, input: &TuiEvent) -> Option<Arc<[Binding<Arc<str>>]>> {
for name in state.modes.read().iter().rev() {
let mode = state.config.get_mode(name).as_ref().map(Arc::clone);
if let Some(mode) = mode {
@ -410,42 +409,30 @@ impl App {
None
}
fn input_cmd_exec (state: &mut Self, bindings: Arc<[Binding<Arc<str>>]>) -> Usually<()> {
fn input_cmds_exec (state: &mut Self, bindings: Arc<[Binding<Arc<str>>]>) -> Usually<()> {
for binding in bindings.iter() {
for cmd in binding.commands.iter() {
if Self::cmd::<AppCmd>(state, cmd)? {
return Ok(())
for src in binding.commands.iter() {
if let Some(command) = Namespace::<AppCmd>::namespace(state, &src)? {
Self::cmd_dispatch(state, command)?;
}
}
}
Ok(())
}
fn cmd <
T: Dispatch<Self> + Clone + Into<AppCmd>
> (state: &mut Self, src: &str) -> Usually<bool> where
Self: Namespace<T>,
{
if let Some(cmd) = Namespace::<T>::namespace(state, &src)? {
return Self::cmd_dispatch(state, cmd.into())
fn cmd_dispatch (state: &mut Self, command: AppCmd) -> Usually<()> {
match command.clone().dispatch(state) {
Ok(undo) => {
state.history.push((command, undo));
Ok(())
},
Err(err) => {
state.history.push((command, None));
Err(err)
}
}
Ok(false)
}
fn cmd_dispatch (state: &mut Self, cmd: AppCmd) -> Usually<bool> where
Self: Namespace<AppCmd>,
{
match cmd.clone().dispatch(state) {
Err(err) => {
state.history.push((cmd.into(), None));
return Err(err)
},
Ok(undo) => {
state.history.push((cmd.into(), undo.map(Into::into)));
return Ok(true)
}
}
}
}
/// A control axis.

View file

@ -30,10 +30,11 @@ impl App {
self.size.0.load(Relaxed),
self.size.1.load(Relaxed)).align_w(),
).align_se(),
Split::East.bar(16,
format!("{}", self.modes.read()[0]),
format!("{}", self.modes.read()[0])
).align_sw()
()
//Split::East.bar(16,
//format!("{}", self.modes.read()[0]),
//format!("{}", self.modes.read()[0])
//).align_sw()
).draw(to)
}
@ -388,6 +389,7 @@ impl View<Tui, App> {
Some("ScenesClips") => draw!(|app|view_scenes_clips(app)),
Some("ScenesNames") => draw!(|app|app.view_scenes_names()),
Some("Sessions") => draw!(|___|view_sessions()),
Some("Selected") => draw!(|app|view_selection(app)),
Some("Templates") => draw!(|app|view_templates(app)),
Some("Time") => draw!(),
Some("Tracks") => draw!("TODO tracks"),
@ -784,58 +786,6 @@ pub trait TracksView:
})
}
fn view_outputs (&self, theme: ItemTheme) -> impl Draw<Tui> {
let height = self.outputs_height();
let list = south(
button_3("o", "utput", self.midi_outs().len(), false).align_w().full_w().exact_h(1),
bg(Color::Rgb(0, 0, 0), draw(|to: &mut Tui|{
for (_index, port) in self.midi_outs().iter().enumerate() {
east(
east(
" ● ",
fg(Rgb(255,255,255), bold(true, port.port_name()))
).align_w(),
east!(
port.port().get_connections().len(),
"/",
port.connections.len(),
" "
).align_e().full_w().exact_h(1)).full_w().draw(to)?;
for (index, conn) in port.connections.iter().enumerate() {
east!(
" c",
index,
conn.info()
).align_w().full_w().exact_h(1).draw(to)?;
}
}
todo!();
})).align_nw().full_wh().exact_h(height - 1).min_h(1)
);
view_track_row_section(theme, list, self.view_track_output_add(),
bg(theme.darker.term, draw(|to: &mut Tui|{
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
let _ = draw(|to: &mut Tui|{
east(
either(true, fg(Green, "play "), "play "),
either(false, fg(Yellow, "solo "), "solo "),
).align_w().exact_h(1).draw(to)?;
for (_index, port) in self.midi_outs().iter().enumerate() {
east(
either(true, fg(Green, " ● "), " · "),
either(false, fg(Yellow, " ● "), " · "),
).align_w().exact_h(1).draw(to)?;
for (_index, _conn) in port.connections.iter().enumerate() {
"".full_w().exact_h(1).draw(to)?;
}
}
todo!()
}).exact_w(track_width(index, track)).draw(to)?;
}
todo!()
}).align_w().full_w())).exact_h(height)
}
fn tracks_devices_height (&self) -> u16 { self.tracks().iter().fold(2, |h, t|h.max(t.devices.len() * 2)) as u16 }
fn tracks_inputs_height (&self) -> u16 { self.tracks().iter().fold(0, |h, t|h.max(t.sequencer.midi_ins.len())) as u16 }
fn outputs_height (&self) -> u16 { self.midi_outs().iter().fold(1, |h, o|h + o.connections.len()) as u16 }
@ -856,36 +806,23 @@ pub trait TracksView:
/// Draw outputs per track
fn view_track_outputs <'a> (&'a self, theme: ItemTheme, _h: u16) -> impl Draw<Tui> {
view_track_row_section(theme,
self.view_track_output_count(),
self.view_track_output_add(),
self.view_track_output_cells()
)
view_track_row_section(theme, self.view_track_output_count(), self.view_track_output_add(),
self.view_track_output_cells())
}
/// Draw name of each track
fn view_track_names (&self, theme: ItemTheme) -> impl Draw<Tui> {
view_track_row_section(theme,
self.view_track_names_count(),
self.view_track_names_add(),
self.view_track_names_cells()
)
}
/// Draw inputs per track
fn view_track_inputs <'a> (&'a self, theme: ItemTheme) -> impl Draw<Tui> {
view_track_row_section(theme,
self.view_track_input_count(),
self.view_track_input_add(),
self.view_track_input_cells(self.tracks_inputs_height())
)
view_track_row_section(theme, self.view_track_input_count(), self.view_track_input_add(),
self.view_track_input_cells(self.tracks_inputs_height()))
}
/// Draw devices of track
fn view_track_devices (&self, theme: ItemTheme) -> impl Draw<Tui> {
let height = self.tracks_devices_height();
let btn1 = self.view_track_device_count();
let btn2 = self.view_track_device_add();
view_track_row_section(theme, btn1, btn2, self.view_track_device_cells(height))
view_track_row_section(theme, self.view_track_device_count(), self.view_track_device_add(),
self.view_track_device_cells(self.tracks_devices_height()))
}
/// Draw name of each track
fn view_track_names (&self, theme: ItemTheme) -> impl Draw<Tui> {
view_track_row_section(theme, self.view_track_names_count(), self.view_track_names_add(),
self.view_track_names_cells())
}
fn view_inputs (&self) -> impl Draw<Tui> + '_ {
@ -894,6 +831,44 @@ pub trait TracksView:
east(title_1, west(title_2, self.view_input_cells()))
}
fn view_outputs (&self, theme: ItemTheme) -> impl Draw<Tui> {
let height = self.outputs_height();
let list = south(
button_3("o", "utput", self.midi_outs().len(), false).align_w().full_w().exact_h(1),
bg(Color::Rgb(0, 0, 0), draw(|to: &mut Tui|{
for (_index, port) in self.midi_outs().iter().enumerate() {
east(
east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name())))
.align_w(),
east!(port.port().get_connections().len(), "/", port.connections.len(), " ")
.align_e().full_w().exact_h(1)).full_w().draw(to)?;
for (index, conn) in port.connections.iter().enumerate() {
east!(" c", index, conn.info()).align_w().full_w().exact_h(1).draw(to)?;
}
}
todo!();
})).align_nw().full_wh().exact_h(height - 1).min_h(1)
);
view_track_row_section(theme, list, self.view_track_output_add(),
bg(theme.darker.term, draw(|to: &mut Tui|{
for (index, track, _x1, _x2) in self.tracks_with_sizes() {
let _ = draw(|to: &mut Tui|{
east(either(true, fg(Green, "play "), "play "),
either(false, fg(Yellow, "solo "), "solo ")).align_w().exact_h(1).draw(to)?;
for (_index, port) in self.midi_outs().iter().enumerate() {
east(either(true, fg(Green, " ● "), " · "),
either(false, fg(Yellow, " ● "), " · ")).align_w().exact_h(1).draw(to)?;
for (_index, _conn) in port.connections.iter().enumerate() {
"".full_w().exact_h(1).draw(to)?;
}
}
todo!()
}).exact_w(track_width(index, track)).draw(to)?;
}
todo!()
}).align_w().full_w())).exact_h(height)
}
}
fn view_n_of_m (key: &str, name: &str, index: Option<usize>, count: usize) -> impl Draw<Tui> {
@ -1186,17 +1161,9 @@ pub fn view_track_row_section <'a> (
button_add: impl Draw<Tui>,
content: impl Draw<Tui>,
) -> impl Draw<Tui> {
bar(
Split::West,
4u16,
button_add.align_ne().full_wh(),
bar(
Split::East,
20u16,
button.full_wh().align_nw(),
content.align_c().full_wh()
)
)
Split::West.bar(4u16, button_add.align_ne().full_wh(),
Split::East.bar(20u16, button.full_wh().align_nw(),
content.align_c().full_wh()))
}
pub fn view_track_header <'a> (theme: ItemTheme, content: impl Draw<Tui>)
@ -1243,6 +1210,10 @@ pub fn view_scene_name_theme (scene: &Scene, track_index: usize) -> (Arc<str>, I
})
}
pub fn view_selection <'a> (state: &'a App) -> impl Draw<Tui> + use<'a> {
format!("{:?}", state.selection())
}
pub fn view_templates <'a> (state: &'a App) -> impl Draw<Tui> + use<'a> {
let height = (state.config.modes.len() * 2) as u16;
draw(move |to: &mut Tui|{
@ -1401,9 +1372,9 @@ pub fn view_sample_status (sample: Option<&Arc<RwLock<Sample>>>) -> impl Draw<Tu
/// let _ = tek::button_2("", "", true);
/// let _ = tek::button_2("", "", false);
/// ```
pub fn button_2 <'a> (key: impl Draw<Tui>, label: impl Draw<Tui>, hide: bool)
-> impl Draw<Tui>
{
pub fn button_2 <'a> (
key: impl Draw<Tui>, label: impl Draw<Tui>, hide: bool
) -> impl Draw<Tui> {
let c1 = tui_orange();
let c2 = tui_g(0);
let c3 = tui_g(96);
@ -1420,10 +1391,7 @@ pub fn button_2 <'a> (key: impl Draw<Tui>, label: impl Draw<Tui>, hide: bool)
/// let _ = tek::button_3("", "", "", false);
/// ```
pub fn button_3 <'a> (
key: impl Draw<Tui>,
label: impl Draw<Tui>,
value: impl Draw<Tui>,
editing: bool,
key: impl Draw<Tui>, label: impl Draw<Tui>, value: impl Draw<Tui>, editing: bool,
) -> impl Draw<Tui> {
let c1 = tui_orange();
let c2 = tui_g(0);
@ -1431,11 +1399,9 @@ pub fn button_3 <'a> (
let c4 = tui_g(255);
let c5 = tui_g(128);
bold(true, bar(Split::East, 3u16,
fg_bg(c1, c2,
bar(Split::East, 1u16, fg(c2, "▐"),
fg_bg(c1, c2, bar(Split::East, 1u16, fg(c2, "▐"),
bar(Split::East, 1u16, key, fg(if editing { c5 } else { c3 }, "▐")))),
east(
when(!editing, east(fg_bg(c4, c3, label), fg_bg(c5, 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, "▌"), ))))
}
@ -1615,29 +1581,6 @@ pub trait InteriorMutable<T>: Gettable<T> {
}
}
//pub fn per_track <'a, T: Draw<'_, Tui> + 'a, U: TracksSizes<'a>> (
//tracks: impl Fn() -> U + Send + Sync + 'a,
//callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
//) -> impl Draw<'_, Tui> + 'a {
//per_track_top(tracks, move|index, track|callback(index, track).full_h().align_y())
//}
//pub fn per_track_top <'a, T: Draw<'_, Tui> + 'a, U: TracksSizes<'a>> (
//tracks: impl Fn() -> U + Send + Sync + 'a,
//callback: impl Fn(usize, &'a Track)->T + Send + Sync + 'a
//) -> impl Draw<'_, Tui> + '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())
//}
//fn tui (&self) -> impl Draw<Tui> {
//iter_south_fixed(1, ||self.tui_entries(), |entry, _index|entry.origin_w().full_w())
//}
//impl<'a> Iterator for EntriesIterator<'a, Tui> {
//type Item = impl Draw<Tui>;
//fn next (&mut self) -> Option<Self::Item> {