Add new repaint logic
This commit is contained in:
parent
6963c7ab95
commit
7f05e11e84
@ -227,7 +227,7 @@ fn anim_step(state: &Arc<UiMutex<State>>) -> glib::Continue {
|
||||
};
|
||||
|
||||
let shell = mut_state.shell.upgrade().unwrap();
|
||||
let shell = shell.borrow();
|
||||
let mut shell = shell.borrow_mut();
|
||||
let point = shell.model.cur_point();
|
||||
shell.on_redraw(&RepaintMode::Area(point));
|
||||
|
||||
|
@ -25,7 +25,7 @@ pub trait RedrawEvents {
|
||||
|
||||
fn on_resize(&mut self, columns: u64, rows: u64) -> RepaintMode;
|
||||
|
||||
fn on_redraw(&self, mode: &RepaintMode);
|
||||
fn on_redraw(&mut self, mode: &RepaintMode);
|
||||
|
||||
fn on_highlight_set(&mut self, attrs: &[(Value, Value)]) -> RepaintMode;
|
||||
|
||||
|
@ -16,6 +16,9 @@ pub fn render(
|
||||
ui_model: &ui_model::UiModel,
|
||||
color_model: &color::ColorModel,
|
||||
) {
|
||||
// TODO: underline
|
||||
// TODO: undercurl
|
||||
// TODO: cursor
|
||||
ctx.set_source_rgb(
|
||||
color_model.bg_color.0,
|
||||
color_model.bg_color.1,
|
||||
|
139
src/shell.rs
139
src/shell.rs
@ -6,7 +6,6 @@ use std::thread;
|
||||
|
||||
use cairo;
|
||||
use pangocairo::CairoContextExt;
|
||||
use pango;
|
||||
use pango::{LayoutExt, FontDescription};
|
||||
use gdk;
|
||||
use gdk::{ModifierType, EventButton, EventMotion, EventType, EventScroll};
|
||||
@ -146,9 +145,9 @@ impl State {
|
||||
|
||||
pub fn set_font_desc(&mut self, desc: &str) {
|
||||
self.font_ctx.update(FontDescription::from_string(desc));
|
||||
self.model.clear_draw_cache();
|
||||
// TODO: rerun itemize/shape
|
||||
// TODO: send repaint event
|
||||
self.model.clear_glyphs();
|
||||
self.update_dirty_glyphs();
|
||||
self.on_redraw(&RepaintMode::All);
|
||||
}
|
||||
|
||||
pub fn open_file(&self, path: &str) {
|
||||
@ -176,28 +175,23 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
fn queue_draw_area<M: AsRef<ModelRect>>(&self, rect_list: &[M]) {
|
||||
let &CellMetrics {
|
||||
line_height,
|
||||
char_width,
|
||||
..
|
||||
} = self.font_ctx.cell_metrics();
|
||||
fn queue_draw_area<M: AsRef<ModelRect>>(&mut self, rect_list: &[M]) {
|
||||
self.update_dirty_glyphs();
|
||||
|
||||
//TODO: run shape here
|
||||
|
||||
for rect in rect_list {
|
||||
let mut rect = rect.as_ref().clone();
|
||||
rect.extend_by_items(&self.model);
|
||||
|
||||
// this need to repain also line under curren line
|
||||
// in case underscore or 'g' symbol is go here
|
||||
// right one for italic symbol
|
||||
rect.extend(0, 1, 0, 1);
|
||||
let (x, y, width, height) = rect.to_area(line_height, char_width);
|
||||
let (x, y, width, height) = rect.to_area_extend_ink(&self.model, self.font_ctx.cell_metrics());
|
||||
self.drawing_area.queue_draw_area(x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_dirty_glyphs(&mut self) {
|
||||
render::shape_dirty(&self.font_ctx, &mut self.model, &self.color_model);
|
||||
}
|
||||
|
||||
fn im_commit(&self, ch: &str) {
|
||||
input::im_input(&mut self.nvim.borrow_mut(), ch);
|
||||
}
|
||||
@ -224,14 +218,9 @@ impl State {
|
||||
}
|
||||
|
||||
fn set_im_location(&self) {
|
||||
let &CellMetrics {
|
||||
line_height,
|
||||
char_width,
|
||||
..
|
||||
} = self.font_ctx.cell_metrics();
|
||||
let (row, col) = self.model.get_cursor();
|
||||
|
||||
let (x, y, width, height) = ModelRect::point(col, row).to_area(line_height, char_width);
|
||||
let (x, y, width, height) = ModelRect::point(col, row).to_area(self.font_ctx.cell_metrics());
|
||||
|
||||
self.im_context.set_cursor_location(&gdk::Rectangle {
|
||||
x,
|
||||
@ -578,7 +567,7 @@ fn gtk_draw(state_arc: &Arc<UiMutex<State>>, ctx: &cairo::Context) -> Inhibit {
|
||||
|
||||
let mut state = state_arc.borrow_mut();
|
||||
if state.nvim.borrow().is_initialized() {
|
||||
render(&mut *state, ctx);
|
||||
render::render(ctx, &state.font_ctx, &state.model, &state.color_model);
|
||||
request_window_resize(&mut *state);
|
||||
} else if state.nvim.borrow().is_initializing() {
|
||||
draw_initializing(&*state, ctx);
|
||||
@ -587,11 +576,6 @@ fn gtk_draw(state_arc: &Arc<UiMutex<State>>, ctx: &cairo::Context) -> Inhibit {
|
||||
Inhibit(false)
|
||||
}
|
||||
|
||||
fn render(state: &mut State, ctx: &cairo::Context) {
|
||||
render::shape_dirty(&state.font_ctx, &mut state.model, &state.color_model);
|
||||
render::render(ctx, &state.font_ctx, &state.model, &state.color_model);
|
||||
}
|
||||
|
||||
fn show_nvim_start_error(err: nvim::NvimInitError, state_arc: Arc<UiMutex<State>>) {
|
||||
let source = err.source();
|
||||
let cmd = err.cmd().unwrap().to_owned();
|
||||
@ -680,25 +664,25 @@ fn init_nvim(state_arc: &Arc<UiMutex<State>>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_model_clip(
|
||||
state: &State,
|
||||
line_height: f64,
|
||||
char_width: f64,
|
||||
clip: (f64, f64, f64, f64),
|
||||
) -> ModelRect {
|
||||
let mut model_clip =
|
||||
ModelRect::from_area(line_height, char_width, clip.0, clip.1, clip.2, clip.3);
|
||||
// in some cases symbols from previous row affect next row
|
||||
// for example underscore symbol or 'g'
|
||||
// also for italic text it is possible that symbol can affect next one
|
||||
// see deference between logical rect and ink rect
|
||||
model_clip.extend(1, 0, 1, 0);
|
||||
state.model.limit_to_model(&mut model_clip);
|
||||
|
||||
model_clip
|
||||
}
|
||||
|
||||
//#[inline]
|
||||
//fn get_model_clip(
|
||||
// state: &State,
|
||||
// line_height: f64,
|
||||
// char_width: f64,
|
||||
// clip: (f64, f64, f64, f64),
|
||||
//) -> ModelRect {
|
||||
// let mut model_clip =
|
||||
// ModelRect::from_area(line_height, char_width, clip.0, clip.1, clip.2, clip.3);
|
||||
// // in some cases symbols from previous row affect next row
|
||||
// // for example underscore symbol or 'g'
|
||||
// // also for italic text it is possible that symbol can affect next one
|
||||
// // see deference between logical rect and ink rect
|
||||
// model_clip.extend(1, 0, 1, 0);
|
||||
// state.model.limit_to_model(&mut model_clip);
|
||||
//
|
||||
// model_clip
|
||||
//}
|
||||
//
|
||||
//#[inline]
|
||||
//fn draw_backgound(
|
||||
// state: &State,
|
||||
@ -1005,7 +989,7 @@ impl RedrawEvents for State {
|
||||
RepaintMode::All
|
||||
}
|
||||
|
||||
fn on_redraw(&self, mode: &RepaintMode) {
|
||||
fn on_redraw(&mut self, mode: &RepaintMode) {
|
||||
match *mode {
|
||||
RepaintMode::All => self.drawing_area.queue_draw(),
|
||||
RepaintMode::Area(ref rect) => self.queue_draw_area(&[rect]),
|
||||
@ -1113,14 +1097,8 @@ impl RedrawEvents for State {
|
||||
row: u64,
|
||||
col: u64,
|
||||
) -> RepaintMode {
|
||||
|
||||
let &CellMetrics {
|
||||
line_height,
|
||||
char_width,
|
||||
..
|
||||
} = self.font_ctx.cell_metrics();
|
||||
let point = ModelRect::point(col as usize, row as usize);
|
||||
let (x, y, width, height) = point.to_area(line_height, char_width);
|
||||
let (x, y, width, height) = point.to_area(self.font_ctx.cell_metrics());
|
||||
|
||||
self.popup_menu.borrow_mut().show(
|
||||
self,
|
||||
@ -1176,52 +1154,3 @@ impl GuiApi for State {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModelBitamp {
|
||||
words_for_cols: usize,
|
||||
model: Vec<u64>,
|
||||
}
|
||||
|
||||
impl ModelBitamp {
|
||||
pub fn new(cols: usize, rows: usize) -> ModelBitamp {
|
||||
let words_for_cols = cols / 64 + 1;
|
||||
|
||||
ModelBitamp {
|
||||
words_for_cols: words_for_cols,
|
||||
model: vec![0; rows * words_for_cols],
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_from_model(&mut self, rect: &ModelRect) {
|
||||
for row in rect.top..rect.bot + 1 {
|
||||
let row_pos = self.words_for_cols * row;
|
||||
for col in rect.left..rect.right + 1 {
|
||||
let col_pos = col / 64;
|
||||
let col_offset = col % 64;
|
||||
self.model[row_pos + col_pos] |= 1 << col_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get(&self, col: usize, row: usize) -> bool {
|
||||
let row_pos = self.words_for_cols * row;
|
||||
let col_pos = col / 64;
|
||||
let col_offset = col % 64;
|
||||
self.model[row_pos + col_pos] & (1 << col_offset) != 0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_bitmap() {
|
||||
let mut bitmap = ModelBitamp::new(80, 24);
|
||||
bitmap.fill_from_model(&ModelRect::new(22, 22, 63, 68));
|
||||
|
||||
assert_eq!(true, bitmap.get(63, 22));
|
||||
assert_eq!(true, bitmap.get(68, 22));
|
||||
assert_eq!(false, bitmap.get(62, 22));
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ impl Line {
|
||||
self.dirty_line = true;
|
||||
}
|
||||
|
||||
pub fn clear_draw_cache(&mut self) {
|
||||
pub fn clear_glyphs(&mut self) {
|
||||
for i in 0..self.item_line.len() {
|
||||
self.item_line[i] = None;
|
||||
self.cell_to_item[i] = -1;
|
||||
@ -176,6 +176,15 @@ impl Line {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item(&self, cell_idx: usize) -> Option<&Item> {
|
||||
let item_idx = self.cell_to_item(cell_idx);
|
||||
if item_idx >= 0 {
|
||||
self.item_line[item_idx as usize].as_ref()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn cell_to_item(&self, cell_idx: usize) -> i32 {
|
||||
self.cell_to_item[cell_idx]
|
||||
|
@ -6,7 +6,7 @@ mod model_rect;
|
||||
pub use self::cell::{Cell, Attrs};
|
||||
pub use self::line::StyledLine;
|
||||
pub use self::item::Item;
|
||||
pub use self::model_rect::{ModelRect, ModelRectVec, ClipRowIterator};
|
||||
pub use self::model_rect::{ModelRect, ModelRectVec};
|
||||
use self::line::Line;
|
||||
|
||||
|
||||
@ -50,33 +50,6 @@ impl UiModel {
|
||||
&mut self.model
|
||||
}
|
||||
|
||||
pub fn limit_to_model(&self, clip: &mut ModelRect) {
|
||||
clip.left = if clip.left >= self.columns {
|
||||
self.columns - 1
|
||||
} else {
|
||||
clip.left
|
||||
};
|
||||
clip.right = if clip.right >= self.columns {
|
||||
self.columns - 1
|
||||
} else {
|
||||
clip.right
|
||||
};
|
||||
clip.top = if clip.top >= self.rows {
|
||||
self.rows - 1
|
||||
} else {
|
||||
clip.top
|
||||
};
|
||||
clip.bot = if clip.bot >= self.rows {
|
||||
self.rows - 1
|
||||
} else {
|
||||
clip.bot
|
||||
};
|
||||
}
|
||||
|
||||
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_col, self.cur_row)
|
||||
}
|
||||
@ -186,9 +159,9 @@ impl UiModel {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_draw_cache(&mut self) {
|
||||
pub fn clear_glyphs(&mut self) {
|
||||
for row in &mut self.model.iter_mut() {
|
||||
row.clear_draw_cache();
|
||||
row.clear_glyphs();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,34 +230,6 @@ mod tests {
|
||||
assert_eq!(2, list.list.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_iterator_border() {
|
||||
let model = UiModel::new(10, 20);
|
||||
let rect = ModelRect::new(0, 9, 0, 19);
|
||||
|
||||
assert_eq!(10, model.clip_model(&rect).count());
|
||||
let (_, first_line) = model.clip_model(&rect).nth(0).unwrap();
|
||||
assert_eq!(20, first_line.iter().count());
|
||||
|
||||
let (idx, _) = first_line.iter().nth(19).unwrap();
|
||||
assert_eq!(19, idx);
|
||||
}
|
||||
|
||||
#[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());
|
||||
let (idx, first_line) = model.clip_model(&rect).nth(0).unwrap();
|
||||
|
||||
assert_eq!(1, idx);
|
||||
assert_eq!(2, first_line.iter().count());
|
||||
|
||||
let (idx, _) = first_line.iter().nth(0).unwrap();
|
||||
assert_eq!(1, idx);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_area() {
|
||||
let rect = ModelRect::from_area(10.0, 5.0, 3.0, 3.0, 9.0, 17.0);
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::slice::Iter;
|
||||
|
||||
use super::{Line, UiModel, Cell};
|
||||
use super::UiModel;
|
||||
use super::item::Item;
|
||||
use render::CellMetrics;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -16,11 +16,13 @@ impl ModelRectVec {
|
||||
fn find_neighbor(&self, neighbor: &ModelRect) -> Option<usize> {
|
||||
for (i, rect) in self.list.iter().enumerate() {
|
||||
if (neighbor.top > 0 && rect.top == neighbor.top - 1 ||
|
||||
rect.bot == neighbor.bot + 1) && neighbor.in_horizontal(rect) {
|
||||
rect.bot == neighbor.bot + 1) && neighbor.in_horizontal(rect)
|
||||
{
|
||||
return Some(i);
|
||||
} else if (neighbor.left > 0 && rect.left == neighbor.left - 1 ||
|
||||
rect.right == neighbor.right + 1) &&
|
||||
neighbor.in_vertical(rect) {
|
||||
rect.right == neighbor.right + 1) &&
|
||||
neighbor.in_vertical(rect)
|
||||
{
|
||||
return Some(i);
|
||||
} else if rect.in_horizontal(neighbor) && rect.in_vertical(neighbor) {
|
||||
return Some(i);
|
||||
@ -73,32 +75,21 @@ impl ModelRect {
|
||||
#[inline]
|
||||
fn in_horizontal(&self, other: &ModelRect) -> bool {
|
||||
other.left >= self.left && other.left <= self.right ||
|
||||
other.right >= self.left && other.right >= self.right
|
||||
other.right >= self.left && other.right >= self.right
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn in_vertical(&self, other: &ModelRect) -> bool {
|
||||
other.top >= self.top && other.top <= self.bot ||
|
||||
other.bot >= self.top && other.bot <= self.bot
|
||||
other.bot >= self.top && other.bot <= self.bot
|
||||
}
|
||||
|
||||
fn contains(&self, other: &ModelRect) -> bool {
|
||||
self.top <= other.top && self.bot >= other.bot && self.left <= other.left &&
|
||||
self.right >= other.right
|
||||
self.right >= other.right
|
||||
}
|
||||
|
||||
pub fn extend(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
||||
if self.top > 0 {
|
||||
self.top -= top;
|
||||
}
|
||||
if self.left > 0 {
|
||||
self.left -= left;
|
||||
}
|
||||
self.bot += bot;
|
||||
self.right += right;
|
||||
}
|
||||
|
||||
/// Extend rect to left and right to make change Item rerendered
|
||||
/// Extend rect to left and right to make changed Item rerendered
|
||||
pub fn extend_by_items(&mut self, model: &UiModel) {
|
||||
let mut left = self.left;
|
||||
let mut right = self.right;
|
||||
@ -120,6 +111,73 @@ impl ModelRect {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_area_extend_ink(
|
||||
&self,
|
||||
model: &UiModel,
|
||||
cell_metrics: &CellMetrics,
|
||||
) -> (i32, i32, i32, i32) {
|
||||
|
||||
let (x, x2) = self.extend_left_right_area(model, cell_metrics);
|
||||
let (y, y2) = self.extend_top_bottom_area(model, cell_metrics);
|
||||
|
||||
(x, y, x2 - x, y2 - y)
|
||||
}
|
||||
|
||||
fn extend_left_right_area(&self, model: &UiModel, cell_metrics: &CellMetrics) -> (i32, i32) {
|
||||
|
||||
let mut x = self.left as i32 * cell_metrics.char_width as i32;
|
||||
let mut x2 = (self.right + 1) as i32 * cell_metrics.char_width as i32;
|
||||
|
||||
for row in self.top..self.bot + 1 {
|
||||
|
||||
// left
|
||||
let line = &model.model[row];
|
||||
if let Some(&Item { ink_rect: Some(ink_rect), .. }) = line.get_item(self.left) {
|
||||
if x > ink_rect.x {
|
||||
x = ink_rect.x;
|
||||
}
|
||||
}
|
||||
|
||||
// right
|
||||
let line = &model.model[row];
|
||||
if let Some(&Item { ink_rect: Some(ink_rect), .. }) = line.get_item(self.right) {
|
||||
let ink_x = ink_rect.x + ink_rect.width;
|
||||
if x2 > ink_x {
|
||||
x2 = ink_x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(x, x2)
|
||||
}
|
||||
|
||||
fn extend_top_bottom_area(&self, model: &UiModel, cell_metrics: &CellMetrics) -> (i32, i32) {
|
||||
let mut y = self.top as i32 * cell_metrics.line_height as i32;
|
||||
let mut y2 = (self.bot + 1) as i32 * cell_metrics.line_height as i32;
|
||||
|
||||
for col in self.left..self.right + 1 {
|
||||
|
||||
// top
|
||||
let line = &model.model[self.top];
|
||||
if let Some(&Item { ink_rect: Some(ink_rect), .. }) = line.get_item(col) {
|
||||
if y > ink_rect.y {
|
||||
y = ink_rect.y;
|
||||
}
|
||||
}
|
||||
|
||||
// bottom
|
||||
let line = &model.model[self.bot];
|
||||
if let Some(&Item { ink_rect: Some(ink_rect), .. }) = line.get_item(col) {
|
||||
let ink_y = ink_rect.y + ink_rect.height;
|
||||
if y2 < ink_y {
|
||||
y2 = ink_y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(y, y2)
|
||||
}
|
||||
|
||||
pub fn join(&mut self, rect: &ModelRect) {
|
||||
self.top = if self.top < rect.top {
|
||||
self.top
|
||||
@ -147,20 +205,29 @@ impl ModelRect {
|
||||
debug_assert!(self.left <= self.right);
|
||||
}
|
||||
|
||||
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 to_area(&self, cell_metrics: &CellMetrics) -> (i32, i32, i32, i32) {
|
||||
let &CellMetrics {
|
||||
char_width,
|
||||
line_height,
|
||||
..
|
||||
} = cell_metrics;
|
||||
|
||||
(
|
||||
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: f64,
|
||||
char_width: f64,
|
||||
x1: f64,
|
||||
y1: f64,
|
||||
x2: f64,
|
||||
y2: f64)
|
||||
-> ModelRect {
|
||||
pub fn from_area(
|
||||
line_height: f64,
|
||||
char_width: f64,
|
||||
x1: f64,
|
||||
y1: f64,
|
||||
x2: f64,
|
||||
y2: f64,
|
||||
) -> ModelRect {
|
||||
let x2 = if x2 > 0.0 { x2 - 1.0 } else { x2 };
|
||||
let y2 = if y2 > 0.0 { y2 - 1.0 } else { y2 };
|
||||
let left = (x1 / char_width) as usize;
|
||||
@ -177,86 +244,3 @@ impl AsRef<ModelRect> for ModelRect {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipRowIterator<'a> {
|
||||
rect: &'a ModelRect,
|
||||
pos: usize,
|
||||
iter: Iter<'a, Line>,
|
||||
}
|
||||
|
||||
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, ClipLine<'a>);
|
||||
|
||||
fn next(&mut self) -> Option<(usize, ClipLine<'a>)> {
|
||||
self.pos += 1;
|
||||
self.iter
|
||||
.next()
|
||||
.map(|line| (self.rect.top + self.pos - 1, ClipLine::new(line, self.rect)))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipLine<'a> {
|
||||
rect: &'a ModelRect,
|
||||
line: &'a Line,
|
||||
}
|
||||
|
||||
impl<'a> ClipLine<'a> {
|
||||
pub fn new(model: &'a Line, rect: &'a ModelRect) -> ClipLine<'a> {
|
||||
ClipLine {
|
||||
line: model,
|
||||
rect: rect,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_double_width(&self, col_idx: usize) -> bool {
|
||||
self.get(col_idx + 1)
|
||||
.map(|c| c.attrs.double_width)
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn get(&self, idx: usize) -> Option<&Cell> {
|
||||
self.line.line.get(idx)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> ClipColIterator<'a> {
|
||||
ClipColIterator::new(self.line, self.rect)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ClipColIterator<'a> {
|
||||
rect: &'a ModelRect,
|
||||
pos: usize,
|
||||
iter: Iter<'a, Cell>,
|
||||
}
|
||||
|
||||
impl<'a> ClipColIterator<'a> {
|
||||
pub fn new(model: &'a Line, rect: &'a ModelRect) -> ClipColIterator<'a> {
|
||||
ClipColIterator {
|
||||
rect: rect,
|
||||
pos: 0,
|
||||
iter: model.line[rect.left..rect.right + 1].iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 - 1, line))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user