Refactor of scroll and shaping

- Scroll is identified by line index and layout index, instead of just
  layout index
- Shaping has the option to prune, where caches outside of the scroll
  view are cleared
- Syntax editor no longer requires layout of all lines, only of lines
  inside scroll
- BufferLine has a metadata field that can be used by other abstractions
  to know when text was changed
This commit is contained in:
Jeremy Soller 2023-12-15 13:37:59 -07:00
parent e7261fc06e
commit d0b4b4635e
16 changed files with 213 additions and 159 deletions

View file

@ -94,12 +94,13 @@ impl Edit for Editor {
}
}
fn shape_as_needed(&mut self, font_system: &mut FontSystem) {
fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
if self.cursor_moved {
self.buffer.shape_until_cursor(font_system, self.cursor);
self.buffer
.shape_until_cursor(font_system, self.cursor, prune);
self.cursor_moved = false;
} else {
self.buffer.shape_until_scroll(font_system);
self.buffer.shape_until_scroll(font_system, prune);
}
}
@ -627,7 +628,7 @@ impl Edit for Editor {
}
Action::Scroll { lines } => {
let mut scroll = self.buffer.scroll();
scroll += lines;
scroll.layout += lines;
self.buffer.set_scroll(scroll);
}
}

View file

@ -231,7 +231,7 @@ pub trait Edit {
fn set_tab_width(&mut self, tab_width: u16);
/// Shape lines until scroll, after adjusting scroll if the cursor moved
fn shape_as_needed(&mut self, font_system: &mut FontSystem);
fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool);
/// Delete text starting at start Cursor and ending at end Cursor
fn delete_range(&mut self, start: Cursor, end: Cursor);
@ -288,8 +288,8 @@ impl<'a, T: Edit> BorrowedWithFontSystem<'a, T> {
}
/// Shape lines until scroll, after adjusting scroll if the cursor moved
pub fn shape_as_needed(&mut self) {
self.inner.shape_as_needed(self.font_system);
pub fn shape_as_needed(&mut self, prune: bool) {
self.inner.shape_as_needed(self.font_system, prune);
}
/// Perform an [Action] on the editor

View file

@ -206,14 +206,15 @@ impl<'a> Edit for SyntaxEditor<'a> {
self.editor.set_tab_width(tab_width);
}
fn shape_as_needed(&mut self, font_system: &mut FontSystem) {
fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
#[cfg(feature = "std")]
let now = std::time::Instant::now();
let cursor = self.cursor();
let buffer = self.editor.buffer_mut();
let lines = buffer.visible_lines();
let scroll_end = buffer.scroll() + lines;
let visible_lines = buffer.visible_lines();
let scroll = buffer.scroll();
let scroll_end = scroll.layout + visible_lines;
let mut total_layout = 0;
let mut highlighted = 0;
for line_i in 0..buffer.lines.len() {
@ -223,15 +224,17 @@ impl<'a> Edit for SyntaxEditor<'a> {
}
let line = &mut buffer.lines[line_i];
if !line.is_reset() && line_i < self.syntax_cache.len() {
if line.metadata().is_some() && line_i < self.syntax_cache.len() {
//TODO: duplicated code!
// Perform shaping and layout of this line in order to count if we have reached scroll
match buffer.line_layout(font_system, line_i) {
Some(layout_lines) => {
total_layout += layout_lines.len() as i32;
}
None => {
//TODO: should this be possible?
if line_i >= scroll.line && total_layout < scroll_end {
// Perform shaping and layout of this line in order to count if we have reached scroll
match buffer.line_layout(font_system, line_i) {
Some(layout_lines) => {
total_layout += layout_lines.len() as i32;
}
None => {
//TODO: should this be possible?
}
}
}
continue;
@ -285,12 +288,14 @@ impl<'a> Edit for SyntaxEditor<'a> {
line.set_attrs_list(attrs_list);
// Perform shaping and layout of this line in order to count if we have reached scroll
match buffer.line_layout(font_system, line_i) {
Some(layout_lines) => {
total_layout += layout_lines.len() as i32;
}
None => {
//TODO: should this be possible?
if line_i >= scroll.line && total_layout < scroll_end {
match buffer.line_layout(font_system, line_i) {
Some(layout_lines) => {
total_layout += layout_lines.len() as i32;
}
None => {
//TODO: should this be possible?
}
}
}
@ -303,6 +308,7 @@ impl<'a> Edit for SyntaxEditor<'a> {
}
}
} else {
buffer.lines[line_i].set_metadata(self.syntax_cache.len());
self.syntax_cache.push(cache_item);
}
}
@ -317,7 +323,7 @@ impl<'a> Edit for SyntaxEditor<'a> {
);
}
self.editor.shape_as_needed(font_system);
self.editor.shape_as_needed(font_system, prune);
}
fn delete_range(&mut self, start: Cursor, end: Cursor) {

View file

@ -291,8 +291,8 @@ impl<'a> Edit for ViEditor<'a> {
self.editor.set_tab_width(tab_width);
}
fn shape_as_needed(&mut self, font_system: &mut FontSystem) {
self.editor.shape_as_needed(font_system);
fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
self.editor.shape_as_needed(font_system, prune);
}
fn delete_range(&mut self, start: Cursor, end: Cursor) {
@ -443,8 +443,8 @@ impl<'a> Edit for ViEditor<'a> {
editor.insert_at(cursor, "\n", None);
editor.insert_at(cursor, data, None);
// Hack to allow immediate up/down
editor.shape_as_needed(font_system);
//TODO: Hack to allow immediate up/down
editor.shape_as_needed(font_system, false);
// Move to inserted line, preserving cursor x position
if after {