mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-08 04:36:45 +01:00
border style macro
This commit is contained in:
parent
afa2a2fd2b
commit
117f4d5363
4 changed files with 123 additions and 139 deletions
26
src/main.rs
26
src/main.rs
|
|
@ -9,21 +9,21 @@ extern crate clap;
|
||||||
extern crate jack as _jack;
|
extern crate jack as _jack;
|
||||||
extern crate crossterm;
|
extern crate crossterm;
|
||||||
|
|
||||||
pub mod cli;
|
mod cli;
|
||||||
pub mod config;
|
mod config;
|
||||||
pub mod control;
|
mod control;
|
||||||
pub mod core;
|
mod core;
|
||||||
pub mod model;
|
mod model;
|
||||||
pub mod view;
|
mod view;
|
||||||
pub mod jack;
|
mod jack;
|
||||||
pub mod edn;
|
mod edn;
|
||||||
|
|
||||||
use crate::{core::*, model::*};
|
use crate::{core::*, model::*};
|
||||||
|
|
||||||
/// Application entrypoint.
|
/// Application entrypoint.
|
||||||
pub fn main () -> Usually<()> {
|
fn main () -> Usually<()> {
|
||||||
let midi_from = ["nanoKEY Studio.*capture.*"];
|
let controller = ["nanoKEY Studio.*capture.*"];
|
||||||
let audio_into = ["Komplete.+:playback_FL", "Komplete.+:playback_FR"];
|
let soundsystem = ["Komplete.+:playback_FL", "Komplete.+:playback_FR"];
|
||||||
// Start main loop
|
// Start main loop
|
||||||
App::new()?.run(Some(|app: Arc<RwLock<App>>|{
|
App::new()?.run(Some(|app: Arc<RwLock<App>>|{
|
||||||
let mut state = app.write().unwrap();
|
let mut state = app.write().unwrap();
|
||||||
|
|
@ -32,7 +32,7 @@ pub fn main () -> Usually<()> {
|
||||||
let client = jack.as_client();
|
let client = jack.as_client();
|
||||||
state.transport = Some(client.transport());
|
state.transport = Some(client.transport());
|
||||||
state.midi_in = Some(client.register_port("midi-in", MidiIn)?);
|
state.midi_in = Some(client.register_port("midi-in", MidiIn)?);
|
||||||
let _ = midi_from
|
controller
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name|client
|
.map(|name|client
|
||||||
.ports(Some(name), None, PortFlags::empty())
|
.ports(Some(name), None, PortFlags::empty())
|
||||||
|
|
@ -45,7 +45,7 @@ pub fn main () -> Usually<()> {
|
||||||
})
|
})
|
||||||
.collect::<Usually<()>>())
|
.collect::<Usually<()>>())
|
||||||
.collect::<Usually<()>>()?;
|
.collect::<Usually<()>>()?;
|
||||||
state.audio_outs = audio_into
|
state.audio_outs = soundsystem
|
||||||
.iter()
|
.iter()
|
||||||
.map(|name|client
|
.map(|name|client
|
||||||
.ports(Some(name), None, PortFlags::empty())
|
.ports(Some(name), None, PortFlags::empty())
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,11 @@ pub use self::sequencer::SequencerView;
|
||||||
use crate::{render, App, core::*};
|
use crate::{render, App, core::*};
|
||||||
|
|
||||||
render!(App |self, buf, area| {
|
render!(App |self, buf, area| {
|
||||||
let track = self.track_cursor;
|
|
||||||
Split::down([
|
Split::down([
|
||||||
&TransportView::new(self),
|
&TransportView::new(self),
|
||||||
&Split::down([
|
&Split::down([
|
||||||
&ArrangerView::new(&self, !self.arranger_mode),
|
&ArrangerView::new(&self, !self.arranger_mode),
|
||||||
&If(track > 0, &Split::right([
|
&If(self.track_cursor > 0, &Split::right([
|
||||||
&ChainView::vertical(&self),
|
&ChainView::vertical(&self),
|
||||||
&SequencerView::new(&self),
|
&SequencerView::new(&self),
|
||||||
]))
|
]))
|
||||||
|
|
|
||||||
|
|
@ -10,154 +10,139 @@ pub trait BorderStyle {
|
||||||
const SW: &'static str = "";
|
const SW: &'static str = "";
|
||||||
const W: &'static str = "";
|
const W: &'static str = "";
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn draw (&self, buf: &mut Buffer, area: Rect) {
|
fn draw (&self, buf: &mut Buffer, area: Rect) {
|
||||||
self.draw_horizontal(buf, area);
|
self.draw_horizontal(buf, area, None);
|
||||||
self.draw_vertical(buf, area);
|
self.draw_vertical(buf, area, None);
|
||||||
self.draw_corners(buf, area);
|
self.draw_corners(buf, area, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_horizontal (&self, buf: &mut Buffer, area: Rect) {
|
#[inline]
|
||||||
let style = self.style();
|
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) {
|
for x in area.x..(area.x+area.width).saturating_sub(1) {
|
||||||
Self::N.blit(buf, x, area.y, style);
|
self.draw_north(buf, x, area.y, style);
|
||||||
Self::S.blit(buf, x, area.y + area.height - 1, 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) {
|
#[inline]
|
||||||
let style = self.style();
|
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) {
|
for y in area.y..(area.y+area.height).saturating_sub(1) {
|
||||||
Self::W.blit(buf, area.x, y, style);
|
Self::W.blit(buf, area.x, y, style);
|
||||||
Self::E.blit(buf, area.x + area.width - 1, y, style);
|
Self::E.blit(buf, area.x + area.width - 1, y, style);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_corners (&self, buf: &mut Buffer, area: Rect) {
|
#[inline]
|
||||||
let style = self.style();
|
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::NW.blit(buf, area.x, area.y, style);
|
||||||
Self::NE.blit(buf, area.x + area.width - 1, 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::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);
|
Self::SE.blit(buf, area.x + area.width - 1, area.y + area.height - 1, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn style (&self) -> Option<Style> {
|
fn style (&self) -> Option<Style> {
|
||||||
None
|
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);
|
pub struct Lozenge(pub Style);
|
||||||
|
pub struct LozengeV(pub Style);
|
||||||
impl BorderStyle for Lozenge {
|
pub struct LozengeDotted(pub Style);
|
||||||
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 Quarter(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 QuarterV(pub Style);
|
||||||
|
pub struct Chamfer(pub Style);
|
||||||
|
|
||||||
impl BorderStyle for QuarterV {
|
border! {
|
||||||
const NW: &'static str = "▎";
|
Lozenge {
|
||||||
const W: &'static str = "▎";
|
"╭" "─" "╮"
|
||||||
const SW: &'static str = "▎";
|
"│" "│"
|
||||||
const NE: &'static str = "🮇";
|
"╰" "─" "╯"
|
||||||
const E: &'static str = "🮇";
|
fn style (&self) -> Option<Style> {
|
||||||
const SE: &'static str = "🮇";
|
Some(self.0)
|
||||||
|
}
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,7 @@ impl<'a> ChainView<'a> {
|
||||||
} else {
|
} else {
|
||||||
style
|
style
|
||||||
};
|
};
|
||||||
lozenge_left(buf, x + x2, y, frame.height, style);
|
LozengeV(style.unwrap_or(Style::default())).draw(buf, frame);
|
||||||
lozenge_right(buf, x + x2 + frame.width - 1, y, frame.height, style);
|
|
||||||
//let mut y2 = 1u16;
|
//let mut y2 = 1u16;
|
||||||
//for port in device.midi_outs()?.iter() {
|
//for port in device.midi_outs()?.iter() {
|
||||||
//port.blit(buf, x + x2 + frame.width, y + y2, Some(Style::default()));
|
//port.blit(buf, x + x2 + frame.width, y + y2, Some(Style::default()));
|
||||||
|
|
@ -165,7 +164,8 @@ impl<'a> ChainView<'a> {
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
if frames.len() > 0 {
|
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))
|
Ok((Rect { x, y: area.y, width: w, height: y - area.y }, frames))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue