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