diff options
Diffstat (limited to 'helix-term/src/ui/spinner.rs')
-rw-r--r-- | helix-term/src/ui/spinner.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/helix-term/src/ui/spinner.rs b/helix-term/src/ui/spinner.rs new file mode 100644 index 00000000..e8a43b48 --- /dev/null +++ b/helix-term/src/ui/spinner.rs @@ -0,0 +1,75 @@ +use std::{collections::HashMap, time::SystemTime}; + +#[derive(Default, Debug)] +pub struct ProgressSpinners { + inner: HashMap<usize, Spinner>, +} + +impl ProgressSpinners { + pub fn get(&self, id: usize) -> Option<&Spinner> { + self.inner.get(&id) + } + + pub fn get_or_create(&mut self, id: usize) -> &mut Spinner { + self.inner.entry(id).or_insert_with(Spinner::default) + } +} + +impl Default for Spinner { + fn default() -> Self { + Self::dots(80) + } +} + +#[derive(Debug)] +pub struct Spinner { + frames: Vec<&'static str>, + count: usize, + start: Option<SystemTime>, + interval: u64, +} + +impl Spinner { + /// Creates a new spinner with `frames` and `interval`. + /// Expects the frames count and interval to be greater than 0. + pub fn new(frames: Vec<&'static str>, interval: u64) -> Self { + let count = frames.len(); + assert!(count > 0); + assert!(interval > 0); + + Self { + frames, + count, + interval, + start: None, + } + } + + pub fn dots(interval: u64) -> Self { + Self::new(vec!["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"], interval) + } + + pub fn start(&mut self) { + self.start = Some(SystemTime::now()); + } + + pub fn frame(&self) -> Option<&str> { + let idx = (self + .start + .map(|time| SystemTime::now().duration_since(time))? + .ok()? + .as_millis() + / self.interval as u128) as usize + % self.count; + + self.frames.get(idx).copied() + } + + pub fn stop(&mut self) { + self.start = None; + } + + pub fn is_stopped(&self) -> bool { + self.start.is_none() + } +} |