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
use crate::color::*;
use crate::geometry::*;
use crate::graphics::*;
use std::io;

pub trait Painter {
    fn paint(&mut self, drawing: Drawing) -> io::Result<()>;
    fn get_area(&self) -> Window;
    fn get_size(&self) -> Point {
        self.get_area().size
    }
    fn fill(&mut self, c: Color) -> io::Result<()> {
        let area = self.get_area();
        self.paint(
            " ".repeat(area.size.area() as usize)
                .as_drawing()
                .size(area.size)
                .bg(c),
        )?;
        Ok(())
    }
}

impl<'a, T> Painter for &'a mut T
where
    T: Painter + ?Sized + 'a,
{
    fn paint(&mut self, drawing: Drawing) -> io::Result<()> {
        Painter::paint(*self, drawing)
    }
    fn get_area(&self) -> Window {
        Painter::get_area(*self)
    }
}

pub struct PainterScope<P> {
    painter: P,
    scope: Window,
    style: Style,
}

impl<P> PainterScope<P> {
    pub fn new(painter: P, scope: Window, style: Style) -> Self {
        PainterScope {
            painter,
            scope,
            style,
        }
    }
}

impl<P> Painter for PainterScope<P>
where
    P: Painter,
{
    fn paint(&mut self, mut drawing: Drawing) -> io::Result<()> {
        drawing.style = drawing.style.or(&self.style);
        drawing.scope.position += self.scope.position;
        drawing.scope = &drawing.scope & &self.scope;
        drawing.scope.position -= self.painter.get_area().position;
        self.painter.paint(drawing)
    }
    fn get_area(&self) -> Window {
        self.scope
    }
}

#[test]
fn test_painter_fill() {
    #[derive(Default, Debug)]
    struct FakePainter {
        drawing: Option<Drawing>,
        window: Window,
        painters: Vec<Box<FakePainter>>,
    }

    impl FakePainter {}

    impl Painter for FakePainter {
        fn paint(&mut self, drawing: Drawing) -> io::Result<()> {
            self.drawing = Some(drawing);
            Ok(())
        }
        fn get_area(&self) -> Window {
            self.window
        }
    }

    let mut sut = FakePainter::default();

    sut.window = window(point(x(0), y(0)), point(x(3), y(4)));
    sut.fill(WHITE);
    assert_eq!(
        sut.drawing,
        Some("            ".as_drawing().width(3).height(4).bg(WHITE))
    );

    sut.window = window(point(x(5), y(3)), point(x(3), y(4)));
    sut.fill(RED);
    assert_eq!(
        sut.drawing,
        Some("            ".as_drawing().width(3).height(4).bg(RED))
    );
}