television_screen/
spinner.rs1use ratatui::{
2 buffer::Buffer, layout::Rect, style::Style, widgets::StatefulWidget,
3};
4
5const FRAMES: &[&str] = &["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
6
7#[derive(Debug, Clone, Copy)]
9pub struct Spinner {
10 frames: &'static [&'static str],
11}
12
13impl Spinner {
14 pub fn new(frames: &'static [&str]) -> Spinner {
15 Spinner { frames }
16 }
17
18 pub fn frame(&self, index: usize) -> &str {
19 self.frames[index]
20 }
21}
22
23impl Default for Spinner {
24 fn default() -> Spinner {
25 Spinner::new(FRAMES)
26 }
27}
28
29#[derive(Debug)]
30pub struct SpinnerState {
31 pub current_frame: usize,
32 total_frames: usize,
33}
34
35impl SpinnerState {
36 pub fn new(total_frames: usize) -> SpinnerState {
37 SpinnerState {
38 current_frame: 0,
39 total_frames,
40 }
41 }
42
43 fn tick(&mut self) {
44 self.current_frame = (self.current_frame + 1) % self.total_frames;
45 }
46}
47
48impl From<&Spinner> for SpinnerState {
49 fn from(spinner: &Spinner) -> SpinnerState {
50 SpinnerState::new(spinner.frames.len())
51 }
52}
53
54impl StatefulWidget for Spinner {
55 type State = SpinnerState;
56
57 fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
59 buf.set_string(
60 area.left(),
61 area.top(),
62 self.frame(state.current_frame),
63 Style::default(),
64 );
65 state.tick();
66 }
67}
68impl StatefulWidget for &Spinner {
69 type State = SpinnerState;
70
71 fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
73 buf.set_string(
74 area.left(),
75 area.top(),
76 self.frame(state.current_frame),
77 Style::default(),
78 );
79 state.tick();
80 }
81}