WIP Extraction of Editor::grid into its own file and struct

macos-click-through
Jon Valdes 5 years ago committed by Jon Valdés
parent 0fe0475b6d
commit e8cb1ef863

@ -0,0 +1,75 @@
use std::sync::Arc;
use super::style::Style;
type GridCell = Option<(String, Option<Arc<Style>>)>;
pub struct CharacterGrid {
pub characters: Vec<GridCell>,
pub width: u64,
pub height: u64,
pub should_clear: bool,
dirty: Vec<bool>,
}
impl CharacterGrid {
pub fn new() -> CharacterGrid {
CharacterGrid {
characters: vec![],
dirty: vec![],
width: 0,
height: 0,
should_clear: true,
}
}
pub fn resize(&mut self, new_size: (u64, u64)) {
trace!("Editor resized");
self.width = new_size.0;
self.height = new_size.1;
self.clear();
}
pub fn clear(&mut self) {
trace!("Editor cleared");
let cell_count = (self.width * self.height) as usize;
self.characters = vec![None; cell_count];
self.dirty = vec![true; cell_count];
self.should_clear = true;
}
pub fn cell_index(&self, x: u64, y: u64) -> Option<usize> {
if x >= self.width || y >= self.height {
None
} else {
Some((x + y * self.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;
}
}
pub fn set_dirty_all(&mut self, value: bool) {
self.dirty.resize(self.dirty.len(), value);
}
pub fn rows<'a>(&'a self) -> Vec<&'a [GridCell]> {
(0..self.height)
.map(|row| {
&self.characters[(row * self.width) as usize..((row + 1) * self.width) as usize]
})
.collect()
}
}

@ -1,5 +1,6 @@
mod cursor;
mod style;
mod grid;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
@ -10,6 +11,7 @@ use log::trace;
pub use cursor::{Cursor, CursorShape, CursorMode};
pub use style::{Colors, Style};
pub use grid::CharacterGrid;
use crate::bridge::{GridLineCell, GuiOption, RedrawEvent};
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::INITIAL_DIMENSIONS;
@ -18,8 +20,6 @@ lazy_static! {
pub static ref EDITOR: Arc<Mutex<Editor>> = Arc::new(Mutex::new(Editor::new()));
}
pub type GridCell = Option<(String, Option<Arc<Style>>)>;
#[derive(new, Debug, Clone)]
pub struct DrawCommand {
pub text: String,
@ -31,10 +31,7 @@ pub struct DrawCommand {
}
pub struct Editor {
pub grid: Vec<GridCell>,
pub dirty: Vec<bool>,
pub should_clear: bool,
pub grid: CharacterGrid,
pub title: String,
pub size: (u64, u64),
pub font_name: Option<String>,
@ -48,9 +45,7 @@ pub struct Editor {
impl Editor {
pub fn new() -> Editor {
let mut editor = Editor {
grid: Vec::new(),
dirty: Vec::new(),
should_clear: true,
grid: CharacterGrid::new(),
title: "Neovide".to_string(),
size: INITIAL_DIMENSIONS,
@ -62,39 +57,10 @@ impl Editor {
previous_style: None
};
editor.clear();
editor.grid.clear();
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) {
match event {
@ -114,11 +80,11 @@ impl Editor {
trace!("Image flushed");
REDRAW_SCHEDULER.queue_next_frame();
},
RedrawEvent::Resize { width, height, .. } => self.resize((width, height)),
RedrawEvent::Resize { width, height, .. } => self.grid.resize((width, height)),
RedrawEvent::DefaultColorsSet { colors } => self.default_style = Arc::new(Style::new(colors)),
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::Clear { .. } => self.clear(),
RedrawEvent::Clear { .. } => self.grid.clear(),
RedrawEvent::CursorGoto { row, column, .. } => self.cursor.position = (row, column),
RedrawEvent::Scroll { top, bottom, left, right, rows, columns, .. } => self.scroll_region(top, bottom, left, right, rows, columns),
_ => {}
@ -127,7 +93,7 @@ impl Editor {
pub fn build_draw_commands(&mut self) -> (Vec<DrawCommand>, bool) {
let mut draw_commands = Vec::new();
for (row_index, row) in self.rows().iter().enumerate() {
for (row_index, row) in self.grid.rows().iter().enumerate() {
let mut command = None;
fn add_command(commands_list: &mut Vec<DrawCommand>, command: Option<DrawCommand>) {
@ -178,25 +144,23 @@ impl Editor {
}
add_command(&mut draw_commands, command);
}
let should_clear = self.should_clear;
let should_clear = self.grid.should_clear;
let (width, height) = self.size;
let draw_commands = draw_commands.into_iter().filter(|command| {
let (x, y) = command.grid_position;
let min = (x as i64 - 1).max(0) as u64;
let max = (x + command.cell_width + 1).min(width);
let max = (x + command.cell_width + 1).min(self.grid.width);
for char_index in min..max {
if self.is_dirty_cell(char_index, y) {
if self.grid.is_dirty_cell(char_index, y) {
return true;
}
}
return false;
}).collect::<Vec<DrawCommand>>();
self.dirty = vec![false; (width * height) as usize];
self.should_clear = false;
self.grid.set_dirty_all(false);
self.grid.should_clear = false;
trace!("Draw commands sent");
(draw_commands, should_clear)
@ -215,15 +179,15 @@ impl Editor {
}
if text.is_empty() {
let cell_index = self.cell_index(*column_pos, row_index).expect("Should not paint outside of grid");
self.grid[cell_index] = Some(("".to_string(), style.clone()));
self.set_dirty_cell(*column_pos, row_index);
let cell_index = self.grid.cell_index(*column_pos, row_index).expect("Should not paint outside of grid");
self.grid.characters[cell_index] = Some(("".to_string(), style.clone())); // TODO -- Encapsulate 'characters' better
self.grid.set_dirty_cell(*column_pos, row_index);
*column_pos = *column_pos + 1;
} else {
for (i, character) in text.graphemes(true).enumerate() {
if let Some(cell_index) = self.cell_index(i as u64 + *column_pos, row_index) {
self.grid[cell_index] = Some((character.to_string(), style.clone()));
self.set_dirty_cell(*column_pos, row_index);
if let Some(cell_index) = self.grid.cell_index(i as u64 + *column_pos, row_index) {
self.grid.characters[cell_index] = Some((character.to_string(), style.clone())); // TODO -- Encapsulate 'characters' better
self.grid.set_dirty_cell(*column_pos, row_index);
}
}
*column_pos = *column_pos + text.graphemes(true).count() as u64;
@ -232,7 +196,7 @@ impl Editor {
}
fn draw_grid_line(&mut self, row: u64, column_start: u64, cells: Vec<GridLineCell>) {
if row < self.grid.len() as u64 {
if row < self.grid.height {
let mut column_pos = column_start;
for cell in cells {
self.draw_grid_line_cell(row, &mut column_pos, cell);
@ -264,12 +228,12 @@ impl Editor {
for x in x_iter {
let dest_x = x - cols;
let source_idx = self.cell_index(x as u64, y as u64);
let dest_idx = self.cell_index(dest_x as u64, dest_y as u64);
let source_idx = self.grid.cell_index(x as u64, y as u64);
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) {
self.grid[dest_idx] = self.grid[source_idx].clone();
self.set_dirty_cell(dest_x as u64, dest_y as u64);
self.grid.characters[dest_idx] = self.grid.characters[source_idx].clone(); // TODO -- Encapsulate 'characters' better
self.grid.set_dirty_cell(dest_x as u64, dest_y as u64);
}
}
}
@ -277,20 +241,6 @@ impl Editor {
trace!("Region scrolled");
}
fn resize(&mut self, new_size: (u64, u64)) {
trace!("Editor resized");
self.size = new_size;
self.clear();
}
fn clear(&mut self) {
trace!("Editor cleared");
let (width, height) = self.size;
self.grid = vec![None; (width * height) as usize];
self.dirty = vec![true; (width * height) as usize];
self.should_clear = true;
}
fn set_option(&mut self, gui_option: GuiOption) {
trace!("Option set {:?}", &gui_option);
match gui_option {

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

Loading…
Cancel
Save