Clip Iterator
This commit is contained in:
parent
c2a6ec88c7
commit
778cbd0af2
21
src/nvim.rs
21
src/nvim.rs
@ -233,3 +233,24 @@ impl RepaintMode {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_mode() {
|
||||
let mode = RepaintMode::Area(ModelRect::point(1, 1));
|
||||
mode.join(&RepaintMode::Nothing);
|
||||
|
||||
match mode {
|
||||
RepaintMode::Area(ref rect) => {
|
||||
assert_eq!(1, rect.top);
|
||||
assert_eq!(1, rect.bot);
|
||||
assert_eq!(1, rect.left);
|
||||
assert_eq!(1, rect.right);
|
||||
}
|
||||
_ => panic!("mode is worng")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
24
src/shell.rs
24
src/shell.rs
@ -14,7 +14,7 @@ use gtk::DrawingArea;
|
||||
use neovim_lib::{Neovim, NeovimApi, Value, Integer};
|
||||
|
||||
use settings;
|
||||
use ui_model::{UiModel, Cell, Attrs, Color, COLOR_BLACK, COLOR_WHITE, COLOR_RED};
|
||||
use ui_model::{UiModel, Cell, Attrs, Color, ModelRect, COLOR_BLACK, COLOR_WHITE, COLOR_RED};
|
||||
use nvim::{RedrawEvents, GuiApi, RepaintMode};
|
||||
use input::{convert_key, keyval_to_input_string};
|
||||
use ui::{UI, Ui, SET};
|
||||
@ -276,17 +276,24 @@ fn draw(shell: &Shell, ctx: &cairo::Context) {
|
||||
|
||||
let line_height = shell.line_height.unwrap();
|
||||
let char_width = shell.char_width.unwrap();
|
||||
let clip = ctx.clip_extents();
|
||||
let model_clip = ModelRect::from_area(line_height, char_width,
|
||||
clip.0, clip.1, clip.2, clip.3);
|
||||
|
||||
let line_x = model_clip.left as f64 * char_width;
|
||||
let mut line_y: f64 = model_clip.top as f64 * line_height;
|
||||
|
||||
let (row, col) = shell.model.get_cursor();
|
||||
let mut buf = String::with_capacity(4);
|
||||
|
||||
let mut line_y: f64 = 0.0;
|
||||
|
||||
|
||||
let layout = pc::create_layout(ctx);
|
||||
let mut desc = shell.create_pango_font();
|
||||
|
||||
for (line_idx, line) in shell.model.model().iter().enumerate() {
|
||||
ctx.move_to(0.0, line_y);
|
||||
// FIXME: col_idx is wrong
|
||||
for (line_idx, line) in shell.model.clip_model(&model_clip) {
|
||||
ctx.move_to(line_x, line_y);
|
||||
|
||||
// first draw background
|
||||
// here we join same bg color for given line
|
||||
@ -319,7 +326,7 @@ fn draw(shell: &Shell, ctx: &cairo::Context) {
|
||||
line_height,
|
||||
from_bg.take().unwrap());
|
||||
|
||||
ctx.move_to(0.0, line_y);
|
||||
ctx.move_to(line_x, line_y);
|
||||
|
||||
for (col_idx, cell) in line.iter().enumerate() {
|
||||
let double_width = line.get(col_idx + 1).map(|c| c.attrs.double_width).unwrap_or(false);
|
||||
@ -508,12 +515,13 @@ impl RedrawEvents for Shell {
|
||||
match mode {
|
||||
&RepaintMode::All => self.drawing_area.queue_draw(),
|
||||
&RepaintMode::Area(ref rect) => {
|
||||
if let Some(line_height) = self.line_height {
|
||||
if let Some(char_width) = self.char_width {
|
||||
match (&self.line_height, &self.char_width) {
|
||||
(&Some(line_height), &Some(char_width)) => {
|
||||
let (x, y, width, height) =
|
||||
rect.to_area(line_height as i32, char_width as i32);
|
||||
rect.to_area(line_height, char_width);
|
||||
self.drawing_area.queue_draw_area(x, y, width, height);
|
||||
}
|
||||
_ => self.drawing_area.queue_draw(),
|
||||
}
|
||||
}
|
||||
&RepaintMode::Nothing => (),
|
||||
|
110
src/ui_model.rs
110
src/ui_model.rs
@ -1,3 +1,4 @@
|
||||
use std::slice::Iter;
|
||||
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct Color(pub f64, pub f64, pub f64);
|
||||
@ -120,6 +121,10 @@ impl UiModel {
|
||||
&self.model
|
||||
}
|
||||
|
||||
pub fn clip_model<'a> (&'a self, clip: &'a ModelRect) -> ClipRowIterator<'a> {
|
||||
ClipRowIterator::new(self, clip)
|
||||
}
|
||||
|
||||
pub fn cur_point(&self) -> ModelRect {
|
||||
ModelRect::point(self.cur_row, self.cur_col)
|
||||
}
|
||||
@ -218,10 +223,10 @@ impl UiModel {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ModelRect {
|
||||
top: usize,
|
||||
bot: usize,
|
||||
left: usize,
|
||||
right: usize,
|
||||
pub top: usize,
|
||||
pub bot: usize,
|
||||
pub left: usize,
|
||||
pub right: usize,
|
||||
}
|
||||
|
||||
impl ModelRect {
|
||||
@ -267,30 +272,105 @@ impl ModelRect {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn to_area(&self, line_height: i32, char_width: i32) -> (i32, i32, i32, i32) {
|
||||
(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)
|
||||
pub fn to_area(&self, line_height: f64, char_width: f64) -> (i32, i32, i32, i32) {
|
||||
(self.left as i32 * char_width as i32,
|
||||
self.top as i32 * line_height as i32,
|
||||
(self.right - self.left + 1) as i32 * char_width as i32,
|
||||
(self.bot - self.top + 1) as i32 * line_height as i32)
|
||||
}
|
||||
|
||||
pub fn from_area(line_height: i32, char_width: i32, x1: f64, y1: f64, x2: f64, y2: f64) -> ModelRect {
|
||||
let left = (x1 / char_width as f64) as usize;
|
||||
let right = (x2 / char_width as f64) as usize;
|
||||
let top = (y1 / line_height as f64) as usize;
|
||||
let bot = (y2 / line_height as f64) as usize;
|
||||
pub fn from_area(line_height: f64, char_width: f64, x1: f64, y1: f64, x2: f64, y2: f64) -> ModelRect {
|
||||
let left = (x1 / char_width) as usize;
|
||||
let right = (x2 / char_width) as usize;
|
||||
let top = (y1 / line_height) as usize;
|
||||
let bot = (y2 / line_height) as usize;
|
||||
|
||||
ModelRect::new(top, bot, left, right)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipRowIterator<'a> {
|
||||
rect: &'a ModelRect,
|
||||
pos: usize,
|
||||
iter: Iter<'a, Vec<Cell>>,
|
||||
}
|
||||
|
||||
impl <'a> ClipRowIterator<'a> {
|
||||
pub fn new(model: &'a UiModel, rect: &'a ModelRect) -> ClipRowIterator<'a> {
|
||||
ClipRowIterator {
|
||||
rect: rect,
|
||||
pos: 0,
|
||||
iter: model.model()[rect.top..rect.bot + 1].iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a> Iterator for ClipRowIterator<'a> {
|
||||
type Item = (usize, ClipColIterator<'a>);
|
||||
|
||||
fn next(&mut self) -> Option<(usize, ClipColIterator<'a>)> {
|
||||
self.pos += 1;
|
||||
self.iter.next().map(|line| {
|
||||
(self.rect.top + self.pos, ClipColIterator::new(line, self.rect))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipColIterator<'a> {
|
||||
rect: &'a ModelRect,
|
||||
len: usize,
|
||||
line: &'a Vec<Cell>,
|
||||
pos: usize,
|
||||
iter: Iter<'a, Cell>,
|
||||
}
|
||||
|
||||
impl <'a> ClipColIterator<'a> {
|
||||
pub fn new(model: &'a Vec<Cell>, rect: &'a ModelRect) -> ClipColIterator<'a> {
|
||||
ClipColIterator {
|
||||
len: rect.right - rect.left + 1,
|
||||
line: model,
|
||||
rect: rect,
|
||||
pos: 0,
|
||||
iter: model[rect.left..rect.right + 1].iter(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.len
|
||||
}
|
||||
|
||||
pub fn get(&self, idx: usize) -> Option<&Cell> {
|
||||
self.line.get(idx)
|
||||
}
|
||||
}
|
||||
|
||||
impl <'a>Iterator for ClipColIterator<'a> {
|
||||
type Item = (usize, &'a Cell);
|
||||
|
||||
fn next(&mut self) -> Option<(usize, &'a Cell)> {
|
||||
self.pos += 1;
|
||||
self.iter.next().map(|line| {
|
||||
(self.rect.left + self.pos, line)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_iterator() {
|
||||
let model = UiModel::new(10, 20);
|
||||
let rect = ModelRect::new(1, 2, 1, 2);
|
||||
|
||||
assert_eq!(2, model.clip_model(&rect).count());
|
||||
assert_eq!(2, model.clip_model(&rect).nth(0).unwrap().count());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_area() {
|
||||
let rect = ModelRect::from_area(10, 5, 3.0, 3.0, 9.0, 17.0);
|
||||
let rect = ModelRect::from_area(10.0, 5.0, 3.0, 3.0, 9.0, 17.0);
|
||||
|
||||
assert_eq!(0, rect.top);
|
||||
assert_eq!(0, rect.left);
|
||||
|
Loading…
Reference in New Issue
Block a user