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
use crate::layout::*;
use crate::*;
use core::marker::PhantomData;

pub struct Grid<L: Layout, const LEN: usize> {
    layout: PhantomData<L>,
    sprite_id: SpriteId,
    state: [Glyph; LEN],
    origins: [Point; LEN],
    invalidate: [bool; LEN],
    cursor: usize,
}

impl<L: Layout, const LEN: usize> Grid<L, LEN>
where
    L: Layout,
{
    pub fn new<SI: Into<SpriteId>>(
        sprite_id: SI,
        val: &str,
        origin: Point,
        sprite_size: Size,
    ) -> Self {
        let mut state: [Glyph; LEN] = [0; LEN];
        let mut invalidate: [bool; LEN] = [false; LEN];

        for (idx, sym) in val.bytes().enumerate() {
            state[idx] = sym;
            invalidate[idx] = true;
        }

        let mut origins: [Point; LEN] = [Point::zero(); LEN];
        for (idx, pos) in origins.iter_mut().enumerate() {
            *pos = L::layout(idx, origin, sprite_size);
        }

        Self {
            origins,
            state,
            invalidate,
            cursor: 0,
            sprite_id: sprite_id.into(),
            layout: PhantomData {},
        }
    }
}

impl<L: Layout, const LEN: usize> Grid<L, LEN> {
    pub fn set_glyph(&mut self, idx: usize, glyph: Glyph) {
        if self.state[idx] != glyph {
            self.state[idx] = glyph;
            self.invalidate[idx] = true;
        }
    }
}

impl<L: Layout, const LEN: usize> Widget<&[Glyph; LEN]> for Grid<L, LEN> {
    fn update(&mut self, state: &[Glyph; LEN]) {
        for (idx, glyph) in state.iter().enumerate() {
            self.set_glyph(idx, *glyph);
        }
        self.cursor = 0;
    }

    fn invalidate(&mut self) {
        for invalidate in self.invalidate.iter_mut() {
            *invalidate = true;
        }
    }

    fn render<D: Display>(&mut self, display: &mut D) {
        for (idx, invalidate) in self.invalidate.iter_mut().enumerate() {
            if *invalidate {
                let glyph = self.state[idx];
                display.render(RenderRequest::new(self.origins[idx], self.sprite_id, glyph));
                *invalidate = false;
            }
        }
    }
}

impl<L: Layout, const LEN: usize> core::fmt::Write for Grid<L, LEN> {
    fn write_str(&mut self, s: &str) -> core::fmt::Result {
        let mut cursor = self.cursor;
        for glyph in s.as_bytes() {
            self.set_glyph(cursor, *glyph);
            cursor += 1;
            if cursor >= LEN {
                cursor = 0;
            }
        }
        self.cursor = cursor;
        Ok(())
    }
}