1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! A simple character spinner for bars with no known size

use super::*;

/// A single character spinner with optional title that can be told to spin whenever it wants. It implements `Spinner` trait, and is the default spinner.
///
/// The spinner takes up a line, and renders it's spinner on the end of its title. Calling the `Spinner::bump()` function will cause the character sequence to advance.
///
/// # Usage
/// To use the spinner you can provide it a `Wheel` (see [[wheel]] module), or it implements the `Default` trait, creating a traditional looking spinner (`|/-\`)
///
/// ```rust
/// let mut spin = Spin::default(); //Default new spinner without a title.
/// ```
///
/// # How it looks
/// It renders in the terminal like:
/// `This is a spinner /`
pub struct Spin
{
    title: String,
    current: char,
    chars: wheel::WheelIntoIter,
}

impl Spin
{
    /// Create a new spinner with title and wheel.
    ///
    /// To give it the default wheel, you can pass `whl` `Default::default()` to use the default one.
    pub fn with_title(title: &str, whl: wheel::Wheel) -> Self
    {
	let mut chars = whl.into_iter();
	let current = chars.next().unwrap();
	Self {
	    title: title.to_string(),
	    current,
	    chars,
	}
    }
    /// Create a new blank spinner with a wheel
    ///
    /// # Example
    /// ```rust
    ///  Spin::new(Default::default()); // Create a spinner with the default wheel ('|/-\')
    /// ```
    pub fn new(whl: wheel::Wheel) -> Self
    {
	let mut chars = whl.into_iter();
	let current = chars.next().unwrap();
	Self {
	    title: String::new(),
	    current,
	    chars,
	}
    }

    /// Consume the spinner and complete it. Removes the spin character.
    pub fn complete(self) {
	println!("{} ", (8u8 as char));
    }
    
    /// Consume the spinner and complete it with a message. Removes the spin character and then prints the message.
    pub fn complete_with(self, msg: &str)
    {
	println!("{}{}", (8u8 as char), msg);
    }
}

impl Default for Spin
{
    fn default() -> Self
    {
	Self {
	    title: String::new(),
	    chars: wheel::Wheel::default().into_iter(),
	    current: '|',
	}
    }
}

impl Display for Spin
{
    fn refresh(&self)
    {
	print!("\r{} {}", self.title, self.current);
	flush!();
    }
    fn blank(&self)
    {
	print!("\r{}  \r", " ".repeat(self.title.chars().count()));
	flush!();
    }
    fn get_title(&self) -> &str
    {
	&self.title[..]
    }
    fn set_title(&mut self, from: &str)
    {
	self.blank();
	self.title = from.to_string();
	self.refresh();
    }
    fn update_dimensions(&mut self, _to:usize){}

    fn println(&self, string: &str)
    {
	self.blank();
	println!("{}", string);
	self.refresh();
    }
}

impl Spinner for Spin
{
    fn bump(&mut self)
    {
	self.current = self.chars.next().unwrap();
	self.refresh();
    }
}