mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-10-08 18:56:42 +02:00
wip: axis bindings
This commit is contained in:
parent
767f917302
commit
057d09cfdf
9 changed files with 205 additions and 95 deletions
|
|
@ -21,14 +21,11 @@ pub trait EditorModel: HasEditor {
|
||||||
/// use std::sync::Arc;
|
/// use std::sync::Arc;
|
||||||
/// use parking_lot::RwLock;
|
/// use parking_lot::RwLock;
|
||||||
/// use tek::{MidiClip, MidiEditor, PianoHorizontal};
|
/// use tek::{MidiClip, MidiEditor, PianoHorizontal};
|
||||||
/// let clip = MidiClip::stop_all();
|
|
||||||
/// let mode = PianoHorizontal::default();
|
/// 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(true);
|
||||||
/// let _ = editor.put_note(false);
|
/// let _ = editor.put_note(false);
|
||||||
/// let _ = editor.clip_status();
|
|
||||||
/// let _ = editor.edit_status();
|
|
||||||
/// ```
|
/// ```
|
||||||
pub struct MidiEditor {
|
pub struct MidiEditor {
|
||||||
/// View mode and state of editor
|
/// View mode and state of editor
|
||||||
|
|
@ -74,7 +71,7 @@ impl MidiEditor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Put note at current position
|
/// Put note at current position
|
||||||
pub fn put_note (&mut self, advance: bool) {
|
pub fn put_note (&self, advance: bool) {
|
||||||
let mut redraw = false;
|
let mut redraw = false;
|
||||||
if let Some(clip) = &*self.mode.clip.read() {
|
if let Some(clip) = &*self.mode.clip.read() {
|
||||||
let note_start = self.get_time_pos();
|
let note_start = self.get_time_pos();
|
||||||
|
|
|
||||||
133
src/tek.edn
133
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))))))
|
(view (bar/s 2 Transport (bar/n 2 StatusBar (align/c (bar/s 2 (align/x Logo) Menu))))))
|
||||||
|
|
||||||
(mode Help
|
(mode Help
|
||||||
(view (bg (g 32) (fg (g 64) (fill/xy
|
(axis Y Index)
|
||||||
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Nobody helps! ))))))))))
|
(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
|
(mode Quit
|
||||||
(keys (@y Quit))
|
(bind (@n leave) (@y quit))
|
||||||
(view (bg (g 32) (fg (g 64) (fill/xy
|
(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? ))))))))))
|
||||||
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Are you sure? ))))))))))
|
|
||||||
|
|
||||||
(mode Save
|
(mode Save
|
||||||
|
(axis X Cursor)
|
||||||
|
(axis Y Index)
|
||||||
(view (bg (g 32) (fg (g 64) (fill/xy
|
(view (bg (g 32) (fg (g 64) (fill/xy
|
||||||
(bg (g 48) (fg (g 224) (align/c (bar/s 1
|
(bg (g 48) (fg (g 224) (align/c (bar/s 1
|
||||||
(expand/wh 2 2 (text Save to: ))
|
(expand/wh 2 2 (text Save to: ))
|
||||||
(text <file browser here>))))))))))
|
(text <file browser here>))))))))))
|
||||||
|
|
||||||
|
(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
|
(mode Load
|
||||||
|
(axis X Cursor)
|
||||||
|
(axis Y Index)
|
||||||
(view (bg (g 32) (fg (g 64) (fill/xy
|
(view (bg (g 32) (fg (g 64) (fill/xy
|
||||||
(bg (g 48) (fg (g 224) (align/c (bar/s 1
|
(bg (g 48) (fg (g 224) (align/c (bar/s 1
|
||||||
(expand/wh 2 2 (text Load from: ))
|
(expand/wh 2 2 (text Load from: ))
|
||||||
(text <file browser here>))))))))))
|
(text <file browser here>))))))))))
|
||||||
|
|
||||||
(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
|
(mode Rename
|
||||||
|
(axis X Cursor)
|
||||||
|
(axis Y Index)
|
||||||
(view (bg (g 32) (fg (g 64) (fill/xy
|
(view (bg (g 32) (fg (g 64) (fill/xy
|
||||||
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Rename item ))))))))))
|
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Rename item ))))))))))
|
||||||
|
|
||||||
(mode Options
|
(mode Options
|
||||||
|
(axis Y Index)
|
||||||
(view (bg (g 32) (fg (g 64) (fill/xy
|
(view (bg (g 32) (fg (g 64) (fill/xy
|
||||||
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Options ))))))))))
|
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Options ))))))))))
|
||||||
|
|
||||||
(mode Transport (name Transport) (info JACK transport controller.)
|
(mode Transport (name Transport) (info JACK transport controller.)
|
||||||
(keys Clock Global)
|
(bind Clock Global)
|
||||||
(view Transport))
|
(view Transport))
|
||||||
|
|
||||||
(mode Arranger (name Arranger) (info Launch grid.)
|
(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)
|
(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/w 20 (bar/s 2 (bar/w 4 TracksOutputsAdd TracksOutputsCount)
|
||||||
(bar/s 2 (bar/w 4 TracksDevicesAdd TracksDevicesCount)
|
(bar/s 2 (bar/w 4 TracksDevicesAdd TracksDevicesCount)
|
||||||
|
|
@ -50,19 +78,24 @@
|
||||||
(bar/s 2 TracksNamesCells TracksInputsCells))))))
|
(bar/s 2 TracksNamesCells TracksInputsCells))))))
|
||||||
(bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips))))))
|
(bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips))))))
|
||||||
|
|
||||||
(mode Edit
|
(mode Edit (info MIDI editor.)
|
||||||
(keys X Y))
|
(axis X Time)
|
||||||
|
(axis Y Pitch))
|
||||||
|
|
||||||
(mode Sequencer (info MIDI sequencer.)
|
(mode Sequencer (info MIDI sequencer.)
|
||||||
(keys Global Clock I IFine Y Page EditorView EditorAdd EditorDel)
|
(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))))))
|
(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.)
|
(mode Sampler (info Sample player.)
|
||||||
(keys SamplerDirs SamplerRec SamplerPlay)
|
(bind SamplerDirs SamplerRec SamplerPlay)
|
||||||
(view (bsp/s (exact/h 1 Transport) (bsp/n (exact/h 1 StatusBar) (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.)
|
(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 (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 ))))))
|
(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))))
|
(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)))))))
|
(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))
|
(@f1 (enter Help))
|
||||||
(@f2 (enter Rename))
|
(@f2 (enter Rename))
|
||||||
(@f3 (project new))
|
(@f3 (project new))
|
||||||
|
|
@ -89,43 +122,33 @@
|
||||||
(@f10 (enter Quit))
|
(@f10 (enter Quit))
|
||||||
(@f12 (enter Devtools)))
|
(@f12 (enter Devtools)))
|
||||||
|
|
||||||
(keys Confirm (@enter confirm))
|
(bind Confirm (@enter confirm))
|
||||||
(keys Page (@pgup page/up) (@pgdn page/down))
|
(bind Page (@pgup page/up) (@pgdn page/down))
|
||||||
(keys Delete (@delete delete) (@backspace delete/back))
|
(bind Delete (@delete delete) (@backspace delete/back))
|
||||||
(keys History (@u (undo 1)) (@r (redo 1)))
|
(bind 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))))
|
|
||||||
|
|
||||||
(keys Clock (@space (clock/toggle 0)) (@shift/space (clock/toggle 0)))
|
(bind 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)))
|
(bind Scenes (@shift/S (scenes add)) (@s (scenes select)))
|
||||||
(keys Tracks (@shift/T (tracks add)) (@t (tracks select)) (@left (tracks prev)) (@right (tracks next)))
|
(bind Tracks (@shift/T (tracks add)) (@t (tracks select)))
|
||||||
(keys Clip (@l (toggle :loop)) (@tab (clip upsert) (edit toggle)))
|
(bind Clip (@l (toggle :loop)) (@tab (clip upsert) (edit toggle)))
|
||||||
(keys Color (@c (color)))
|
(bind Color (@c (color)))
|
||||||
(keys Launch (@q (launch)))
|
(bind Launch (@q (launch)))
|
||||||
|
|
||||||
(keys EditorView (see X XFine Z ZFine) (@z toggle :lock))
|
(bind EditorView (see X XFine Z ZFine) (@z toggle :lock))
|
||||||
(keys EditorAdd (@a editor/append :true) (@enter editor/append :false))
|
(bind EditorAdd (@a editor/append :true) (@enter editor/append :false))
|
||||||
(keys EditorDel (@del editor/delete/note) (@shift/del editor/delete/note))
|
(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))
|
(bind SamplerRec (@r sampler/record/toggle SelectedSample) (@shift/R sampler/record/back))
|
||||||
(keys SamplerPlay (@p sampler/play/sample SelectedSample) (@P sampler/stop/sample SelectedSample))
|
(bind SamplerPlay (@p sampler/play/sample SelectedSample) (@P sampler/stop/sample SelectedSample))
|
||||||
(keys SamplerImpEx (@shift/f6 dialog :export/sample) (@shift/f9 dialog Import/sample))
|
(bind 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 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))
|
(bind 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))
|
(bind Scene (see Color Launch Z ZFine Delete))
|
||||||
(keys Input (see X Delete) (:char input))
|
(bind Input (see X Delete) (:char input))
|
||||||
(keys List (see Y Confirm))
|
(bind List (see Y Confirm))
|
||||||
(keys Length (see X Y Confirm))
|
(bind Length (see X Y Confirm))
|
||||||
(keys Browse (see List Input))
|
(bind 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 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))
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ fn run_new_plain (config: Config) -> Usually<()> {
|
||||||
/// Total application state.
|
/// Total application state.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tek::{HasTracks, HasScenes, TracksView, ScenesView};
|
/// use tek::{HasTracks, HasScenes, TracksView, ScenesView, ScenesControl};
|
||||||
/// let mut app = tek::App::default();
|
/// let mut app = tek::App::default();
|
||||||
/// let _ = app.scenes_add_one(None, None).unwrap();
|
/// let _ = app.scenes_add_one(None, None).unwrap();
|
||||||
/// let _ = app.update_clock();
|
/// let _ = app.update_clock();
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,20 @@ use crate::*;
|
||||||
|
|
||||||
/// Collection of input bindings.
|
/// Collection of input bindings.
|
||||||
#[derive(Default, Clone, Debug)]
|
#[derive(Default, Clone, Debug)]
|
||||||
pub struct Binds(pub Arc<RwLock<BTreeMap<
|
pub struct Binds(pub Arc<RwLock<BTreeMap<Arc<str>, Arc<Bind<TuiEvent, Arc<str>>>>>>);
|
||||||
Arc<str>,
|
|
||||||
Arc<Bind<TuiEvent, Arc<str>>>
|
|
||||||
>>>);
|
|
||||||
|
|
||||||
impl Binds {
|
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 name = expr.head()?.ok_or("bind: missing name")?;
|
||||||
let body = expr.tail()?.unwrap_or("");
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,11 +40,10 @@ impl Binds {
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use ::{std::sync::Arc, tek::{Bind, tengri::TuiEvent}};
|
/// use ::{std::sync::Arc, tek::{Bind, tengri::TuiEvent}};
|
||||||
/// let bind = Bind::<TuiEvent, Arc<str>>::load(&stringify!(
|
/// let src = stringify!((@x (nop)) (@y (nop) (nop)));
|
||||||
/// (@x (nop))
|
/// let bind = Bind::<TuiEvent, Arc<str>>::load_keys(&src).unwrap();
|
||||||
/// (@y (nop) (nop)))).unwrap();
|
|
||||||
/// assert_eq!(bind.query(&'x'.into()).map(|x|x.len()), Some(1));
|
/// 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)]
|
#[derive(Debug)]
|
||||||
pub struct Bind<E, C>(
|
pub struct Bind<E, C>(
|
||||||
|
|
@ -64,14 +67,6 @@ pub struct Bind<E, C>(
|
||||||
pub source: Option<Arc<PathBuf>>,
|
pub source: Option<Arc<PathBuf>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 Arc<Box<dyn Fn()->bool + Send + Sync>>);
|
|
||||||
|
|
||||||
/// Default is always empty map regardless if `E` and `C` implement [Default].
|
/// Default is always empty map regardless if `E` and `C` implement [Default].
|
||||||
impl<E, C> Default for Bind<E, C> {
|
impl<E, C> Default for Bind<E, C> {
|
||||||
fn default () -> Self { Self(Default::default()) }
|
fn default () -> Self { Self(Default::default()) }
|
||||||
|
|
@ -89,14 +84,28 @@ impl<C: Default> Default for Binding<C> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bind<TuiEvent, Arc<str>> {
|
impl Bind<TuiEvent, Arc<str>> {
|
||||||
pub fn load (body: impl Language) -> Usually<Self> {
|
pub fn load_keys (body: impl Language) -> Usually<Self> {
|
||||||
let mut bind: Bind<TuiEvent, Arc<str>> = Bind::new();
|
let mut bind: Bind<TuiEvent, Arc<str>> = Bind::new();
|
||||||
body.each((), |_, item: &str|if matches!(item.expr().head(), Ok(Some("see"))) {
|
body.each((), |_, item: &str|if matches!(item.expr().head(), Ok(Some("see"))) {
|
||||||
bind.add_ref(item)
|
bind.add_ref(item)
|
||||||
} else if let Ok(Some(_word)) = item.expr().head().word() {
|
} else if let Ok(Some(_word)) = item.expr().head().word() {
|
||||||
bind.add_def(item)
|
bind.add_def(item)
|
||||||
} else {
|
} 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<Self> {
|
||||||
|
let mut bind: Bind<TuiEvent, Arc<str>> = 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)
|
Ok(bind)
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +138,6 @@ impl Bind<TuiEvent, Arc<str>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Clone + Ord, C> Bind<E, C> {
|
impl<E: Clone + Ord, C> Bind<E, C> {
|
||||||
|
|
||||||
/// Create a new event map
|
/// Create a new event map
|
||||||
pub fn new () -> Self {
|
pub fn new () -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
|
|
@ -159,7 +167,17 @@ impl<E: Clone + Ord, C> Bind<E, C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 Arc<Box<dyn Fn()->bool + Send + Sync>>);
|
||||||
|
|
||||||
|
impl_debug!(Condition |self, w| {
|
||||||
|
write!(w, "*")
|
||||||
|
});
|
||||||
|
|
||||||
//take!(DeviceCmd|state: Project, iter|state.selected_device().as_ref()
|
//take!(DeviceCmd|state: Project, iter|state.selected_device().as_ref()
|
||||||
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
//.map(|t|Take::take(t, iter)).transpose().map(|x|x.flatten()));
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,11 @@ use notify_debouncer_full::notify::{RecursiveMode, PollWatcher, Config as Notify
|
||||||
/// ```
|
/// ```
|
||||||
/// use ::{std::sync::Arc, tek::{Config, Modes, Mode}};
|
/// use ::{std::sync::Arc, tek::{Config, Modes, Mode}};
|
||||||
/// let config: Config = Default::default();
|
/// 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
|
/// (view (bg (g 0) (bsp/s PortsOut (bsp/n PortsIn
|
||||||
/// (bg (g 30) (bsp/s (exact/y 7 Logo) (fill Dialog))))))));
|
/// (bg (g 30) (bsp/s (exact/y 7 Logo) (fill Dialog))))))));
|
||||||
/// Modes::add(&config.modes, mode).unwrap();
|
/// Modes::add(&config.modes, mode).unwrap();
|
||||||
/// let mode: Arc<Mode> = config.get_mode(":menu").unwrap();
|
/// let mode: Arc<Mode> = config.get_mode("Menu").unwrap();
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
|
@ -56,9 +56,10 @@ impl Config {
|
||||||
pub fn load_item <C: AsRef<Config>, L: Language> (config: C, src: L) -> Usually<C> {
|
pub fn load_item <C: AsRef<Config>, L: Language> (config: C, src: L) -> Usually<C> {
|
||||||
if let Some(expr) = src.expr()? {
|
if let Some(expr) = src.expr()? {
|
||||||
match expr.head()? {
|
match expr.head()? {
|
||||||
Some("mode") => Modes::add(&config.as_ref().modes, expr.tail()),
|
Some("mode") => config.as_ref().modes.add(expr.tail()),
|
||||||
Some("keys") => config.as_ref().binds.add(expr.tail()),
|
Some("view") => config.as_ref().views.add(expr.tail()),
|
||||||
Some("view") => Views::add(&config.as_ref().views, 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())
|
_ => return Err(format!("Config::load: expected view/keys/mode expr, got: {src:?}").into())
|
||||||
}?;
|
}?;
|
||||||
Ok(config)
|
Ok(config)
|
||||||
|
|
|
||||||
|
|
@ -738,6 +738,7 @@ impl<T> BrowseControl for T where T:
|
||||||
#[tek_proc::commands(AxisCmd)] impl App {
|
#[tek_proc::commands(AxisCmd)] impl App {
|
||||||
/// Increment the given data axis.
|
/// Increment the given data axis.
|
||||||
#[command(Inc = "inc")] pub fn inc (&mut self, axis: ControlAxis) -> Perhaps<AxisCmd> {
|
#[command(Inc = "inc")] pub fn inc (&mut self, axis: ControlAxis) -> Perhaps<AxisCmd> {
|
||||||
|
panic!("inc {axis:?}");
|
||||||
Ok(match (&self.dialog, axis) {
|
Ok(match (&self.dialog, axis) {
|
||||||
(Dialog::None, _) => todo!(),
|
(Dialog::None, _) => todo!(),
|
||||||
(Dialog::Menu(_, _), ControlAxis::Y) => {
|
(Dialog::Menu(_, _), ControlAxis::Y) => {
|
||||||
|
|
@ -749,6 +750,7 @@ impl<T> BrowseControl for T where T:
|
||||||
}
|
}
|
||||||
/// Decrement the given data axis.
|
/// Decrement the given data axis.
|
||||||
#[command(Dec = "dec")] pub fn dec (&mut self, axis: ControlAxis) -> Perhaps<AxisCmd> {
|
#[command(Dec = "dec")] pub fn dec (&mut self, axis: ControlAxis) -> Perhaps<AxisCmd> {
|
||||||
|
panic!("dec {axis:?}");
|
||||||
Ok(match (&self.dialog, axis) {
|
Ok(match (&self.dialog, axis) {
|
||||||
(Dialog::None, _) => None,
|
(Dialog::None, _) => None,
|
||||||
(Dialog::Menu(_, _), ControlAxis::Y) => {
|
(Dialog::Menu(_, _), ControlAxis::Y) => {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@ pub struct Mode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mode {
|
impl Mode {
|
||||||
|
|
||||||
/// Add a definition to the mode.
|
/// Add a definition to the mode.
|
||||||
///
|
///
|
||||||
/// Supported definitions:
|
/// Supported definitions:
|
||||||
|
|
@ -86,12 +85,29 @@ impl Mode {
|
||||||
modes.0.write().insert(name.into(), Arc::new(submode));
|
modes.0.write().insert(name.into(), Arc::new(submode));
|
||||||
mode
|
mode
|
||||||
},
|
},
|
||||||
"keys" => {
|
"bind" => {
|
||||||
tail.each(mode, |mut mode: T, expr: &str|{
|
tail.each(mode, |mut mode: T, expr: &str|{
|
||||||
mode.as_mut().keys.push(expr.trim().into());
|
mode.as_mut().keys.push(expr.trim().into());
|
||||||
Ok(mode)
|
Ok(mode)
|
||||||
})?
|
})?
|
||||||
},
|
},
|
||||||
|
"axis" => {
|
||||||
|
let mut ctrl: Option<Arc<str>> = None;
|
||||||
|
let mut data: Option<Arc<str>> = 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 },
|
"name" => { mode.as_mut().name.push(tail.into()); mode },
|
||||||
"info" => { mode.as_mut().info.push(tail.into()); mode },
|
"info" => { mode.as_mut().info.push(tail.into()); mode },
|
||||||
"view" => { mode.as_mut().view.push(View::new(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());
|
return Err(format!("Mode::add: unexpected: {dsl:?}").into());
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsMut<Mode> for Mode {
|
impl AsMut<Mode> for Mode {
|
||||||
|
|
|
||||||
|
|
@ -86,8 +86,8 @@ pub struct Views(pub Arc<RwLock<BTreeMap<
|
||||||
|
|
||||||
impl Views {
|
impl Views {
|
||||||
/// Load custom view definition.
|
/// Load custom view definition.
|
||||||
pub fn add <'a> (views: &Views, expr: impl Language) -> UsuallyRef<'a, ()> {
|
pub fn add <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> {
|
||||||
views.0.write().insert(
|
self.0.write().insert(
|
||||||
expr.head()?.ok_or("view: missing name")?.into(),
|
expr.head()?.ok_or("view: missing name")?.into(),
|
||||||
View::new(expr.tail()?.ok_or("view: missing body")?)?.into()
|
View::new(expr.tail()?.ok_or("view: missing body")?)?.into()
|
||||||
);
|
);
|
||||||
|
|
@ -373,6 +373,7 @@ impl View<Tui, App> {
|
||||||
Some("Beat") => view!(),
|
Some("Beat") => view!(),
|
||||||
Some("Bpm") => view!(),
|
Some("Bpm") => view!(),
|
||||||
Some("BrowseTitle") => view!(|app|view_browse_title(app)),
|
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("Debug") => Box::new(move|_, to|format!("[{:?}]", to.area()).exact_h(1).draw(to)),
|
||||||
Some("Device") => view!(|app|view_device(app)),
|
Some("Device") => view!(|app|view_device(app)),
|
||||||
Some("Menu") => view!(|app|view_menu(app)),
|
Some("Menu") => view!(|app|view_menu(app)),
|
||||||
|
|
@ -381,6 +382,7 @@ impl View<Tui, App> {
|
||||||
Some("MetersOut") => view!(|___|bg(Rgb(30, 30, 30), "Output Meters".align_s().full_h())),
|
Some("MetersOut") => view!(|___|bg(Rgb(30, 30, 30), "Output Meters".align_s().full_h())),
|
||||||
Some("ModeList") => view!(|app|view_modes(app)),
|
Some("ModeList") => view!(|app|view_modes(app)),
|
||||||
Some("HistoryCount") => view!(|app|app.history.len()),
|
Some("HistoryCount") => view!(|app|app.history.len()),
|
||||||
|
Some("HistoryList") => view!(|app|view_history_list(app)),
|
||||||
Some("ScenesClips") => view!(|app|view_scenes_clips(app)),
|
Some("ScenesClips") => view!(|app|view_scenes_clips(app)),
|
||||||
Some("ScenesNames") => view!(|app|app.view_scenes_names()),
|
Some("ScenesNames") => view!(|app|app.view_scenes_names()),
|
||||||
Some("Sessions") => view!(|___|view_sessions()),
|
Some("Sessions") => view!(|___|view_sessions()),
|
||||||
|
|
@ -426,6 +428,58 @@ pub fn view_menu (app: &App) -> impl Draw<Tui> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn view_history_list (app: &App) -> impl Draw<Tui> {
|
||||||
|
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<Tui> {
|
||||||
|
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<Tui> {
|
||||||
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// let _ = tek::button_play_pause(true, true);
|
/// let _ = tek::button_play_pause(true, true);
|
||||||
/// let _ = tek::button_play_pause(true, false);
|
/// let _ = tek::button_play_pause(true, false);
|
||||||
|
|
|
||||||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
||||||
Subproject commit 1e8b18134d8ad234e5d0142d706f21f1366668d0
|
Subproject commit 50c0ed1c66c9db97b83b95eb23a7b0bf00c5a760
|
||||||
Loading…
Add table
Add a link
Reference in a new issue