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}