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
//! attr modules defines the attributes(colors, effects) of a terminal cell

use bitflags::bitflags;

pub use crate::color::Color;

/// `Attr` is a rendering attribute that contains fg color, bg color and text effect.
///
/// ```
/// use tuikit::attr::{Attr, Effect, Color};
///
/// let attr = Attr { fg: Color::RED, effect: Effect::BOLD, ..Attr::default() };
/// ```
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Attr {
    pub fg: Color,
    pub bg: Color,
    pub effect: Effect,
}

impl Default for Attr {
    fn default() -> Self {
        Attr {
            fg: Color::default(),
            bg: Color::default(),
            effect: Effect::empty(),
        }
    }
}

impl Attr {
    /// extend the properties with the new attr's if the properties in new attr is not default.
    /// ```
    /// use tuikit::attr::{Attr, Color, Effect};
    ///
    /// let default = Attr{fg: Color::BLUE, bg: Color::YELLOW, effect: Effect::BOLD};
    /// let new = Attr{fg: Color::Default, bg: Color::WHITE, effect: Effect::REVERSE};
    /// let extended = default.extend(new);
    ///
    /// assert_eq!(Color::BLUE, extended.fg);
    /// assert_eq!(Color::WHITE, extended.bg);
    /// assert_eq!(Effect::BOLD | Effect::REVERSE, extended.effect);
    /// ```
    pub fn extend(&self, new_attr: Self) -> Attr {
        Attr {
            fg: if new_attr.fg != Color::default() {
                new_attr.fg
            } else {
                self.fg
            },
            bg: if new_attr.bg != Color::default() {
                new_attr.bg
            } else {
                self.bg
            },
            effect: self.effect | new_attr.effect,
        }
    }

    pub fn fg(mut self, fg: Color) -> Self {
        self.fg = fg;
        self
    }

    pub fn bg(mut self, bg: Color) -> Self {
        self.bg = bg;
        self
    }

    pub fn effect(mut self, effect: Effect) -> Self {
        self.effect = effect;
        self
    }
}

bitflags! {
    /// `Effect` is the effect of a text
    pub struct Effect: u8 {
        const BOLD = 0b00000001;
        const DIM = 0b00000010;
        const UNDERLINE = 0b00000100;
        const BLINK = 0b00001000;
        const REVERSE = 0b00010000;
    }
}

impl From<Color> for Attr {
    fn from(fg: Color) -> Self {
        Attr {
            fg,
            ..Default::default()
        }
    }
}

impl From<Effect> for Attr {
    fn from(effect: Effect) -> Self {
        Attr {
            effect,
            ..Default::default()
        }
    }
}