Basic text buffer drawing is working again.
This commit is contained in:
parent
3ae51f7f7e
commit
6f2cbe5b87
|
@ -375,7 +375,7 @@ impl Buffer {
|
|||
}
|
||||
|
||||
|
||||
fn get_line<'a>(&'a self, index: usize) -> &'a Line {
|
||||
pub fn get_line<'a>(&'a self, index: usize) -> &'a Line {
|
||||
if index >= self.line_count() {
|
||||
panic!("get_line(): index out of bounds.");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use buffer::line::{Line, LineGraphemeIter};
|
||||
use std::cmp::min;
|
||||
use std::cmp::{min, max};
|
||||
|
||||
#[derive(Copy, PartialEq)]
|
||||
pub enum RoundingBehavior {
|
||||
|
@ -10,11 +10,67 @@ pub enum RoundingBehavior {
|
|||
|
||||
|
||||
pub trait LineFormatter<'a> {
|
||||
type Iter: Iterator<Item=(&'a str, (usize, usize), (usize, usize))> + 'a;
|
||||
// The iterator yields the grapheme, the 2d position of the grapheme, and the grapheme's width
|
||||
type Iter: Iterator<Item=(&'a str, (usize, usize), usize)> + 'a;
|
||||
|
||||
fn single_line_height(&self) -> usize;
|
||||
|
||||
fn iter(&'a self, line: &'a Line) -> Self::Iter;
|
||||
|
||||
|
||||
/// Returns the 2d visual dimensions of the given line when formatted
|
||||
/// by the formatter.
|
||||
fn dimensions(&'a self, line: &'a Line) -> (usize, usize) {
|
||||
let mut dim: (usize, usize) = (0, 0);
|
||||
|
||||
for (_, pos, width) in self.iter(line) {
|
||||
dim = (max(dim.0, pos.0), max(dim.1, pos.1 + width));
|
||||
}
|
||||
|
||||
dim.0 += self.single_line_height();
|
||||
|
||||
return dim;
|
||||
}
|
||||
|
||||
|
||||
/// Converts a grapheme index within a line into a visual 2d position.
|
||||
fn index_to_v2d(&'a self, line: &'a Line, index: usize) -> (usize, usize) {
|
||||
let mut pos = (0, 0);
|
||||
let mut i = 0;
|
||||
let mut last_width = 0;
|
||||
|
||||
for (_, _pos, width) in self.iter(line) {
|
||||
pos = _pos;
|
||||
last_width = width;
|
||||
i += 1;
|
||||
|
||||
if i > index {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
|
||||
return (pos.0, pos.1 + last_width);
|
||||
}
|
||||
|
||||
|
||||
/// Converts a visual 2d position into a grapheme index within a line.
|
||||
fn v2d_to_index(&'a self, line: &'a Line, v2d: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize {
|
||||
// TODO: handle rounding modes
|
||||
let mut i = 0;
|
||||
|
||||
for (_, pos, _) in self.iter(line) {
|
||||
if pos.0 > v2d.0 {
|
||||
break;
|
||||
}
|
||||
else if pos.0 == v2d.0 && pos.1 >= v2d.1 {
|
||||
break;
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -31,13 +87,13 @@ pub struct TestLineFormatIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for TestLineFormatIter<'a> {
|
||||
type Item = (&'a str, (usize, usize), (usize, usize));
|
||||
type Item = (&'a str, (usize, usize), usize);
|
||||
|
||||
fn next(&mut self) -> Option<(&'a str, (usize, usize), (usize, usize))> {
|
||||
fn next(&mut self) -> Option<(&'a str, (usize, usize), usize)> {
|
||||
if let Some(g) = self.grapheme_iter.next() {
|
||||
let pos = self.pos;
|
||||
self.pos = (pos.0, pos.1 + 1);
|
||||
return Some((g, pos, (1, self.f.tab_width as usize)));
|
||||
return Some((g, pos, 1));
|
||||
}
|
||||
else {
|
||||
return None;
|
||||
|
|
|
@ -54,21 +54,21 @@ pub struct ConsoleLineFormatterVisIter<'a> {
|
|||
|
||||
|
||||
impl<'a> Iterator for ConsoleLineFormatterVisIter<'a> {
|
||||
type Item = (&'a str, (usize, usize), (usize, usize));
|
||||
type Item = (&'a str, (usize, usize), usize);
|
||||
|
||||
fn next(&mut self) -> Option<(&'a str, (usize, usize), (usize, usize))> {
|
||||
fn next(&mut self) -> Option<(&'a str, (usize, usize), usize)> {
|
||||
if let Some(g) = self.grapheme_iter.next() {
|
||||
let width = grapheme_vis_width_at_vis_pos(g, self.pos.1, self.f.tab_width as usize);
|
||||
|
||||
if (self.pos.1 + width) > self.f.wrap_width {
|
||||
let pos = (self.pos.0 + self.f.single_line_height(), 0);
|
||||
self.pos = (self.pos.0 + self.f.single_line_height(), width);
|
||||
return Some((g, pos, (1, width)));
|
||||
return Some((g, pos, width));
|
||||
}
|
||||
else {
|
||||
let pos = self.pos;
|
||||
self.pos = (self.pos.0, self.pos.1 + width);
|
||||
return Some((g, pos, (1, width)));
|
||||
return Some((g, pos, width));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -354,79 +354,76 @@ impl<'a> TermUI<'a> {
|
|||
fn draw_editor_text(&self, editor: &Editor<ConsoleLineFormatter>, c1: (usize, usize), c2: (usize, usize)) {
|
||||
// TODO: update to new formatting code
|
||||
|
||||
//// Calculate all the starting info
|
||||
//let editor_corner_index = editor.buffer.v2d_to_index(editor.view_pos, (RoundingBehavior::Floor, RoundingBehavior::Floor));
|
||||
//let (starting_line, _) = editor.buffer.index_to_line_col(editor_corner_index);
|
||||
//let mut grapheme_index = editor.buffer.line_col_to_index((starting_line, 0));
|
||||
//let (vis_starting_line, _) = editor.buffer.index_to_v2d(grapheme_index);
|
||||
//
|
||||
//let mut screen_line = c1.0 as isize + vis_starting_line as isize;
|
||||
//let screen_col = c1.1 as isize;
|
||||
//
|
||||
//let mut line_iter = editor.buffer.line_iter_at_index(starting_line);
|
||||
//
|
||||
//for line in line_iter {
|
||||
// let mut g_iter = editor.buffer.formatter.vis_grapheme_iter(line);
|
||||
//
|
||||
// // Loop through the graphemes of the line and print them to
|
||||
// // the screen.
|
||||
// for (g, (pos_y, pos_x), width) in g_iter {
|
||||
// // Calculate the cell coordinates at which to draw the grapheme
|
||||
// let px = pos_x as isize + screen_col - editor.view_pos.1 as isize;
|
||||
// let py = pos_y as isize + screen_line - editor.view_pos.0 as isize;
|
||||
//
|
||||
// // If we're off the bottom, we're done
|
||||
// if py > c2.0 as isize {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // Draw the grapheme to the screen if it's in bounds
|
||||
// if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize) {
|
||||
// // Check if the character is within a cursor
|
||||
// let mut at_cursor = false;
|
||||
// for c in editor.cursors.iter() {
|
||||
// if grapheme_index >= c.range.0 && grapheme_index <= c.range.1 {
|
||||
// at_cursor = true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Actually print the character
|
||||
// if is_line_ending(g) {
|
||||
// if at_cursor {
|
||||
// self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::Black, Color::White, " ");
|
||||
// }
|
||||
// }
|
||||
// else if g == "\t" {
|
||||
// for i in 0..width {
|
||||
// let tpx = px as usize + i;
|
||||
// if tpx <= c2.1 {
|
||||
// self.rb.print(tpx as usize, py as usize, rustbox::RB_NORMAL, Color::White, Color::Black, " ");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if at_cursor {
|
||||
// self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::Black, Color::White, " ");
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if at_cursor {
|
||||
// self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::Black, Color::White, g);
|
||||
// }
|
||||
// else {
|
||||
// self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::White, Color::Black, g);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// grapheme_index += 1;
|
||||
// }
|
||||
//
|
||||
// let (dim_y, _) = editor.buffer.formatter.dimensions(line);
|
||||
// screen_line += dim_y as isize;
|
||||
//}
|
||||
//
|
||||
//
|
||||
//
|
||||
// Calculate all the starting info
|
||||
let (starting_line, _) = editor.buffer.index_to_line_col(editor.view_pos.0);
|
||||
let mut grapheme_index = editor.buffer.line_col_to_index((starting_line, 0));
|
||||
let (vis_line_offset, _) = editor.formatter.index_to_v2d(editor.buffer.get_line(starting_line), editor.view_pos.0 - grapheme_index);
|
||||
|
||||
let mut screen_line = c1.0 as isize - vis_line_offset as isize;
|
||||
let screen_col = c1.1 as isize;
|
||||
|
||||
let mut line_iter = editor.buffer.line_iter_at_index(starting_line);
|
||||
for line in line_iter {
|
||||
let mut g_iter = editor.formatter.iter(line);
|
||||
|
||||
// Loop through the graphemes of the line and print them to
|
||||
// the screen.
|
||||
for (g, (pos_y, pos_x), width) in g_iter {
|
||||
// Calculate the cell coordinates at which to draw the grapheme
|
||||
let px = pos_x as isize + screen_col - editor.view_pos.1 as isize;
|
||||
let py = pos_y as isize + screen_line;
|
||||
|
||||
// If we're off the bottom, we're done
|
||||
if py > c2.0 as isize {
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw the grapheme to the screen if it's in bounds
|
||||
if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize) {
|
||||
// Check if the character is within a cursor
|
||||
let mut at_cursor = false;
|
||||
for c in editor.cursors.iter() {
|
||||
if grapheme_index >= c.range.0 && grapheme_index <= c.range.1 {
|
||||
at_cursor = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Actually print the character
|
||||
if is_line_ending(g) {
|
||||
if at_cursor {
|
||||
self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::Black, Color::White, " ");
|
||||
}
|
||||
}
|
||||
else if g == "\t" {
|
||||
for i in 0..width {
|
||||
let tpx = px as usize + i;
|
||||
if tpx <= c2.1 {
|
||||
self.rb.print(tpx as usize, py as usize, rustbox::RB_NORMAL, Color::White, Color::Black, " ");
|
||||
}
|
||||
}
|
||||
|
||||
if at_cursor {
|
||||
self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::Black, Color::White, " ");
|
||||
}
|
||||
}
|
||||
else {
|
||||
if at_cursor {
|
||||
self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::Black, Color::White, g);
|
||||
}
|
||||
else {
|
||||
self.rb.print(px as usize, py as usize, rustbox::RB_NORMAL, Color::White, Color::Black, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
grapheme_index += 1;
|
||||
}
|
||||
|
||||
let (dim_y, _) = editor.formatter.dimensions(line);
|
||||
screen_line += dim_y as isize;
|
||||
}
|
||||
|
||||
|
||||
//// If we get here, it means we reached the end of the text buffer
|
||||
//// without going off the bottom of the screen. So draw the cursor
|
||||
//// at the end if needed.
|
||||
|
|
Loading…
Reference in New Issue
Block a user