wip: modularize dialog

This commit is contained in:
🪞👃🪞 2025-05-18 18:32:39 +03:00
parent baad8254a2
commit 3e9545fe26
17 changed files with 171 additions and 173 deletions

View file

@ -39,18 +39,6 @@ pub enum Selection {
/// Focus identification methods
impl Selection {
pub fn is_mix (&self) -> bool {
matches!(self, Self::Mix)
}
pub fn is_track (&self) -> bool {
matches!(self, Self::Track(_))
}
pub fn is_scene (&self) -> bool {
matches!(self, Self::Scene(_))
}
pub fn is_clip (&self) -> bool {
matches!(self, Self::TrackClip {..})
}
pub fn track (&self) -> Option<usize> {
use Selection::*;
match self {
@ -62,7 +50,7 @@ impl Selection {
_ => None
}
}
pub fn track_header (&self, track_count: usize) -> Self {
pub fn select_track (&self, track_count: usize) -> Self {
use Selection::*;
match self {
Mix => Track(0),
@ -72,7 +60,7 @@ impl Selection {
_ => todo!(),
}
}
pub fn track_next (&self, len: usize) -> Self {
pub fn select_track_next (&self, len: usize) -> Self {
use Selection::*;
match self {
Mix => Track(0),
@ -90,7 +78,7 @@ impl Selection {
_ => todo!()
}
}
pub fn track_prev (&self) -> Self {
pub fn select_track_prev (&self) -> Self {
use Selection::*;
match self {
Mix => Mix,
@ -109,7 +97,16 @@ impl Selection {
_ => None
}
}
pub fn scene_next (&self, len: usize) -> Self {
pub fn select_scene (&self, scene_count: usize) -> Self {
use Selection::*;
match self {
Mix | Track(_) => Scene(0),
Scene(s) => Scene((s + 1) % scene_count),
TrackClip { scene, .. } => Track(*scene),
_ => todo!(),
}
}
pub fn select_scene_next (&self, len: usize) -> Self {
use Selection::*;
match self {
Mix => Scene(0),
@ -127,7 +124,7 @@ impl Selection {
_ => todo!()
}
}
pub fn scene_prev (&self) -> Self {
pub fn select_scene_prev (&self) -> Self {
use Selection::*;
match self {
Mix | Scene(0) => Mix,
@ -142,11 +139,9 @@ impl Selection {
use Selection::*;
format!("{}", match self {
Mix => "Everything".to_string(),
Scene(s) => scenes.get(*s)
.map(|scene|format!("S{s}: {}", &scene.name))
Scene(s) => scenes.get(*s).map(|scene|format!("S{s}: {}", &scene.name))
.unwrap_or_else(||"S??".into()),
Track(t) => tracks.get(*t)
.map(|track|format!("T{t}: {}", &track.name))
Track(t) => tracks.get(*t).map(|track|format!("T{t}: {}", &track.name))
.unwrap_or_else(||"T??".into()),
TrackClip { track, scene } => match (tracks.get(*track), scenes.get(*scene)) {
(Some(_), Some(s)) => match s.clip(*track) {
@ -159,6 +154,3 @@ impl Selection {
}).into()
}
}
impl Arrangement {
}

View file

@ -90,8 +90,11 @@ impl Arrangement {
for (index, track, x1, x2) in self.tracks_with_sizes() {
add(&Fixed::xy(self.track_width(index, track), h + 1,
Tui::bg(track.color.dark.rgb, Align::nw(Map::south(2, move||0..h,
|_, index|Fixed::xy(track.width as u16, 2, Tui::bg(ItemTheme::G[32].base.rgb,
Align::nw(format!(" · {}", "--")))))))));
|_, index|Fixed::xy(track.width as u16, 2,
Tui::fg_bg(
ItemTheme::G[32].lightest.rgb,
ItemTheme::G[32].dark.rgb,
Align::nw(format!(" · {}", "--")))))))));
}
}))
}

View file

@ -1,4 +1,6 @@
use crate::*;
mod dialog_api; pub use self::dialog_api::*;
mod dialog_view; pub use self::dialog_view::*;
/// Various possible dialog overlays
#[derive(Clone, Debug)]
@ -16,98 +18,3 @@ pub enum Dialog {
pub enum Message {
FailedToAddDevice,
}
content!(TuiOut: |self: Message| match self {
Self::FailedToAddDevice => "Failed to add device."
});
content!(TuiOut: |self: Dialog| match self {
Self::Menu(_) =>
self.view_dialog_menu().boxed(),
Self::Help(offset) =>
self.view_dialog_help(*offset).boxed(),
Self::Browser(target, browser) =>
self.view_dialog_browser(target, browser).boxed(),
Self::Options =>
self.view_dialog_options().boxed(),
Self::Device(index) =>
self.view_dialog_device(*index).boxed(),
Self::Message(message) =>
self.view_dialog_message(message).boxed(),
});
impl Dialog {
pub fn view_dialog_menu (&self) -> impl Content<TuiOut> {
let options = ||["Projects", "Settings", "Help", "Quit"].iter();
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a));
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
}
pub fn view_dialog_help <'a> (&'a self, offset: usize) -> impl Content<TuiOut> + use<'a> {
Bsp::s(Tui::bold(true, "Help"), "FIXME")
//Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1,
//move||self.config.keys.layers.iter()
//.filter_map(|a|(a.0)(self).then_some(a.1))
//.flat_map(|a|a)
//.filter_map(|x|if let Value::Exp(_, iter)=x.value{ Some(iter) } else { None })
//.skip(offset)
//.take(20),
//|mut b,i|Fixed::x(60, Align::w(Bsp::e("(", Bsp::e(
//b.next().map(|t|Fixed::x(16, Align::w(Tui::fg(Rgb(64,224,0), format!("{}", t.value))))),
//Bsp::e(" ", Align::w(format!("{}", b.0.0.trim()))))))))))
}
pub fn view_dialog_device (&self, index: usize) -> impl Content<TuiOut> + use<'_> {
let choices = ||device_kinds().iter();
let choice = move|label, i|
Fill::x(Tui::bg(if i == index { Rgb(64,128,32) } else { Rgb(0,0,0) },
Bsp::e(if i == index { "[ " } else { " " },
Bsp::w(if i == index { " ]" } else { " " },
label))));
Bsp::s(Tui::bold(true, "Add device"), Map::south(1, choices, choice))
}
pub fn view_dialog_message <'a> (&'a self, message: &'a Message) -> impl Content<TuiOut> + use<'a> {
Bsp::s(message, Bsp::s("", "[ OK ]"))
}
pub fn view_dialog_browser <'a> (&'a self, target: &BrowserTarget, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Padding::xy(3, 1, Fill::x(Align::w(FieldV(
Default::default(),
match target {
BrowserTarget::SaveProject => "Save project:",
BrowserTarget::LoadProject => "Load project:",
BrowserTarget::ImportSample(_) => "Import sample:",
BrowserTarget::ExportSample(_) => "Export sample:",
BrowserTarget::ImportClip(_) => "Import clip:",
BrowserTarget::ExportClip(_) => "Export clip:",
},
Shrink::x(3, Fixed::y(1, Tui::fg(Tui::g(96), RepeatH("🭻")))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_load <'a> (&'a self, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Fill::x(Align::w(Margin::xy(1, 1, Bsp::e(
Tui::bold(true, " Load project: "),
Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_export <'a> (&'a self, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Fill::x(Align::w(Margin::xy(1, 1, Bsp::e(
Tui::bold(true, " Export: "),
Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_import <'a> (&'a self, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Fill::x(Align::w(Margin::xy(1, 1, Bsp::e(
Tui::bold(true, " Import: "),
Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_options <'a> (&'a self) -> impl Content<TuiOut> + use<'a> {
"TODO"
}
}

View file

@ -0,0 +1,9 @@
use crate::*;
#[tengri_proc::command(Option<Dialog>)]
impl DialogCommand {
fn dismiss (dialog: &mut Option<Dialog>) -> Perhaps<Self> {
*dialog = None;
Ok(None)
}
}

View file

@ -0,0 +1,96 @@
use crate::*;
content!(TuiOut: |self: Dialog| match self {
Self::Menu(_) =>
self.view_dialog_menu().boxed(),
Self::Help(offset) =>
self.view_dialog_help(*offset).boxed(),
Self::Browser(target, browser) =>
self.view_dialog_browser(target, browser).boxed(),
Self::Options =>
self.view_dialog_options().boxed(),
Self::Device(index) =>
self.view_dialog_device(*index).boxed(),
Self::Message(message) =>
self.view_dialog_message(message).boxed(),
});
content!(TuiOut: |self: Message| match self {
Self::FailedToAddDevice => "Failed to add device."
});
impl Dialog {
pub fn view_dialog_menu (&self) -> impl Content<TuiOut> {
let options = ||["Projects", "Settings", "Help", "Quit"].iter();
let option = |a,i|Tui::fg(Rgb(255,255,255), format!("{}", a));
Bsp::s(Tui::bold(true, "tek!"), Bsp::s("", Map::south(1, options, option)))
}
pub fn view_dialog_help <'a> (&'a self, offset: usize) -> impl Content<TuiOut> + use<'a> {
Bsp::s(Tui::bold(true, "Help"), "FIXME")
//Bsp::s(Tui::bold(true, "Help"), Bsp::s("", Map::south(1,
//move||self.config.keys.layers.iter()
//.filter_map(|a|(a.0)(self).then_some(a.1))
//.flat_map(|a|a)
//.filter_map(|x|if let Value::Exp(_, iter)=x.value{ Some(iter) } else { None })
//.skip(offset)
//.take(20),
//|mut b,i|Fixed::x(60, Align::w(Bsp::e("(", Bsp::e(
//b.next().map(|t|Fixed::x(16, Align::w(Tui::fg(Rgb(64,224,0), format!("{}", t.value))))),
//Bsp::e(" ", Align::w(format!("{}", b.0.0.trim()))))))))))
}
pub fn view_dialog_device (&self, index: usize) -> impl Content<TuiOut> + use<'_> {
let choices = ||device_kinds().iter();
let choice = move|label, i|
Fill::x(Tui::bg(if i == index { Rgb(64,128,32) } else { Rgb(0,0,0) },
Bsp::e(if i == index { "[ " } else { " " },
Bsp::w(if i == index { " ]" } else { " " },
label))));
Bsp::s(Tui::bold(true, "Add device"), Map::south(1, choices, choice))
}
pub fn view_dialog_message <'a> (&'a self, message: &'a Message) -> impl Content<TuiOut> + use<'a> {
Bsp::s(message, Bsp::s("", "[ OK ]"))
}
pub fn view_dialog_browser <'a> (&'a self, target: &BrowserTarget, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Padding::xy(3, 1, Fill::x(Align::w(FieldV(
Default::default(),
match target {
BrowserTarget::SaveProject => "Save project:",
BrowserTarget::LoadProject => "Load project:",
BrowserTarget::ImportSample(_) => "Import sample:",
BrowserTarget::ExportSample(_) => "Export sample:",
BrowserTarget::ImportClip(_) => "Import clip:",
BrowserTarget::ExportClip(_) => "Export clip:",
},
Shrink::x(3, Fixed::y(1, Tui::fg(Tui::g(96), RepeatH("🭻")))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_load <'a> (&'a self, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Fill::x(Align::w(Margin::xy(1, 1, Bsp::e(
Tui::bold(true, " Load project: "),
Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_export <'a> (&'a self, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Fill::x(Align::w(Margin::xy(1, 1, Bsp::e(
Tui::bold(true, " Export: "),
Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_import <'a> (&'a self, browser: &'a Browser) -> impl Content<TuiOut> + use<'a> {
Bsp::s(
Fill::x(Align::w(Margin::xy(1, 1, Bsp::e(
Tui::bold(true, " Import: "),
Shrink::x(3, Fixed::y(1, RepeatH("🭻"))))))),
Outer(true, Style::default().fg(Tui::g(96)))
.enclose(Fill::xy(browser)))
}
pub fn view_dialog_options <'a> (&'a self) -> impl Content<TuiOut> + use<'a> {
"TODO"
}
}