tui_temp_fork/widgets/
tabs.rs1use unicode_width::UnicodeWidthStr;
2
3use crate::buffer::Buffer;
4use crate::layout::Rect;
5use crate::style::Style;
6use crate::symbols::line;
7use crate::widgets::{Block, Widget};
8
9pub struct Tabs<'a, T>
27where
28 T: AsRef<str> + 'a,
29{
30 block: Option<Block<'a>>,
32 titles: &'a [T],
34 selected: usize,
36 style: Style,
38 highlight_style: Style,
40 divider: &'a str,
42}
43
44impl<'a, T> Default for Tabs<'a, T>
45where
46 T: AsRef<str>,
47{
48 fn default() -> Tabs<'a, T> {
49 Tabs {
50 block: None,
51 titles: &[],
52 selected: 0,
53 style: Default::default(),
54 highlight_style: Default::default(),
55 divider: line::VERTICAL,
56 }
57 }
58}
59
60impl<'a, T> Tabs<'a, T>
61where
62 T: AsRef<str>,
63{
64 pub fn block(mut self, block: Block<'a>) -> Tabs<'a, T> {
65 self.block = Some(block);
66 self
67 }
68
69 pub fn titles(mut self, titles: &'a [T]) -> Tabs<'a, T> {
70 self.titles = titles;
71 self
72 }
73
74 pub fn select(mut self, selected: usize) -> Tabs<'a, T> {
75 self.selected = selected;
76 self
77 }
78
79 pub fn style(mut self, style: Style) -> Tabs<'a, T> {
80 self.style = style;
81 self
82 }
83
84 pub fn highlight_style(mut self, style: Style) -> Tabs<'a, T> {
85 self.highlight_style = style;
86 self
87 }
88
89 pub fn divider(mut self, divider: &'a str) -> Tabs<'a, T> {
90 self.divider = divider;
91 self
92 }
93}
94
95impl<'a, T> Widget for Tabs<'a, T>
96where
97 T: AsRef<str>,
98{
99 fn draw(&mut self, area: Rect, buf: &mut Buffer) {
100 let tabs_area = match self.block {
101 Some(ref mut b) => {
102 b.draw(area, buf);
103 b.inner(area)
104 }
105 None => area,
106 };
107
108 if tabs_area.height < 1 {
109 return;
110 }
111
112 self.background(tabs_area, buf, self.style.bg);
113
114 let mut x = tabs_area.left();
115 let titles_length = self.titles.len();
116 let divider_width = self.divider.width() as u16;
117 for (title, style, last_title) in self.titles.iter().enumerate().map(|(i, t)| {
118 let lt = i + 1 == titles_length;
119 if i == self.selected {
120 (t, self.highlight_style, lt)
121 } else {
122 (t, self.style, lt)
123 }
124 }) {
125 x += 1;
126 if x > tabs_area.right() {
127 break;
128 } else {
129 buf.set_string(x, tabs_area.top(), title.as_ref(), style);
130 x += title.as_ref().width() as u16 + 1;
131 if x >= tabs_area.right() || last_title {
132 break;
133 } else {
134 buf.set_string(x, tabs_area.top(), self.divider, self.style);
135 x += divider_width;
136 }
137 }
138 }
139 }
140}