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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142


use ::pty;
use std::fmt;
use std::mem;
use std::ops::{BitAnd, Index, RangeTo};

use super::relative::Relative;

#[repr(C)]
#[derive(Copy)]
pub struct Tooltip {
    cardinal: Relative,
    message: [pty::Character; 1024],
}

impl Tooltip {
    /// Return the height of the message, assuming all `\n`
    pub fn get_height(&self) -> usize {
        self.message.iter().filter(|&&nl| nl.is_enter()).count() + 1
    }

    /// Return the width of the message, assuming the characters between all `\n`
    pub fn get_width(&self) -> usize {
        self.message.split(|&nl| nl.is_enter()).fold(0, |acc, x| {
            if x.iter().find(|&x| x.is_null()).is_none() && acc < x.len() {
                x.len()
            } else if x.iter().find(|&&x| x.is_null()).is_some() {
                match x.iter().position(|&x| x.is_null()) {
                    Some(i) => if acc < i { i } else { acc },
                    None => acc,
                }
            } else {
                acc
            }
        })
    }

    pub fn get_cardinal(&self) -> &Relative {
        &self.cardinal
    }

    pub fn get_message(&self) -> &[pty::Character; 1024] {
        &self.message
    }

    pub fn set_message(&mut self, message: String) {
        self.message
            .iter_mut()
            .zip(message.chars())
            .all(|(mut_character, character): (&mut pty::Character, char)| {
                *mut_character = pty::Character::from(character);
                true
            });
        self.message
            .iter_mut()
            .skip(message.len())
            .all(|mut_character: &mut pty::Character| {
                mut_character.clear();
                true
            });
    }

    pub fn set_cardinal(&mut self, cardinal: Relative) {
        self.cardinal = cardinal
    }
}

impl Index<usize> for Tooltip {
    type Output = pty::Character;

    fn index(&self, count: usize) -> &pty::Character {
        &self.message[count]
    }
}

impl Index<RangeTo<usize>> for Tooltip {
    type Output = [pty::Character];

    fn index(&self, range: RangeTo<usize>) -> &[pty::Character] {
        &self.message[range]
    }
}

impl PartialEq for Tooltip {
    fn eq(&self, other: &Tooltip) -> bool {
        self.cardinal
            .eq(&other.cardinal)
            .bitand(self.message
                .iter()
                .zip(other.message.iter())
                .all(|(letter, other_letter)| letter.eq(&other_letter)))
    }
}

impl fmt::Display for Tooltip {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Tooltip {{ cardinal: {:?}, message: \"{}\"... }}",
               self.cardinal,
               self.message
                   .iter()
                   .take(5)
                   .map(|character| character.get_glyph())
                   .collect::<String>())
    }
}

impl fmt::Debug for Tooltip {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "Tooltip {{ cardinal: {:?}, message: {} }}",
               self.cardinal,
               self.message
                   .iter()
                   .take(1024)
                   .map(|character| character.get_glyph())
                   .collect::<String>())
    }
}

impl Clone for Tooltip {
    fn clone(&self) -> Self {
        unsafe {
            let mut message: [pty::Character; 1024] = mem::uninitialized();
            message.copy_from_slice(&self.message);
            Tooltip {
                cardinal: self.cardinal,
                message: message,
            }
        }
    }
}

impl Default for Tooltip {
    fn default() -> Self {
        Tooltip {
            cardinal: Relative::Left,
            message: [pty::Character::from('\0'); 1024],
        }
    }
}