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); } } } }