1use ratatui::buffer::Buffer;
5use ratatui::layout::{Rect, Size};
6use ratatui::prelude::{BlockExt, Widget};
7use ratatui::style::{Style, Stylize};
8use ratatui::widgets::{Block, Padding};
9use std::{fmt, mem};
10
11pub fn union_non_empty(area1: Rect, area2: Rect) -> Rect {
15 if area1.is_empty() && area2.is_empty() {
16 Rect::new(area1.x, area1.y, 0, 0)
17 } else if area1.is_empty() {
18 area2
19 } else if area2.is_empty() {
20 area1
21 } else {
22 area1.union(area2)
23 }
24}
25
26pub fn revert_style(mut style: Style) -> Style {
32 if style.fg.is_some() || style.bg.is_some() {
33 mem::swap(&mut style.fg, &mut style.bg);
34 style
35 } else {
36 style.black().on_white()
37 }
38}
39
40pub fn fallback_select_style(style: Style) -> Style {
42 if style.fg.is_some() || style.bg.is_some() {
43 style
44 } else {
45 style.underlined()
46 }
47}
48
49pub fn reset_buf_area(area: Rect, buf: &mut Buffer) {
51 for y in area.top()..area.bottom() {
52 for x in area.left()..area.right() {
53 if let Some(cell) = buf.cell_mut((x, y)) {
54 cell.reset();
55 }
56 }
57 }
58}
59
60pub fn fill_buf_area(buf: &mut Buffer, area: Rect, symbol: &str, style: impl Into<Style>) {
62 let style = style.into();
63
64 for y in area.top()..area.bottom() {
65 for x in area.left()..area.right() {
66 if let Some(cell) = buf.cell_mut((x, y)) {
67 cell.reset();
68 cell.set_symbol(symbol);
69 cell.set_style(style);
70 }
71 }
72 }
73}
74
75pub fn rect_dbg(area: Rect) -> String {
76 use fmt::Write;
77 let mut buf = String::new();
78 _ = write!(buf, "{}:{}+{}+{}", area.x, area.y, area.width, area.height);
79 buf
80}
81
82pub(crate) const DOUBLE_VERTICAL_SINGLE_LEFT: &str = "\u{2562}";
83pub(crate) const DOUBLE_VERTICAL_SINGLE_RIGHT: &str = "\u{255F}";
84pub(crate) const THICK_VERTICAL_SINGLE_LEFT: &str = "\u{2528}";
85pub(crate) const THICK_VERTICAL_SINGLE_RIGHT: &str = "\u{2520}";
86
87pub fn block_padding(block: &Option<Block<'_>>) -> Padding {
89 let area = Rect::new(0, 0, 20, 20);
90 let inner = block.inner_if_some(area);
91 Padding {
92 left: inner.left() - area.left(),
93 right: area.right() - inner.right(),
94 top: inner.top() - area.top(),
95 bottom: area.bottom() - inner.bottom(),
96 }
97}
98
99pub fn block_padding2(block: &Block<'_>) -> Padding {
101 let area = Rect::new(0, 0, 20, 20);
102 let inner = block.inner(area);
103 Padding {
104 left: inner.left() - area.left(),
105 right: area.right() - inner.right(),
106 top: inner.top() - area.top(),
107 bottom: area.bottom() - inner.bottom(),
108 }
109}
110
111pub fn block_size(block: &Option<Block<'_>>) -> Size {
113 let area = Rect::new(0, 0, 20, 20);
114 let inner = block.inner_if_some(area);
115 Size {
116 width: (inner.left() - area.left()) + (area.right() - inner.right()),
117 height: (inner.top() - area.top()) + (area.bottom() - inner.bottom()),
118 }
119}
120
121pub(crate) fn block_left(block: &Block<'_>) -> String {
122 let area = Rect::new(0, 0, 3, 3);
123 let mut buf = Buffer::empty(area);
124 block.clone().render(area, &mut buf);
125 buf.cell((0, 1)).expect("cell").symbol().into()
126}
127
128pub(crate) fn block_right(block: &Block<'_>) -> String {
129 let area = Rect::new(0, 0, 3, 3);
130 let mut buf = Buffer::empty(area);
131 block.clone().render(area, &mut buf);
132 buf.cell((2, 1)).expect("cell").symbol().into()
133}
134
135#[allow(dead_code)]
136pub(crate) fn block_top(block: &Block<'_>) -> String {
137 let area = Rect::new(0, 0, 3, 3);
138 let mut buf = Buffer::empty(area);
139 block.clone().render(area, &mut buf);
140 buf.cell((1, 0)).expect("cell").symbol().into()
141}
142
143#[allow(dead_code)]
144pub(crate) fn block_bottom(block: &Block<'_>) -> String {
145 let area = Rect::new(0, 0, 3, 3);
146 let mut buf = Buffer::empty(area);
147 block.clone().render(area, &mut buf);
148 buf.cell((1, 2)).expect("cell").symbol().into()
149}