Invalidate rect passed to draw
This commit is contained in:
parent
51dcd7f4e8
commit
89e6600325
67
src/nvim.rs
67
src/nvim.rs
@ -7,35 +7,35 @@ use shell::Shell;
|
||||
use glib;
|
||||
|
||||
pub trait RedrawEvents {
|
||||
fn on_cursor_goto(&mut self, row: u64, col: u64);
|
||||
fn on_cursor_goto(&mut self, row: u64, col: u64) -> RepaintMode;
|
||||
|
||||
fn on_put(&mut self, text: &str);
|
||||
fn on_put(&mut self, text: &str) -> RepaintMode;
|
||||
|
||||
fn on_clear(&mut self);
|
||||
fn on_clear(&mut self) -> RepaintMode;
|
||||
|
||||
fn on_resize(&mut self, columns: u64, rows: u64);
|
||||
fn on_resize(&mut self, columns: u64, rows: u64) -> RepaintMode;
|
||||
|
||||
fn on_redraw(&self, mode: &RepaintMode);
|
||||
|
||||
fn on_highlight_set(&mut self, attrs: &Vec<(Value, Value)>);
|
||||
fn on_highlight_set(&mut self, attrs: &Vec<(Value, Value)>) -> RepaintMode;
|
||||
|
||||
fn on_eol_clear(&mut self);
|
||||
fn on_eol_clear(&mut self) -> RepaintMode;
|
||||
|
||||
fn on_set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64);
|
||||
fn on_set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64) -> RepaintMode;
|
||||
|
||||
fn on_scroll(&mut self, count: i64);
|
||||
fn on_scroll(&mut self, count: i64) -> RepaintMode;
|
||||
|
||||
fn on_update_bg(&mut self, bg: i64);
|
||||
fn on_update_bg(&mut self, bg: i64) -> RepaintMode;
|
||||
|
||||
fn on_update_fg(&mut self, fg: i64);
|
||||
fn on_update_fg(&mut self, fg: i64) -> RepaintMode;
|
||||
|
||||
fn on_update_sp(&mut self, sp: i64);
|
||||
fn on_update_sp(&mut self, sp: i64) -> RepaintMode;
|
||||
|
||||
fn on_mode_change(&mut self, mode: &str);
|
||||
fn on_mode_change(&mut self, mode: &str) -> RepaintMode;
|
||||
|
||||
fn on_mouse_on(&mut self);
|
||||
fn on_mouse_on(&mut self) -> RepaintMode;
|
||||
|
||||
fn on_mouse_off(&mut self);
|
||||
fn on_mouse_off(&mut self) -> RepaintMode;
|
||||
}
|
||||
|
||||
pub trait GuiApi {
|
||||
@ -96,6 +96,8 @@ fn nvim_cb(method: &str, params: Vec<Value>) {
|
||||
match method {
|
||||
"redraw" => {
|
||||
safe_call(move |ui| {
|
||||
let mut repaint_mode = RepaintMode::Nothing;
|
||||
|
||||
for ev in ¶ms {
|
||||
if let &Value::Array(ref ev_args) = ev {
|
||||
if let Value::String(ref ev_name) = ev_args[0] {
|
||||
@ -104,7 +106,8 @@ fn nvim_cb(method: &str, params: Vec<Value>) {
|
||||
&Value::Array(ref ar) => ar.clone(),
|
||||
_ => vec![],
|
||||
};
|
||||
call(ui, ev_name, &args)?;
|
||||
let call_reapint_mode = call(ui, ev_name, &args)?;
|
||||
repaint_mode = repaint_mode.join(&call_reapint_mode);
|
||||
}
|
||||
} else {
|
||||
println!("Unsupported event {:?}", ev_args);
|
||||
@ -114,7 +117,7 @@ fn nvim_cb(method: &str, params: Vec<Value>) {
|
||||
}
|
||||
}
|
||||
|
||||
ui.on_redraw(&RepaintMode::All);
|
||||
ui.on_redraw(&repaint_mode);
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
@ -148,8 +151,8 @@ fn call_gui_event(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Re
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<(), String> {
|
||||
match method {
|
||||
fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<RepaintMode, String> {
|
||||
Ok(match method {
|
||||
"cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])),
|
||||
"put" => ui.on_put(try_str!(args[0])),
|
||||
"clear" => ui.on_clear(),
|
||||
@ -160,6 +163,7 @@ fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<(), S
|
||||
} else {
|
||||
panic!("Supports only map value as argument");
|
||||
}
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
"eol_clear" => ui.on_eol_clear(),
|
||||
"set_scroll_region" => {
|
||||
@ -167,6 +171,7 @@ fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<(), S
|
||||
try_uint!(args[1]),
|
||||
try_uint!(args[2]),
|
||||
try_uint!(args[3]));
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
"scroll" => ui.on_scroll(try_int!(args[0])),
|
||||
"update_bg" => ui.on_update_bg(try_int!(args[0])),
|
||||
@ -175,10 +180,11 @@ fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<(), S
|
||||
"mode_change" => ui.on_mode_change(try_str!(args[0])),
|
||||
"mouse_on" => ui.on_mouse_on(),
|
||||
"mouse_off" => ui.on_mouse_off(),
|
||||
_ => println!("Event {}({:?})", method, args),
|
||||
};
|
||||
|
||||
Ok(())
|
||||
_ => {
|
||||
println!("Event {}({:?})", method, args);
|
||||
RepaintMode::Nothing
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn safe_call<F>(cb: F)
|
||||
@ -205,8 +211,25 @@ impl<T> ErrorReport for result::Result<T, CallError> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum RepaintMode {
|
||||
Nothing,
|
||||
All,
|
||||
Area(ModelRect),
|
||||
}
|
||||
|
||||
impl RepaintMode {
|
||||
pub fn join(&self, mode: &RepaintMode) -> RepaintMode {
|
||||
match (self, mode) {
|
||||
(&RepaintMode::Nothing, m) => m.clone(),
|
||||
(m, &RepaintMode::Nothing) => m.clone(),
|
||||
(&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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
src/shell.rs
48
src/shell.rs
@ -459,24 +459,26 @@ fn gtk_configure_event(_: &DrawingArea, ev: &EventConfigure) -> bool {
|
||||
}
|
||||
|
||||
impl RedrawEvents for Shell {
|
||||
fn on_cursor_goto(&mut self, row: u64, col: u64) {
|
||||
self.model.set_cursor(row, col);
|
||||
fn on_cursor_goto(&mut self, row: u64, col: u64) -> RepaintMode {
|
||||
RepaintMode::Area(self.model.set_cursor(row, col))
|
||||
}
|
||||
|
||||
fn on_put(&mut self, text: &str) {
|
||||
self.model.put(text, self.cur_attrs.as_ref());
|
||||
fn on_put(&mut self, text: &str) -> RepaintMode {
|
||||
RepaintMode::Area(self.model.put(text, self.cur_attrs.as_ref()))
|
||||
}
|
||||
|
||||
fn on_clear(&mut self) {
|
||||
fn on_clear(&mut self) -> RepaintMode {
|
||||
self.model.clear();
|
||||
RepaintMode::All
|
||||
}
|
||||
|
||||
fn on_eol_clear(&mut self) {
|
||||
self.model.eol_clear();
|
||||
fn on_eol_clear(&mut self) -> RepaintMode {
|
||||
RepaintMode::Area(self.model.eol_clear())
|
||||
}
|
||||
|
||||
fn on_resize(&mut self, columns: u64, rows: u64) {
|
||||
fn on_resize(&mut self, columns: u64, rows: u64) -> RepaintMode {
|
||||
self.model = UiModel::new(rows, columns);
|
||||
RepaintMode::All
|
||||
}
|
||||
|
||||
fn on_redraw(&self, mode: &RepaintMode) {
|
||||
@ -492,18 +494,20 @@ impl RedrawEvents for Shell {
|
||||
}
|
||||
});
|
||||
},
|
||||
&RepaintMode::Nothing => (),
|
||||
}
|
||||
}
|
||||
|
||||
fn on_set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64) {
|
||||
fn on_set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64) -> RepaintMode {
|
||||
self.model.set_scroll_region(top, bot, left, right);
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
fn on_scroll(&mut self, count: i64) {
|
||||
self.model.scroll(count as usize);
|
||||
fn on_scroll(&mut self, count: i64) -> RepaintMode {
|
||||
RepaintMode::Area(self.model.scroll(count as usize))
|
||||
}
|
||||
|
||||
fn on_highlight_set(&mut self, attrs: &Vec<(Value, Value)>) {
|
||||
fn on_highlight_set(&mut self, attrs: &Vec<(Value, Value)>) -> RepaintMode {
|
||||
let mut model_attrs = Attrs::new();
|
||||
|
||||
for &(ref key_val, ref val) in attrs {
|
||||
@ -537,46 +541,54 @@ impl RedrawEvents for Shell {
|
||||
}
|
||||
|
||||
self.cur_attrs = Some(model_attrs);
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
fn on_update_bg(&mut self, bg: i64) {
|
||||
fn on_update_bg(&mut self, bg: i64) -> RepaintMode {
|
||||
if bg >= 0 {
|
||||
self.bg_color = split_color(bg as u64);
|
||||
} else {
|
||||
self.bg_color = COLOR_BLACK;
|
||||
}
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
fn on_update_fg(&mut self, fg: i64) {
|
||||
fn on_update_fg(&mut self, fg: i64) -> RepaintMode {
|
||||
if fg >= 0 {
|
||||
self.fg_color = split_color(fg as u64);
|
||||
} else {
|
||||
self.fg_color = COLOR_WHITE;
|
||||
}
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
fn on_update_sp(&mut self, sp: i64) {
|
||||
fn on_update_sp(&mut self, sp: i64) -> RepaintMode {
|
||||
if sp >= 0 {
|
||||
self.sp_color = split_color(sp as u64);
|
||||
} else {
|
||||
self.sp_color = COLOR_RED;
|
||||
}
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
fn on_mode_change(&mut self, mode: &str) {
|
||||
fn on_mode_change(&mut self, mode: &str) -> RepaintMode {
|
||||
match mode {
|
||||
"normal" => self.mode = NvimMode::Normal,
|
||||
"insert" => self.mode = NvimMode::Insert,
|
||||
_ => self.mode = NvimMode::Other,
|
||||
}
|
||||
|
||||
RepaintMode::Area(self.model.cur_point())
|
||||
}
|
||||
|
||||
fn on_mouse_on(&mut self) {
|
||||
fn on_mouse_on(&mut self) -> RepaintMode {
|
||||
self.mouse_enabled = true;
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
|
||||
fn on_mouse_off(&mut self) {
|
||||
fn on_mouse_off(&mut self) -> RepaintMode {
|
||||
self.mouse_enabled = false;
|
||||
RepaintMode::Nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,13 +120,17 @@ impl UiModel {
|
||||
&self.model
|
||||
}
|
||||
|
||||
pub fn cur_point(&self) -> ModelRect {
|
||||
ModelRect::point(self.cur_row, self.cur_col)
|
||||
}
|
||||
|
||||
pub fn set_cursor(&mut self, row: u64, col: u64) -> ModelRect {
|
||||
let mut changed_region = ModelRect::point(self.cur_row, self.cur_col);
|
||||
let mut changed_region = self.cur_point();
|
||||
|
||||
self.cur_row = row as usize;
|
||||
self.cur_col = col as usize;
|
||||
|
||||
changed_region.join(&ModelRect::point(self.cur_row, self.cur_col));
|
||||
changed_region.join(&self.cur_point());
|
||||
|
||||
changed_region
|
||||
|
||||
@ -137,8 +141,8 @@ impl UiModel {
|
||||
}
|
||||
|
||||
pub fn put(&mut self, text: &str, attrs: Option<&Attrs>) -> ModelRect {
|
||||
let changed_region = self.cur_point();
|
||||
let mut cell = &mut self.model[self.cur_row][self.cur_col];
|
||||
let changed_region = ModelRect::point(self.cur_row, self.cur_col);
|
||||
|
||||
cell.ch = text.chars().last().unwrap_or(' ');
|
||||
cell.attrs = attrs.map(Attrs::clone).unwrap_or_else(|| Attrs::new());
|
||||
@ -183,21 +187,19 @@ impl UiModel {
|
||||
self.clear_region(top, (top - count - 1), left, right);
|
||||
}
|
||||
|
||||
ModelRect::new(top, bot, left ,right)
|
||||
ModelRect::new(top, bot, left, right)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) -> ModelRect {
|
||||
pub fn clear(&mut self) {
|
||||
let (rows, columns) = (self.rows, self.columns);
|
||||
self.clear_region(0, rows - 1, 0, columns - 1);
|
||||
|
||||
ModelRect::new(0, 0, rows -1, columns -1)
|
||||
}
|
||||
|
||||
pub fn eol_clear(&mut self) -> ModelRect {
|
||||
let (cur_row, cur_col, columns) = (self.cur_row, self.cur_col, self.columns);
|
||||
self.clear_region(cur_row, cur_row, cur_col, columns - 1);
|
||||
|
||||
ModelRect::new(cur_row, cur_col, cur_col, columns -1)
|
||||
ModelRect::new(cur_row, cur_col, cur_col, columns - 1)
|
||||
}
|
||||
|
||||
fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
||||
@ -209,6 +211,7 @@ impl UiModel {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ModelRect {
|
||||
top: usize,
|
||||
bot: usize,
|
||||
@ -260,8 +263,81 @@ impl ModelRect {
|
||||
}
|
||||
|
||||
pub fn to_area(&self, line_height: i32, char_width: i32) -> (i32, i32, i32, i32) {
|
||||
let y = self.top as i32 * line_height;
|
||||
let x = self.left as i32 * char_width;
|
||||
(x, y, self.right as i32 * char_width - x, self.bot as i32 * line_height - y)
|
||||
(self.left as i32 * char_width,
|
||||
self.top as i32 * line_height,
|
||||
(self.right - self.left + 1) as i32 * char_width,
|
||||
(self.bot - self.top + 1) as i32 * line_height)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_cursor_area() {
|
||||
let mut model = UiModel::new(10, 20);
|
||||
|
||||
model.set_cursor(1, 1);
|
||||
|
||||
let rect = model.set_cursor(5, 5);
|
||||
|
||||
assert_eq!(1, rect.top);
|
||||
assert_eq!(1, rect.left);
|
||||
assert_eq!(5, rect.bot);
|
||||
assert_eq!(5, rect.right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_eol_clear_area() {
|
||||
let mut model = UiModel::new(10, 20);
|
||||
|
||||
model.set_cursor(1, 1);
|
||||
|
||||
let rect = model.eol_clear();
|
||||
|
||||
assert_eq!(1, rect.top);
|
||||
assert_eq!(1, rect.left);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(19, rect.right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_repaint_rect() {
|
||||
let rect = ModelRect::point(1, 1);
|
||||
let (x, y, width, height) = rect.to_area(10, 5);
|
||||
|
||||
assert_eq!(5, x);
|
||||
assert_eq!(10, y);
|
||||
assert_eq!(5, width);
|
||||
assert_eq!(10, height);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_put_area() {
|
||||
let mut model = UiModel::new(10, 20);
|
||||
|
||||
model.set_cursor(1, 1);
|
||||
|
||||
let rect = model.put(" ", None);
|
||||
|
||||
assert_eq!(1, rect.top);
|
||||
assert_eq!(1, rect.left);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(1, rect.right);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scroll_area() {
|
||||
let mut model = UiModel::new(10, 20);
|
||||
|
||||
model.set_scroll_region(1, 5, 1, 5);
|
||||
|
||||
let rect = model.scroll(3);
|
||||
|
||||
assert_eq!(1, rect.top);
|
||||
assert_eq!(1, rect.left);
|
||||
assert_eq!(5, rect.bot);
|
||||
assert_eq!(5, rect.right);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user