From 057d09cfdfb3db64c7aaa36892687e3cbc66408d Mon Sep 17 00:00:00 2001 From: i do not exist Date: Thu, 24 Sep 2026 19:11:04 +0300 Subject: [PATCH] wip: axis bindings --- src/midi_edit.rs | 9 ++-- src/tek.edn | 133 +++++++++++++++++++++++++++-------------------- src/tek.rs | 2 +- src/tek_bind.rs | 62 ++++++++++++++-------- src/tek_conf.rs | 11 ++-- src/tek_ctrl.rs | 2 + src/tek_mode.rs | 21 ++++++-- src/tek_view.rs | 58 ++++++++++++++++++++- tengri | 2 +- 9 files changed, 205 insertions(+), 95 deletions(-) diff --git a/src/midi_edit.rs b/src/midi_edit.rs index 49e19cce..cfc362e8 100644 --- a/src/midi_edit.rs +++ b/src/midi_edit.rs @@ -21,14 +21,11 @@ pub trait EditorModel: HasEditor { /// use std::sync::Arc; /// use parking_lot::RwLock; /// use tek::{MidiClip, MidiEditor, PianoHorizontal}; -/// let clip = MidiClip::stop_all(); /// let mode = PianoHorizontal::default(); -/// let mut editor = MidiEditor { mode, size: Default::default() }; -/// +/// let editor = MidiEditor::new(); +/// editor.mode.clip.set(Some(MidiClip::stop_all())); /// let _ = editor.put_note(true); /// let _ = editor.put_note(false); -/// let _ = editor.clip_status(); -/// let _ = editor.edit_status(); /// ``` pub struct MidiEditor { /// View mode and state of editor @@ -74,7 +71,7 @@ impl MidiEditor { } /// Put note at current position - pub fn put_note (&mut self, advance: bool) { + pub fn put_note (&self, advance: bool) { let mut redraw = false; if let Some(clip) = &*self.mode.clip.read() { let note_start = self.get_time_pos(); diff --git a/src/tek.edn b/src/tek.edn index ed05b994..83743a9f 100644 --- a/src/tek.edn +++ b/src/tek.edn @@ -1,45 +1,73 @@ -(mode Menu (name Main Menu) (info Welcome to Tek!) (keys Y Confirm) +(axis X @left @right ) +(axis Y @up @down ) +(axis Z @minus @equal ) +(axis I @comma @period ) +(axis W @openbracket @closebracket) +(axis XFine @shift/left @shift/right ) +(axis YFine @shift/up @shift/down ) +(axis ZFine @underscore @plus ) +(axis IFine @lt @gt ) +(axis WFine @openbrace @closebrace ) + +(mode Menu + (name Main Menu) + (info Welcome to Tek!) + (axis Y Index) + (bind Confirm) (view (bar/s 2 Transport (bar/n 2 StatusBar (align/c (bar/s 2 (align/x Logo) Menu)))))) (mode Help - (view (bg (g 32) (fg (g 64) (fill/xy - (bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Nobody helps! )))))))))) + (axis Y Index) + (axis P Page) + (view (bg (g 32) (fg (g 64) (fill/xy (bg (g 48) (fg (g 224) + (align/c (bar/s 2 (expand/wh 2 2 (text Nobody helps! )) Config))))))))) (mode Quit - (keys (@y Quit)) - (view (bg (g 32) (fg (g 64) (fill/xy - (bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Are you sure? )))))))))) + (bind (@n leave) (@y quit)) + (view (bg (g 32) (fg (g 64) (fill/xy (bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Are you sure? )))))))))) (mode Save + (axis X Cursor) + (axis Y Index) (view (bg (g 32) (fg (g 64) (fill/xy (bg (g 48) (fg (g 224) (align/c (bar/s 1 (expand/wh 2 2 (text Save to: )) (text )))))))))) +(mode History + (axis Y Index) + (view (bg (g 32) (fg (g 64) (fill/xy + (bg (g 48) (fg (g 224) (align/c (bar/s 1 + (expand/wh 2 2 (text Undo/redo history )) + HistoryList))))))))) + (mode Load + (axis X Cursor) + (axis Y Index) (view (bg (g 32) (fg (g 64) (fill/xy (bg (g 48) (fg (g 224) (align/c (bar/s 1 (expand/wh 2 2 (text Load from: )) (text )))))))))) -(mode History - (view (bg (g 32) (fg (g 64) (fill/xy - (bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Undo/redo history )))))))))) - (mode Rename + (axis X Cursor) + (axis Y Index) (view (bg (g 32) (fg (g 64) (fill/xy (bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Rename item )))))))))) (mode Options + (axis Y Index) (view (bg (g 32) (fg (g 64) (fill/xy (bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Options )))))))))) (mode Transport (name Transport) (info JACK transport controller.) - (keys Clock Global) + (bind Clock Global) (view Transport)) (mode Arranger (name Arranger) (info Launch grid.) - (keys Global Clock Tracks Scenes Clip Launch Color History) + (bind Global Clock Tracks Scenes Clip Launch Color History) + (axis X Track) + (axis Y Clip) (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) @@ -50,19 +78,24 @@ (bar/s 2 TracksNamesCells TracksInputsCells)))))) (bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips)))))) -(mode Edit - (keys X Y)) +(mode Edit (info MIDI editor.) + (axis X Time) + (axis Y Pitch)) (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 StatusBar) (fill/xy (bsp/a (fill/xy (align/e Pool)) Editor)))))) + (bind Global Clock I IFine Y Page EditorView EditorAdd EditorDel) + (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 StatusBar) (fill/xy SampleGrid))))) + (bind SamplerDirs SamplerRec SamplerPlay) + (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) + (bind Global Clock Sampler I IFine Y Page EditorView EditorAdd EditorDel) (view (bsp/w MetersOut (bsp/e MetersIn (bsp/w GrooveMeta GrooveEditor))))) (view Logo (bg (g 255) (pad/xy 1 0 (bg (g 0) (fg (g 255) (text tek! 0.4.0 )))))) @@ -78,7 +111,7 @@ (bar/e 24 (bg (g 42) (full/x (pad/x 1 (bar/s 1 (text Mode) ModeList)))) (bg (g 34) (full/x (pad/x 1 (bar/s 1 (text History) HistoryCount))))))) -(keys Global (@escape leave) +(bind Global (@escape leave) (@f1 (enter Help)) (@f2 (enter Rename)) (@f3 (project new)) @@ -89,43 +122,33 @@ (@f10 (enter Quit)) (@f12 (enter Devtools))) -(keys Confirm (@enter confirm)) -(keys Page (@pgup page/up) (@pgdn page/down)) -(keys Delete (@delete delete) (@backspace delete/back)) -(keys History (@u (undo 1)) (@r (redo 1))) -(keys X (@left (axis (dec X))) (@right (axis (inc X)))) -(keys Y (@up (axis (dec Y))) (@down (axis (inc Y)))) -(keys Z (@minus (axis (dec Z))) (@equal (axis (inc Z)))) -(keys I (@comma (axis (dec I))) (@period (axis (inc Z)))) -(keys W (@openbracket (axis (dec W))) (@closebracket (axis (inc W)))) -(keys XFine (@shift/left (axis (dec XFine))) (@shift/right (axis (inc XFine)))) -(keys YFine (@shift/up (axis (dec YFine))) (@shift/down (axis (inc YFine)))) -(keys ZFine (@underscore (axis (dec ZFine))) (@plus (axis (inc ZFine)))) -(keys IFine (@lt (axis (dec IFine))) (@gt (axis (inc ZFine)))) -(keys WFine (@openbrace (axis (dec WFine))) (@closebrace (axis (inc WFine)))) +(bind Confirm (@enter confirm)) +(bind Page (@pgup page/up) (@pgdn page/down)) +(bind Delete (@delete delete) (@backspace delete/back)) +(bind History (@u (undo 1)) (@r (redo 1))) -(keys Clock (@space (clock/toggle 0)) (@shift/space (clock/toggle 0))) -(keys Scenes (@shift/S (scenes add)) (@s (scenes select)) (@up (scenes prev)) (@down (scenes next))) -(keys Tracks (@shift/T (tracks add)) (@t (tracks select)) (@left (tracks prev)) (@right (tracks next))) -(keys Clip (@l (toggle :loop)) (@tab (clip upsert) (edit toggle))) -(keys Color (@c (color))) -(keys Launch (@q (launch))) +(bind Clock (@space (clock/toggle 0)) (@shift/space (clock/toggle 0))) +(bind Scenes (@shift/S (scenes add)) (@s (scenes select))) +(bind Tracks (@shift/T (tracks add)) (@t (tracks select))) +(bind Clip (@l (toggle :loop)) (@tab (clip upsert) (edit toggle))) +(bind Color (@c (color))) +(bind Launch (@q (launch))) -(keys EditorView (see X XFine Z ZFine) (@z toggle :lock)) -(keys EditorAdd (@a editor/append :true) (@enter editor/append :false)) -(keys EditorDel (@del editor/delete/note) (@shift/del editor/delete/note)) +(bind EditorView (see X XFine Z ZFine) (@z toggle :lock)) +(bind EditorAdd (@a editor/append :true) (@enter editor/append :false)) +(bind EditorDel (@del editor/delete/note) (@shift/del editor/delete/note)) -(keys Sequencer (see Color Launch) (@shift/I input/add) (@shift/O output/add)) +(bind Sequencer (see Color Launch) (@shift/I input/add) (@shift/O output/add)) -(keys SamplerRec (@r sampler/record/toggle SelectedSample) (@shift/R sampler/record/back)) -(keys SamplerPlay (@p sampler/play/sample SelectedSample) (@P sampler/stop/sample SelectedSample)) -(keys SamplerImpEx (@shift/f6 dialog :export/sample) (@shift/f9 dialog Import/sample)) -(keys SamplerDirs (@up sampler/select :sample/above) (@down sampler/select :sample/below) (@left sampler/select :sample/to/left) (@right sampler/select :sample/to/right)) +(bind SamplerRec (@r sampler/record/toggle SelectedSample) (@shift/R sampler/record/back)) +(bind SamplerPlay (@p sampler/play/sample SelectedSample) (@P sampler/stop/sample SelectedSample)) +(bind SamplerImpEx (@shift/f6 dialog :export/sample) (@shift/f9 dialog Import/sample)) +(bind SamplerDirs (@up sampler/select :sample/above) (@down sampler/select :sample/below) (@left sampler/select :sample/to/left) (@right sampler/select :sample/to/right)) -(keys Track (see Color Launch Z ZFine Delete) (@r toggle :rec) (@m toggle :mon) (@p toggle :play) (@P toggle :solo)) -(keys Scene (see Color Launch Z ZFine Delete)) -(keys Input (see X Delete) (:char input)) -(keys List (see Y Confirm)) -(keys Length (see X Y Confirm)) -(keys Browse (see List Input)) -(keys Pool (see Y W ZFine Color Delete) (@n rename/begin) (@t length/begin) (@m import/begin) (@x export/begin) (@shift/A clip/add :after :newClip) (@shift/D clip/add :after :clonedClip)) +(bind Track (see Color Launch Z ZFine Delete) (@r toggle :rec) (@m toggle :mon) (@p toggle :play) (@P toggle :solo)) +(bind Scene (see Color Launch Z ZFine Delete)) +(bind Input (see X Delete) (:char input)) +(bind List (see Y Confirm)) +(bind Length (see X Y Confirm)) +(bind Browse (see List Input)) +(bind Pool (see Y W ZFine Color Delete) (@n rename/begin) (@t length/begin) (@m import/begin) (@x export/begin) (@shift/A clip/add :after :newClip) (@shift/D clip/add :after :clonedClip)) diff --git a/src/tek.rs b/src/tek.rs index 1e32d4b8..d6abec23 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -95,7 +95,7 @@ fn run_new_plain (config: Config) -> Usually<()> { /// Total application state. /// /// ``` -/// use tek::{HasTracks, HasScenes, TracksView, ScenesView}; +/// use tek::{HasTracks, HasScenes, TracksView, ScenesView, ScenesControl}; /// let mut app = tek::App::default(); /// let _ = app.scenes_add_one(None, None).unwrap(); /// let _ = app.update_clock(); diff --git a/src/tek_bind.rs b/src/tek_bind.rs index 76536114..b6fe4159 100644 --- a/src/tek_bind.rs +++ b/src/tek_bind.rs @@ -2,16 +2,20 @@ use crate::*; /// Collection of input bindings. #[derive(Default, Clone, Debug)] -pub struct Binds(pub Arc, - Arc>> ->>>); +pub struct Binds(pub Arc, Arc>>>>>); impl Binds { - pub fn add <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> { + pub fn add_keys <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> { let name = expr.head()?.ok_or("bind: missing name")?; let body = expr.tail()?.unwrap_or(""); - self.0.try_write().unwrap().insert(name.into(), Bind::load(body)?.into()); + self.0.try_write().unwrap().insert(name.into(), Bind::load_keys(body)?.into()); + Ok(()) + } + + pub fn add_axis <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> { + let name = expr.head()?.ok_or("axis: missing name")?; + let body = expr.tail()?.unwrap_or(""); + self.0.try_write().unwrap().insert(name.into(), Bind::load_axis(name, body)?.into()); Ok(()) } @@ -36,11 +40,10 @@ impl Binds { /// /// ``` /// use ::{std::sync::Arc, tek::{Bind, tengri::TuiEvent}}; -/// let bind = Bind::>::load(&stringify!( -/// (@x (nop)) -/// (@y (nop) (nop)))).unwrap(); +/// let src = stringify!((@x (nop)) (@y (nop) (nop))); +/// let bind = Bind::>::load_keys(&src).unwrap(); /// assert_eq!(bind.query(&'x'.into()).map(|x|x.len()), Some(1)); -/// //assert_eq!(bind.query(&'y'.into()).map(|x|x.len()), Some(2)); +/// assert_eq!(bind.query(&'y'.into()).map(|x|x.len()), Some(2)); /// ``` #[derive(Debug)] pub struct Bind( @@ -64,14 +67,6 @@ pub struct Bind( pub source: Option>, } -/// Condition that must evaluate to true in order to enable an input layer. -/// -/// ``` -/// let condition = tek::Condition(std::sync::Arc::new(Box::new(||{true}))); -/// ``` -#[derive(Clone)] -pub struct Condition(pub Arcbool + Send + Sync>>); - /// Default is always empty map regardless if `E` and `C` implement [Default]. impl Default for Bind { fn default () -> Self { Self(Default::default()) } @@ -89,14 +84,28 @@ impl Default for Binding { } impl Bind> { - pub fn load (body: impl Language) -> Usually { + pub fn load_keys (body: impl Language) -> Usually { let mut bind: Bind> = Bind::new(); body.each((), |_, item: &str|if matches!(item.expr().head(), Ok(Some("see"))) { bind.add_ref(item) } else if let Ok(Some(_word)) = item.expr().head().word() { bind.add_def(item) } else { - return err!("Binds::add: unexpected: {item:?}") + return err!("Bind::load_keys: unexpected: {item:?}") + })?; + Ok(bind) + } + + pub fn load_axis (name: &str, body: impl Language) -> Usually { + let mut bind: Bind> = Bind::new(); + body.each(0, |index, key: &str|if index == 0 { + bind.add_def(&format!("({key} (axis (inc {name})))"))?; + Ok(1) + } else if index == 1 { + bind.add_def(&format!("({key} (axis (dec {name})))"))?; + Ok(2) + } else { + err!("top-level (axis) takes 2 keysyms: inc and dec") })?; Ok(bind) } @@ -129,7 +138,6 @@ impl Bind> { } impl Bind { - /// Create a new event map pub fn new () -> Self { Default::default() @@ -159,7 +167,17 @@ impl Bind { } } -impl_debug!(Condition |self, w| { write!(w, "*") }); +/// Condition that must evaluate to true in order to enable an input binding. +/// +/// ``` +/// let condition = tek::Condition(std::sync::Arc::new(Box::new(||{true}))); +/// ``` +#[derive(Clone)] +pub struct Condition(pub Arcbool + Send + Sync>>); + +impl_debug!(Condition |self, w| { + write!(w, "*") +}); //take!(DeviceCmd|state: Project, iter|state.selected_device().as_ref() //.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten())); diff --git a/src/tek_conf.rs b/src/tek_conf.rs index 0d1d5b19..467c9638 100644 --- a/src/tek_conf.rs +++ b/src/tek_conf.rs @@ -7,11 +7,11 @@ use notify_debouncer_full::notify::{RecursiveMode, PollWatcher, Config as Notify /// ``` /// use ::{std::sync::Arc, tek::{Config, Modes, Mode}}; /// let config: Config = Default::default(); -/// let mode = stringify!(mode :menu (name Menu) (info Mode selector.) (keys Y Confirm) +/// let mode = stringify!(mode Menu (name Menu) (info Mode selector.) (keys Y Confirm) /// (view (bg (g 0) (bsp/s PortsOut (bsp/n PortsIn /// (bg (g 30) (bsp/s (exact/y 7 Logo) (fill Dialog)))))))); /// Modes::add(&config.modes, mode).unwrap(); -/// let mode: Arc = config.get_mode(":menu").unwrap(); +/// let mode: Arc = config.get_mode("Menu").unwrap(); /// ``` #[derive(Default, Debug)] pub struct Config { @@ -56,9 +56,10 @@ impl Config { pub fn load_item , L: Language> (config: C, src: L) -> Usually { if let Some(expr) = src.expr()? { match expr.head()? { - Some("mode") => Modes::add(&config.as_ref().modes, expr.tail()), - Some("keys") => config.as_ref().binds.add(expr.tail()), - Some("view") => Views::add(&config.as_ref().views, expr.tail()), + Some("mode") => config.as_ref().modes.add(expr.tail()), + Some("view") => config.as_ref().views.add(expr.tail()), + Some("bind") => config.as_ref().binds.add_keys(expr.tail()), + Some("axis") => config.as_ref().binds.add_axis(expr.tail()), _ => return Err(format!("Config::load: expected view/keys/mode expr, got: {src:?}").into()) }?; Ok(config) diff --git a/src/tek_ctrl.rs b/src/tek_ctrl.rs index 9a527f85..d31a84cf 100644 --- a/src/tek_ctrl.rs +++ b/src/tek_ctrl.rs @@ -738,6 +738,7 @@ impl BrowseControl for T where T: #[tek_proc::commands(AxisCmd)] impl App { /// Increment the given data axis. #[command(Inc = "inc")] pub fn inc (&mut self, axis: ControlAxis) -> Perhaps { + panic!("inc {axis:?}"); Ok(match (&self.dialog, axis) { (Dialog::None, _) => todo!(), (Dialog::Menu(_, _), ControlAxis::Y) => { @@ -749,6 +750,7 @@ impl BrowseControl for T where T: } /// Decrement the given data axis. #[command(Dec = "dec")] pub fn dec (&mut self, axis: ControlAxis) -> Perhaps { + panic!("dec {axis:?}"); Ok(match (&self.dialog, axis) { (Dialog::None, _) => None, (Dialog::Menu(_, _), ControlAxis::Y) => { diff --git a/src/tek_mode.rs b/src/tek_mode.rs index 85cdd27c..68244c9b 100644 --- a/src/tek_mode.rs +++ b/src/tek_mode.rs @@ -58,7 +58,6 @@ pub struct Mode { } impl Mode { - /// Add a definition to the mode. /// /// Supported definitions: @@ -86,12 +85,29 @@ impl Mode { modes.0.write().insert(name.into(), Arc::new(submode)); mode }, - "keys" => { + "bind" => { tail.each(mode, |mut mode: T, expr: &str|{ mode.as_mut().keys.push(expr.trim().into()); Ok(mode) })? }, + "axis" => { + let mut ctrl: Option> = None; + let mut data: Option> = None; + tail.each(0, |index: usize, src: &str|if index == 0 { + ctrl = Some(src.into()); + Ok(1) + } else if index == 1 { + data = Some(src.into()); + Ok(2) + } else { + err!("(mode (axis)) takes 2 keysyms, control and data") + })?; + // TODO: get inc/dec keys from axis? + //mode.as_mut().keys.push(format!("({inc} (inc ({axis})))").into()); + //mode.as_mut().keys.push(format!("({dec} (dec ({axis})))").into()); + mode + }, "name" => { mode.as_mut().name.push(tail.into()); mode }, "info" => { mode.as_mut().info.push(tail.into()); mode }, "view" => { mode.as_mut().view.push(View::new(tail)?.into()); mode }, @@ -104,7 +120,6 @@ impl Mode { return Err(format!("Mode::add: unexpected: {dsl:?}").into()); }) } - } impl AsMut for Mode { diff --git a/src/tek_view.rs b/src/tek_view.rs index 278801ca..b5b59835 100644 --- a/src/tek_view.rs +++ b/src/tek_view.rs @@ -86,8 +86,8 @@ pub struct Views(pub Arc (views: &Views, expr: impl Language) -> UsuallyRef<'a, ()> { - views.0.write().insert( + pub fn add <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> { + self.0.write().insert( expr.head()?.ok_or("view: missing name")?.into(), View::new(expr.tail()?.ok_or("view: missing body")?)?.into() ); @@ -373,6 +373,7 @@ impl View { Some("Beat") => view!(), Some("Bpm") => view!(), Some("BrowseTitle") => view!(|app|view_browse_title(app)), + Some("Config") => view!(|app|view_config(app)), Some("Debug") => Box::new(move|_, to|format!("[{:?}]", to.area()).exact_h(1).draw(to)), Some("Device") => view!(|app|view_device(app)), Some("Menu") => view!(|app|view_menu(app)), @@ -381,6 +382,7 @@ impl View { Some("MetersOut") => view!(|___|bg(Rgb(30, 30, 30), "Output Meters".align_s().full_h())), Some("ModeList") => view!(|app|view_modes(app)), Some("HistoryCount") => view!(|app|app.history.len()), + Some("HistoryList") => view!(|app|view_history_list(app)), Some("ScenesClips") => view!(|app|view_scenes_clips(app)), Some("ScenesNames") => view!(|app|app.view_scenes_names()), Some("Sessions") => view!(|___|view_sessions()), @@ -426,6 +428,58 @@ pub fn view_menu (app: &App) -> impl Draw { } } +pub fn view_history_list (app: &App) -> impl Draw { + above( + Outer(true, Style::default().fg(Color::Rgb(0, 192, 0))), + draw(|to: &mut Tui|{ + let area = to.area(); + let XYWH(x0, mut y0, w, h) = area; + for (done, undo) in app.history.iter().rev() { + to.clip(XYWH(x0 + 1, y0, w, 1), &|to|format!("{done:?}").draw(to))?; + y0 += 1; + } + Ok(Some(area)) + }) + ) +} + +pub fn view_config (app: &App) -> impl Draw { + above( + Outer(true, Style::default().fg(Color::Rgb(0, 192, 0))), + draw(|to: &mut Tui|{ + let area = to.area(); + let XYWH(x0, mut y0, w, h) = area; + for key in app.modes.read().iter().rev() { + if let Some(mode) = app.config.modes.get(key) { + to.clip(XYWH(x0 + 1, y0, w, 1), &|to|Split::East.bar(16, key, mode.info.get(0)).draw(to))?; + y0 += 1; + for bind in mode.keys.iter() { + to.clip(XYWH(x0 + 3, y0, w, 1), &|to|bind.draw(to))?; + y0 += 1; + if let Some(bind) = app.config.binds.find(bind) { + for (key, binding) in bind.0.iter() { + to.clip(XYWH(x0 + 5, y0, 40, 1), + &|to|Split::East.bar(20, format!("{:?}", key.0), "").draw(to))?; + y0 += 1; + } + } + } + y0 += 1; + } + } + //for (index, (key, mode)) in app.config.modes.0.read().iter().enumerate() { + //to.clip(XYWH(x0, y0 + index as u16, w, 1), &|to|Split::East.bar(16, + //key, mode.info.get(0), + //).draw(to))?; + //} + Ok(Some(area)) + }) + ) +} + +pub fn view_config_mode (mode: &Mode) -> impl Draw { +} + /// ``` /// let _ = tek::button_play_pause(true, true); /// let _ = tek::button_play_pause(true, false); diff --git a/tengri b/tengri index 1e8b1813..50c0ed1c 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit 1e8b18134d8ad234e5d0142d706f21f1366668d0 +Subproject commit 50c0ed1c66c9db97b83b95eb23a7b0bf00c5a760