Initial implementation of linearization of the Editor grid storage

Converts the Editor grid from a nested Vec<Vec<GridCell>> to a Vec<GridCell> structure.
Does the same thing with the dirty structure
macos-click-through
Jon Valdes 5 years ago committed by Jon Valdés
parent b411bd786d
commit 0fe0475b6d

@ -31,8 +31,8 @@ pub struct DrawCommand {
} }
pub struct Editor { pub struct Editor {
pub grid: Vec<Vec<GridCell>>, pub grid: Vec<GridCell>,
pub dirty: Vec<Vec<bool>>, pub dirty: Vec<bool>,
pub should_clear: bool, pub should_clear: bool,
pub title: String, pub title: String,
@ -66,6 +66,36 @@ impl Editor {
editor editor
} }
pub fn cell_index(&self, x: u64, y: u64) -> Option<usize> {
let (width, height) = self.size;
if x >= width || y >= height {
None
}else{
Some((x + y * width) as usize)
}
}
pub fn is_dirty_cell(&self, x: u64, y: u64) -> bool{
if let Some(idx) = self.cell_index(x, y) {
self.dirty[idx]
}else{
false
}
}
pub fn set_dirty_cell(&mut self, x: u64, y: u64) {
if let Some(idx) = self.cell_index(x, y) {
self.dirty[idx] = true;
}
}
fn rows<'a> (&'a self) -> Vec<&'a [GridCell]> {
let (width, height) = self.size;
(0..height).map(|row| {
&self.grid[(row * width) as usize .. ((row+1) * width) as usize]
}).collect()
}
pub fn handle_redraw_event(&mut self, event: RedrawEvent) { pub fn handle_redraw_event(&mut self, event: RedrawEvent) {
match event { match event {
RedrawEvent::SetTitle { title } => self.title = title, RedrawEvent::SetTitle { title } => self.title = title,
@ -97,7 +127,7 @@ impl Editor {
pub fn build_draw_commands(&mut self) -> (Vec<DrawCommand>, bool) { pub fn build_draw_commands(&mut self) -> (Vec<DrawCommand>, bool) {
let mut draw_commands = Vec::new(); let mut draw_commands = Vec::new();
for (row_index, row) in self.grid.iter().enumerate() { for (row_index, row) in self.rows().iter().enumerate() {
let mut command = None; let mut command = None;
fn add_command(commands_list: &mut Vec<DrawCommand>, command: Option<DrawCommand>) { fn add_command(commands_list: &mut Vec<DrawCommand>, command: Option<DrawCommand>) {
@ -150,22 +180,22 @@ impl Editor {
} }
let should_clear = self.should_clear; let should_clear = self.should_clear;
let (width, height) = self.size;
let draw_commands = draw_commands.into_iter().filter(|command| { let draw_commands = draw_commands.into_iter().filter(|command| {
let (x, y) = command.grid_position; let (x, y) = command.grid_position;
let dirty_row = &self.dirty[y as usize];
let min = (x as i64 - 1).max(0) as u64; let min = (x as i64 - 1).max(0) as u64;
let max = (x + command.cell_width + 1).min(dirty_row.len() as u64); let max = (x + command.cell_width + 1).min(width);
for char_index in min..max { for char_index in min..max {
if dirty_row[char_index as usize] { if self.is_dirty_cell(char_index, y) {
return true; return true;
} }
} }
return false; return false;
}).collect::<Vec<DrawCommand>>(); }).collect::<Vec<DrawCommand>>();
let (width, height) = self.size; self.dirty = vec![false; (width * height) as usize];
self.dirty = vec![vec![false; width as usize]; height as usize];
self.should_clear = false; self.should_clear = false;
trace!("Draw commands sent"); trace!("Draw commands sent");
@ -184,19 +214,16 @@ impl Editor {
text = text.repeat(times as usize); text = text.repeat(times as usize);
} }
let row = self.grid.get_mut(row_index as usize).expect("Grid must have size greater than row_index");
let dirty_row = &mut self.dirty[row_index as usize];
if text.is_empty() { if text.is_empty() {
row[*column_pos as usize] = Some(("".to_string(), style.clone())); let cell_index = self.cell_index(*column_pos, row_index).expect("Should not paint outside of grid");
dirty_row[*column_pos as usize] = true; self.grid[cell_index] = Some(("".to_string(), style.clone()));
self.set_dirty_cell(*column_pos, row_index);
*column_pos = *column_pos + 1; *column_pos = *column_pos + 1;
} else { } else {
for (i, character) in text.graphemes(true).enumerate() { for (i, character) in text.graphemes(true).enumerate() {
let pointer_index = i + *column_pos as usize; if let Some(cell_index) = self.cell_index(i as u64 + *column_pos, row_index) {
if pointer_index < row.len() { self.grid[cell_index] = Some((character.to_string(), style.clone()));
row[pointer_index] = Some((character.to_string(), style.clone())); self.set_dirty_cell(*column_pos, row_index);
dirty_row[pointer_index] = true;
} }
} }
*column_pos = *column_pos + text.graphemes(true).count() as u64; *column_pos = *column_pos + text.graphemes(true).count() as u64;
@ -223,12 +250,11 @@ impl Editor {
Box::new((top as i64 .. (bot as i64 + rows)).rev()) Box::new((top as i64 .. (bot as i64 + rows)).rev())
}; };
let grid_width = self.size.0; let (_, height) = self.size;
let grid_height = self.size.1;
for y in y_iter { for y in y_iter {
let dest_y = y - rows; let dest_y = y - rows;
if dest_y >= 0 && dest_y < grid_height as i64 { if dest_y >= 0 && dest_y < height as i64 {
let x_iter : Box<dyn Iterator<Item=i64>> = if cols > 0 { let x_iter : Box<dyn Iterator<Item=i64>> = if cols > 0 {
Box::new((left as i64 + cols) .. right as i64) Box::new((left as i64 + cols) .. right as i64)
@ -238,10 +264,12 @@ impl Editor {
for x in x_iter { for x in x_iter {
let dest_x = x - cols; let dest_x = x - cols;
if dest_x >= 0 && dest_x < grid_width as i64 { let source_idx = self.cell_index(x as u64, y as u64);
let cell = self.grid[y as usize][x as usize].clone(); let dest_idx = self.cell_index(dest_x as u64, dest_y as u64);
self.grid[dest_y as usize][dest_x as usize] = cell;
self.dirty[dest_y as usize][dest_x as usize] = true; if let (Some(source_idx), Some(dest_idx)) = (source_idx, dest_idx) {
self.grid[dest_idx] = self.grid[source_idx].clone();
self.set_dirty_cell(dest_x as u64, dest_y as u64);
} }
} }
} }
@ -258,8 +286,8 @@ impl Editor {
fn clear(&mut self) { fn clear(&mut self) {
trace!("Editor cleared"); trace!("Editor cleared");
let (width, height) = self.size; let (width, height) = self.size;
self.grid = vec![vec![None; width as usize]; height as usize]; self.grid = vec![None; (width * height) as usize];
self.dirty = vec![vec![true; width as usize]; height as usize]; self.dirty = vec![true; (width * height) as usize];
self.should_clear = true; self.should_clear = true;
} }

@ -201,16 +201,13 @@ impl CursorRenderer {
let (character, font_dimensions): (String, Point) = { let (character, font_dimensions): (String, Point) = {
let editor = EDITOR.lock().unwrap(); let editor = EDITOR.lock().unwrap();
let character = editor.grid let character = editor.cell_index(grid_x, grid_y)
.get(grid_y as usize) .and_then(|idx| editor.grid[idx].as_ref())
.and_then(|row| row.get(grid_x as usize).cloned()) .map(|(character, _)| character.clone())
.flatten() .unwrap_or_else(|| ' '.to_string());
.map(|(character, _)| character)
.unwrap_or(' '.to_string()); let is_double = editor.cell_index(grid_x + 1, grid_y)
let is_double = editor.grid .and_then(|idx| editor.grid[idx].as_ref())
.get(grid_y as usize)
.and_then(|row| row.get(grid_x as usize + 1).cloned())
.flatten()
.map(|(character, _)| character.is_empty()) .map(|(character, _)| character.is_empty())
.unwrap_or(false); .unwrap_or(false);

Loading…
Cancel
Save