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;
|
use glib;
|
||||||
|
|
||||||
pub trait RedrawEvents {
|
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_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 {
|
pub trait GuiApi {
|
||||||
@ -96,6 +96,8 @@ fn nvim_cb(method: &str, params: Vec<Value>) {
|
|||||||
match method {
|
match method {
|
||||||
"redraw" => {
|
"redraw" => {
|
||||||
safe_call(move |ui| {
|
safe_call(move |ui| {
|
||||||
|
let mut repaint_mode = RepaintMode::Nothing;
|
||||||
|
|
||||||
for ev in ¶ms {
|
for ev in ¶ms {
|
||||||
if let &Value::Array(ref ev_args) = ev {
|
if let &Value::Array(ref ev_args) = ev {
|
||||||
if let Value::String(ref ev_name) = ev_args[0] {
|
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(),
|
&Value::Array(ref ar) => ar.clone(),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
};
|
};
|
||||||
call(ui, ev_name, &args)?;
|
let call_reapint_mode = call(ui, ev_name, &args)?;
|
||||||
|
repaint_mode = repaint_mode.join(&call_reapint_mode);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("Unsupported event {:?}", ev_args);
|
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(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -148,8 +151,8 @@ fn call_gui_event(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Re
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<(), String> {
|
fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<RepaintMode, String> {
|
||||||
match method {
|
Ok(match method {
|
||||||
"cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])),
|
"cursor_goto" => ui.on_cursor_goto(try_uint!(args[0]), try_uint!(args[1])),
|
||||||
"put" => ui.on_put(try_str!(args[0])),
|
"put" => ui.on_put(try_str!(args[0])),
|
||||||
"clear" => ui.on_clear(),
|
"clear" => ui.on_clear(),
|
||||||
@ -160,6 +163,7 @@ fn call(ui: &mut Shell, method: &str, args: &Vec<Value>) -> result::Result<(), S
|
|||||||
} else {
|
} else {
|
||||||
panic!("Supports only map value as argument");
|
panic!("Supports only map value as argument");
|
||||||
}
|
}
|
||||||
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
"eol_clear" => ui.on_eol_clear(),
|
"eol_clear" => ui.on_eol_clear(),
|
||||||
"set_scroll_region" => {
|
"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[1]),
|
||||||
try_uint!(args[2]),
|
try_uint!(args[2]),
|
||||||
try_uint!(args[3]));
|
try_uint!(args[3]));
|
||||||
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
"scroll" => ui.on_scroll(try_int!(args[0])),
|
"scroll" => ui.on_scroll(try_int!(args[0])),
|
||||||
"update_bg" => ui.on_update_bg(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])),
|
"mode_change" => ui.on_mode_change(try_str!(args[0])),
|
||||||
"mouse_on" => ui.on_mouse_on(),
|
"mouse_on" => ui.on_mouse_on(),
|
||||||
"mouse_off" => ui.on_mouse_off(),
|
"mouse_off" => ui.on_mouse_off(),
|
||||||
_ => println!("Event {}({:?})", method, args),
|
_ => {
|
||||||
};
|
println!("Event {}({:?})", method, args);
|
||||||
|
RepaintMode::Nothing
|
||||||
Ok(())
|
},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn safe_call<F>(cb: F)
|
fn safe_call<F>(cb: F)
|
||||||
@ -205,8 +211,25 @@ impl<T> ErrorReport for result::Result<T, CallError> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum RepaintMode {
|
pub enum RepaintMode {
|
||||||
|
Nothing,
|
||||||
All,
|
All,
|
||||||
Area(ModelRect),
|
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 {
|
impl RedrawEvents for Shell {
|
||||||
fn on_cursor_goto(&mut self, row: u64, col: u64) {
|
fn on_cursor_goto(&mut self, row: u64, col: u64) -> RepaintMode {
|
||||||
self.model.set_cursor(row, col);
|
RepaintMode::Area(self.model.set_cursor(row, col))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_put(&mut self, text: &str) {
|
fn on_put(&mut self, text: &str) -> RepaintMode {
|
||||||
self.model.put(text, self.cur_attrs.as_ref());
|
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();
|
self.model.clear();
|
||||||
|
RepaintMode::All
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_eol_clear(&mut self) {
|
fn on_eol_clear(&mut self) -> RepaintMode {
|
||||||
self.model.eol_clear();
|
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);
|
self.model = UiModel::new(rows, columns);
|
||||||
|
RepaintMode::All
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_redraw(&self, mode: &RepaintMode) {
|
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);
|
self.model.set_scroll_region(top, bot, left, right);
|
||||||
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_scroll(&mut self, count: i64) {
|
fn on_scroll(&mut self, count: i64) -> RepaintMode {
|
||||||
self.model.scroll(count as usize);
|
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();
|
let mut model_attrs = Attrs::new();
|
||||||
|
|
||||||
for &(ref key_val, ref val) in attrs {
|
for &(ref key_val, ref val) in attrs {
|
||||||
@ -537,46 +541,54 @@ impl RedrawEvents for Shell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.cur_attrs = Some(model_attrs);
|
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 {
|
if bg >= 0 {
|
||||||
self.bg_color = split_color(bg as u64);
|
self.bg_color = split_color(bg as u64);
|
||||||
} else {
|
} else {
|
||||||
self.bg_color = COLOR_BLACK;
|
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 {
|
if fg >= 0 {
|
||||||
self.fg_color = split_color(fg as u64);
|
self.fg_color = split_color(fg as u64);
|
||||||
} else {
|
} else {
|
||||||
self.fg_color = COLOR_WHITE;
|
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 {
|
if sp >= 0 {
|
||||||
self.sp_color = split_color(sp as u64);
|
self.sp_color = split_color(sp as u64);
|
||||||
} else {
|
} else {
|
||||||
self.sp_color = COLOR_RED;
|
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 {
|
match mode {
|
||||||
"normal" => self.mode = NvimMode::Normal,
|
"normal" => self.mode = NvimMode::Normal,
|
||||||
"insert" => self.mode = NvimMode::Insert,
|
"insert" => self.mode = NvimMode::Insert,
|
||||||
_ => self.mode = NvimMode::Other,
|
_ => 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;
|
self.mouse_enabled = true;
|
||||||
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_mouse_off(&mut self) {
|
fn on_mouse_off(&mut self) -> RepaintMode {
|
||||||
self.mouse_enabled = false;
|
self.mouse_enabled = false;
|
||||||
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +120,17 @@ impl UiModel {
|
|||||||
&self.model
|
&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 {
|
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_row = row as usize;
|
||||||
self.cur_col = col 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
|
changed_region
|
||||||
|
|
||||||
@ -137,8 +141,8 @@ impl UiModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(&mut self, text: &str, attrs: Option<&Attrs>) -> ModelRect {
|
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 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.ch = text.chars().last().unwrap_or(' ');
|
||||||
cell.attrs = attrs.map(Attrs::clone).unwrap_or_else(|| Attrs::new());
|
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);
|
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);
|
let (rows, columns) = (self.rows, self.columns);
|
||||||
self.clear_region(0, rows - 1, 0, columns - 1);
|
self.clear_region(0, rows - 1, 0, columns - 1);
|
||||||
|
|
||||||
ModelRect::new(0, 0, rows -1, columns -1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eol_clear(&mut self) -> ModelRect {
|
pub fn eol_clear(&mut self) -> ModelRect {
|
||||||
let (cur_row, cur_col, columns) = (self.cur_row, self.cur_col, self.columns);
|
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);
|
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) {
|
fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
||||||
@ -209,6 +211,7 @@ impl UiModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct ModelRect {
|
pub struct ModelRect {
|
||||||
top: usize,
|
top: usize,
|
||||||
bot: usize,
|
bot: usize,
|
||||||
@ -260,8 +263,81 @@ impl ModelRect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_area(&self, line_height: i32, char_width: i32) -> (i32, i32, i32, i32) {
|
pub fn to_area(&self, line_height: i32, char_width: i32) -> (i32, i32, i32, i32) {
|
||||||
let y = self.top as i32 * line_height;
|
(self.left as i32 * char_width,
|
||||||
let x = self.left as i32 * char_width;
|
self.top as i32 * line_height,
|
||||||
(x, y, self.right as i32 * char_width - x, self.bot as i32 * line_height - y)
|
(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