mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-08-07 14:06:57 +02:00
use #[namespace]
This commit is contained in:
parent
34bd2eeacf
commit
b19d5bef24
10 changed files with 641 additions and 697 deletions
996
Cargo.lock
generated
996
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +1,14 @@
|
|||
# https://dystroy.org/bacon/config/
|
||||
default_job = "test"
|
||||
env.CARGO_TERM_COLOR = "always"
|
||||
|
||||
[keybindings]
|
||||
c = "job:check"
|
||||
t = "job:test"
|
||||
n = "job:nextest"
|
||||
l = "job:clippy"
|
||||
r = "job:run"
|
||||
|
||||
[jobs]
|
||||
[jobs.check]
|
||||
command = ["cargo", "check"]
|
||||
|
|
@ -47,9 +50,9 @@ command = [
|
|||
"cargo", "run",
|
||||
# put launch parameters for your program behind a `--` separator
|
||||
]
|
||||
need_stdout = true
|
||||
need_stdout = false
|
||||
allow_warnings = true
|
||||
background = true
|
||||
background = false
|
||||
[jobs.run-long]
|
||||
watch = ["dizzle", "tengri", "app"]
|
||||
command = [ "cargo", "run", ]
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
pkgs.libclang
|
||||
pkgs.mold
|
||||
pkgs.cloc
|
||||
pkgs.watchexec
|
||||
];
|
||||
buildInputs = [
|
||||
pkgs.libclang
|
||||
|
|
|
|||
211
src/app.rs
211
src/app.rs
|
|
@ -29,7 +29,21 @@ pub mod size; pub use self::size::*;
|
|||
/// //let _ = app.project.h_outputs();
|
||||
/// let _ = app.project.h_scenes();
|
||||
/// ```
|
||||
#[derive(Default, Debug)] pub struct App {
|
||||
#[derive(Default, Debug)]
|
||||
#[namespace(u8)]
|
||||
#[namespace(isize)]
|
||||
#[namespace(ItemTheme)]
|
||||
#[namespace(Arc<str> get_arc_str)]
|
||||
#[namespace(u16 get_u16)]
|
||||
#[namespace(usize get_usize)]
|
||||
#[namespace(bool get_bool)]
|
||||
#[namespace(Selection get_selection)]
|
||||
#[namespace(Color get_color)]
|
||||
#[namespace(Option<u7> get_opt_u7)]
|
||||
#[namespace(Option<u16> get_opt_u16)]
|
||||
#[namespace(Option<usize> get_opt_usize)]
|
||||
#[namespace(Option<Arc<RwLock<MidiClip>>> get_clip)]
|
||||
pub struct App {
|
||||
/// Base color.
|
||||
pub color: ItemTheme,
|
||||
/// Must not be dropped for the duration of the process
|
||||
|
|
@ -54,6 +68,129 @@ pub mod size; pub use self::size::*;
|
|||
pub error: Arc<RwLock<Option<Arc<str>>>>
|
||||
}
|
||||
|
||||
fn get_arc_str (_state: &App, src: impl Language) -> Perhaps<Arc<str>> {
|
||||
Ok(src.src()?.map(|x|x.into()))
|
||||
}
|
||||
|
||||
fn get_u16 (state: &App, src: impl Language) -> Perhaps<u16> {
|
||||
if let Some(sym) = src.word()? {
|
||||
Ok(Some(match sym {
|
||||
":w/sidebar" => state.project.w_sidebar(state.editor().is_some()),
|
||||
":h/sample-detail" => 6.max(state.size.h() as u16 * 3 / 9),
|
||||
_ => return Err(format!("not a u16: {sym}").into())
|
||||
}))
|
||||
} else {
|
||||
try_to_u16(src)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_usize (state: &App, src: impl Language) -> Perhaps<usize> {
|
||||
if let Some(sym) = src.word()? {
|
||||
Ok(Some(match sym {
|
||||
":scene-count" => state.scenes().len(),
|
||||
":track-count" => state.tracks().len(),
|
||||
":device-kind" => state.dialog.device_kind().unwrap_or(0),
|
||||
":device-kind/next" => state.dialog.device_kind_next().unwrap_or(0),
|
||||
":device-kind/prev" => state.dialog.device_kind_prev().unwrap_or(0),
|
||||
_ => return Err(format!("not usize: {sym}").into())
|
||||
}))
|
||||
} else {
|
||||
try_to_usize(src)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_bool (state: &App, src: impl Language) -> Perhaps<bool> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
"Y" => true,
|
||||
"N" => false,
|
||||
":mode/editor" => state.project.editor.is_some(),
|
||||
":focused/dialog" => !matches!(state.dialog, Dialog::None),
|
||||
":focused/message" => matches!(state.dialog, Dialog::Message(..)),
|
||||
":focused/add_device" => matches!(state.dialog, Dialog::Device(..)),
|
||||
":focused/browser" => state.dialog.browser().is_some(),
|
||||
":focused/pool/import" => matches!(state.pool.mode, Some(PoolMode::Import(..))),
|
||||
":focused/pool/export" => matches!(state.pool.mode, Some(PoolMode::Export(..))),
|
||||
":focused/pool/rename" => matches!(state.pool.mode, Some(PoolMode::Rename(..))),
|
||||
":focused/pool/length" => matches!(state.pool.mode, Some(PoolMode::Length(..))),
|
||||
":focused/clip" => !state.editor_focused() && matches!(state.selection(), Selection::TrackClip{..}),
|
||||
":focused/track" => !state.editor_focused() && matches!(state.selection(), Selection::Track(..)),
|
||||
":focused/scene" => !state.editor_focused() && matches!(state.selection(), Selection::Scene(..)),
|
||||
":focused/mix" => !state.editor_focused() && matches!(state.selection(), Selection::Mix),
|
||||
_ => return Err(format!("not bool: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_selection (state: &App, src: impl Language) -> Perhaps<Selection> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":select/scene" => state.selection().select_scene(state.tracks().len()),
|
||||
":select/scene/next" => state.selection().select_scene_next(state.scenes().len()),
|
||||
":select/scene/prev" => state.selection().select_scene_prev(),
|
||||
":select/track" => state.selection().select_track(state.tracks().len()),
|
||||
":select/track/next" => state.selection().select_track_next(state.tracks().len()),
|
||||
":select/track/prev" => state.selection().select_track_prev(),
|
||||
_ => return Err(format!("not selection: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_color (state: &App, src: impl Language) -> Perhaps<Color> {
|
||||
Ok(if let Some(sym) = src.word()? {
|
||||
match sym {
|
||||
":color/bg" => Some(Color::Rgb(28, 32, 36)),
|
||||
_ => return Err(format!("not a color: {sym}").into())
|
||||
}
|
||||
} else if let Some(expr) = src.expr()? {
|
||||
match expr.head()? {
|
||||
Some("g") => {
|
||||
let n = try_to_u8(expr.tail())?
|
||||
.ok_or::<Box<dyn Error>>(format!("not gray: {expr}").into())?;
|
||||
Some(Color::Rgb(n, n, n))
|
||||
},
|
||||
Some("rgb") => {
|
||||
let r = try_to_u8(expr.tail().head())?
|
||||
.ok_or::<Box<dyn Error>>(format!("not red: {expr}").into())?;
|
||||
let g = try_to_u8(expr.tail().tail().head())?
|
||||
.ok_or::<Box<dyn Error>>(format!("not green: {expr}").into())?;
|
||||
let b = try_to_u8(expr.tail().tail().tail().head())?
|
||||
.ok_or::<Box<dyn Error>>(format!("not blue: {expr}").into())?;
|
||||
Some(Color::Rgb(r, g, b))
|
||||
},
|
||||
Some(_) => return Err(format!("not a color expression: {expr}").into()),
|
||||
None => return Err(format!("not a color expression: {expr}").into())
|
||||
}
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
fn get_opt_u7 (state: &App, src: impl Language) -> Perhaps<Option<u7>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":editor/pitch" => Some((
|
||||
state.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8
|
||||
).into()),
|
||||
_ => return Err(format!("unknown midi note: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_opt_u16 (_state: &App, _src: impl Language) -> Perhaps<Option<u16>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn get_opt_usize (state: &App, src: impl Language) -> Perhaps<Option<usize>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/scene" => state.selection().scene(),
|
||||
":selected/track" => state.selection().track(),
|
||||
_ => return Err(format!("unknown opt<usize>: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
fn get_clip (state: &App, src: impl Language) -> Perhaps<Option<Arc<RwLock<MidiClip>>>> {
|
||||
src.word()?.map(|word|Ok(match word {
|
||||
":selected/clip" if let Selection::TrackClip { track, scene } = state.selection() =>
|
||||
state.scenes()[*scene].clips[*track].clone(),
|
||||
_ => return Err(format!("not a clip: {word}").into())
|
||||
})).transpose()
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
||||
/// Create a new application instance from a backend, project, config, and mode
|
||||
|
|
@ -247,78 +384,6 @@ primitive!(u16: try_to_u16);
|
|||
primitive!(usize: try_to_usize);
|
||||
primitive!(isize: try_to_isize);
|
||||
|
||||
namespace!(App: Arc<str> { literal = |dsl|Ok(dsl.src()?.map(|x|x.into())); });
|
||||
|
||||
namespace!(App: u8 { literal = |dsl|try_to_u8(dsl); });
|
||||
|
||||
namespace!(App: u16 { literal = |dsl|try_to_u16(dsl); symbol = |app| {
|
||||
":w/sidebar" => app.project.w_sidebar(app.editor().is_some()),
|
||||
":h/sample-detail" => 6.max(app.size.h() as u16 * 3 / 9), }; });
|
||||
|
||||
namespace!(App: isize { literal = |dsl|try_to_isize(dsl); });
|
||||
|
||||
namespace!(App: usize { literal = |dsl|try_to_usize(dsl); symbol = |app| {
|
||||
":scene-count" => app.scenes().len(),
|
||||
":track-count" => app.tracks().len(),
|
||||
":device-kind" => app.dialog.device_kind().unwrap_or(0),
|
||||
":device-kind/next" => app.dialog.device_kind_next().unwrap_or(0),
|
||||
":device-kind/prev" => app.dialog.device_kind_prev().unwrap_or(0), }; });
|
||||
|
||||
namespace!(App: bool { symbol = |app| { // Provide boolean values.
|
||||
":mode/editor" => app.project.editor.is_some(),
|
||||
":focused/dialog" => !matches!(app.dialog, Dialog::None),
|
||||
":focused/message" => matches!(app.dialog, Dialog::Message(..)),
|
||||
":focused/add_device" => matches!(app.dialog, Dialog::Device(..)),
|
||||
":focused/browser" => app.dialog.browser().is_some(),
|
||||
":focused/pool/import" => matches!(app.pool.mode, Some(PoolMode::Import(..))),
|
||||
":focused/pool/export" => matches!(app.pool.mode, Some(PoolMode::Export(..))),
|
||||
":focused/pool/rename" => matches!(app.pool.mode, Some(PoolMode::Rename(..))),
|
||||
":focused/pool/length" => matches!(app.pool.mode, Some(PoolMode::Length(..))),
|
||||
":focused/clip" => !app.editor_focused() && matches!(app.selection(), Selection::TrackClip{..}),
|
||||
":focused/track" => !app.editor_focused() && matches!(app.selection(), Selection::Track(..)),
|
||||
":focused/scene" => !app.editor_focused() && matches!(app.selection(), Selection::Scene(..)),
|
||||
":focused/mix" => !app.editor_focused() && matches!(app.selection(), Selection::Mix),
|
||||
}; });
|
||||
|
||||
namespace!(App: ItemTheme {}); // TODO: provide colors here
|
||||
//
|
||||
namespace!(App: Selection { symbol = |app| {
|
||||
":select/scene" => app.selection().select_scene(app.tracks().len()),
|
||||
":select/scene/next" => app.selection().select_scene_next(app.scenes().len()),
|
||||
":select/scene/prev" => app.selection().select_scene_prev(),
|
||||
":select/track" => app.selection().select_track(app.tracks().len()),
|
||||
":select/track/next" => app.selection().select_track_next(app.tracks().len()),
|
||||
":select/track/prev" => app.selection().select_track_prev(),
|
||||
}; });
|
||||
|
||||
namespace!(App: Color {
|
||||
symbol = |app| {
|
||||
":color/bg" => Color::Rgb(28, 32, 36),
|
||||
};
|
||||
expression = |app| {
|
||||
"g" (n: u8) => Color::Rgb(n, n, n),
|
||||
"rgb" (r: u8, g: u8, b: u8) => Color::Rgb(r, g, b),
|
||||
};
|
||||
});
|
||||
|
||||
namespace!(App: Option<u7> { symbol = |app| {
|
||||
":editor/pitch" => Some((app.editor().as_ref().map(|e|e.get_note_pos()).unwrap() as u8).into())
|
||||
}; });
|
||||
|
||||
namespace!(App: Option<u16> { symbol = |app| {}; });
|
||||
|
||||
namespace!(App: Option<usize> { symbol = |app| {
|
||||
":selected/scene" => app.selection().scene(),
|
||||
":selected/track" => app.selection().track(),
|
||||
}; });
|
||||
|
||||
namespace!(App: Option<Arc<RwLock<MidiClip>>> { symbol = |app| {
|
||||
":selected/clip" => if let Selection::TrackClip { track, scene } = app.selection() {
|
||||
app.scenes()[*scene].clips[*track].clone()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}; });
|
||||
|
||||
pub fn swap_value <T: Clone + PartialEq, U> (
|
||||
target: &mut T, value: &T, returned: impl Fn(T)->U
|
||||
|
|
|
|||
|
|
@ -145,13 +145,12 @@ pub fn draw_templates (to: &mut Tui, frags: std::str::Split<&str>, state: &App)
|
|||
/// let _ = tek::view_logo();
|
||||
/// ```
|
||||
pub fn view_logo () -> impl Draw<Tui> {
|
||||
bold(true, fg(Rgb(240, 200, 180), south!{
|
||||
"".exact_h(1),
|
||||
"".exact_h(1),
|
||||
fg(Rgb(240, 200, 180), south!{
|
||||
"~~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~~~~~~~~~".exact_h(1),
|
||||
east("~~~~ ║ ~ ╟─╌ ~╟─< ~~ ", east(fg(Rgb(230,100,40), "v0.3.0"), " ~~")).exact_h(1),
|
||||
"~~~~ ║ ~ ╟─╌ ~╟─< ~~ v0.3.0 ~~".exact_h(1),
|
||||
//east("~~~~ ║ ~ ╟─╌ ~╟─< ~~ ", east(fg(Rgb(230,100,40), "v0.3.0"), " ~~")).exact_h(1),
|
||||
"~~~~ ╨ ~ ╙──╜ ╨ ╜ ~~~~~~~~~~~~".exact_h(1),
|
||||
})).exact_wh(32, 7)
|
||||
}.exact_w(32))
|
||||
}
|
||||
|
||||
/// ```
|
||||
|
|
@ -465,7 +464,7 @@ pub fn view_track_outputs (
|
|||
south(button_2("o", "utput", false).align_w().full_w(),
|
||||
thunk(|to: &mut Tui|{
|
||||
for port in midi_outs {
|
||||
port.port_name().align_w().full_w().draw(to);
|
||||
let _ = port.port_name().align_w().full_w().draw(to)?;
|
||||
}
|
||||
Ok(Some(XYWH(0, 0, 0, 0)))
|
||||
})),
|
||||
|
|
@ -584,7 +583,7 @@ pub fn view_inputs (tracks: impl TracksSizes<'_>, midi_ins: &[MidiInput]) -> imp
|
|||
let title_2 = button_2("I", "+", false).exact_wh(4, 1);
|
||||
east(title_1, west(title_2, thunk(move|to: &mut Tui|{
|
||||
for (_index, track, x1, _x2) in tracks {
|
||||
south(
|
||||
let _ = south(
|
||||
bg(track.color.dark.term, east!(
|
||||
either(track.sequencer.monitoring, fg(Green, "mon "), "mon "),
|
||||
either(track.sequencer.recording, fg(Red, "rec "), "rec "),
|
||||
|
|
@ -592,26 +591,24 @@ pub fn view_inputs (tracks: impl TracksSizes<'_>, midi_ins: &[MidiInput]) -> imp
|
|||
).exact_w(track.width as u16)).align_w().push_x(x1 as u16),
|
||||
thunk(move |to: &mut Tui|{
|
||||
for (index, port) in midi_ins.iter().enumerate() {
|
||||
east(
|
||||
let _ = east(
|
||||
east(
|
||||
" ● ",
|
||||
bold(true, fg(Rgb(255,255,255), port.port_name()))
|
||||
).align_w().exact_w(20),
|
||||
west(
|
||||
().exact_w(4),
|
||||
thunk(move|to: &mut Tui|{
|
||||
bg(track.color.darker.term, east!(
|
||||
either(track.sequencer.monitoring, fg(Green, " ● "), " · "),
|
||||
either(track.sequencer.recording, fg(Red, " ● "), " · "),
|
||||
either(track.sequencer.overdub, fg(Yellow, " ● "), " · "),
|
||||
).exact_w(track.width as u16).align_w()).draw(to);
|
||||
todo!()
|
||||
}))
|
||||
).push_x(index as u16 * 10).exact_h(1).draw(to);
|
||||
bg(track.color.darker.term, east!(
|
||||
either(track.sequencer.monitoring, fg(Green, " ● "), " · "),
|
||||
either(track.sequencer.recording, fg(Red, " ● "), " · "),
|
||||
either(track.sequencer.overdub, fg(Yellow, " ● "), " · "),
|
||||
).exact_w(track.width as u16).align_w())
|
||||
)
|
||||
).push_x(index as u16 * 10).exact_h(1).draw(to)?;
|
||||
}
|
||||
todo!()
|
||||
})
|
||||
).draw(to);
|
||||
).draw(to)?;
|
||||
}
|
||||
todo!()
|
||||
})))
|
||||
|
|
@ -646,7 +643,7 @@ pub fn view_outputs (
|
|||
view_track_row_section(theme, list, button_2("O", "+", false),
|
||||
bg(theme.darker.term, thunk(|to: &mut Tui|{
|
||||
for (index, track, _x1, _x2) in tracks {
|
||||
thunk(|to: &mut Tui|{
|
||||
let _ = thunk(|to: &mut Tui|{
|
||||
east(
|
||||
either(true, fg(Green, "play "), "play "),
|
||||
either(false, fg(Yellow, "solo "), "solo "),
|
||||
|
|
@ -661,7 +658,7 @@ pub fn view_outputs (
|
|||
}
|
||||
}
|
||||
todo!()
|
||||
}).exact_w(track_width(index, track)).draw(to);
|
||||
}).exact_w(track_width(index, track)).draw(to)?;
|
||||
}
|
||||
todo!()
|
||||
}).align_w().full_w())).exact_h(height)
|
||||
|
|
@ -711,10 +708,14 @@ pub fn per_track_top <'a, T: Draw<Tui> + 'a, U: TracksSizes<'a>> (
|
|||
}).align_x())
|
||||
}
|
||||
|
||||
pub fn field_h <T: Screen> (theme: ItemTheme, head: impl Draw<T>, body: impl Draw<T>) -> impl Draw<T> {
|
||||
pub fn field_h <T: Screen> (
|
||||
theme: ItemTheme, head: impl Draw<T>, body: impl Draw<T>
|
||||
) -> impl Draw<T> {
|
||||
}
|
||||
|
||||
pub fn field_v <T: Screen> (theme: ItemTheme, head: impl Draw<T>, body: impl Draw<T>) -> impl Draw<T> {
|
||||
pub fn field_v <T: Screen> (
|
||||
theme: ItemTheme, head: impl Draw<T>, body: impl Draw<T>
|
||||
) -> impl Draw<T> {
|
||||
}
|
||||
|
||||
pub fn view_sessions () -> impl Draw<Tui> {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ pub(crate) use ::xdg::BaseDirectories;
|
|||
pub(crate) use ::midly::{Smf, TrackEventKind, MidiMessage, Error as MidiError, num::*, live::*};
|
||||
|
||||
pub(crate) use tengri::{
|
||||
*, lang::*,
|
||||
*,
|
||||
lang::*,
|
||||
crossterm::event::{Event, KeyEvent},
|
||||
ratatui::{
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -14,26 +14,41 @@ use crate::{*, browse::*, device::*, menu::*};
|
|||
Browse(BrowseTarget, Arc<Browse>),
|
||||
Options,
|
||||
}
|
||||
namespace!(App: Dialog { symbol = |app| {
|
||||
":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(BrowseTarget::SaveProject,
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/load" => Dialog::Browse(BrowseTarget::LoadProject,
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/import/clip" => Dialog::Browse(BrowseTarget::ImportClip(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/export/clip" => Dialog::Browse(BrowseTarget::ExportClip(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/import/sample" => Dialog::Browse(BrowseTarget::ImportSample(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/export/sample" => Dialog::Browse(BrowseTarget::ExportSample(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
}; });
|
||||
|
||||
impl<'n> Namespace<'n, Dialog> for App {
|
||||
fn namespace (&self, src: impl Language) -> Perhaps<Dialog> {
|
||||
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(
|
||||
BrowseTarget::SaveProject,
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/load" => Dialog::Browse(
|
||||
BrowseTarget::LoadProject,
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/import/clip" => Dialog::Browse(
|
||||
BrowseTarget::ImportClip(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/export/clip" => Dialog::Browse(
|
||||
BrowseTarget::ExportClip(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/import/sample" => Dialog::Browse(
|
||||
BrowseTarget::ImportSample(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
":dialog/export/sample" => Dialog::Browse(
|
||||
BrowseTarget::ExportSample(Default::default()),
|
||||
Browse::new(None).unwrap().into()),
|
||||
_ => return Err(
|
||||
format!("not a dialog: {}", src.src()?.unwrap_or("<???>")).into()
|
||||
)
|
||||
})).transpose()
|
||||
}
|
||||
}
|
||||
|
||||
impl Dialog {
|
||||
/// ```
|
||||
/// let _ = tek::Dialog::welcome();
|
||||
|
|
|
|||
|
|
@ -16,12 +16,12 @@
|
|||
(info Mode selector.)
|
||||
(keys :axis/y :confirm)
|
||||
(view (bg (g 0) (bsp/s
|
||||
:ports/out
|
||||
(bg (g 10) :ports/out)
|
||||
(bsp/n
|
||||
:ports/in
|
||||
(bg (g 10) :ports/in)
|
||||
(bg (g 30) (bsp/s
|
||||
(fixed/y 7 :logo)
|
||||
(fill :dialog/menu))))))))
|
||||
:logo
|
||||
:dialog/menu)))))))
|
||||
|
||||
(view :ports/out (fill/x (fixed/y 3 (bsp/a
|
||||
(fill/x (align/w (text L-AUDIO-OUT)))
|
||||
|
|
|
|||
10
src/tek.rs
10
src/tek.rs
|
|
@ -25,10 +25,14 @@ pub extern crate tengri;
|
|||
}).map(|_|())
|
||||
}
|
||||
|
||||
pub mod deps; pub use self::deps::*;
|
||||
pub mod device; pub use self::device::*;
|
||||
pub mod app; pub use self::app::*;
|
||||
pub mod deps;
|
||||
pub(crate) use self::deps::*;
|
||||
|
||||
pub mod device;
|
||||
pub use self::device::*;
|
||||
|
||||
pub mod app;
|
||||
pub use self::app::*;
|
||||
|
||||
/// CLI banner.
|
||||
pub(crate) const HEADER: &'static str = r#"
|
||||
|
|
|
|||
2
tengri
2
tengri
|
|
@ -1 +1 @@
|
|||
Subproject commit 482b6241690f7b116b07d06fb4950754f6fdf584
|
||||
Subproject commit be98e666f53eedf95618396239641ad846a772bd
|
||||
Loading…
Add table
Add a link
Reference in a new issue