2017-08-23 09:45:56 +00:00
|
|
|
mod cell;
|
|
|
|
mod line;
|
2016-03-31 16:19:08 +00:00
|
|
|
|
2017-08-23 09:45:56 +00:00
|
|
|
pub use self::cell::{Cell, Attrs};
|
|
|
|
use self::line::Line;
|
2016-04-03 13:04:52 +00:00
|
|
|
|
2017-08-23 09:45:56 +00:00
|
|
|
use std::slice::Iter;
|
2016-03-19 08:47:23 +00:00
|
|
|
|
|
|
|
pub struct UiModel {
|
2016-04-03 22:34:44 +00:00
|
|
|
pub columns: usize,
|
|
|
|
pub rows: usize,
|
2016-03-28 15:05:10 +00:00
|
|
|
cur_row: usize,
|
|
|
|
cur_col: usize,
|
2017-08-23 09:45:56 +00:00
|
|
|
model: Box<[Line]>,
|
2016-04-03 15:13:18 +00:00
|
|
|
top: usize,
|
|
|
|
bot: usize,
|
|
|
|
left: usize,
|
|
|
|
right: usize,
|
2016-03-19 08:47:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl UiModel {
|
2016-03-28 15:05:10 +00:00
|
|
|
pub fn new(rows: u64, columns: u64) -> UiModel {
|
|
|
|
let mut model = Vec::with_capacity(rows as usize);
|
|
|
|
for i in 0..rows as usize {
|
2017-08-23 09:45:56 +00:00
|
|
|
model.push(Line::new(columns as usize));
|
2016-03-19 08:47:23 +00:00
|
|
|
}
|
|
|
|
|
2016-03-31 16:19:08 +00:00
|
|
|
UiModel {
|
2016-03-28 15:05:10 +00:00
|
|
|
columns: columns as usize,
|
|
|
|
rows: rows as usize,
|
2016-03-19 08:47:23 +00:00
|
|
|
cur_row: 0,
|
|
|
|
cur_col: 0,
|
2017-08-23 09:45:56 +00:00
|
|
|
model: model.into_boxed_slice(),
|
2016-04-03 15:13:18 +00:00
|
|
|
top: 0,
|
2017-03-09 13:51:34 +00:00
|
|
|
bot: (rows - 1) as usize,
|
2016-04-03 15:13:18 +00:00
|
|
|
left: 0,
|
2017-03-09 13:51:34 +00:00
|
|
|
right: (columns - 1) as usize,
|
2016-03-19 08:47:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-23 09:45:56 +00:00
|
|
|
pub fn model(&self) -> &[Line] {
|
2016-03-31 16:19:08 +00:00
|
|
|
&self.model
|
2016-03-31 10:09:34 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 10:10:55 +00:00
|
|
|
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
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
pub fn clip_model<'a>(&'a self, clip: &'a ModelRect) -> ClipRowIterator<'a> {
|
2017-03-20 15:18:08 +00:00
|
|
|
ClipRowIterator::new(self, clip)
|
|
|
|
}
|
|
|
|
|
2017-03-18 09:45:05 +00:00
|
|
|
pub fn cur_point(&self) -> ModelRect {
|
2017-04-19 08:40:53 +00:00
|
|
|
ModelRect::point(self.cur_col, self.cur_row)
|
2017-03-18 09:45:05 +00:00
|
|
|
}
|
|
|
|
|
2017-04-22 19:18:59 +00:00
|
|
|
pub fn set_cursor(&mut self, row: usize, col: usize) -> ModelRectVec {
|
|
|
|
let mut changed_region = ModelRectVec::new(self.cur_point());
|
2017-03-17 20:38:12 +00:00
|
|
|
|
2017-03-24 19:23:22 +00:00
|
|
|
self.cur_row = row;
|
|
|
|
self.cur_col = col;
|
2017-03-17 20:38:12 +00:00
|
|
|
|
2017-03-18 09:45:05 +00:00
|
|
|
changed_region.join(&self.cur_point());
|
2017-03-17 20:38:12 +00:00
|
|
|
|
|
|
|
changed_region
|
|
|
|
|
2016-05-03 17:25:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_cursor(&self) -> (usize, usize) {
|
|
|
|
(self.cur_row, self.cur_col)
|
2016-03-28 15:05:10 +00:00
|
|
|
}
|
|
|
|
|
2017-03-17 20:38:12 +00:00
|
|
|
pub fn put(&mut self, text: &str, attrs: Option<&Attrs>) -> ModelRect {
|
2017-03-18 10:21:20 +00:00
|
|
|
let mut changed_region = self.cur_point();
|
2016-03-31 16:19:08 +00:00
|
|
|
let mut cell = &mut self.model[self.cur_row][self.cur_col];
|
2017-03-17 20:38:12 +00:00
|
|
|
|
2017-03-12 09:20:18 +00:00
|
|
|
cell.ch = text.chars().last().unwrap_or(' ');
|
2017-07-25 14:55:31 +00:00
|
|
|
cell.attrs = attrs.map(Attrs::clone).unwrap_or_else(Attrs::new);
|
|
|
|
cell.attrs.double_width = text.is_empty();
|
2016-03-28 15:05:10 +00:00
|
|
|
self.cur_col += 1;
|
2017-03-18 10:21:20 +00:00
|
|
|
if self.cur_col >= self.columns {
|
|
|
|
self.cur_col -= 1;
|
|
|
|
}
|
|
|
|
|
2017-04-19 08:40:53 +00:00
|
|
|
changed_region.join(&ModelRect::point(self.cur_col, self.cur_row));
|
2017-03-17 20:38:12 +00:00
|
|
|
|
|
|
|
changed_region
|
2016-03-19 08:47:23 +00:00
|
|
|
}
|
2016-03-29 09:22:16 +00:00
|
|
|
|
2016-04-03 15:13:18 +00:00
|
|
|
pub fn set_scroll_region(&mut self, top: u64, bot: u64, left: u64, right: u64) {
|
|
|
|
self.top = top as usize;
|
|
|
|
self.bot = bot as usize;
|
|
|
|
self.left = left as usize;
|
|
|
|
self.right = right as usize;
|
|
|
|
}
|
|
|
|
|
2017-03-17 20:38:12 +00:00
|
|
|
#[inline]
|
2017-03-18 10:21:20 +00:00
|
|
|
fn copy_row(&mut self, row: i64, offset: i64, left: usize, right: usize) {
|
2016-04-03 15:13:18 +00:00
|
|
|
for col in left..right + 1 {
|
2017-03-18 10:21:20 +00:00
|
|
|
let from_row = (row + offset) as usize;
|
2017-02-26 19:33:44 +00:00
|
|
|
let from_cell = self.model[from_row][col].clone();
|
2017-03-18 10:21:20 +00:00
|
|
|
self.model[row as usize][col] = from_cell;
|
2017-02-26 19:33:44 +00:00
|
|
|
}
|
2016-04-03 15:13:18 +00:00
|
|
|
}
|
|
|
|
|
2017-03-18 10:21:20 +00:00
|
|
|
pub fn scroll(&mut self, count: i64) -> ModelRect {
|
|
|
|
let (top, bot, left, right) = (self.top as i64, self.bot as i64, self.left, self.right);
|
2016-04-03 15:13:18 +00:00
|
|
|
|
|
|
|
if count > 0 {
|
2017-03-17 20:38:12 +00:00
|
|
|
for row in top..(bot - count + 1) {
|
2016-04-03 15:13:18 +00:00
|
|
|
self.copy_row(row, count, left, right);
|
|
|
|
}
|
|
|
|
} else {
|
2017-03-17 20:38:12 +00:00
|
|
|
for row in ((top - count)..(bot + 1)).rev() {
|
2016-04-03 15:13:18 +00:00
|
|
|
self.copy_row(row, count, left, right);
|
2016-03-29 09:22:16 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-03 15:13:18 +00:00
|
|
|
|
|
|
|
if count > 0 {
|
2017-03-18 10:21:20 +00:00
|
|
|
self.clear_region((bot - count + 1) as usize, bot as usize, left, right);
|
2016-04-03 15:13:18 +00:00
|
|
|
} else {
|
2017-03-18 10:21:20 +00:00
|
|
|
self.clear_region(top as usize, (top - count - 1) as usize, left, right);
|
2016-04-03 15:13:18 +00:00
|
|
|
}
|
2017-03-17 20:38:12 +00:00
|
|
|
|
2017-03-18 10:21:20 +00:00
|
|
|
ModelRect::new(top as usize, bot as usize, left, right)
|
2016-04-03 15:13:18 +00:00
|
|
|
}
|
|
|
|
|
2017-03-18 09:45:05 +00:00
|
|
|
pub fn clear(&mut self) {
|
2016-04-03 15:13:18 +00:00
|
|
|
let (rows, columns) = (self.rows, self.columns);
|
|
|
|
self.clear_region(0, rows - 1, 0, columns - 1);
|
2016-03-29 09:22:16 +00:00
|
|
|
}
|
2016-04-03 13:04:52 +00:00
|
|
|
|
2017-03-17 20:38:12 +00:00
|
|
|
pub fn eol_clear(&mut self) -> ModelRect {
|
2016-04-03 13:04:52 +00:00
|
|
|
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);
|
2017-03-17 20:38:12 +00:00
|
|
|
|
2017-04-22 14:22:01 +00:00
|
|
|
ModelRect::new(cur_row, cur_row, cur_col, columns - 1)
|
2016-04-03 13:04:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn clear_region(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
2016-04-03 15:13:18 +00:00
|
|
|
for row in &mut self.model[top..bot + 1] {
|
|
|
|
for cell in &mut row[left..right + 1] {
|
|
|
|
cell.clear();
|
2016-04-03 13:04:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-03-19 08:47:23 +00:00
|
|
|
}
|
2017-03-17 20:38:12 +00:00
|
|
|
|
2017-04-22 19:18:59 +00:00
|
|
|
#[derive(Clone, Debug)]
|
2017-04-21 15:26:06 +00:00
|
|
|
pub struct ModelRectVec {
|
2017-04-22 11:31:06 +00:00
|
|
|
pub list: Vec<ModelRect>,
|
2017-04-21 15:26:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ModelRectVec {
|
|
|
|
pub fn new(first: ModelRect) -> ModelRectVec {
|
|
|
|
ModelRectVec { list: vec![first] }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn find_neighbor(&self, neighbor: &ModelRect) -> Option<usize> {
|
|
|
|
for (i, rect) in self.list.iter().enumerate() {
|
2017-04-22 11:31:06 +00:00
|
|
|
if (neighbor.top > 0 && rect.top == neighbor.top - 1 ||
|
|
|
|
rect.bot == neighbor.bot + 1) && neighbor.in_horizontal(rect) {
|
2017-04-21 15:26:06 +00:00
|
|
|
return Some(i);
|
2017-04-22 11:31:06 +00:00
|
|
|
} else if (neighbor.left > 0 && rect.left == neighbor.left - 1 ||
|
|
|
|
rect.right == neighbor.right + 1) &&
|
2017-04-21 15:26:06 +00:00
|
|
|
neighbor.in_vertical(rect) {
|
|
|
|
return Some(i);
|
2017-04-22 19:18:59 +00:00
|
|
|
} else if rect.in_horizontal(neighbor) && rect.in_vertical(neighbor) {
|
|
|
|
return Some(i);
|
|
|
|
} else if rect.contains(neighbor) {
|
2017-04-21 15:26:06 +00:00
|
|
|
return Some(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2017-04-22 11:31:06 +00:00
|
|
|
pub fn join(&mut self, other: &ModelRect) {
|
|
|
|
match self.find_neighbor(other) {
|
2017-07-25 14:55:31 +00:00
|
|
|
Some(i) => self.list[i].join(other),
|
2017-04-22 11:31:06 +00:00
|
|
|
None => self.list.push(other.clone()),
|
2017-04-21 15:26:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-22 10:15:02 +00:00
|
|
|
#[derive(Clone, PartialEq, Debug)]
|
2017-03-17 20:38:12 +00:00
|
|
|
pub struct ModelRect {
|
2017-03-20 15:18:08 +00:00
|
|
|
pub top: usize,
|
|
|
|
pub bot: usize,
|
|
|
|
pub left: usize,
|
|
|
|
pub right: usize,
|
2017-03-17 20:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ModelRect {
|
|
|
|
pub fn new(top: usize, bot: usize, left: usize, right: usize) -> ModelRect {
|
2017-04-22 14:22:01 +00:00
|
|
|
debug_assert!(top <= bot);
|
|
|
|
debug_assert!(left <= right);
|
|
|
|
|
2017-03-17 20:38:12 +00:00
|
|
|
ModelRect {
|
|
|
|
top: top,
|
|
|
|
bot: bot,
|
|
|
|
left: left,
|
|
|
|
right: right,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn point(x: usize, y: usize) -> ModelRect {
|
|
|
|
ModelRect {
|
2017-04-19 08:40:53 +00:00
|
|
|
top: y,
|
|
|
|
bot: y,
|
|
|
|
left: x,
|
|
|
|
right: x,
|
2017-03-17 20:38:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-21 15:26:06 +00:00
|
|
|
#[inline]
|
|
|
|
fn in_horizontal(&self, other: &ModelRect) -> bool {
|
|
|
|
other.left >= self.left && other.left <= 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
|
|
|
|
}
|
|
|
|
|
2017-04-22 19:18:59 +00:00
|
|
|
fn contains(&self, other: &ModelRect) -> bool {
|
2017-04-23 10:42:05 +00:00
|
|
|
self.top <= other.top && self.bot >= other.bot && self.left <= other.left &&
|
2017-04-22 19:18:59 +00:00
|
|
|
self.right >= other.right
|
|
|
|
}
|
|
|
|
|
2017-04-22 09:08:03 +00:00
|
|
|
pub fn extend(&mut self, top: usize, bot: usize, left: usize, right: usize) {
|
|
|
|
if self.top > 0 {
|
|
|
|
self.top -= top;
|
|
|
|
}
|
2017-04-22 11:31:06 +00:00
|
|
|
if self.left > 0 {
|
2017-04-22 09:08:03 +00:00
|
|
|
self.left -= left;
|
|
|
|
}
|
|
|
|
self.bot += bot;
|
|
|
|
self.right += right;
|
|
|
|
}
|
|
|
|
|
2017-03-17 20:38:12 +00:00
|
|
|
pub fn join(&mut self, rect: &ModelRect) {
|
|
|
|
self.top = if self.top < rect.top {
|
|
|
|
self.top
|
|
|
|
} else {
|
|
|
|
rect.top
|
|
|
|
};
|
|
|
|
self.left = if self.left < rect.left {
|
|
|
|
self.left
|
|
|
|
} else {
|
|
|
|
rect.left
|
|
|
|
};
|
|
|
|
|
|
|
|
self.bot = if self.bot > rect.bot {
|
|
|
|
self.bot
|
|
|
|
} else {
|
|
|
|
rect.bot
|
|
|
|
};
|
|
|
|
self.right = if self.right > rect.right {
|
|
|
|
self.right
|
|
|
|
} else {
|
|
|
|
rect.right
|
|
|
|
};
|
2017-04-22 14:22:01 +00:00
|
|
|
|
|
|
|
debug_assert!(self.top <= self.bot);
|
|
|
|
debug_assert!(self.left <= self.right);
|
2017-03-17 20:38:12 +00:00
|
|
|
}
|
2017-03-17 22:18:41 +00:00
|
|
|
|
2017-03-20 15:18:08 +00:00
|
|
|
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,
|
2017-03-24 19:23:22 +00:00
|
|
|
(self.right - self.left + 1) as i32 * char_width as i32,
|
|
|
|
(self.bot - self.top + 1) as i32 * line_height as i32)
|
2017-03-18 09:45:05 +00:00
|
|
|
}
|
2017-03-18 11:19:36 +00:00
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
pub fn from_area(line_height: f64,
|
|
|
|
char_width: f64,
|
|
|
|
x1: f64,
|
|
|
|
y1: f64,
|
|
|
|
x2: f64,
|
|
|
|
y2: f64)
|
|
|
|
-> ModelRect {
|
2017-04-12 10:12:05 +00:00
|
|
|
let x2 = if x2 > 0.0 { x2 - 1.0 } else { x2 };
|
|
|
|
let y2 = if y2 > 0.0 { y2 - 1.0 } else { y2 };
|
2017-03-20 15:18:08 +00:00
|
|
|
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;
|
2017-03-18 11:19:36 +00:00
|
|
|
|
|
|
|
ModelRect::new(top, bot, left, right)
|
|
|
|
}
|
2017-03-18 09:45:05 +00:00
|
|
|
}
|
|
|
|
|
2017-04-22 11:31:06 +00:00
|
|
|
impl AsRef<ModelRect> for ModelRect {
|
|
|
|
fn as_ref(&self) -> &ModelRect {
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-20 15:18:08 +00:00
|
|
|
pub struct ClipRowIterator<'a> {
|
|
|
|
rect: &'a ModelRect,
|
|
|
|
pos: usize,
|
|
|
|
iter: Iter<'a, Vec<Cell>>,
|
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
impl<'a> ClipRowIterator<'a> {
|
2017-03-20 15:18:08 +00:00
|
|
|
pub fn new(model: &'a UiModel, rect: &'a ModelRect) -> ClipRowIterator<'a> {
|
2017-03-25 08:31:52 +00:00
|
|
|
ClipRowIterator {
|
2017-03-20 15:18:08 +00:00
|
|
|
rect: rect,
|
|
|
|
pos: 0,
|
|
|
|
iter: model.model()[rect.top..rect.bot + 1].iter(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
impl<'a> Iterator for ClipRowIterator<'a> {
|
2017-03-21 10:10:55 +00:00
|
|
|
type Item = (usize, ClipLine<'a>);
|
2017-03-20 15:18:08 +00:00
|
|
|
|
2017-03-21 10:10:55 +00:00
|
|
|
fn next(&mut self) -> Option<(usize, ClipLine<'a>)> {
|
2017-03-20 15:18:08 +00:00
|
|
|
self.pos += 1;
|
2017-04-12 10:12:05 +00:00
|
|
|
self.iter
|
|
|
|
.next()
|
|
|
|
.map(|line| (self.rect.top + self.pos - 1, ClipLine::new(line, self.rect)))
|
2017-03-20 15:18:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
pub struct ClipLine<'a> {
|
2017-03-20 15:18:08 +00:00
|
|
|
rect: &'a ModelRect,
|
2017-07-25 14:55:31 +00:00
|
|
|
line: &'a [Cell],
|
2017-03-21 10:10:55 +00:00
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
impl<'a> ClipLine<'a> {
|
2017-07-25 14:55:31 +00:00
|
|
|
pub fn new(model: &'a [Cell], rect: &'a ModelRect) -> ClipLine<'a> {
|
2017-03-21 10:10:55 +00:00
|
|
|
ClipLine {
|
|
|
|
line: model,
|
|
|
|
rect: rect,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-23 10:42:05 +00:00
|
|
|
#[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)
|
|
|
|
}
|
|
|
|
|
2017-03-21 10:10:55 +00:00
|
|
|
pub fn get(&self, idx: usize) -> Option<&Cell> {
|
|
|
|
self.line.get(idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn iter(&self) -> ClipColIterator<'a> {
|
|
|
|
ClipColIterator::new(self.line, self.rect)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct ClipColIterator<'a> {
|
|
|
|
rect: &'a ModelRect,
|
2017-03-20 15:18:08 +00:00
|
|
|
pos: usize,
|
|
|
|
iter: Iter<'a, Cell>,
|
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
impl<'a> ClipColIterator<'a> {
|
2017-07-25 14:55:31 +00:00
|
|
|
pub fn new(model: &'a [Cell], rect: &'a ModelRect) -> ClipColIterator<'a> {
|
2017-03-25 08:31:52 +00:00
|
|
|
ClipColIterator {
|
2017-03-20 15:18:08 +00:00
|
|
|
rect: rect,
|
|
|
|
pos: 0,
|
|
|
|
iter: model[rect.left..rect.right + 1].iter(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
impl<'a> Iterator for ClipColIterator<'a> {
|
2017-03-20 15:18:08 +00:00
|
|
|
type Item = (usize, &'a Cell);
|
|
|
|
|
|
|
|
fn next(&mut self) -> Option<(usize, &'a Cell)> {
|
|
|
|
self.pos += 1;
|
2017-04-12 10:12:05 +00:00
|
|
|
self.iter
|
|
|
|
.next()
|
|
|
|
.map(|line| (self.rect.left + self.pos - 1, line))
|
2017-03-20 15:18:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-18 09:45:05 +00:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
|
|
|
|
2017-04-22 19:18:59 +00:00
|
|
|
#[test]
|
|
|
|
fn test_vec_join_inside() {
|
2017-04-23 10:42:05 +00:00
|
|
|
let mut list = ModelRectVec::new(ModelRect::new(0, 23, 0, 69));
|
2017-04-22 19:18:59 +00:00
|
|
|
|
|
|
|
let inside = ModelRect::new(23, 23, 68, 69);
|
|
|
|
|
|
|
|
list.join(&inside);
|
|
|
|
assert_eq!(1, list.list.len());
|
|
|
|
}
|
|
|
|
|
2017-04-22 11:31:06 +00:00
|
|
|
#[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());
|
|
|
|
}
|
|
|
|
|
2017-04-22 19:18:59 +00:00
|
|
|
#[test]
|
|
|
|
fn test_model_vec_join_right() {
|
|
|
|
let mut list = ModelRectVec::new(ModelRect::new(23, 23, 69, 69));
|
|
|
|
|
|
|
|
let neighbor = ModelRect::new(23, 23, 69, 70);
|
|
|
|
|
|
|
|
list.join(&neighbor);
|
|
|
|
assert_eq!(1, list.list.len());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_model_vec_join_right2() {
|
|
|
|
let mut list = ModelRectVec::new(ModelRect::new(0, 1, 0, 9));
|
|
|
|
|
|
|
|
let neighbor = ModelRect::new(1, 1, 9, 10);
|
|
|
|
|
|
|
|
list.join(&neighbor);
|
|
|
|
assert_eq!(1, list.list.len());
|
|
|
|
}
|
|
|
|
|
2017-04-21 15:26:06 +00:00
|
|
|
#[test]
|
|
|
|
fn test_model_vec_join() {
|
|
|
|
let mut list = ModelRectVec::new(ModelRect::point(5, 5));
|
|
|
|
|
|
|
|
let neighbor = ModelRect::point(6, 5);
|
|
|
|
|
2017-04-22 11:31:06 +00:00
|
|
|
list.join(&neighbor);
|
2017-04-21 15:26:06 +00:00
|
|
|
assert_eq!(1, list.list.len());
|
2017-04-21 19:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_model_vec_no_join() {
|
|
|
|
let mut list = ModelRectVec::new(ModelRect::point(5, 5));
|
|
|
|
|
|
|
|
let not_neighbor = ModelRect::point(6, 6);
|
2017-04-21 15:26:06 +00:00
|
|
|
|
2017-04-22 11:31:06 +00:00
|
|
|
list.join(¬_neighbor);
|
2017-04-21 15:26:06 +00:00
|
|
|
assert_eq!(2, list.list.len());
|
|
|
|
}
|
|
|
|
|
2017-03-21 10:10:55 +00:00
|
|
|
#[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);
|
|
|
|
}
|
|
|
|
|
2017-03-20 15:18:08 +00:00
|
|
|
#[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());
|
2017-03-21 10:10:55 +00:00
|
|
|
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);
|
2017-03-20 15:18:08 +00:00
|
|
|
}
|
|
|
|
|
2017-03-18 11:19:36 +00:00
|
|
|
#[test]
|
|
|
|
fn test_from_area() {
|
2017-03-20 15:18:08 +00:00
|
|
|
let rect = ModelRect::from_area(10.0, 5.0, 3.0, 3.0, 9.0, 17.0);
|
2017-03-18 11:19:36 +00:00
|
|
|
|
|
|
|
assert_eq!(0, rect.top);
|
|
|
|
assert_eq!(0, rect.left);
|
|
|
|
assert_eq!(1, rect.bot);
|
|
|
|
assert_eq!(1, rect.right);
|
2017-03-21 10:10:55 +00:00
|
|
|
|
|
|
|
|
2017-03-25 08:31:52 +00:00
|
|
|
let rect = ModelRect::from_area(10.0, 5.0, 0.0, 0.0, 10.0, 20.0);
|
2017-03-21 10:10:55 +00:00
|
|
|
|
|
|
|
assert_eq!(0, rect.top);
|
|
|
|
assert_eq!(0, rect.left);
|
|
|
|
assert_eq!(1, rect.bot);
|
|
|
|
assert_eq!(1, rect.right);
|
2017-03-25 08:31:52 +00:00
|
|
|
|
|
|
|
|
|
|
|
let rect = ModelRect::from_area(10.0, 5.0, 0.0, 0.0, 11.0, 21.0);
|
|
|
|
|
|
|
|
assert_eq!(0, rect.top);
|
|
|
|
assert_eq!(0, rect.left);
|
|
|
|
assert_eq!(2, rect.bot);
|
|
|
|
assert_eq!(2, rect.right);
|
2017-03-18 11:19:36 +00:00
|
|
|
}
|
|
|
|
|
2017-03-18 09:45:05 +00:00
|
|
|
#[test]
|
|
|
|
fn test_cursor_area() {
|
|
|
|
let mut model = UiModel::new(10, 20);
|
|
|
|
|
|
|
|
model.set_cursor(1, 1);
|
|
|
|
|
|
|
|
let rect = model.set_cursor(5, 5);
|
|
|
|
|
2017-04-22 19:18:59 +00:00
|
|
|
assert_eq!(2, rect.list.len());
|
|
|
|
|
|
|
|
assert_eq!(1, rect.list[0].top);
|
|
|
|
assert_eq!(1, rect.list[0].left);
|
|
|
|
assert_eq!(1, rect.list[0].bot);
|
|
|
|
assert_eq!(1, rect.list[0].right);
|
|
|
|
|
|
|
|
|
|
|
|
assert_eq!(5, rect.list[1].top);
|
|
|
|
assert_eq!(5, rect.list[1].left);
|
|
|
|
assert_eq!(5, rect.list[1].bot);
|
|
|
|
assert_eq!(5, rect.list[1].right);
|
2017-03-18 09:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_eol_clear_area() {
|
|
|
|
let mut model = UiModel::new(10, 20);
|
|
|
|
|
2017-04-22 14:22:01 +00:00
|
|
|
model.set_cursor(1, 2);
|
2017-03-18 09:45:05 +00:00
|
|
|
|
|
|
|
let rect = model.eol_clear();
|
|
|
|
|
|
|
|
assert_eq!(1, rect.top);
|
2017-04-22 14:22:01 +00:00
|
|
|
assert_eq!(2, rect.left);
|
2017-03-18 09:45:05 +00:00
|
|
|
assert_eq!(1, rect.bot);
|
|
|
|
assert_eq!(19, rect.right);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_repaint_rect() {
|
|
|
|
let rect = ModelRect::point(1, 1);
|
2017-03-21 10:10:55 +00:00
|
|
|
let (x, y, width, height) = rect.to_area(10.0, 5.0);
|
2017-03-18 09:45:05 +00:00
|
|
|
|
|
|
|
assert_eq!(5, x);
|
|
|
|
assert_eq!(10, y);
|
2017-03-24 19:23:22 +00:00
|
|
|
assert_eq!(5, width);
|
|
|
|
assert_eq!(10, height);
|
2017-03-18 09:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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);
|
2017-03-18 10:21:20 +00:00
|
|
|
assert_eq!(2, rect.right);
|
2017-03-18 09:45:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[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);
|
2017-03-17 22:18:41 +00:00
|
|
|
}
|
2017-03-17 20:38:12 +00:00
|
|
|
}
|