5 widgets::{Borders, Widget},
7use helix_view::graphics::{Rect, Style};
9#[derive(Debug, Clone, Copy, PartialEq)]
18 pub fn line_symbols(border_type: BorderType) -> line::Set {
20 BorderType::Plain => line::NORMAL,
21 BorderType::Rounded => line::ROUNDED,
22 BorderType::Double => line::DOUBLE,
23 BorderType::Thick => line::THICK,
28/// Base widget to be used with all upper level ones. It may be used to display a box border around
29/// the widget and/or add a title.
34/// # use helix_tui::widgets::{Block, BorderType, Borders};
35/// # use helix_view::graphics::{Style, Color};
38/// .borders(Borders::LEFT | Borders::RIGHT)
39/// .border_style(Style::default().fg(Color::White))
40/// .border_type(BorderType::Rounded)
41/// .style(Style::default().bg(Color::Black));
43#[derive(Debug, Clone, PartialEq)]
45 /// Optional title place on the upper left of the block
46 title: Option<Spans<'a>>,
51 /// Type of the border. The default is plain lines but one can choose to have rounded corners
52 /// or doubled lines instead.
53 border_type: BorderType,
58impl<'a> Default for Block<'a> {
59 fn default() -> Block<'a> {
62 borders: Borders::NONE,
63 border_style: Default::default(),
64 border_type: BorderType::Plain,
65 style: Default::default(),
71 pub fn title<T>(mut self, title: T) -> Block<'a>
75 self.title = Some(title.into());
81 note = "You should use styling capabilities of `text::Spans` given as argument of the `title` method to apply styling to the title."
83 pub fn title_style(mut self, style: Style) -> Block<'a> {
84 if let Some(t) = self.title {
85 let title = String::from(t);
86 self.title = Some(Spans::from(Span::styled(title, style)));
91 pub fn border_style(mut self, style: Style) -> Block<'a> {
92 self.border_style = style;
96 pub fn style(mut self, style: Style) -> Block<'a> {
101 pub fn borders(mut self, flag: Borders) -> Block<'a> {
106 pub fn border_type(mut self, border_type: BorderType) -> Block<'a> {
107 self.border_type = border_type;
111 /// Compute the inner area of a block based on its border visibility rules.
112 pub fn inner(&self, area: Rect) -> Rect {
113 let mut inner = area;
114 if self.borders.intersects(Borders::LEFT) {
115 inner.x = inner.x.saturating_add(1).min(inner.right());
116 inner.width = inner.width.saturating_sub(1);
118 if self.borders.intersects(Borders::TOP) || self.title.is_some() {
119 inner.y = inner.y.saturating_add(1).min(inner.bottom());
120 inner.height = inner.height.saturating_sub(1);
122 if self.borders.intersects(Borders::RIGHT) {
123 inner.width = inner.width.saturating_sub(1);
125 if self.borders.intersects(Borders::BOTTOM) {
126 inner.height = inner.height.saturating_sub(1);
132impl<'a> Widget for Block<'a> {
133 fn render(self, area: Rect, buf: &mut Buffer) {
134 if area.area() == 0 {
137 buf.set_style(area, self.style);
138 let symbols = BorderType::line_symbols(self.border_type);
141 if self.borders.intersects(Borders::LEFT) {
142 for y in area.top()..area.bottom() {
143 buf.get_mut(area.left(), y)
144 .set_symbol(symbols.vertical)
145 .set_style(self.border_style);
148 if self.borders.intersects(Borders::TOP) {
149 for x in area.left()..area.right() {
150 buf.get_mut(x, area.top())
151 .set_symbol(symbols.horizontal)
152 .set_style(self.border_style);
155 if self.borders.intersects(Borders::RIGHT) {
156 let x = area.right() - 1;
157 for y in area.top()..area.bottom() {
159 .set_symbol(symbols.vertical)
160 .set_style(self.border_style);
163 if self.borders.intersects(Borders::BOTTOM) {
164 let y = area.bottom() - 1;
165 for x in area.left()..area.right() {
167 .set_symbol(symbols.horizontal)
168 .set_style(self.border_style);
173 if self.borders.contains(Borders::RIGHT | Borders::BOTTOM) {
174 buf.get_mut(area.right() - 1, area.bottom() - 1)
175 .set_symbol(symbols.bottom_right)
176 .set_style(self.border_style);
178 if self.borders.contains(Borders::RIGHT | Borders::TOP) {
179 buf.get_mut(area.right() - 1, area.top())
180 .set_symbol(symbols.top_right)
181 .set_style(self.border_style);
183 if self.borders.contains(Borders::LEFT | Borders::BOTTOM) {
184 buf.get_mut(area.left(), area.bottom() - 1)
185 .set_symbol(symbols.bottom_left)
186 .set_style(self.border_style);
188 if self.borders.contains(Borders::LEFT | Borders::TOP) {
189 buf.get_mut(area.left(), area.top())
190 .set_symbol(symbols.top_left)
191 .set_style(self.border_style);
194 if let Some(title) = self.title {
195 let lx = if self.borders.intersects(Borders::LEFT) {
200 let rx = if self.borders.intersects(Borders::RIGHT) {
205 let width = area.width.saturating_sub(lx).saturating_sub(rx);
206 buf.set_spans(area.left() + lx, area.top(), &title, width);
216 fn inner_takes_into_account_the_borders() {
219 Block::default().inner(Rect::default()),
226 "no borders, width=0, height=0"
229 Block::default().inner(Rect {
241 "no borders, width=1, height=1"
246 Block::default().borders(Borders::LEFT).inner(Rect {
261 Block::default().borders(Borders::LEFT).inner(Rect {
276 Block::default().borders(Borders::LEFT).inner(Rect {
293 Block::default().borders(Borders::TOP).inner(Rect {
308 Block::default().borders(Borders::TOP).inner(Rect {
323 Block::default().borders(Borders::TOP).inner(Rect {
340 Block::default().borders(Borders::RIGHT).inner(Rect {
355 Block::default().borders(Borders::RIGHT).inner(Rect {
370 Block::default().borders(Borders::RIGHT).inner(Rect {
387 Block::default().borders(Borders::BOTTOM).inner(Rect {
402 Block::default().borders(Borders::BOTTOM).inner(Rect {
417 Block::default().borders(Borders::BOTTOM).inner(Rect {
435 .borders(Borders::ALL)
436 .inner(Rect::default()),
443 "all borders, width=0, height=0"
446 Block::default().borders(Borders::ALL).inner(Rect {
458 "all borders, width=1, height=1"
461 Block::default().borders(Borders::ALL).inner(Rect {
473 "all borders, width=2, height=2"
476 Block::default().borders(Borders::ALL).inner(Rect {
488 "all borders, width=3, height=3"
493 fn inner_takes_into_account_the_title() {
495 Block::default().title("Test").inner(Rect {
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list