nvim_gtk/
grid.rs

1use std::ops::{Index, IndexMut};
2use std::rc::Rc;
3
4use fnv::FnvHashMap;
5
6use neovim_lib::Value;
7
8use crate::highlight::{Highlight, HighlightMap};
9use crate::ui_model::{ModelRect, ModelRectVec, UiModel};
10
11const DEFAULT_GRID: u64 = 1;
12
13pub struct GridMap {
14    grids: FnvHashMap<u64, Grid>,
15}
16
17impl Index<u64> for GridMap {
18    type Output = Grid;
19
20    fn index(&self, idx: u64) -> &Grid {
21        &self.grids[&idx]
22    }
23}
24
25impl IndexMut<u64> for GridMap {
26    fn index_mut(&mut self, idx: u64) -> &mut Grid {
27        self.grids.get_mut(&idx).unwrap()
28    }
29}
30
31impl GridMap {
32    pub fn new() -> Self {
33        GridMap {
34            grids: FnvHashMap::default(),
35        }
36    }
37
38    pub fn current(&self) -> Option<&Grid> {
39        self.grids.get(&DEFAULT_GRID)
40    }
41
42    pub fn current_model_mut(&mut self) -> Option<&mut UiModel> {
43        self.grids.get_mut(&DEFAULT_GRID).map(|g| &mut g.model)
44    }
45
46    pub fn current_model(&self) -> Option<&UiModel> {
47        self.grids.get(&DEFAULT_GRID).map(|g| &g.model)
48    }
49
50    pub fn get_or_create(&mut self, idx: u64) -> &mut Grid {
51        if self.grids.contains_key(&idx) {
52            return self.grids.get_mut(&idx).unwrap();
53        }
54
55        self.grids.insert(idx, Grid::new());
56        self.grids.get_mut(&idx).unwrap()
57    }
58
59    pub fn destroy(&mut self, idx: u64) {
60        self.grids.remove(&idx);
61    }
62
63    pub fn clear_glyphs(&mut self) {
64        for grid in self.grids.values_mut() {
65            grid.model.clear_glyphs();
66        }
67    }
68}
69
70pub struct Grid {
71    model: UiModel,
72}
73
74impl Grid {
75    pub fn new() -> Self {
76        Grid {
77            model: UiModel::empty(),
78        }
79    }
80
81    pub fn get_cursor(&self) -> (usize, usize) {
82        self.model.get_cursor()
83    }
84
85    pub fn cur_point(&self) -> ModelRect {
86        self.model.cur_point()
87    }
88
89    pub fn resize(&mut self, columns: u64, rows: u64) {
90        if self.model.columns != columns as usize || self.model.rows != rows as usize {
91            self.model = UiModel::new(rows, columns);
92        }
93    }
94
95    pub fn cursor_goto(&mut self, row: usize, col: usize) -> ModelRectVec {
96        self.model.set_cursor(row, col)
97    }
98
99    pub fn clear(&mut self, default_hl: &Rc<Highlight>) {
100        self.model.clear(default_hl);
101    }
102
103    pub fn line(
104        &mut self,
105        row: usize,
106        col_start: usize,
107        cells: Vec<Vec<Value>>,
108        highlights: &HighlightMap,
109    ) -> ModelRect {
110        let mut hl_id = None;
111        let mut col_end = col_start;
112
113        for cell in cells {
114            let ch = cell.get(0).unwrap().as_str().unwrap_or("");
115            hl_id = cell.get(1).and_then(|h| h.as_u64()).or(hl_id);
116            let repeat = cell.get(2).and_then(|r| r.as_u64()).unwrap_or(1) as usize;
117
118            self.model.put(
119                row,
120                col_end,
121                ch,
122                ch.is_empty(),
123                repeat,
124                highlights.get(hl_id),
125            );
126            col_end += repeat;
127        }
128
129        ModelRect::new(row, row, col_start, col_end - 1)
130    }
131
132    pub fn scroll(
133        &mut self,
134        top: u64,
135        bot: u64,
136        left: u64,
137        right: u64,
138        rows: i64,
139        _: i64,
140        default_hl: &Rc<Highlight>,
141    ) -> ModelRect {
142        self.model.scroll(
143            top as i64,
144            bot as i64 - 1,
145            left as usize,
146            right as usize - 1,
147            rows,
148            default_hl,
149        )
150    }
151}