mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: prototype chains/stacks
This commit is contained in:
parent
dc09ea901f
commit
d330d31ce4
3 changed files with 239 additions and 66 deletions
|
|
@ -1,6 +1,9 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use ratatui::style::Stylize;
|
use ratatui::style::Stylize;
|
||||||
|
|
||||||
|
mod midi;
|
||||||
|
pub use midi::*;
|
||||||
|
|
||||||
pub const ACTIONS: [(&'static str, &'static str);4] = [
|
pub const ACTIONS: [(&'static str, &'static str);4] = [
|
||||||
("+/-", "Zoom"),
|
("+/-", "Zoom"),
|
||||||
("A/D", "Add/delete note"),
|
("A/D", "Add/delete note"),
|
||||||
|
|
@ -14,10 +17,13 @@ pub struct Sequencer {
|
||||||
playing: Arc<AtomicBool>,
|
playing: Arc<AtomicBool>,
|
||||||
recording: Arc<AtomicBool>,
|
recording: Arc<AtomicBool>,
|
||||||
overdub: Arc<AtomicBool>,
|
overdub: Arc<AtomicBool>,
|
||||||
sequence: Arc<Mutex<Vec<Vec<Option<Event>>>>>,
|
inputs_open: Arc<AtomicBool>,
|
||||||
|
outputs_open: Arc<AtomicBool>,
|
||||||
cursor: (u16, u16, u16),
|
cursor: (u16, u16, u16),
|
||||||
timesig: (f32, f32),
|
timesig: (f32, f32),
|
||||||
pub jack_client: Jack<Notifications>,
|
pub jack_client: Jack<Notifications>,
|
||||||
|
sequence: Arc<Mutex<Vec<Vec<Option<Event>>>>>,
|
||||||
|
sequences: Arc<Mutex<Vec<MIDISequence>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
@ -76,6 +82,10 @@ impl Sequencer {
|
||||||
recording: recording.clone(),
|
recording: recording.clone(),
|
||||||
overdub: overdub.clone(),
|
overdub: overdub.clone(),
|
||||||
sequence: sequence.clone(),
|
sequence: sequence.clone(),
|
||||||
|
inputs_open: Arc::new(AtomicBool::new(false)),
|
||||||
|
outputs_open: Arc::new(AtomicBool::new(false)),
|
||||||
|
sequences: Arc::new(Mutex::new(vec![
|
||||||
|
])),
|
||||||
cursor: (11, 0, 0),
|
cursor: (11, 0, 0),
|
||||||
timesig: (4.0, 4.0),
|
timesig: (4.0, 4.0),
|
||||||
jack_client: crate::engine::activate_jack_client(
|
jack_client: crate::engine::activate_jack_client(
|
||||||
|
|
@ -194,6 +204,12 @@ fn handle (state: &mut Sequencer, event: &crate::engine::Event) -> Result<(), Bo
|
||||||
KeyCode::Char(']') => {
|
KeyCode::Char(']') => {
|
||||||
state.cursor.2 = state.cursor.2 + 1
|
state.cursor.2 = state.cursor.2 + 1
|
||||||
},
|
},
|
||||||
|
KeyCode::Char('i') => {
|
||||||
|
state.inputs_open.fetch_xor(true, Ordering::Relaxed);
|
||||||
|
},
|
||||||
|
KeyCode::Char('o') => {
|
||||||
|
state.outputs_open.fetch_xor(true, Ordering::Relaxed);
|
||||||
|
},
|
||||||
KeyCode::Char('a') => {
|
KeyCode::Char('a') => {
|
||||||
let row = state.cursor.0 as usize;
|
let row = state.cursor.0 as usize;
|
||||||
let step = state.cursor.1 as usize;
|
let step = state.cursor.1 as usize;
|
||||||
|
|
@ -213,10 +229,10 @@ fn handle (state: &mut Sequencer, event: &crate::engine::Event) -> Result<(), Bo
|
||||||
}
|
}
|
||||||
|
|
||||||
const NOTE_NAMES: [&'static str;12] = [
|
const NOTE_NAMES: [&'static str;12] = [
|
||||||
"C ", "C#", "D ", "D#", "E ", "F ", "F#", "G ", "G#", "A ", "A#", "B ",
|
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
|
||||||
];
|
];
|
||||||
|
|
||||||
const KEYS: [&'static str; 6] = [
|
const KEYS_VERTICAL: [&'static str; 6] = [
|
||||||
"▀", "▀", "▀", "█", "▄", "▄",
|
"▀", "▀", "▀", "█", "▄", "▄",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -227,42 +243,138 @@ impl WidgetRef for Sequencer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_sequencer (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect) {
|
fn draw_sequencer (sequencer: &Sequencer, buf: &mut Buffer, mut area: Rect) {
|
||||||
area.height = 15;
|
area.height = 18;
|
||||||
draw_box(buf, area);
|
//draw_box(buf, area);
|
||||||
let Rect { x, y, width, height } = area;
|
let Rect { x, y, width, height } = area;
|
||||||
|
//{
|
||||||
|
//let mut area = area.clone();
|
||||||
|
//area.y = area.y + 3;
|
||||||
|
//area.x = area.x + 1;
|
||||||
|
//area.height = area.height - 2;
|
||||||
|
//draw_sequence_keys(area, buf,
|
||||||
|
//&sequencer.jack_client.as_client().transport().query().unwrap(),
|
||||||
|
//&sequencer.sequence,
|
||||||
|
//&sequencer.cursor);
|
||||||
|
//draw_sequence_cursor(area, buf,
|
||||||
|
//&sequencer.cursor);
|
||||||
|
//}
|
||||||
|
//draw_box(buf, Rect { x, y, width: 18, height });
|
||||||
|
|
||||||
|
draw_box(buf, Rect { x, y, width: 40, height: 8 });
|
||||||
|
draw_box(buf, Rect { x, y, width: 40, height: 6 });
|
||||||
|
let style = Style::default().gray();
|
||||||
|
buf.set_string(x + 1, y + 1, &format!(" │ 00:00.00 / 00:00.00"), style);
|
||||||
|
buf.set_string(x + 2, y + 1, &format!("{}", &sequencer.name), style.bold());
|
||||||
|
buf.set_string(x + 1, y + 2, &format!(" ▶ PLAY │ ⏹ STOP │ ⏺ REC │ ⏺ DUB "), style);
|
||||||
|
buf.set_string(x + 0, y + 3, &format!("├--------------------------------------┤"), style.dim());
|
||||||
|
buf.set_string(x + 1, y + 6, &format!(" Inputs... │ Outputs... "), style);
|
||||||
|
buf.set_string(x + 0, y + 5, &format!("├--------------------------------------┤"), style.dim());
|
||||||
|
for i in 0..3 {
|
||||||
|
buf.set_string(1 + i * 12 + x + 1, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
buf.set_string(1 + i * 12 + x + 2, y + 4, &format!(" "), Style::default().on_black());
|
||||||
|
buf.set_string(1 + i * 12 + x + 3, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
buf.set_string(1 + i * 12 + x + 4, y + 4, &format!(" "), Style::default().on_black());
|
||||||
|
buf.set_string(1 + i * 12 + x + 5, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
buf.set_string(1 + i * 12 + x + 6, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
buf.set_string(1 + i * 12 + x + 7, y + 4, &format!(" "), Style::default().on_black());
|
||||||
|
buf.set_string(1 + i * 12 + x + 8, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
buf.set_string(1 + i * 12 + x + 9, y + 4, &format!(" "), Style::default().on_black());
|
||||||
|
buf.set_string(1 + i * 12 + x + 10, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
buf.set_string(1 + i * 12 + x + 11, y + 4, &format!(" "), Style::default().on_black());
|
||||||
|
buf.set_string(1 + i * 12 + x + 12, y + 4, &format!(" "), Style::default().on_white());
|
||||||
|
}
|
||||||
|
//buf.set_string(x + 1, y + 3,
|
||||||
|
//&format!(" │ INPUT │ OUTPUT │"),
|
||||||
|
//Style::default().gray());
|
||||||
|
//buf.set_string(x + 1, y + 5,
|
||||||
|
//&format!(" {} │ IN │ ⏺ REC │ ⏺ DUB │ ▶ PLAY │ ⏹ STOP │ OUT │ 00:00.00 / 00:00.00", &sequencer.name),
|
||||||
|
//Style::default().gray());
|
||||||
|
if sequencer.inputs_open.fetch_and(true, Ordering::Relaxed) {
|
||||||
|
buf.set_string(x + 15, y + 1, "IN", Style::default().green().bold());
|
||||||
|
}
|
||||||
|
if sequencer.outputs_open.fetch_and(true, Ordering::Relaxed) {
|
||||||
|
buf.set_string(x + 54, y + 1, "OUT", Style::default().green().bold());
|
||||||
|
}
|
||||||
|
|
||||||
let mut command = |y2: u16, c: &str, ommand: &str, value: &str| {
|
let mut command = |y2: u16, c: &str, ommand: &str, value: &str| {
|
||||||
buf.set_string(x + 1, y + y2, c, Style::default().bold());
|
buf.set_string(x + 1, y + y2, c, Style::default().bold());
|
||||||
buf.set_string(x + 2, y + y2, ommand, Style::default().dim());
|
buf.set_string(x + 2, y + y2, ommand, Style::default().dim());
|
||||||
buf.set_string(x + 4 + ommand.len() as u16, y + y2, value, Style::default().bold());
|
buf.set_string(x + 4 + ommand.len() as u16, y + y2, value, Style::default().bold());
|
||||||
};
|
};
|
||||||
for (y, c, ommand, value) in [
|
//for (y, c, ommand, value) in [
|
||||||
(5, "I", "nputs", "[+]"),
|
////(5, "I", "nputs", "[+]"),
|
||||||
(6, "O", "utputs", "[+]"),
|
////(6, "O", "utputs", "[+]"),
|
||||||
(7, "C", "hannel", "01"),
|
////(7, "C", "hannel", "01"),
|
||||||
(8, "G", "rid", "1/16"),
|
//(8, "G", "rid", "1/16"),
|
||||||
(9, "Z", "oom", "1/64"),
|
//(9, "Z", "oom", "1/64"),
|
||||||
(10, "R", "ate", "1/1"),
|
//(10, "R", "ate", "1/1"),
|
||||||
(11, "S", "ync", "1 bar"),
|
//(11, "S", "ync", "1 bar"),
|
||||||
(12, "A", "dd note", ""),
|
//(12, "A", "dd note", ""),
|
||||||
(13, "D", "elete note", ""),
|
//(13, "D", "elete note", ""),
|
||||||
] {
|
//] {
|
||||||
command(y, c, ommand, value)
|
//command(y, c, ommand, value)
|
||||||
}
|
//}
|
||||||
{
|
//draw_box(buf, Rect { x, y: y + height - 1, width, height: 3 });
|
||||||
let mut area = area.clone();
|
//buf.set_string(x + 1, y + height,
|
||||||
//area.y = area.y + 1;
|
//&format!(" Grid 1/16 │ Zoom 1/64 │ Rate 1/1 │ Sync 1 bar │ Add note │ Delete note "),
|
||||||
area.x = area.x + 19;
|
//Style::default().gray());
|
||||||
area.height = area.height - 2;
|
//buf.set_string(x + 1, y + 1, &format!(" ▶ {} ", &sequencer.name),
|
||||||
draw_sequence_keys(area, buf,
|
//Style::default().white().bold().not_dim());
|
||||||
&sequencer.jack_client.as_client().transport().query().unwrap(),
|
//buf.set_string(x + 4, y + 0, "┬", Style::default().gray());
|
||||||
&sequencer.sequence,
|
//buf.set_string(x + 4, y + 1, "│", Style::default().gray().dim());
|
||||||
&sequencer.cursor);
|
//buf.set_string(x + 4, y + 2, "┴", Style::default().gray());
|
||||||
draw_sequence_cursor(area, buf,
|
//buf.set_string(x + 21, y + 1, " ⏺ REC DUB ",
|
||||||
&sequencer.cursor);
|
//Style::default().white().bold().not_dim());
|
||||||
}
|
//buf.set_string(x + 18, y + 0, "┬", Style::default().gray());
|
||||||
draw_box(buf, Rect { x, y, width: 18, height });
|
//buf.set_string(x + 18, y + 1, "│", Style::default().gray().dim());
|
||||||
draw_rec_dub_button(buf, x, y + 2);
|
//buf.set_string(x + 18, y + 2, "┴", Style::default().gray());
|
||||||
draw_sequence_button(buf, x, y, &sequencer.name);
|
|
||||||
|
//draw_rec_dub_button(buf, x + 17, y);
|
||||||
|
//draw_sequence_button(buf, x, y, &sequencer.name);
|
||||||
|
|
||||||
|
//draw_leaf(buf, Rect { x, y: y + height, width, height: 2 }, 0, 0, "Inputs ");
|
||||||
|
//draw_leaf(buf, Rect { x, y: y + height, width, height: 2 }, 0, 8, "Outputs");
|
||||||
|
//for x2 in 0..4 {
|
||||||
|
//for y2 in 0..4 {
|
||||||
|
//buf.set_string(
|
||||||
|
//x + 2 + x2 * 3,
|
||||||
|
//y + 5 + y2,
|
||||||
|
//format!("{:>02} ", 1 + x2 + y2 * 4),
|
||||||
|
//Style::default().green().bold().not_dim()
|
||||||
|
//)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
let y = y + 8;
|
||||||
|
draw_box(buf, Rect { x, y: y, width: 40, height: 10 });
|
||||||
|
buf.set_string(x + 1, y + 1, &format!(" LV2Host#00"), style.bold());
|
||||||
|
buf.set_string(x + 13, y + 1, &format!("│ Plugin Name"), style.not_dim());
|
||||||
|
buf.set_string(x + 0, y + 2, &format!("├--------------------------------------┤"), style.dim());
|
||||||
|
buf.set_string(x + 1, y + 3, &format!(" Parameter 1 0.0"), style);
|
||||||
|
buf.set_string(x + 1, y + 4, &format!(" Parameter 2 0.0"), style);
|
||||||
|
buf.set_string(x + 1, y + 5, &format!(" Parameter 3 0.0"), style);
|
||||||
|
buf.set_string(x + 1, y + 6, &format!(" Parameter 4 0.0"), style);
|
||||||
|
buf.set_string(x + 0, y + 7, &format!("├--------------------------------------┤"), style.dim());
|
||||||
|
buf.set_string(x + 1, y + 8, &format!(" Inputs... │ Outputs... "), style);
|
||||||
|
|
||||||
|
let y = y + 10;
|
||||||
|
draw_box(buf, Rect { x, y: y, width: 40, height: 14 });
|
||||||
|
buf.set_string(x + 1, y + 1, &format!(" Sampler#00 │"), style.bold());
|
||||||
|
buf.set_string(x + 0, y + 2, &format!("├--------------------------------------┤"), style.dim());
|
||||||
|
buf.set_string(x + 2, y + 3, &format!("C0 Sample#000"), style.bold());
|
||||||
|
buf.set_string(x + 2, y + 4, &format!(" {:.03}s",
|
||||||
|
100000.0/44100.0), style);
|
||||||
|
buf.set_string(x + 2, y + 5, &format!("C#0 Sample#001"), style.bold());
|
||||||
|
buf.set_string(x + 2, y + 6, &format!(" {:.03}-{:.03}s",
|
||||||
|
50000.0/44100.0, 100000.0/44100.0), style);
|
||||||
|
buf.set_string(x + 2, y + 7, &format!("D0 Sample#002"), style.bold());
|
||||||
|
buf.set_string(x + 2, y + 8, &format!(" {:.03}-{:.03}/{:.03}s",
|
||||||
|
0.0, 50000.0/44100.0, 100000.0/44100.0), style);
|
||||||
|
buf.set_string(x + 2, y + 9, &format!("D#0 Sample#003"), style.bold());
|
||||||
|
buf.set_string(x + 2, y + 10, &format!(" {:.03}-[{:.03}-{:.03}]/{:.03}s ",
|
||||||
|
10000.0/44100.0, 25000.0/44100.0, 50000.0/44100.0, 100000.0/44100.0), style);
|
||||||
|
buf.set_string(x + 0, y + 7 + 4, &format!("├--------------------------------------┤"), style.dim());
|
||||||
|
buf.set_string(x + 1, y + 7 + 5, &format!(" Inputs... │ Outputs... "), style);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_sequence_button (
|
fn draw_sequence_button (
|
||||||
|
|
@ -285,11 +397,14 @@ fn draw_rec_dub_button (
|
||||||
y: u16,
|
y: u16,
|
||||||
) {
|
) {
|
||||||
draw_box(buf, Rect { x, y, width: 18, height: 3 });
|
draw_box(buf, Rect { x, y, width: 18, height: 3 });
|
||||||
buf.set_string(x + 1, y + 1, " ⏺ REC DUB ",
|
buf.set_string(x + 1, y + 1, " ⏺ REC DUB ",
|
||||||
Style::default().white().bold().not_dim());
|
Style::default().white().bold().not_dim());
|
||||||
buf.set_string(x + 4, y + 0, "┬", Style::default().gray());
|
buf.set_string(x + 5, y + 0, "┬", Style::default().gray());
|
||||||
buf.set_string(x + 4, y + 1, "│", Style::default().gray().dim());
|
buf.set_string(x + 5, y + 1, "│", Style::default().gray().dim());
|
||||||
buf.set_string(x + 4, y + 2, "┴", Style::default().gray());
|
buf.set_string(x + 5, y + 2, "┴", Style::default().gray());
|
||||||
|
buf.set_string(x + 11, y + 0, "┬", Style::default().gray());
|
||||||
|
buf.set_string(x + 11, y + 1, "│", Style::default().gray().dim());
|
||||||
|
buf.set_string(x + 11, y + 2, "┴", Style::default().gray());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_sequence_keys (
|
fn draw_sequence_keys (
|
||||||
|
|
@ -324,7 +439,7 @@ fn draw_sequence_keys (
|
||||||
//);
|
//);
|
||||||
let sequence = sequence.lock().unwrap();
|
let sequence = sequence.lock().unwrap();
|
||||||
for key in 0..12 {
|
for key in 0..12 {
|
||||||
buf.set_string(area.x, area.y + 1 + key, KEYS[(key % 6) as usize],
|
buf.set_string(area.x, area.y + 1 + key, KEYS_VERTICAL[(key % 6) as usize],
|
||||||
Style::default().dim());
|
Style::default().dim());
|
||||||
buf.set_string(area.x + 1, area.y + 1 + key, "█",
|
buf.set_string(area.x + 1, area.y + 1 + key, "█",
|
||||||
Style::default().dim());
|
Style::default().dim());
|
||||||
|
|
|
||||||
52
src/device/sequencer/midi.rs
Normal file
52
src/device/sequencer/midi.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
pub struct MIDISequence {
|
||||||
|
channels: [MIDISequenceChannel;16],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MIDISequenceChannel {
|
||||||
|
number: u8,
|
||||||
|
notes: [MIDISequenceVoice;128],
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type MIDISequenceVoice = std::collections::BTreeMap<u32, NoteEvent>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum NoteEvent {
|
||||||
|
On(u8),
|
||||||
|
Off(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
const VOICE_EMPTY: MIDISequenceVoice = MIDISequenceVoice::new();
|
||||||
|
|
||||||
|
impl MIDISequence {
|
||||||
|
fn new () -> Self {
|
||||||
|
Self {
|
||||||
|
channels: [
|
||||||
|
MIDISequenceChannel::new(1),
|
||||||
|
MIDISequenceChannel::new(2),
|
||||||
|
MIDISequenceChannel::new(3),
|
||||||
|
MIDISequenceChannel::new(4),
|
||||||
|
MIDISequenceChannel::new(5),
|
||||||
|
MIDISequenceChannel::new(6),
|
||||||
|
MIDISequenceChannel::new(7),
|
||||||
|
MIDISequenceChannel::new(8),
|
||||||
|
MIDISequenceChannel::new(9),
|
||||||
|
MIDISequenceChannel::new(10),
|
||||||
|
MIDISequenceChannel::new(11),
|
||||||
|
MIDISequenceChannel::new(12),
|
||||||
|
MIDISequenceChannel::new(13),
|
||||||
|
MIDISequenceChannel::new(14),
|
||||||
|
MIDISequenceChannel::new(15),
|
||||||
|
MIDISequenceChannel::new(16),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MIDISequenceChannel {
|
||||||
|
fn new (number: u8) -> Self {
|
||||||
|
Self {
|
||||||
|
number,
|
||||||
|
notes: [VOICE_EMPTY;128]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
62
src/main.rs
62
src/main.rs
|
|
@ -48,9 +48,6 @@ fn main () -> Result<(), Box<dyn Error>> {
|
||||||
)?,
|
)?,
|
||||||
focus: 0,
|
focus: 0,
|
||||||
devices: vec![
|
devices: vec![
|
||||||
crate::device::Device::Mixer(
|
|
||||||
crate::device::mixer::Mixer::new()?
|
|
||||||
),
|
|
||||||
crate::device::Device::Sequencer(
|
crate::device::Device::Sequencer(
|
||||||
crate::device::sequencer::Sequencer::new(
|
crate::device::sequencer::Sequencer::new(
|
||||||
Some("Melody#000"),
|
Some("Melody#000"),
|
||||||
|
|
@ -58,19 +55,22 @@ fn main () -> Result<(), Box<dyn Error>> {
|
||||||
None
|
None
|
||||||
)?
|
)?
|
||||||
),
|
),
|
||||||
crate::device::Device::Sequencer(
|
//crate::device::Device::Sequencer(
|
||||||
crate::device::sequencer::Sequencer::new(
|
//crate::device::sequencer::Sequencer::new(
|
||||||
Some("Rhythm#000"),
|
//Some("Rhythm#000"),
|
||||||
None,
|
//None,
|
||||||
None,
|
//None,
|
||||||
)?
|
//)?
|
||||||
),
|
//),
|
||||||
crate::device::Device::Sampler(
|
//crate::device::Device::Mixer(
|
||||||
crate::device::sampler::Sampler::new()?
|
//crate::device::mixer::Mixer::new()?
|
||||||
),
|
//),
|
||||||
crate::device::Device::Looper(
|
//crate::device::Device::Sampler(
|
||||||
crate::device::looper::Looper::new()?
|
//crate::device::sampler::Sampler::new()?
|
||||||
),
|
//),
|
||||||
|
//crate::device::Device::Looper(
|
||||||
|
//crate::device::looper::Looper::new()?
|
||||||
|
//),
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -106,24 +106,30 @@ impl WidgetRef for App {
|
||||||
fn render_ref (&self, area: Rect, buffer: &mut Buffer) {
|
fn render_ref (&self, area: Rect, buffer: &mut Buffer) {
|
||||||
use ratatui::style::Stylize;
|
use ratatui::style::Stylize;
|
||||||
let mut constraints = vec![
|
let mut constraints = vec![
|
||||||
Constraint::Length(4),
|
Constraint::Max(40),
|
||||||
Constraint::Length(10),
|
Constraint::Max(40),
|
||||||
Constraint::Max(18),
|
|
||||||
Constraint::Max(18),
|
|
||||||
Constraint::Max(0),
|
|
||||||
Constraint::Max(0),
|
|
||||||
Constraint::Max(0),
|
|
||||||
];
|
];
|
||||||
let areas = Layout::default()
|
let areas = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Horizontal)
|
||||||
.constraints(&constraints)
|
.constraints(&constraints)
|
||||||
.split(area);
|
.split(Rect {
|
||||||
|
x: area.x,
|
||||||
|
y: area.y,
|
||||||
|
width: area.width,
|
||||||
|
height: area.height - 4
|
||||||
|
});
|
||||||
|
|
||||||
|
self.transport.render(Rect {
|
||||||
|
x: area.width.saturating_sub(80u16) / 2,
|
||||||
|
y: area.y + area.height - 4,
|
||||||
|
width: area.width,
|
||||||
|
height: 4
|
||||||
|
}, buffer);
|
||||||
|
|
||||||
self.transport.render(areas[0], buffer);
|
|
||||||
for (index, device) in self.devices.iter().enumerate() {
|
for (index, device) in self.devices.iter().enumerate() {
|
||||||
device.render(areas[index + 1], buffer);
|
device.render(areas[index], buffer);
|
||||||
if index == self.focus {
|
if index == self.focus {
|
||||||
draw_focus_corners(buffer, areas[index+1]);
|
draw_focus_corners(buffer, areas[index]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue