border style macro

This commit is contained in:
🪞👃🪞 2024-07-09 19:58:13 +03:00
parent afa2a2fd2b
commit 117f4d5363
4 changed files with 123 additions and 139 deletions

View file

@ -9,21 +9,21 @@ extern crate clap;
extern crate jack as _jack;
extern crate crossterm;
pub mod cli;
pub mod config;
pub mod control;
pub mod core;
pub mod model;
pub mod view;
pub mod jack;
pub mod edn;
mod cli;
mod config;
mod control;
mod core;
mod model;
mod view;
mod jack;
mod edn;
use crate::{core::*, model::*};
/// Application entrypoint.
pub fn main () -> Usually<()> {
let midi_from = ["nanoKEY Studio.*capture.*"];
let audio_into = ["Komplete.+:playback_FL", "Komplete.+:playback_FR"];
fn main () -> Usually<()> {
let controller = ["nanoKEY Studio.*capture.*"];
let soundsystem = ["Komplete.+:playback_FL", "Komplete.+:playback_FR"];
// Start main loop
App::new()?.run(Some(|app: Arc<RwLock<App>>|{
let mut state = app.write().unwrap();
@ -32,7 +32,7 @@ pub fn main () -> Usually<()> {
let client = jack.as_client();
state.transport = Some(client.transport());
state.midi_in = Some(client.register_port("midi-in", MidiIn)?);
let _ = midi_from
controller
.iter()
.map(|name|client
.ports(Some(name), None, PortFlags::empty())
@ -45,7 +45,7 @@ pub fn main () -> Usually<()> {
})
.collect::<Usually<()>>())
.collect::<Usually<()>>()?;
state.audio_outs = audio_into
state.audio_outs = soundsystem
.iter()
.map(|name|client
.ports(Some(name), None, PortFlags::empty())

View file

@ -17,12 +17,11 @@ pub use self::sequencer::SequencerView;
use crate::{render, App, core::*};
render!(App |self, buf, area| {
let track = self.track_cursor;
Split::down([
&TransportView::new(self),
&Split::down([
&ArrangerView::new(&self, !self.arranger_mode),
&If(track > 0, &Split::right([
&If(self.track_cursor > 0, &Split::right([
&ChainView::vertical(&self),
&SequencerView::new(&self),
]))

View file

@ -10,154 +10,139 @@ pub trait BorderStyle {
const SW: &'static str = "";
const W: &'static str = "";
#[inline]
fn draw (&self, buf: &mut Buffer, area: Rect) {
self.draw_horizontal(buf, area);
self.draw_vertical(buf, area);
self.draw_corners(buf, area);
self.draw_horizontal(buf, area, None);
self.draw_vertical(buf, area, None);
self.draw_corners(buf, area, None);
}
fn draw_horizontal (&self, buf: &mut Buffer, area: Rect) {
let style = self.style();
#[inline]
fn draw_horizontal (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) {
let style = style.or_else(||self.style_horizontal());
for x in area.x..(area.x+area.width).saturating_sub(1) {
Self::N.blit(buf, x, area.y, style);
Self::S.blit(buf, x, area.y + area.height - 1, style);
self.draw_north(buf, x, area.y, style);
self.draw_south(buf, x, (area.y + area.height).saturating_sub(1), style);
}
}
#[inline]
fn draw_north (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) {
Self::N.blit(buf, x, y, style);
}
#[inline]
fn draw_south (&self, buf: &mut Buffer, x: u16, y: u16, style: Option<Style>) {
Self::S.blit(buf, x, y, style);
}
fn draw_vertical (&self, buf: &mut Buffer, area: Rect) {
let style = self.style();
#[inline]
fn draw_vertical (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) {
let style = style.or_else(||self.style_vertical());
for y in area.y..(area.y+area.height).saturating_sub(1) {
Self::W.blit(buf, area.x, y, style);
Self::E.blit(buf, area.x + area.width - 1, y, style);
}
}
fn draw_corners (&self, buf: &mut Buffer, area: Rect) {
let style = self.style();
#[inline]
fn draw_corners (&self, buf: &mut Buffer, area: Rect, style: Option<Style>) {
let style = style.or_else(||self.style_corners());
Self::NW.blit(buf, area.x, area.y, style);
Self::NE.blit(buf, area.x + area.width - 1, area.y, style);
Self::SW.blit(buf, area.x, area.y + area.height - 1, style);
Self::SE.blit(buf, area.x + area.width - 1, area.y + area.height - 1, style);
}
#[inline]
fn style (&self) -> Option<Style> {
None
}
#[inline]
fn style_horizontal (&self) -> Option<Style> {
self.style()
}
#[inline]
fn style_vertical (&self) -> Option<Style> {
self.style()
}
#[inline]
fn style_corners (&self) -> Option<Style> {
self.style()
}
}
macro_rules! border {
($($T:ty {
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
$($x:tt)*
}),+) => {
$(impl BorderStyle for $T {
const NW: &'static str = $nw;
const N: &'static str = $n;
const NE: &'static str = $ne;
const W: &'static str = $w;
const E: &'static str = $e;
const SW: &'static str = $sw;
const S: &'static str = $s;
const SE: &'static str = $se;
$($x)*
})+
}
}
pub struct Lozenge(pub Style);
impl BorderStyle for Lozenge {
const N: &'static str = "";
const S: &'static str = "";
const NW: &'static str = "";
const W: &'static str = "";
const SW: &'static str = "";
const NE: &'static str = "";
const E: &'static str = "";
const SE: &'static str = "";
fn style (&self) -> Option<Style> {
Some(self.0)
}
}
pub struct LozengeV(pub Style);
pub struct LozengeDotted(pub Style);
pub struct Quarter(pub Style);
impl BorderStyle for Quarter {
const N: &'static str = "";
const S: &'static str = "";
const NW: &'static str = "";
const W: &'static str = "";
const SW: &'static str = "";
const NE: &'static str = "🮇";
const E: &'static str = "🮇";
const SE: &'static str = "🮇";
fn style (&self) -> Option<Style> {
Some(self.0)
}
}
pub struct QuarterV(pub Style);
pub struct Chamfer(pub Style);
impl BorderStyle for QuarterV {
const NW: &'static str = "";
const W: &'static str = "";
const SW: &'static str = "";
const NE: &'static str = "🮇";
const E: &'static str = "🮇";
const SE: &'static str = "🮇";
fn style (&self) -> Option<Style> {
Some(self.0)
border! {
Lozenge {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
LozengeV {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
LozengeDotted {
"" "" ""
"" ""
"" "" ""
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Quarter {
"" "" "🮇"
"" "🮇"
"" "" "🮇"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
QuarterV {
"" "" "🮇"
"" "🮇"
"" "" "🮇"
fn style (&self) -> Option<Style> {
Some(self.0)
}
},
Chamfer {
"🭂" "" "🭍"
"" "🮇"
"🭓" "" "🭞"
fn style (&self) -> Option<Style> {
Some(self.0)
}
}
}
const LOZENGE: [[&'static str;3];3] = [
["", "", ""],
["", " ", ""],
["", "", ""],
];
pub fn lozenge_left (buf: &mut Buffer, x: u16, y1: u16, h: u16, style: Option<Style>) {
let y2 = y1 + h;
let y3 = y2.saturating_sub(1);
for y in y1..y2 {
if y == y1 {
LOZENGE[0][0]
} else if y == y3 {
LOZENGE[2][0]
} else {
LOZENGE[1][0]
}.blit(buf, x, y, style)
}
}
pub fn lozenge_right (buf: &mut Buffer, x: u16, y1: u16, h: u16, style: Option<Style>) {
let y2 = y1 + h;
let y3 = y2.saturating_sub(1);
for y in y1..y2 {
if y == y1 {
LOZENGE[0][2]
} else if y == y3 {
LOZENGE[2][2]
} else {
LOZENGE[1][2]
}.blit(buf, x, y, style)
}
}
pub fn draw_box (buffer: &mut Buffer, area: Rect) -> Rect {
draw_box_styled(buffer, area, Some(Style::default().gray().dim()))
}
pub fn draw_box_styled (buffer: &mut Buffer, area: Rect, style: Option<Style>) -> Rect {
if area.width < 1 || area.height < 1 {
return area
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
"".blit(buffer, area.x, y, style);
"".blit(buffer, area.x + area.width - 1, y, style);
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y + area.height - 1, style);
area
}
pub fn draw_box_styled_dotted (buffer: &mut Buffer, area: Rect, style: Option<Style>) -> Rect {
if area.width < 1 || area.height < 1 {
return area
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
"".blit(buffer, area.x, y, style);
"".blit(buffer, area.x + area.width - 1, y, style);
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y + area.height - 1, style);
area
}

View file

@ -97,8 +97,7 @@ impl<'a> ChainView<'a> {
} else {
style
};
lozenge_left(buf, x + x2, y, frame.height, style);
lozenge_right(buf, x + x2 + frame.width - 1, y, frame.height, style);
LozengeV(style.unwrap_or(Style::default())).draw(buf, frame);
//let mut y2 = 1u16;
//for port in device.midi_outs()?.iter() {
//port.blit(buf, x + x2 + frame.width, y + y2, Some(Style::default()));
@ -165,7 +164,8 @@ impl<'a> ChainView<'a> {
//}
}
if frames.len() > 0 {
draw_box_styled(buf, frames[track.device], selected);
Lozenge(selected.unwrap_or(Style::default()))
.draw(buf, frames[track.device]);
}
Ok((Rect { x, y: area.y, width: w, height: y - area.y }, frames))