diff --git a/src/nvim.rs b/src/nvim.rs index 1af7200..cfb99b1 100644 --- a/src/nvim.rs +++ b/src/nvim.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use ui::UiMutex; use neovim_lib::{Handler, Neovim, NeovimApi, Session, Value, UiAttachOptions, CallError}; -use ui_model::ModelRect; +use ui_model::{ModelRect, ModelRectVec}; use shell; use glib; @@ -262,6 +262,7 @@ impl ErrorReport for result::Result { pub enum RepaintMode { Nothing, All, + AreaList(ModelRectVec), Area(ModelRect), } @@ -273,9 +274,22 @@ impl RepaintMode { (&RepaintMode::All, _) => RepaintMode::All, (_, &RepaintMode::All) => RepaintMode::All, (&RepaintMode::Area(ref mr1), &RepaintMode::Area(ref mr2)) => { - let mut area = mr1.clone(); - area.join(mr2); - RepaintMode::Area(area) + let mut vec = ModelRectVec::new(mr1.clone()); + vec.join(mr2); + RepaintMode::AreaList(vec) + } + (&RepaintMode::AreaList(_), &RepaintMode::AreaList(_)) => { + panic!("Not implmeneted"); + } + (&RepaintMode::AreaList(ref l1), &RepaintMode::Area(ref l2)) => { + let mut list = l1.clone(); + list.join(l2); + RepaintMode::AreaList(list) + } + (&RepaintMode::Area(ref l1), &RepaintMode::AreaList(ref l2)) => { + let mut list = l2.clone(); + list.join(l1); + RepaintMode::AreaList(list) } } } diff --git a/src/shell.rs b/src/shell.rs index babd243..7b259f9 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -129,6 +129,23 @@ impl State { nvim.input("").report_err(&mut *nvim); } } + + fn queue_draw_area>(&self, rect_list: &Vec) { + match (&self.line_height, &self.char_width) { + (&Some(line_height), &Some(char_width)) => { + for rect in rect_list { + let mut rect = rect.as_ref().clone(); + // this need to repain also line under curren line + // in case underscore or 'g' symbol is go here + rect.extend(0, 1, 0, 0); + let (x, y, width, height) = rect.to_area(line_height, char_width); + self.drawing_area.queue_draw_area(x, y, width, height); + } + } + _ => self.drawing_area.queue_draw(), + } + } + } pub struct UiState { @@ -716,19 +733,8 @@ impl RedrawEvents for State { fn on_redraw(&self, mode: &RepaintMode) { match mode { &RepaintMode::All => self.drawing_area.queue_draw(), - &RepaintMode::Area(ref rect) => { - match (&self.line_height, &self.char_width) { - (&Some(line_height), &Some(char_width)) => { - let mut rect = rect.clone(); - // this need to repain also line under curren line - // in case underscore or 'g' symbol is go here - rect.extend(0, 1, 0, 0); - let (x, y, width, height) = rect.to_area(line_height, char_width); - self.drawing_area.queue_draw_area(x, y, width, height); - } - _ => self.drawing_area.queue_draw(), - } - } + &RepaintMode::Area(ref rect) => self.queue_draw_area(&vec![rect]), + &RepaintMode::AreaList(ref list) => self.queue_draw_area(&list.list), &RepaintMode::Nothing => (), } } diff --git a/src/ui_model.rs b/src/ui_model.rs index da88cda..4df3093 100644 --- a/src/ui_model.rs +++ b/src/ui_model.rs @@ -230,8 +230,9 @@ impl UiModel { } } +#[derive(Clone)] pub struct ModelRectVec { - list: Vec, + pub list: Vec, } impl ModelRectVec { @@ -241,10 +242,11 @@ impl ModelRectVec { fn find_neighbor(&self, neighbor: &ModelRect) -> Option { for (i, rect) in self.list.iter().enumerate() { - if (rect.top == neighbor.top - 1 || rect.bot == neighbor.bot + 1) && - neighbor.in_horizontal(rect) { + if (neighbor.top > 0 && rect.top == neighbor.top - 1 || + rect.bot == neighbor.bot + 1) && neighbor.in_horizontal(rect) { return Some(i); - } else if (rect.left == neighbor.left - 1 || rect.right == neighbor.right + 1) && + } else if (neighbor.left > 0 && rect.left == neighbor.left - 1 || + rect.right == neighbor.right + 1) && neighbor.in_vertical(rect) { return Some(i); } else if rect == neighbor { @@ -255,10 +257,10 @@ impl ModelRectVec { None } - pub fn join(&mut self, other: ModelRect) { - match self.find_neighbor(&other) { - Some(i) => self.list.get_mut(i).unwrap().join(&other), - None => self.list.push(other), + pub fn join(&mut self, other: &ModelRect) { + match self.find_neighbor(other) { + Some(i) => self.list.get_mut(i).unwrap().join(other), + None => self.list.push(other.clone()), } } } @@ -306,7 +308,7 @@ impl ModelRect { if self.top > 0 { self.top -= top; } - if self.left > 0 { + if self.left > 0 { self.left -= left; } self.bot += bot; @@ -372,6 +374,12 @@ impl ModelRect { } } +impl AsRef for ModelRect { + fn as_ref(&self) -> &ModelRect { + self + } +} + pub struct ClipRowIterator<'a> { rect: &'a ModelRect, pos: usize, @@ -452,13 +460,23 @@ impl<'a> Iterator for ClipColIterator<'a> { mod tests { use super::*; + #[test] + fn test_vec_join_top() { + let mut list = ModelRectVec::new(ModelRect::point(0, 0)); + + let neighbor = ModelRect::point(1, 0); + + list.join(&neighbor); + assert_eq!(1, list.list.len()); + } + #[test] fn test_model_vec_join() { let mut list = ModelRectVec::new(ModelRect::point(5, 5)); let neighbor = ModelRect::point(6, 5); - list.join(neighbor); + list.join(&neighbor); assert_eq!(1, list.list.len()); } @@ -468,7 +486,7 @@ mod tests { let not_neighbor = ModelRect::point(6, 6); - list.join(not_neighbor); + list.join(¬_neighbor); assert_eq!(2, list.list.len()); }