105 lines
3.3 KiB
Rust
105 lines
3.3 KiB
Rust
use crate::theme;
|
|
use ratatui::buffer::Buffer;
|
|
use ratatui::layout::Rect;
|
|
use ratatui::widgets::Widget;
|
|
|
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
|
pub enum MuteStatus {
|
|
Normal,
|
|
Muted,
|
|
Soloed,
|
|
EffectivelyMuted, // Solo active on another pattern
|
|
}
|
|
|
|
pub struct ActivePatterns<'a> {
|
|
patterns: &'a [(usize, usize, usize)], // (bank, pattern, iter)
|
|
mute_status: Option<&'a [MuteStatus]>,
|
|
current_step: Option<(usize, usize)>, // (current_step, total_steps)
|
|
}
|
|
|
|
impl<'a> ActivePatterns<'a> {
|
|
pub fn new(patterns: &'a [(usize, usize, usize)]) -> Self {
|
|
Self {
|
|
patterns,
|
|
mute_status: None,
|
|
current_step: None,
|
|
}
|
|
}
|
|
|
|
pub fn with_step(mut self, current: usize, total: usize) -> Self {
|
|
self.current_step = Some((current, total));
|
|
self
|
|
}
|
|
|
|
pub fn with_mute_status(mut self, status: &'a [MuteStatus]) -> Self {
|
|
self.mute_status = Some(status);
|
|
self
|
|
}
|
|
}
|
|
|
|
impl Widget for ActivePatterns<'_> {
|
|
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
if area.width < 10 || area.height == 0 {
|
|
return;
|
|
}
|
|
let theme = theme::get();
|
|
|
|
let max_pattern_rows = if self.current_step.is_some() {
|
|
area.height.saturating_sub(1) as usize
|
|
} else {
|
|
area.height as usize
|
|
};
|
|
|
|
for (row, &(bank, pattern, iter)) in self.patterns.iter().enumerate() {
|
|
if row >= max_pattern_rows {
|
|
break;
|
|
}
|
|
|
|
let mute_status = self
|
|
.mute_status
|
|
.and_then(|s| s.get(row))
|
|
.copied()
|
|
.unwrap_or(MuteStatus::Normal);
|
|
|
|
let (prefix, fg, bg) = match mute_status {
|
|
MuteStatus::Soloed => ("S", theme.list.soloed_fg, theme.list.soloed_bg),
|
|
MuteStatus::Muted => ("M", theme.list.muted_fg, theme.list.muted_bg),
|
|
MuteStatus::EffectivelyMuted => (" ", theme.list.muted_fg, theme.list.muted_bg),
|
|
MuteStatus::Normal => {
|
|
let bg = if row % 2 == 0 {
|
|
theme.table.row_even
|
|
} else {
|
|
theme.table.row_odd
|
|
};
|
|
(" ", theme.ui.text_primary, bg)
|
|
}
|
|
};
|
|
|
|
let text = format!("{}B{:02}:{:02}({:02})", prefix, bank + 1, pattern + 1, iter.min(99));
|
|
let y = area.y + row as u16;
|
|
|
|
let mut chars = text.chars();
|
|
for col in 0..area.width as usize {
|
|
let ch = chars.next().unwrap_or(' ');
|
|
buf[(area.x + col as u16, y)]
|
|
.set_char(ch)
|
|
.set_fg(fg)
|
|
.set_bg(bg);
|
|
}
|
|
}
|
|
|
|
if let Some((current, total)) = self.current_step {
|
|
let text = format!("{:02}/{:02}", current + 1, total);
|
|
let y = area.y + area.height.saturating_sub(1);
|
|
let mut chars = text.chars();
|
|
for col in 0..area.width as usize {
|
|
let ch = chars.next().unwrap_or(' ');
|
|
buf[(area.x + col as u16, y)]
|
|
.set_char(ch)
|
|
.set_fg(theme.ui.text_primary)
|
|
.set_bg(theme.table.row_even);
|
|
}
|
|
}
|
|
}
|
|
}
|