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
use super::{Coord, Size};
use rgb24::Rgb24;

#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ViewCell {
    pub character: Option<char>,
    pub bold: Option<bool>,
    pub underline: Option<bool>,
    pub foreground: Option<Rgb24>,
    pub background: Option<Rgb24>,
}

impl ViewCell {
    pub const fn new() -> Self {
        Self {
            character: None,
            bold: None,
            underline: None,
            foreground: None,
            background: None,
        }
    }
    pub const fn with_character(self, character: char) -> Self {
        Self {
            character: Some(character),
            ..self
        }
    }
    pub const fn with_bold(self, bold: bool) -> Self {
        Self {
            bold: Some(bold),
            ..self
        }
    }
    pub const fn with_underline(self, underline: bool) -> Self {
        Self {
            underline: Some(underline),
            ..self
        }
    }
    pub const fn with_foreground(self, foreground: Rgb24) -> Self {
        Self {
            foreground: Some(foreground),
            ..self
        }
    }
    pub const fn with_background(self, background: Rgb24) -> Self {
        Self {
            background: Some(background),
            ..self
        }
    }
    pub fn set_character(&mut self, character: char) {
        self.character = Some(character);
    }
    pub fn clear_character(&mut self) {
        self.character = None;
    }
    pub fn set_bold(&mut self, bold: bool) {
        self.bold = Some(bold);
    }
    pub fn clear_bold(&mut self) {
        self.bold = None;
    }
    pub fn set_underline(&mut self, underline: bool) {
        self.underline = Some(underline);
    }
    pub fn clear_underline(&mut self) {
        self.underline = None;
    }
    pub fn set_foreground(&mut self, foreground: Rgb24) {
        self.foreground = Some(foreground);
    }
    pub fn clear_foreground(&mut self) {
        self.foreground = None;
    }
    pub fn set_background(&mut self, background: Rgb24) {
        self.background = Some(background);
    }
    pub fn clear_background(&mut self) {
        self.background = None;
    }
    pub fn coalesce(self, other: Self) -> Self {
        Self {
            character: (self.character.or(other.character)),
            bold: (self.bold.or(other.bold)),
            underline: (self.underline.or(other.underline)),
            foreground: (self.foreground.or(other.foreground)),
            background: (self.background.or(other.background)),
        }
    }
}

/// A grid of cells
pub trait ViewGrid {
    fn set_cell(&mut self, coord: Coord, depth: i32, info: ViewCell);
    fn size(&self) -> Size;
}

/// Defines a method for rendering a `T` to the terminal.
pub trait View<T: ?Sized> {
    /// Update the cells in `grid` to describe how a type should be rendered.
    /// This mutably borrows `self` to allow the view to contain buffers/caches which
    /// are updated during rendering.
    fn view<G: ViewGrid>(&mut self, data: &T, offset: Coord, depth: i32, grid: &mut G);
}

/// Report the size of a `T` when rendered.
pub trait ViewSize<T: ?Sized> {
    /// Returns the size in cells of the rectangle containing a ui element.
    /// This allows for the implementation of decorator ui components that
    /// render a border around some inner element.
    fn size(&mut self, data: &T) -> Size;
}