diff --git a/src/core/text/build.rs b/src/core/text/build.rs index f69b389..a0373fc 100644 --- a/src/core/text/build.rs +++ b/src/core/text/build.rs @@ -92,11 +92,7 @@ impl TextBuilderOutput for TextEditOutput { builder.attrs.font_size, builder.attrs.line_height, )); - let mut text = TextEdit { - view: TextView::new(buf, builder.attrs, builder.hint.get(ui)), - selection: Default::default(), - history: Default::default(), - }; + let mut text = TextEdit::new(TextView::new(buf, builder.attrs, builder.hint.get(ui))); let font_system = &mut ui.data.text.font_system; text.buf .set_text(font_system, &builder.content, &Attrs::new(), SHAPING, None); diff --git a/src/core/text/edit.rs b/src/core/text/edit.rs index ade69f2..6db8aaf 100644 --- a/src/core/text/edit.rs +++ b/src/core/text/edit.rs @@ -9,12 +9,21 @@ use winit::{ }; pub struct TextEdit { - pub(super) view: TextView, - pub(super) selection: TextSelection, - pub(super) history: Vec<(String, TextSelection)>, + view: TextView, + selection: TextSelection, + history: Vec<(String, TextSelection)>, + double_hit: Option, } impl TextEdit { + pub fn new(view: TextView) -> Self { + Self { + view, + selection: Default::default(), + history: Default::default(), + double_hit: None, + } + } pub fn select_content(&self, start: Cursor, end: Cursor) -> String { let (start, end) = sort_cursors(start, end); let mut iter = self.buf.lines.iter().skip(start.line); @@ -106,6 +115,9 @@ fn iter_layout_lines( } } for line in iter { + if line.line_i > end.line { + return; + } if line.line_i == end.line && let Some(end_x) = index_x(&line, end.index) { @@ -339,6 +351,14 @@ impl<'a> TextEditCtx<'a> { } } + pub fn select_line_at(&mut self, cursor: Cursor) { + let end = self.text.buf.lines[cursor.line].text().len(); + self.text.selection = TextSelection::Span { + start: Cursor::new(cursor.line, 0), + end: Cursor::new(cursor.line, end), + } + } + pub fn select(&mut self, pos: Vec2, size: Vec2, drag: bool, recent: bool) { let pos = pos - self.text.region().top_left().to_abs(size); let hit = self.text.buf.hit(pos.x, pos.y); @@ -354,6 +374,7 @@ impl<'a> TextEditCtx<'a> { (None, true) => (), (Some(hit), false) => { if recent && hit == *pos { + self.text.double_hit = Some(hit); return self.select_word_at(hit); } else { *pos = hit @@ -364,7 +385,16 @@ impl<'a> TextEditCtx<'a> { TextSelection::Span { start, end } => match (hit, drag) { (None, false) => *sel = TextSelection::None, (None, true) => *sel = TextSelection::Pos(*start), - (Some(hit), false) => *sel = TextSelection::Pos(hit), + (Some(hit), false) => { + if recent + && let Some(double) = self.text.double_hit + && double == hit + { + return self.select_line_at(hit); + } else { + *sel = TextSelection::Pos(hit) + } + } (Some(hit), true) => *end = hit, }, }