datui_lib/widgets/ui/
working.rs1use crate::render::context::RenderContext;
5use ratatui::buffer::Buffer;
6use ratatui::layout::Rect;
7use ratatui::style::{Modifier, Style};
8use ratatui::text::{Line, Span};
9use ratatui::widgets::{Clear, Paragraph, Widget};
10
11#[derive(Clone, Copy)]
12pub struct Working<'a> {
13 pub text: &'a str,
14 pub frame: usize,
16}
17
18impl Working<'_> {
19 pub fn line(&self, ctx: &RenderContext) -> Line<'static> {
20 let g = crate::glyphs::get();
21 Line::from(vec![
22 Span::styled(
23 format!("{} ", g.spinner[self.frame % g.spinner.len()]),
24 Style::default().fg(ctx.throbber),
25 ),
26 Span::styled(
27 self.text.to_string(),
28 Style::default()
29 .fg(ctx.text_primary)
30 .add_modifier(Modifier::BOLD),
31 ),
32 ])
33 }
34
35 pub fn render_centered(&self, area: Rect, buf: &mut Buffer, ctx: &RenderContext) {
38 Clear.render(area, buf);
39 if area.height == 0 {
40 return;
41 }
42 let y = area.y + (area.height / 2).saturating_sub(1);
43 Paragraph::new(self.line(ctx)).centered().render(
44 Rect {
45 y,
46 height: 1,
47 ..area
48 },
49 buf,
50 );
51 }
52
53 pub fn render_corner(&self, area: Rect, buf: &mut Buffer, ctx: &RenderContext) {
56 let line = self.line(ctx);
57 let width = (line.width() as u16 + 2).min(area.width);
59 if area.height == 0 || width == 0 {
60 return;
61 }
62 let spot = Rect {
63 x: area.right() - width,
64 y: area.y,
65 width,
66 height: 1,
67 };
68 Clear.render(spot, buf);
69 Paragraph::new(line).centered().render(spot, buf);
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn centered_replaces_what_was_there() {
79 let ctx = RenderContext::for_test();
80 let area = Rect::new(0, 0, 30, 5);
81 let mut buf = Buffer::empty(area);
82 Paragraph::new(vec![Line::from("old"); 5]).render(area, &mut buf);
83 Working {
84 text: "Applying SQL query...",
85 frame: 0,
86 }
87 .render_centered(area, &mut buf, &ctx);
88 let rows = crate::tests::buffer_lines(&buf);
89 assert!(rows[1].contains("Applying SQL query..."), "{rows:#?}");
90 assert!(rows.iter().all(|row| !row.contains("old")), "{rows:#?}");
91 }
92
93 #[test]
94 fn corner_keeps_what_is_under_it() {
95 let ctx = RenderContext::for_test();
96 let area = Rect::new(0, 0, 40, 3);
97 let mut buf = Buffer::empty(area);
98 Paragraph::new(vec![Line::from("chart"); 3]).render(area, &mut buf);
99 Working {
100 text: "Computing...",
101 frame: 0,
102 }
103 .render_corner(area, &mut buf, &ctx);
104 let rows = crate::tests::buffer_lines(&buf);
105 assert!(rows[0].trim_end().ends_with("Computing..."), "{rows:#?}");
106 assert!(rows.iter().all(|row| row.starts_with("chart")), "{rows:#?}");
107 }
108}