Starting update queue area code rewriting
This commit is contained in:
parent
ecae1d09c6
commit
6963c7ab95
@ -44,7 +44,7 @@ pub fn render(
|
|||||||
ctx.rectangle(
|
ctx.rectangle(
|
||||||
line_x,
|
line_x,
|
||||||
line_y,
|
line_y,
|
||||||
char_width * line.item_len(i) as f64,
|
char_width * line.item_len_from_idx(i) as f64,
|
||||||
line_height,
|
line_height,
|
||||||
);
|
);
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
|
@ -147,6 +147,8 @@ impl State {
|
|||||||
pub fn set_font_desc(&mut self, desc: &str) {
|
pub fn set_font_desc(&mut self, desc: &str) {
|
||||||
self.font_ctx.update(FontDescription::from_string(desc));
|
self.font_ctx.update(FontDescription::from_string(desc));
|
||||||
self.model.clear_draw_cache();
|
self.model.clear_draw_cache();
|
||||||
|
// TODO: rerun itemize/shape
|
||||||
|
// TODO: send repaint event
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_file(&self, path: &str) {
|
pub fn open_file(&self, path: &str) {
|
||||||
@ -180,8 +182,13 @@ impl State {
|
|||||||
char_width,
|
char_width,
|
||||||
..
|
..
|
||||||
} = self.font_ctx.cell_metrics();
|
} = self.font_ctx.cell_metrics();
|
||||||
|
|
||||||
|
//TODO: run shape here
|
||||||
|
|
||||||
for rect in rect_list {
|
for rect in rect_list {
|
||||||
let mut rect = rect.as_ref().clone();
|
let mut rect = rect.as_ref().clone();
|
||||||
|
rect.extend_by_items(&self.model);
|
||||||
|
|
||||||
// this need to repain also line under curren line
|
// this need to repain also line under curren line
|
||||||
// in case underscore or 'g' symbol is go here
|
// in case underscore or 'g' symbol is go here
|
||||||
// right one for italic symbol
|
// right one for italic symbol
|
||||||
|
44
src/ui_model/item.rs
Normal file
44
src/ui_model/item.rs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
use sys::pango as sys_pango;
|
||||||
|
use pango;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct Item {
|
||||||
|
pub item: sys_pango::Item,
|
||||||
|
pub glyphs: Option<pango::GlyphString>,
|
||||||
|
pub ink_rect: Option<pango::Rectangle>,
|
||||||
|
font: pango::Font,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Item {
|
||||||
|
pub fn new(item: sys_pango::Item) -> Self {
|
||||||
|
Item {
|
||||||
|
font: item.analysis().font(),
|
||||||
|
item,
|
||||||
|
glyphs: None,
|
||||||
|
ink_rect: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, item: sys_pango::Item) {
|
||||||
|
self.font = item.analysis().font();
|
||||||
|
self.item = item;
|
||||||
|
self.glyphs = None;
|
||||||
|
self.ink_rect = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_glyphs(&mut self, glyphs: pango::GlyphString) {
|
||||||
|
let mut glyphs = glyphs;
|
||||||
|
let (ink_rect, _) = glyphs.extents(&self.font);
|
||||||
|
self.ink_rect = Some(ink_rect);
|
||||||
|
self.glyphs = Some(glyphs);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn font(&self) -> &pango::Font {
|
||||||
|
&self.font
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn analysis(&self) -> sys_pango::Analysis {
|
||||||
|
self.item.analysis()
|
||||||
|
}
|
||||||
|
}
|
@ -2,50 +2,10 @@ use std::ops::{Index, IndexMut};
|
|||||||
|
|
||||||
use color;
|
use color;
|
||||||
use super::cell::Cell;
|
use super::cell::Cell;
|
||||||
|
use super::item::Item;
|
||||||
use sys::pango as sys_pango;
|
use sys::pango as sys_pango;
|
||||||
use pango;
|
use pango;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Item {
|
|
||||||
pub item: sys_pango::Item,
|
|
||||||
pub glyphs: Option<pango::GlyphString>,
|
|
||||||
pub ink_rect: Option<pango::Rectangle>,
|
|
||||||
font: pango::Font,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Item {
|
|
||||||
pub fn new(item: sys_pango::Item) -> Self {
|
|
||||||
Item {
|
|
||||||
font: item.analysis().font(),
|
|
||||||
item,
|
|
||||||
glyphs: None,
|
|
||||||
ink_rect: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update(&mut self, item: sys_pango::Item) {
|
|
||||||
self.font = item.analysis().font();
|
|
||||||
self.item = item;
|
|
||||||
self.glyphs = None;
|
|
||||||
self.ink_rect = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_glyphs(&mut self, glyphs: pango::GlyphString) {
|
|
||||||
let mut glyphs = glyphs;
|
|
||||||
let (ink_rect, _) = glyphs.extents(&self.font);
|
|
||||||
self.ink_rect = Some(ink_rect);
|
|
||||||
self.glyphs = Some(glyphs);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn font(&self) -> &pango::Font {
|
|
||||||
&self.font
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn analysis(&self) -> sys_pango::Analysis {
|
|
||||||
self.item.analysis()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Line {
|
pub struct Line {
|
||||||
pub line: Box<[Cell]>,
|
pub line: Box<[Cell]>,
|
||||||
|
|
||||||
@ -53,7 +13,7 @@ pub struct Line {
|
|||||||
// [Item1, Item2, None, None, Item3]
|
// [Item1, Item2, None, None, Item3]
|
||||||
// Item2 take 3 cells and renders as one
|
// Item2 take 3 cells and renders as one
|
||||||
pub item_line: Box<[Option<Item>]>,
|
pub item_line: Box<[Option<Item>]>,
|
||||||
pub cell_to_item: Box<[i32]>,
|
cell_to_item: Box<[i32]>,
|
||||||
|
|
||||||
pub dirty_line: bool,
|
pub dirty_line: bool,
|
||||||
}
|
}
|
||||||
@ -216,18 +176,19 @@ impl Line {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cell_to_item(&self, cell_idx: usize) -> i32 {
|
#[inline]
|
||||||
|
pub fn cell_to_item(&self, cell_idx: usize) -> i32 {
|
||||||
self.cell_to_item[cell_idx]
|
self.cell_to_item[cell_idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn item_len(&self, mut item_idx: usize) -> usize {
|
pub fn item_len_from_idx(&self, mut start_idx: usize) -> usize {
|
||||||
let mut len = 1;
|
let mut len = 1;
|
||||||
item_idx += 1;
|
start_idx += 1;
|
||||||
|
|
||||||
while item_idx < self.item_line.len() && self.is_binded_to_item(item_idx) &&
|
while start_idx < self.item_line.len() && self.is_binded_to_item(start_idx) &&
|
||||||
self.item_line[item_idx].is_none()
|
self.item_line[start_idx].is_none()
|
||||||
{
|
{
|
||||||
item_idx += 1;
|
start_idx += 1;
|
||||||
len += 1;
|
len += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
mod cell;
|
mod cell;
|
||||||
mod line;
|
mod line;
|
||||||
|
mod item;
|
||||||
|
mod model_rect;
|
||||||
|
|
||||||
pub use self::cell::{Cell, Attrs};
|
pub use self::cell::{Cell, Attrs};
|
||||||
pub use self::line::{Item, StyledLine};
|
pub use self::line::StyledLine;
|
||||||
|
pub use self::item::Item;
|
||||||
|
pub use self::model_rect::{ModelRect, ModelRectVec, ClipRowIterator};
|
||||||
use self::line::Line;
|
use self::line::Line;
|
||||||
|
|
||||||
use std::slice::Iter;
|
|
||||||
|
|
||||||
pub struct UiModel {
|
pub struct UiModel {
|
||||||
pub columns: usize,
|
pub columns: usize,
|
||||||
@ -190,242 +193,6 @@ impl UiModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
|
||||||
pub struct ModelRectVec {
|
|
||||||
pub list: Vec<ModelRect>,
|
|
||||||
}
|
|
||||||
|
|
||||||
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() {
|
|
||||||
if (neighbor.top > 0 && rect.top == neighbor.top - 1 ||
|
|
||||||
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) {
|
|
||||||
return Some(i);
|
|
||||||
} else if rect.in_horizontal(neighbor) && rect.in_vertical(neighbor) {
|
|
||||||
return Some(i);
|
|
||||||
} else if rect.contains(neighbor) {
|
|
||||||
return Some(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn join(&mut self, other: &ModelRect) {
|
|
||||||
match self.find_neighbor(other) {
|
|
||||||
Some(i) => self.list[i].join(other),
|
|
||||||
None => self.list.push(other.clone()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
pub struct ModelRect {
|
|
||||||
pub top: usize,
|
|
||||||
pub bot: usize,
|
|
||||||
pub left: usize,
|
|
||||||
pub right: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModelRect {
|
|
||||||
pub fn new(top: usize, bot: usize, left: usize, right: usize) -> ModelRect {
|
|
||||||
debug_assert!(top <= bot);
|
|
||||||
debug_assert!(left <= right);
|
|
||||||
|
|
||||||
ModelRect {
|
|
||||||
top: top,
|
|
||||||
bot: bot,
|
|
||||||
left: left,
|
|
||||||
right: right,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn point(x: usize, y: usize) -> ModelRect {
|
|
||||||
ModelRect {
|
|
||||||
top: y,
|
|
||||||
bot: y,
|
|
||||||
left: x,
|
|
||||||
right: x,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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
|
|
||||||
}
|
|
||||||
|
|
||||||
fn contains(&self, other: &ModelRect) -> bool {
|
|
||||||
self.top <= other.top && self.bot >= other.bot && self.left <= other.left &&
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
};
|
|
||||||
|
|
||||||
debug_assert!(self.top <= self.bot);
|
|
||||||
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 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;
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<ModelRect> for ModelRect {
|
|
||||||
fn as_ref(&self) -> &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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
262
src/ui_model/model_rect.rs
Normal file
262
src/ui_model/model_rect.rs
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
use std::slice::Iter;
|
||||||
|
|
||||||
|
use super::{Line, UiModel, Cell};
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ModelRectVec {
|
||||||
|
pub list: Vec<ModelRect>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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() {
|
||||||
|
if (neighbor.top > 0 && rect.top == neighbor.top - 1 ||
|
||||||
|
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) {
|
||||||
|
return Some(i);
|
||||||
|
} else if rect.in_horizontal(neighbor) && rect.in_vertical(neighbor) {
|
||||||
|
return Some(i);
|
||||||
|
} else if rect.contains(neighbor) {
|
||||||
|
return Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join(&mut self, other: &ModelRect) {
|
||||||
|
match self.find_neighbor(other) {
|
||||||
|
Some(i) => self.list[i].join(other),
|
||||||
|
None => self.list.push(other.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct ModelRect {
|
||||||
|
pub top: usize,
|
||||||
|
pub bot: usize,
|
||||||
|
pub left: usize,
|
||||||
|
pub right: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ModelRect {
|
||||||
|
pub fn new(top: usize, bot: usize, left: usize, right: usize) -> ModelRect {
|
||||||
|
debug_assert!(top <= bot);
|
||||||
|
debug_assert!(left <= right);
|
||||||
|
|
||||||
|
ModelRect {
|
||||||
|
top: top,
|
||||||
|
bot: bot,
|
||||||
|
left: left,
|
||||||
|
right: right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn point(x: usize, y: usize) -> ModelRect {
|
||||||
|
ModelRect {
|
||||||
|
top: y,
|
||||||
|
bot: y,
|
||||||
|
left: x,
|
||||||
|
right: x,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contains(&self, other: &ModelRect) -> bool {
|
||||||
|
self.top <= other.top && self.bot >= other.bot && self.left <= other.left &&
|
||||||
|
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
|
||||||
|
pub fn extend_by_items(&mut self, model: &UiModel) {
|
||||||
|
let mut left = self.left;
|
||||||
|
let mut right = self.right;
|
||||||
|
|
||||||
|
for i in self.top..self.bot + 1 {
|
||||||
|
let line = &model.model[i];
|
||||||
|
let item_idx = line.cell_to_item(self.left);
|
||||||
|
if item_idx >= 0 {
|
||||||
|
let item_idx = item_idx as usize;
|
||||||
|
if item_idx < left {
|
||||||
|
left = item_idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let len_since_right = line.item_len_from_idx(self.right) - 1;
|
||||||
|
if right < self.right + len_since_right {
|
||||||
|
right = self.right + len_since_right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
||||||
|
|
||||||
|
debug_assert!(self.top <= self.bot);
|
||||||
|
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 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;
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<ModelRect> for ModelRect {
|
||||||
|
fn as_ref(&self) -> &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