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