Add support for rendering cursors as a block and underscore

This commit is contained in:
Keith Simmons 2022-03-10 01:09:02 -08:00
parent 90c2de7342
commit 178442a4a8
2 changed files with 51 additions and 6 deletions

View file

@ -450,6 +450,7 @@ pub struct Editor {
document_highlights_task: Option<Task<()>>, document_highlights_task: Option<Task<()>>,
pending_rename: Option<RenameState>, pending_rename: Option<RenameState>,
searchable: bool, searchable: bool,
cursor_shape: CursorShape,
} }
pub struct EditorSnapshot { pub struct EditorSnapshot {
@ -930,6 +931,7 @@ impl Editor {
document_highlights_task: Default::default(), document_highlights_task: Default::default(),
pending_rename: Default::default(), pending_rename: Default::default(),
searchable: true, searchable: true,
cursor_shape: Default::default(),
}; };
this.end_selection(cx); this.end_selection(cx);
this this
@ -1021,6 +1023,14 @@ impl Editor {
cx.notify(); cx.notify();
} }
pub fn set_cursor_shape(
&mut self,
cursor_shape: CursorShape
) {
self.cursor_shape = cursor_shape;
// TODO: Do we need to notify?
}
pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F { pub fn scroll_position(&self, cx: &mut ViewContext<Self>) -> Vector2F {
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor) compute_scroll_position(&display_map, self.scroll_position, &self.scroll_top_anchor)
@ -5569,7 +5579,7 @@ impl View for Editor {
self.display_map.update(cx, |map, cx| { self.display_map.update(cx, |map, cx| {
map.set_font(style.text.font_id, style.text.font_size, cx) map.set_font(style.text.font_id, style.text.font_size, cx)
}); });
EditorElement::new(self.handle.clone(), style.clone()).boxed() EditorElement::new(self.handle.clone(), style.clone(), self.cursor_shape).boxed()
} }
fn ui_name() -> &'static str { fn ui_name() -> &'static str {

View file

@ -32,11 +32,12 @@ use std::{
pub struct EditorElement { pub struct EditorElement {
view: WeakViewHandle<Editor>, view: WeakViewHandle<Editor>,
style: EditorStyle, style: EditorStyle,
cursor_shape: CursorShape,
} }
impl EditorElement { impl EditorElement {
pub fn new(view: WeakViewHandle<Editor>, style: EditorStyle) -> Self { pub fn new(view: WeakViewHandle<Editor>, style: EditorStyle, cursor_shape: CursorShape) -> Self {
Self { view, style } Self { view, style, cursor_shape }
} }
fn view<'a>(&self, cx: &'a AppContext) -> &'a Editor { fn view<'a>(&self, cx: &'a AppContext) -> &'a Editor {
@ -362,13 +363,24 @@ impl EditorElement {
if (start_row..end_row).contains(&cursor_position.row()) { if (start_row..end_row).contains(&cursor_position.row()) {
let cursor_row_layout = let cursor_row_layout =
&layout.line_layouts[(cursor_position.row() - start_row) as usize]; &layout.line_layouts[(cursor_position.row() - start_row) as usize];
let x = cursor_row_layout.x_for_index(cursor_position.column() as usize) let cursor_column = cursor_position.column() as usize;
- scroll_left; let cursor_character_x = cursor_row_layout.x_for_index(cursor_column);
let mut character_width = cursor_row_layout.x_for_index(cursor_column + 1) - cursor_character_x;
// TODO: Is there a better option here for the character size
// at the end of the line?
// Default to 1/3 the line height
if character_width == 0.0 {
character_width = layout.line_height / 3.0;
}
let x = cursor_character_x - scroll_left;
let y = cursor_position.row() as f32 * layout.line_height - scroll_top; let y = cursor_position.row() as f32 * layout.line_height - scroll_top;
cursors.push(Cursor { cursors.push(Cursor {
color: style.cursor, color: style.cursor,
character_width,
origin: content_origin + vec2f(x, y), origin: content_origin + vec2f(x, y),
line_height: layout.line_height, line_height: layout.line_height,
shape: self.cursor_shape,
}); });
} }
} }
@ -1212,16 +1224,39 @@ impl PaintState {
} }
} }
#[derive(Copy, Clone)]
pub enum CursorShape {
Bar,
Block,
Underscore
}
impl Default for CursorShape {
fn default() -> Self {
CursorShape::Bar
}
}
struct Cursor { struct Cursor {
origin: Vector2F, origin: Vector2F,
character_width: f32,
line_height: f32, line_height: f32,
color: Color, color: Color,
shape: CursorShape
} }
impl Cursor { impl Cursor {
fn paint(&self, cx: &mut PaintContext) { fn paint(&self, cx: &mut PaintContext) {
let bounds = match self.shape {
CursorShape::Bar => RectF::new(self.origin, vec2f(2.0, self.line_height)),
CursorShape::Block => RectF::new(self.origin, vec2f(self.character_width, self.line_height)),
CursorShape::Underscore => RectF::new(
self.origin + Vector2F::new(0.0, self.line_height - 2.0),
vec2f(self.character_width, 2.0)),
};
cx.scene.push_quad(Quad { cx.scene.push_quad(Quad {
bounds: RectF::new(self.origin, vec2f(2.0, self.line_height)), bounds,
background: Some(self.color), background: Some(self.color),
border: Border::new(0., Color::black()), border: Border::new(0., Color::black()),
corner_radius: 0., corner_radius: 0.,