mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
wrapper impls for Render and Handle
This commit is contained in:
parent
3a7aa9e9a3
commit
777904cb35
4 changed files with 118 additions and 120 deletions
|
|
@ -28,7 +28,7 @@ pub fn input_thread (
|
|||
}
|
||||
|
||||
/// Trait for things that handle input events.
|
||||
pub trait Handle {
|
||||
pub trait Handle: Send + Sync {
|
||||
/// Handle an input event.
|
||||
/// Returns Ok(true) if the device handled the event.
|
||||
/// This is the mechanism which allows nesting of components;.
|
||||
|
|
@ -37,6 +37,45 @@ pub trait Handle {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Handle> Handle for &mut T {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
(*self).handle(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Handle> Handle for Option<T> {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
match self {
|
||||
Some(handle) => handle.handle(e),
|
||||
None => Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Handle> Handle for Mutex<T> {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
self.lock().unwrap().handle(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Handle> Handle for Arc<Mutex<T>> {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
self.lock().unwrap().handle(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Handle> Handle for RwLock<T> {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
self.write().unwrap().handle(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Handle> Handle for Arc<RwLock<T>> {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
self.write().unwrap().handle(e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implement the `Handle` trait.
|
||||
#[macro_export] macro_rules! handle {
|
||||
($T:ty) => {
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
/// A collection of [Focusable] items.
|
||||
pub struct Focus {
|
||||
index: usize,
|
||||
items: Vec<Focusable>
|
||||
}
|
||||
|
||||
impl Focus {
|
||||
pub fn new (items: Vec<Focusable>) -> Self {
|
||||
Self {
|
||||
index: 0,
|
||||
items
|
||||
}
|
||||
}
|
||||
pub fn item_mut (&mut self) -> &mut impl Handle {
|
||||
&mut self.items[self.index]
|
||||
}
|
||||
/// Select next item.
|
||||
pub fn next (&mut self) -> Usually<bool> {
|
||||
self.index = (self.index + 1) % self.items.len();
|
||||
Ok(true)
|
||||
}
|
||||
/// Select previous item.
|
||||
pub fn prev (&mut self) -> Usually<bool> {
|
||||
self.index = match self.index {
|
||||
0 => self.items.len().saturating_sub(1),
|
||||
_ => self.index - 1
|
||||
};
|
||||
Ok(true)
|
||||
}
|
||||
}
|
||||
|
||||
handle!(Focus |self, e| Ok(
|
||||
handle_keymap(self, e, KEYMAP_FOCUS)? || self.item_mut().handle(e)?
|
||||
));
|
||||
|
||||
pub const KEYMAP_FOCUS: &'static [KeyBinding<Focus>] = keymap!(Focus {
|
||||
[Tab, NONE, "focus_next", "focus next item", Focus::next],
|
||||
[Tab, SHIFT, "focus_prev", "focus previous item", Focus::prev],
|
||||
});
|
||||
|
||||
/// A wrapper around items that can be focused.
|
||||
pub enum Focusable {
|
||||
/// A monolithic focus item.
|
||||
Mono(Arc<dyn Handle + Send + Sync>),
|
||||
/// A focus item that contains other focus items.
|
||||
Poly(Box<Focusable>),
|
||||
}
|
||||
|
||||
handle!(Focusable |self, e| { todo!("{e:?}"); Ok(false) });
|
||||
|
|
@ -46,7 +46,6 @@ use crossterm::terminal::{
|
|||
submod! {
|
||||
exit
|
||||
handle
|
||||
handle_focus
|
||||
handle_keymap
|
||||
jack_core
|
||||
jack_device
|
||||
|
|
|
|||
|
|
@ -9,59 +9,76 @@ pub fn main () -> Usually<()> {
|
|||
|
||||
struct ArrangerStandalone {
|
||||
/// Contains all the sequencers.
|
||||
arranger: Arc<Arranger>,
|
||||
arranger: Arranger,
|
||||
/// Controls the JACK transport.
|
||||
transport: Option<Arc<RwLock<TransportToolbar>>>,
|
||||
transport: Option<TransportToolbar>,
|
||||
/// This allows the sequencer view to be moved or hidden.
|
||||
show_sequencer: Option<tek_core::Direction>,
|
||||
/// Proxies input events to the currently active sequencer.
|
||||
sequencer_proxy: SequencerProxy,
|
||||
///
|
||||
focus_order: Vec<FocusItem>,
|
||||
focus: usize,
|
||||
}
|
||||
|
||||
struct SequencerProxy;
|
||||
|
||||
impl Focus for SequencerProxy {}
|
||||
impl ArrangerStandalone {
|
||||
fn focus_prev (&mut self) {
|
||||
self.focus = if self.focus > 0 { 1 } else { self.focus - 1 };
|
||||
}
|
||||
fn focus_next (&mut self) {
|
||||
self.focus = if self.focus < 2 { self.focus + 1 } else { 0 };
|
||||
}
|
||||
fn focused (&self) -> &dyn Render {
|
||||
self.focusable()[self.focus]
|
||||
}
|
||||
fn focusable (&self) -> [&dyn Render;2] {
|
||||
[
|
||||
&self.transport as &dyn Render,
|
||||
&self.arranger as &dyn Render,
|
||||
]
|
||||
}
|
||||
fn focused_mut (&mut self) -> &mut dyn Handle {
|
||||
let focus = self.focus;
|
||||
self.focusable_mut()[focus]
|
||||
}
|
||||
fn focusable_mut (&mut self) -> [&mut dyn Handle;2] {
|
||||
[
|
||||
&mut self.transport as &mut dyn Handle,
|
||||
&mut self.arranger as &mut dyn Handle
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct ArrangerCli {
|
||||
/// Name of JACK client
|
||||
#[arg(short, long)] name: Option<String>,
|
||||
#[arg(short, long)]
|
||||
name: Option<String>,
|
||||
/// Pulses per quarter note (arruencer resolution; default: 96)
|
||||
#[arg(short, long)] ppq: Option<usize>,
|
||||
#[arg(short, long)]
|
||||
ppq: Option<usize>,
|
||||
/// Whether to include a transport toolbar (default: true)
|
||||
#[arg(short, long)] transport: Option<bool>,
|
||||
#[arg(short, long)]
|
||||
transport: Option<bool>,
|
||||
/// Number of tracks
|
||||
#[arg(short = 'x', long, default_value_t = 8)] tracks: usize,
|
||||
#[arg(short = 'x', long, default_value_t = 8)]
|
||||
tracks: usize,
|
||||
/// Number of scenes
|
||||
#[arg(short, long, default_value_t = 8)] scenes: usize,
|
||||
#[arg(short, long, default_value_t = 8)]
|
||||
scenes: usize,
|
||||
}
|
||||
|
||||
impl<'a> ArrangerStandalone<'a> {
|
||||
impl ArrangerStandalone {
|
||||
pub fn from_args () -> Usually<Self> {
|
||||
let args = ArrangerCli::parse();
|
||||
let arranger = Arranger::new("");
|
||||
let mut arranger = Arranger::new("");
|
||||
let transport = match args.transport {
|
||||
Some(true) => Some(Arc::new(RwLock::new(TransportToolbar::new(None)))),
|
||||
Some(true) => Some(TransportToolbar::new(None)),
|
||||
_ => None
|
||||
};
|
||||
let sequencer_proxy = SequencerProxy;
|
||||
let mut app = ArrangerStandalone {
|
||||
transport,
|
||||
show_sequencer: Some(tek_core::Direction::Down),
|
||||
arranger,
|
||||
sequencer_proxy,
|
||||
focus_order: vec![],
|
||||
};
|
||||
app.focus_order.push(FocusItem::Mono(&app.arranger));
|
||||
app.focus_order.push(FocusItem::Poly(&app.sequencer_proxy));
|
||||
if let Some(name) = args.name {
|
||||
*app.arranger.name.write().unwrap() = name.clone();
|
||||
*arranger.name.write().unwrap() = name.clone();
|
||||
}
|
||||
for _ in 0..args.tracks {
|
||||
let track = app.arranger.track_add(None)?;
|
||||
let track = arranger.track_add(None)?;
|
||||
for _ in 0..args.scenes {
|
||||
track.phrases.push(
|
||||
Arc::new(RwLock::new(Phrase::new("", 96 * 4, None)))
|
||||
|
|
@ -69,30 +86,28 @@ impl<'a> ArrangerStandalone<'a> {
|
|||
}
|
||||
}
|
||||
for _ in 0..args.scenes {
|
||||
let scene = app.arranger.scene_add(None)?;
|
||||
let _scene = arranger.scene_add(None)?;
|
||||
//for i in 0..args.tracks {
|
||||
//scene.clips[i] = Some(i);
|
||||
//}
|
||||
}
|
||||
Ok(app)
|
||||
Ok(ArrangerStandalone {
|
||||
transport,
|
||||
show_sequencer: Some(tek_core::Direction::Down),
|
||||
arranger,
|
||||
focus: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for ArrangerStandalone {
|
||||
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||
let mut layout = Split::down();
|
||||
if let Some(transport) = &self.transport {
|
||||
layout = layout.add_ref(transport);
|
||||
}
|
||||
let sequencer = self.arranger.sequencer();
|
||||
if let Some(direction) = self.show_sequencer {
|
||||
layout = layout.add(Split::new(direction)
|
||||
.add_ref(&self.arranger)
|
||||
.add(sequencer))
|
||||
} else {
|
||||
layout = layout.add_ref(&self.arranger)
|
||||
}
|
||||
let result = layout.render(buf, area)?;
|
||||
let result = Split::down()
|
||||
.add_ref(&self.transport)
|
||||
.add_ref(&self.arranger)
|
||||
.add_ref(&sequencer)
|
||||
.render(buf, area)?;
|
||||
if let Some(ref modal) = self.arranger.modal {
|
||||
fill_bg(buf, area, Nord::bg_lo(false, false));
|
||||
fill_fg(buf, area, Nord::bg_hi(false, false));
|
||||
|
|
@ -104,31 +119,27 @@ impl Render for ArrangerStandalone {
|
|||
|
||||
impl Handle for ArrangerStandalone {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
if let Some(modal) = self.arranger.modal.as_mut() {
|
||||
let result = modal.handle(e)?;
|
||||
if modal.exited() {
|
||||
self.arranger.modal = None;
|
||||
}
|
||||
Ok(result)
|
||||
} else {
|
||||
match e {
|
||||
AppEvent::Input(Event::Key(k)) => {
|
||||
Ok(false)
|
||||
//if k.code == KeyCode::Tab {
|
||||
//self.arranger.focus_sequencer = !self.arranger.focus_sequencer;
|
||||
//Ok(true)
|
||||
//} else if self.arranger.focus_sequencer {
|
||||
//if let Some(sequencer) = self.arranger.sequencer_mut() {
|
||||
//handle_keymap(sequencer, e, KEYMAP_SEQUENCER)
|
||||
//} else {
|
||||
//Ok(false)
|
||||
//}
|
||||
//} else {
|
||||
//handle_keymap(&mut self.arranger, e, KEYMAP_ARRANGER)
|
||||
//}
|
||||
},
|
||||
_ => Ok(false),
|
||||
}
|
||||
match e {
|
||||
AppEvent::Input(Event::Key(KeyEvent { code: KeyCode::Tab, .. })) => {
|
||||
self.focus_next();
|
||||
Ok(true)
|
||||
},
|
||||
AppEvent::Input(Event::Key(KeyEvent { code: KeyCode::BackTab, .. })) => {
|
||||
self.focus_prev();
|
||||
Ok(true)
|
||||
},
|
||||
_ => self.focused_mut().handle(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SequencerProxy(Arc<RwLock<Arranger>>);
|
||||
|
||||
impl Handle for SequencerProxy {
|
||||
fn handle (&mut self, e: &AppEvent) -> Usually<bool> {
|
||||
match self.0.write().unwrap().sequencer_mut() {
|
||||
Some(sequencer) => sequencer.handle(e),
|
||||
None => Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue