pub(crate) use tek_core::crossterm::event::{KeyCode, KeyModifiers}; pub(crate) use tek_core::midly::{num::u7, live::LiveEvent, MidiMessage}; pub(crate) use tek_core::jack::*; pub(crate) use tek_api::*; pub(crate) use tek_snd::*; pub(crate) use std::collections::BTreeMap; pub(crate) use std::sync::{Arc, Mutex, RwLock}; pub(crate) use std::path::PathBuf; pub(crate) use std::ffi::OsString; pub(crate) use std::fs::read_dir; use std::fmt::Debug; submod! { tui_arranger //tui_mixer // TODO tui_phrase //tui_plugin // TODO //tui_plugin_lv2 //tui_plugin_lv2_gui //tui_plugin_vst2 //tui_plugin_vst3 tui_pool tui_pool_length tui_pool_rename //tui_sampler // TODO //tui_sampler_cmd tui_sequencer tui_status tui_theme tui_transport } pub struct AppView where E: Engine, A: Widget + Audio, C: Command, S: StatusBar, { pub app: A, pub cursor: (usize, usize), pub entered: bool, pub menu_bar: Option>, pub status_bar: Option, pub history: Vec, pub size: Measure, } #[derive(Debug, Clone)] pub enum AppViewCommand { Focus(FocusCommand), Undo, Redo, App(T) } #[derive(Debug, Copy, Clone, PartialEq)] pub enum AppViewFocus { Menu, Content(F), } impl AppView where E: Engine, A: Widget + Audio, C: Command, S: StatusBar { pub fn new ( app: A, menu_bar: Option>, status_bar: Option, ) -> Self { Self { app, cursor: (0, 0), entered: false, history: vec![], size: Measure::new(), menu_bar, status_bar, } } } impl Content for AppView where A: Widget + Audio, C: Command, S: StatusBar, { type Engine = Tui; fn content (&self) -> impl Widget { let menus = self.menu_bar.as_ref().map_or_else( ||&[] as &[Menu<_, _, _>], |m|m.menus.as_slice() ); Split::down( if self.menu_bar.is_some() { 1 } else { 0 }, row!(menu in menus.iter() => { row!(" ", menu.title.as_str(), " ") }), Either( self.status_bar.is_some(), Split::up( 1, widget(self.status_bar.as_ref().unwrap()), widget(&self.app) ), widget(&self.app) ) ) } }