Better external API for EditorGrid, returning Option<&mut GridCell> for external code to modify the cells

macos-click-through
Jon Valdés 5 years ago
parent d8e974ee12
commit 9450ea62d8

@ -3,15 +3,15 @@ use log::trace;
use super::style::Style; use super::style::Style;
type GridCell = Option<(String, Option<Arc<Style>>)>; pub type GridCell = Option<(String, Option<Arc<Style>>)>;
pub struct CharacterGrid { pub struct CharacterGrid {
pub characters: Vec<GridCell>,
pub width: u64, pub width: u64,
pub height: u64, pub height: u64,
pub should_clear: bool, pub should_clear: bool,
dirty: Vec<bool>, dirty: Vec<bool>,
characters: Vec<GridCell>,
} }
impl CharacterGrid { impl CharacterGrid {
@ -25,22 +25,25 @@ impl CharacterGrid {
} }
} }
pub fn resize(&mut self, new_size: (u64, u64)) { pub fn resize(&mut self, width: u64, height: u64) {
trace!("Editor resized"); trace!("Editor resized");
self.width = new_size.0; self.width = width;
self.height = new_size.1; self.height = height;
self.clear(); self.clear();
} }
pub fn clear(&mut self) { pub fn clear(&mut self) {
trace!("Editor cleared"); trace!("Editor cleared");
self.characters.clear();
self.dirty.clear();
let cell_count = (self.width * self.height) as usize; let cell_count = (self.width * self.height) as usize;
self.characters = vec![None; cell_count]; self.characters.resize_with(cell_count, || None);
self.dirty = vec![true; cell_count]; self.dirty.resize_with(cell_count, || true);
self.should_clear = true; self.should_clear = true;
} }
pub fn cell_index(&self, x: u64, y: u64) -> Option<usize> { fn cell_index(&self, x: u64, y: u64) -> Option<usize> {
if x >= self.width || y >= self.height { if x >= self.width || y >= self.height {
None None
} else { } else {
@ -48,6 +51,14 @@ impl CharacterGrid {
} }
} }
pub fn get_cell<'a>(&'a self, x: u64, y: u64) -> Option<&'a GridCell> {
self.cell_index(x,y).map(|idx| &self.characters[idx])
}
pub fn get_cell_mut<'a>(&'a mut self, x: u64, y: u64) -> Option<&'a mut GridCell> {
self.cell_index(x,y).map(move |idx| &mut self.characters[idx])
}
pub fn is_dirty_cell(&self, x: u64, y: u64) -> bool { pub fn is_dirty_cell(&self, x: u64, y: u64) -> bool {
if let Some(idx) = self.cell_index(x, y) { if let Some(idx) = self.cell_index(x, y) {
self.dirty[idx] self.dirty[idx]
@ -63,7 +74,8 @@ impl CharacterGrid {
} }
pub fn set_dirty_all(&mut self, value: bool) { pub fn set_dirty_all(&mut self, value: bool) {
self.dirty.resize(self.dirty.len(), value); self.dirty.clear();
self.dirty.resize_with((self.width * self.height) as usize, || value);
} }
pub fn rows<'a>(&'a self) -> Vec<&'a [GridCell]> { pub fn rows<'a>(&'a self) -> Vec<&'a [GridCell]> {

@ -80,7 +80,7 @@ impl Editor {
trace!("Image flushed"); trace!("Image flushed");
REDRAW_SCHEDULER.queue_next_frame(); REDRAW_SCHEDULER.queue_next_frame();
}, },
RedrawEvent::Resize { width, height, .. } => self.grid.resize((width, height)), RedrawEvent::Resize { width, height, .. } => self.grid.resize(width, height),
RedrawEvent::DefaultColorsSet { colors } => self.default_style = Arc::new(Style::new(colors)), RedrawEvent::DefaultColorsSet { colors } => self.default_style = Arc::new(Style::new(colors)),
RedrawEvent::HighlightAttributesDefine { id, style } => { self.defined_styles.insert(id, Arc::new(style)); }, RedrawEvent::HighlightAttributesDefine { id, style } => { self.defined_styles.insert(id, Arc::new(style)); },
RedrawEvent::GridLine { row, column_start, cells, .. } => self.draw_grid_line(row, column_start, cells), RedrawEvent::GridLine { row, column_start, cells, .. } => self.draw_grid_line(row, column_start, cells),
@ -179,14 +179,16 @@ impl Editor {
} }
if text.is_empty() { if text.is_empty() {
let cell_index = self.grid.cell_index(*column_pos, row_index).expect("Should not paint outside of grid"); if let Some(cell) = self.grid.get_cell_mut(*column_pos, row_index) {
self.grid.characters[cell_index] = Some(("".to_string(), style.clone())); // TODO -- Encapsulate 'characters' better *cell = Some(("".to_string(), style.clone()));
}
self.grid.set_dirty_cell(*column_pos, row_index); self.grid.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() {
if let Some(cell_index) = self.grid.cell_index(i as u64 + *column_pos, row_index) { if let Some(cell) = self.grid.get_cell_mut(i as u64 + *column_pos, row_index) {
self.grid.characters[cell_index] = Some((character.to_string(), style.clone())); // TODO -- Encapsulate 'characters' better *cell = Some((character.to_string(), style.clone()));
self.grid.set_dirty_cell(*column_pos, row_index); self.grid.set_dirty_cell(*column_pos, row_index);
} }
} }
@ -228,12 +230,13 @@ impl Editor {
for x in x_iter { for x in x_iter {
let dest_x = x - cols; let dest_x = x - cols;
let source_idx = self.grid.cell_index(x as u64, y as u64); let cell_data = self.grid.get_cell(x as u64, y as u64).cloned();
let dest_idx = self.grid.cell_index(dest_x as u64, dest_y as u64);
if let (Some(source_idx), Some(dest_idx)) = (source_idx, dest_idx) { if let Some(cell_data) = cell_data.clone() {
self.grid.characters[dest_idx] = self.grid.characters[source_idx].clone(); // TODO -- Encapsulate 'characters' better if let Some(dest_cell) = self.grid.get_cell_mut(dest_x as u64, dest_y as u64) {
self.grid.set_dirty_cell(dest_x as u64, dest_y as u64); *dest_cell = cell_data.clone();
self.grid.set_dirty_cell(dest_x as u64, dest_y as u64);
}
} }
} }
} }

@ -201,15 +201,15 @@ 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.cell_index(grid_x, grid_y) let character = match editor.grid.get_cell(grid_x, grid_y) {
.and_then(|idx| editor.grid.characters[idx].as_ref()) Some(Some((character, _))) => character.clone(),
.map(|(character, _)| character.clone()) _ => ' '.to_string(),
.unwrap_or_else(|| ' '.to_string()); };
let is_double = editor.grid.cell_index(grid_x + 1, grid_y) let is_double = match editor.grid.get_cell(grid_x + 1, grid_y) {
.and_then(|idx| editor.grid.characters[idx].as_ref()) Some(Some((character, _))) => character.is_empty(),
.map(|(character, _)| character.is_empty()) _ => false,
.unwrap_or(false); };
let font_width = match (is_double, &cursor.shape) { let font_width = match (is_double, &cursor.shape) {
(true, CursorShape::Block) => font_width * 2.0, (true, CursorShape::Block) => font_width * 2.0,

Loading…
Cancel
Save