use crate::core::buffer::Buffer;
use crate::core::color::Color;
use crate::core::rect::Rect;
use crate::style::Style;
use crate::widgets::Widget;
#[derive(Debug, Clone)]
pub struct Tabs<'a> {
pub titles: &'a [&'a str],
pub selected: usize,
pub style: Style,
pub highlight_style: Style,
pub divider: &'a str,
}
impl<'a> Tabs<'a> {
pub fn new(titles: &'a [&'a str]) -> Self {
Self {
titles,
selected: 0,
style: Style::new().fg(Color::rgb(139, 148, 158)),
highlight_style: Style::new().fg(Color::rgb(88, 166, 255)).bold(),
divider: " │ ",
}
}
pub fn with_selected(mut self, selected: usize) -> Self {
self.selected = selected;
self
}
pub fn with_style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn with_highlight_style(mut self, style: Style) -> Self {
self.highlight_style = style;
self
}
pub fn select_next(&mut self) {
self.selected = (self.selected + 1) % self.titles.len();
}
pub fn select_prev(&mut self) {
self.selected = if self.selected == 0 {
self.titles.len() - 1
} else {
self.selected - 1
};
}
}
impl<'a> Widget for Tabs<'a> {
fn render(&self, buffer: &mut Buffer, area: Rect) {
let mut x = area.x as usize;
for (i, title) in self.titles.iter().enumerate() {
if x >= area.right() as usize {
break;
}
let is_selected = i == self.selected;
let (fg, bg, _bold) = if is_selected {
(
self.highlight_style.fg_or_default(),
self.highlight_style.bg,
self.highlight_style.bold,
)
} else {
(self.style.fg_or_default(), self.style.bg, self.style.bold)
};
let display: String = title
.chars()
.take(area.width as usize - x + area.x as usize)
.collect();
buffer.set_str_bold(x, area.y as usize, &display, fg, bg);
x += display.len();
if i < self.titles.len() - 1 && x < area.right() as usize {
let div: String = self
.divider
.chars()
.take(area.width as usize - x + area.x as usize)
.collect();
buffer.set_str(x, area.y as usize, &div, self.style.fg_or_default(), bg);
x += div.len();
}
}
}
}