Simplify editor cursor handling and rendering
This commit is contained in:
parent
542ea7bc66
commit
ea6be7bf32
1 changed files with 28 additions and 49 deletions
|
|
@ -32,10 +32,8 @@ pub struct EditorState {
|
||||||
/// horizontally.
|
/// horizontally.
|
||||||
cursor_col: usize,
|
cursor_col: usize,
|
||||||
|
|
||||||
/// Width of the text when the editor was last rendered.
|
/// Position of the cursor when the editor was last rendered.
|
||||||
///
|
last_cursor_pos: Pos,
|
||||||
/// Does not include additional column for cursor.
|
|
||||||
last_width: u16,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorState {
|
impl EditorState {
|
||||||
|
|
@ -47,7 +45,7 @@ impl EditorState {
|
||||||
Self {
|
Self {
|
||||||
cursor_idx: text.len(),
|
cursor_idx: text.len(),
|
||||||
cursor_col: 0,
|
cursor_col: 0,
|
||||||
last_width: u16::MAX,
|
last_cursor_pos: Pos::ZERO,
|
||||||
text,
|
text,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,6 +315,10 @@ impl EditorState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn last_cursor_pos(&self) -> Pos {
|
||||||
|
self.last_cursor_pos
|
||||||
|
}
|
||||||
|
|
||||||
pub fn widget(&mut self) -> Editor<'_> {
|
pub fn widget(&mut self) -> Editor<'_> {
|
||||||
Editor {
|
Editor {
|
||||||
highlighted: Styled::new_plain(&self.text),
|
highlighted: Styled::new_plain(&self.text),
|
||||||
|
|
@ -404,14 +406,6 @@ impl Editor<'_> {
|
||||||
(row, line_idx)
|
(row, line_idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cursor_row(&self, widthdb: &mut WidthDb) -> usize {
|
|
||||||
let width = self.state.last_width;
|
|
||||||
let text_width = (width - 1) as usize;
|
|
||||||
let indices = wrap(widthdb, &self.state.text, text_width);
|
|
||||||
let (row, _) = Self::wrapped_cursor(self.state.cursor_idx, &indices);
|
|
||||||
row
|
|
||||||
}
|
|
||||||
|
|
||||||
fn indices(&self, widthdb: &mut WidthDb, max_width: Option<u16>) -> Vec<usize> {
|
fn indices(&self, widthdb: &mut WidthDb, max_width: Option<u16>) -> Vec<usize> {
|
||||||
let max_width = max_width
|
let max_width = max_width
|
||||||
// One extra column for cursor
|
// One extra column for cursor
|
||||||
|
|
@ -425,7 +419,10 @@ impl Editor<'_> {
|
||||||
text.clone().split_at_indices(indices)
|
text.clone().split_at_indices(indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(widthdb: &mut WidthDb, rows: &[Styled]) -> Size {
|
fn size_impl(&self, widthdb: &mut WidthDb, max_width: Option<u16>) -> Size {
|
||||||
|
let indices = self.indices(widthdb, max_width);
|
||||||
|
let rows = self.rows(&indices);
|
||||||
|
|
||||||
let width = rows
|
let width = rows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|row| widthdb.width(row.text()))
|
.map(|row| widthdb.width(row.text()))
|
||||||
|
|
@ -440,19 +437,9 @@ impl Editor<'_> {
|
||||||
Size::new(width, height)
|
Size::new(width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cursor(
|
fn cursor(&self, widthdb: &mut WidthDb, width: u16, indices: &[usize], rows: &[Styled]) -> Pos {
|
||||||
&self,
|
|
||||||
widthdb: &mut WidthDb,
|
|
||||||
width: u16,
|
|
||||||
indices: &[usize],
|
|
||||||
rows: &[Styled],
|
|
||||||
) -> Option<Pos> {
|
|
||||||
if !self.focus {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.hidden.is_some() {
|
if self.hidden.is_some() {
|
||||||
return Some(Pos::new(0, 0));
|
return Pos::new(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (cursor_row, cursor_line_idx) = Self::wrapped_cursor(self.state.cursor_idx, indices);
|
let (cursor_row, cursor_line_idx) = Self::wrapped_cursor(self.state.cursor_idx, indices);
|
||||||
|
|
@ -463,17 +450,23 @@ impl Editor<'_> {
|
||||||
|
|
||||||
let cursor_row: i32 = cursor_row.try_into().unwrap_or(i32::MAX);
|
let cursor_row: i32 = cursor_row.try_into().unwrap_or(i32::MAX);
|
||||||
let cursor_col: i32 = cursor_col.try_into().unwrap_or(i32::MAX);
|
let cursor_col: i32 = cursor_col.try_into().unwrap_or(i32::MAX);
|
||||||
Some(Pos::new(cursor_row, cursor_col))
|
Pos::new(cursor_row, cursor_col)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(frame: &mut Frame, rows: Vec<Styled>, cursor: Option<Pos>) {
|
fn draw_impl(&mut self, frame: &mut Frame) {
|
||||||
|
let size = frame.size();
|
||||||
|
let indices = self.indices(frame.widthdb(), Some(size.width));
|
||||||
|
let rows = self.rows(&indices);
|
||||||
|
let cursor = self.cursor(frame.widthdb(), size.width, &indices, &rows);
|
||||||
|
|
||||||
for (i, row) in rows.into_iter().enumerate() {
|
for (i, row) in rows.into_iter().enumerate() {
|
||||||
frame.write(Pos::new(0, i as i32), row);
|
frame.write(Pos::new(0, i as i32), row);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cursor) = cursor {
|
if self.focus {
|
||||||
frame.set_cursor(Some(cursor));
|
frame.set_cursor(Some(cursor));
|
||||||
}
|
}
|
||||||
|
self.state.last_cursor_pos = cursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -484,18 +477,11 @@ impl<E> Widget<E> for Editor<'_> {
|
||||||
max_width: Option<u16>,
|
max_width: Option<u16>,
|
||||||
_max_height: Option<u16>,
|
_max_height: Option<u16>,
|
||||||
) -> Result<Size, E> {
|
) -> Result<Size, E> {
|
||||||
let indices = self.indices(widthdb, max_width);
|
Ok(self.size_impl(widthdb, max_width))
|
||||||
let rows = self.rows(&indices);
|
|
||||||
Ok(Self::size(widthdb, &rows))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
fn draw(mut self, frame: &mut Frame) -> Result<(), E> {
|
||||||
let size = frame.size();
|
self.draw_impl(frame);
|
||||||
let widthdb = frame.widthdb();
|
|
||||||
let indices = self.indices(widthdb, Some(size.width));
|
|
||||||
let rows = self.rows(&indices);
|
|
||||||
let cursor = self.cursor(widthdb, size.width, &indices, &rows);
|
|
||||||
Self::draw(frame, rows, cursor);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -509,18 +495,11 @@ impl<E> AsyncWidget<E> for Editor<'_> {
|
||||||
max_width: Option<u16>,
|
max_width: Option<u16>,
|
||||||
_max_height: Option<u16>,
|
_max_height: Option<u16>,
|
||||||
) -> Result<Size, E> {
|
) -> Result<Size, E> {
|
||||||
let indices = self.indices(widthdb, max_width);
|
Ok(self.size_impl(widthdb, max_width))
|
||||||
let rows = self.rows(&indices);
|
|
||||||
Ok(Self::size(widthdb, &rows))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn draw(self, frame: &mut Frame) -> Result<(), E> {
|
async fn draw(mut self, frame: &mut Frame) -> Result<(), E> {
|
||||||
let size = frame.size();
|
self.draw_impl(frame);
|
||||||
let widthdb = frame.widthdb();
|
|
||||||
let indices = self.indices(widthdb, Some(size.width));
|
|
||||||
let rows = self.rows(&indices);
|
|
||||||
let cursor = self.cursor(widthdb, size.width, &indices, &rows);
|
|
||||||
Self::draw(frame, rows, cursor);
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue