Console drawing is almost back up to snuff.
Just missing drawing the cursors if it's at the end of the text buffer.
This commit is contained in:
parent
c69ebc240f
commit
4caad17e56
|
@ -288,7 +288,7 @@ impl<T: LineFormatter> Buffer<T> {
|
|||
/// If the index is off the end of the text, returns the line and column
|
||||
/// number of the last valid text position.
|
||||
pub fn index_to_line_col(&self, pos: usize) -> (usize, usize) {
|
||||
return self.text.pos_1d_to_closest_2d_recursive(pos);
|
||||
return self.text.index_to_line_col_recursive(pos);
|
||||
}
|
||||
|
||||
|
||||
|
@ -300,7 +300,7 @@ impl<T: LineFormatter> Buffer<T> {
|
|||
/// beyond the end of the buffer, returns the index of the buffer's last
|
||||
/// valid position.
|
||||
pub fn line_col_to_index(&self, pos: (usize, usize)) -> usize {
|
||||
return self.text.pos_2d_to_closest_1d_recursive(pos);
|
||||
return self.text.line_col_to_index_recursive(pos);
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,11 +309,11 @@ impl<T: LineFormatter> Buffer<T> {
|
|||
/// If the index is off the end of the text, returns the visual line and
|
||||
/// column number of the last valid text position.
|
||||
pub fn index_to_v2d(&self, pos: usize) -> (usize, usize) {
|
||||
// TODO: update this to use the new LineFormatter stuff
|
||||
//let (v, h) = self.text.pos_1d_to_closest_2d_recursive(pos);
|
||||
//let vis_h = self.get_line(v).grapheme_index_to_closest_vis_pos(h, self.tab_width);
|
||||
//return (v, vis_h);
|
||||
return (0, 0);
|
||||
let mut index = pos;
|
||||
if index > self.grapheme_count() {
|
||||
index = self.grapheme_count();
|
||||
}
|
||||
return self.text.index_to_v2d_recursive(&self.formatter, index);
|
||||
}
|
||||
|
||||
|
||||
|
@ -324,16 +324,7 @@ impl<T: LineFormatter> Buffer<T> {
|
|||
/// number given is beyond the end of the buffer, returns the index of
|
||||
/// the buffer's last valid position.
|
||||
pub fn v2d_to_index(&self, pos: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize {
|
||||
// TODO: update this to use the new LineFormatter stuff
|
||||
//if pos.0 >= self.line_count() {
|
||||
// return self.grapheme_count();
|
||||
//}
|
||||
//else {
|
||||
// let gs = self.line_col_to_index((pos.0, 0));
|
||||
// let h = self.get_line(pos.0).vis_pos_to_closest_grapheme_index(pos.1, self.tab_width);
|
||||
// return gs + h;
|
||||
//}
|
||||
return 0;
|
||||
return self.text.v2d_to_index_recursive(&self.formatter, pos, rounding);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::mem;
|
||||
use std::cmp::{min, max};
|
||||
|
||||
use line_formatter::LineFormatter;
|
||||
use line_formatter::{LineFormatter, RoundingBehavior};
|
||||
use string_utils::is_line_ending;
|
||||
use super::line::{Line, LineEnding, LineGraphemeIter, str_to_line_ending};
|
||||
|
||||
|
@ -234,7 +234,26 @@ impl BufferNode {
|
|||
}
|
||||
|
||||
|
||||
pub fn pos_2d_to_closest_1d_recursive(&self, pos: (usize, usize)) -> usize {
|
||||
pub fn index_to_line_col_recursive(&self, index: usize) -> (usize, usize) {
|
||||
match self.data {
|
||||
BufferNodeData::Leaf(_) => {
|
||||
return (0, min(index, self.grapheme_count));
|
||||
},
|
||||
|
||||
BufferNodeData::Branch(ref left, ref right) => {
|
||||
if index < left.grapheme_count {
|
||||
return left.index_to_line_col_recursive(index);
|
||||
}
|
||||
else {
|
||||
let (v, h) = right.index_to_line_col_recursive((index - left.grapheme_count));
|
||||
return (v + left.line_count, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn line_col_to_index_recursive(&self, pos: (usize, usize)) -> usize {
|
||||
match self.data {
|
||||
BufferNodeData::Leaf(ref line) => {
|
||||
if pos.0 != 0 {
|
||||
|
@ -256,29 +275,60 @@ impl BufferNode {
|
|||
|
||||
BufferNodeData::Branch(ref left, ref right) => {
|
||||
if pos.0 < left.line_count {
|
||||
return left.pos_2d_to_closest_1d_recursive(pos);
|
||||
return left.line_col_to_index_recursive(pos);
|
||||
}
|
||||
else {
|
||||
return left.grapheme_count + right.pos_2d_to_closest_1d_recursive((pos.0 - left.line_count, pos.1));
|
||||
return left.grapheme_count + right.line_col_to_index_recursive((pos.0 - left.line_count, pos.1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn pos_1d_to_closest_2d_recursive(&self, pos: usize) -> (usize, usize) {
|
||||
pub fn index_to_v2d_recursive<T: LineFormatter>(&self, f: &T, index: usize) -> (usize, usize) {
|
||||
match self.data {
|
||||
BufferNodeData::Leaf(_) => {
|
||||
return (0, min(pos, self.grapheme_count));
|
||||
BufferNodeData::Leaf(ref line) => {
|
||||
return f.index_to_v2d(line, index);
|
||||
},
|
||||
|
||||
BufferNodeData::Branch(ref left, ref right) => {
|
||||
if pos < left.grapheme_count {
|
||||
return left.pos_1d_to_closest_2d_recursive(pos);
|
||||
if index < left.grapheme_count {
|
||||
return left.index_to_v2d_recursive(f, index);
|
||||
}
|
||||
else {
|
||||
let (v, h) = right.pos_1d_to_closest_2d_recursive((pos - left.grapheme_count));
|
||||
return (v + left.line_count, h);
|
||||
let (y, x) = right.index_to_v2d_recursive(f, (index - left.grapheme_count));
|
||||
return (y + left.vis_dim.0, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn v2d_to_index_recursive<T: LineFormatter>(&self, f: &T, pos: (usize, usize), rounding: (RoundingBehavior, RoundingBehavior)) -> usize {
|
||||
match self.data {
|
||||
BufferNodeData::Leaf(ref line) => {
|
||||
return f.v2d_to_index(line, pos, rounding);
|
||||
},
|
||||
|
||||
BufferNodeData::Branch(ref left, ref right) => {
|
||||
let lh = f.single_line_height();
|
||||
|
||||
if rounding.0 == RoundingBehavior::Round {
|
||||
// TODO
|
||||
return 0;
|
||||
|
||||
}
|
||||
else if rounding.0 == RoundingBehavior::Floor {
|
||||
if pos.0 < left.vis_dim.0 {
|
||||
return left.v2d_to_index_recursive(f, pos, rounding);
|
||||
}
|
||||
else {
|
||||
return left.grapheme_count + right.v2d_to_index_recursive(f, (pos.0 - left.vis_dim.0, pos.1), rounding);
|
||||
}
|
||||
}
|
||||
else { // RoundingBehavior::Ceiling
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,11 +58,11 @@ impl Editor {
|
|||
};
|
||||
|
||||
// For multiple-cursor testing
|
||||
let mut cur = Cursor::new();
|
||||
cur.range.0 = 30;
|
||||
cur.range.1 = 30;
|
||||
cur.update_vis_start(&(ed.buffer));
|
||||
ed.cursors.add_cursor(cur);
|
||||
//let mut cur = Cursor::new();
|
||||
//cur.range.0 = 30;
|
||||
//cur.range.1 = 30;
|
||||
//cur.update_vis_start(&(ed.buffer));
|
||||
//ed.cursors.add_cursor(cur);
|
||||
|
||||
ed.auto_detect_indentation_style();
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use buffer::line::{Line, LineGraphemeIter};
|
||||
use string_utils::{is_line_ending};
|
||||
|
||||
#[derive(Copy, PartialEq)]
|
||||
pub enum RoundingBehavior {
|
||||
Round,
|
||||
Floor,
|
||||
|
@ -8,6 +9,8 @@ pub enum RoundingBehavior {
|
|||
}
|
||||
|
||||
pub trait LineFormatter {
|
||||
fn single_line_height(&self) -> usize;
|
||||
|
||||
fn dimensions(&self, line: &Line) -> (usize, usize);
|
||||
|
||||
fn index_to_v2d(&self, line: &Line, index: usize) -> (usize, usize);
|
||||
|
@ -36,8 +39,10 @@ impl<'a> Iterator for ConsoleLineFormatterVisIter<'a> {
|
|||
fn next(&mut self) -> Option<(&'a str, usize, usize)> {
|
||||
if let Some(g) = self.grapheme_iter.next() {
|
||||
let pos = self.pos;
|
||||
|
||||
let width = grapheme_vis_width_at_vis_pos(g, self.pos.1, self.f.tab_width as usize);
|
||||
self.pos = (self.pos.0, self.pos.1 + width);
|
||||
|
||||
return Some((g, pos.0, pos.1));
|
||||
}
|
||||
else {
|
||||
|
@ -84,6 +89,10 @@ impl ConsoleLineFormatter {
|
|||
|
||||
|
||||
impl<'a> LineFormatter for ConsoleLineFormatter {
|
||||
fn single_line_height(&self) -> usize {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fn dimensions(&self, line: &Line) -> (usize, usize) {
|
||||
return (1, self.vis_width(line));
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::char;
|
|||
use std::time::duration::Duration;
|
||||
use string_utils::{is_line_ending};
|
||||
use buffer::line::{line_ending_to_str, LineEnding};
|
||||
use line_formatter::LineFormatter;
|
||||
use line_formatter::{LineFormatter, RoundingBehavior};
|
||||
|
||||
// Key codes
|
||||
const K_ENTER: u16 = 13;
|
||||
|
@ -335,31 +335,67 @@ impl TermUI {
|
|||
|
||||
|
||||
fn draw_editor_text(&self, editor: &Editor, c1: (usize, usize), c2: (usize, usize)) {
|
||||
let mut line_iter = editor.buffer.line_iter_at_index(editor.view_pos.0);
|
||||
// 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 grapheme_index;
|
||||
let mut screen_line = c1.0 as isize + vis_starting_line as isize;
|
||||
let screen_col = c1.1 as isize;
|
||||
|
||||
let mut vis_line_num = editor.view_pos.0;
|
||||
let mut vis_col_num = editor.view_pos.1;
|
||||
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);
|
||||
let mut last_y = 0;
|
||||
|
||||
let mut print_line_num = c1.0;
|
||||
let mut print_col_num = c1.1;
|
||||
// Loop through the graphemes of the line and print them to
|
||||
// the screen.
|
||||
for (g, pos_y, pos_x) in g_iter {
|
||||
last_y = pos_y;
|
||||
|
||||
let max_print_line = c2.0;
|
||||
let max_print_col = c2.1;
|
||||
// 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;
|
||||
|
||||
loop {
|
||||
if let Some(line) = line_iter.next() {
|
||||
let mut g_iter = editor.buffer.formatter.vis_grapheme_iter(line);
|
||||
|
||||
for (g, pos_y, pos_x) in g_iter {
|
||||
self.rb.print(pos_x, pos_y, rustbox::RB_NORMAL, Color::White, Color::Black, g);
|
||||
// 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) || g == "\t" {
|
||||
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;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
screen_line += last_y as isize + 1;
|
||||
}
|
||||
|
||||
// TODO: handle printing the cursor when it's at the end of the buffer.
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user