diff --git a/src/widget/text/edit.rs b/src/widget/text/edit.rs index faec85d..608ad00 100644 --- a/src/widget/text/edit.rs +++ b/src/widget/text/edit.rs @@ -111,7 +111,7 @@ impl<'a> TextEditCtx<'a> { self.text.view.buf.layout() } - fn refresh(&mut self) { + fn clamp_selection_to_layout(&mut self) { if let Some(sel) = self.text.selection { let layout = self.layout(); self.text.selection = Some(sel.refresh(layout)); @@ -119,8 +119,8 @@ impl<'a> TextEditCtx<'a> { } pub fn take(&mut self) -> String { - let text = self.text.view.buf.text().to_string(); - self.set(""); + let text = std::mem::take(self.text.view.buf.edit()); + self.text.selection = None; text } @@ -219,23 +219,21 @@ impl<'a> TextEditCtx<'a> { if end == 0 { return; } - let start = { - let layout = self.layout(); - if word { - sel.focus().previous_logical_word(layout).index() + let layout = self.layout(); + let start = if word { + sel.focus().previous_logical_word(layout).index() + } else { + let Some(cluster) = sel.focus().logical_clusters(layout)[0] else { + return; + }; + let range = cluster.text_range(); + if cluster.is_hard_line_break() || cluster.is_emoji() { + range.start } else { - let Some(cluster) = sel.focus().logical_clusters(layout)[0] else { - return; - }; - let range = cluster.text_range(); - if cluster.is_hard_line_break() || cluster.is_emoji() { - range.start - } else { - self.text.view.buf.text()[..range.end] - .char_indices() - .next_back() - .map_or(range.start, |(start, _)| start) - } + self.text.view.buf.text()[..range.end] + .char_indices() + .next_back() + .map_or(range.start, |(start, _)| start) } }; self.delete_range(start, end); @@ -252,27 +250,20 @@ impl<'a> TextEditCtx<'a> { if start >= self.text.view.buf.text().len() { return; } - let end = { - let layout = self.layout(); - if word { - sel.focus().next_logical_word(layout).index() - } else { - let clusters = sel.focus().logical_clusters(layout); - let Some(cluster) = clusters[1].as_ref() else { - return; - }; - cluster.text_range().end - } + let layout = self.layout(); + let end = if word { + sel.focus().next_logical_word(layout).index() + } else { + let clusters = sel.focus().logical_clusters(layout); + let Some(cluster) = clusters[1].as_ref() else { + return; + }; + cluster.text_range().end }; self.delete_range(start, end); } fn delete_range(&mut self, start: usize, end: usize) { - let len = self.text.view.buf.text().len(); - let (start, end) = (start.min(end).min(len), start.max(end).min(len)); - if start == end { - return; - } self.text.view.buf.edit().replace_range(start..end, ""); self.text.view.buf.changed = true; self.set_caret(start); @@ -294,31 +285,30 @@ impl<'a> TextEditCtx<'a> { let prev_sel = self.text.selection; let prev_hit = self.text.double_hit; - let outcome = { - let layout = self.layout(); - if drag { - prev_sel.map(|sel| (Some(sel.extend_to_point(layout, pos.x, pos.y)), prev_hit)) + let layout = self.layout(); + let (selection, double_hit) = if drag { + let Some(selection) = prev_sel else { + return; + }; + (selection.extend_to_point(layout, pos.x, pos.y), prev_hit) + } else { + let hit = Selection::from_point(layout, pos.x, pos.y); + let index = hit.focus().index(); + // Successive clicks at one index select the word, then the line. + if recent && prev_hit == Some(index) { + (Selection::line_from_point(layout, pos.x, pos.y), None) + } else if recent && prev_sel.map(|s| s.focus().index()) == Some(index) { + ( + Selection::word_from_point(layout, pos.x, pos.y), + Some(index), + ) } else { - let hit = Selection::from_point(layout, pos.x, pos.y); - let index = hit.focus().index(); - // Successive clicks at one index select the word, then the line. - Some(if recent && prev_hit == Some(index) { - (Some(Selection::line_from_point(layout, pos.x, pos.y)), None) - } else if recent && prev_sel.map(|s| s.focus().index()) == Some(index) { - ( - Some(Selection::word_from_point(layout, pos.x, pos.y)), - Some(index), - ) - } else { - (Some(hit), None) - }) + (hit, None) } }; - if let Some((selection, double_hit)) = outcome { - self.text.selection = selection; - self.text.double_hit = double_hit; - } + self.text.selection = Some(selection); + self.text.double_hit = double_hit; } pub fn deselect(&mut self) { @@ -334,7 +324,7 @@ impl<'a> TextEditCtx<'a> { if let Some((old, selection)) = self.text.history.pop() { self.set(&old); self.text.selection = selection; - self.refresh(); + self.clamp_selection_to_layout(); } } else if self.text.view.buf.text() != old.0 { self.text.history.push(old); diff --git a/src/widget/text/mod.rs b/src/widget/text/mod.rs index c72c53e..15bc8ce 100644 --- a/src/widget/text/mod.rs +++ b/src/widget/text/mod.rs @@ -23,7 +23,7 @@ pub struct TextView { } impl TextView { - fn is_blank(&self) -> bool { + fn is_empty(&self) -> bool { self.buf.is_empty() } @@ -76,7 +76,7 @@ impl TextView { self.tex.as_ref() } pub fn desired_width(&mut self, ctx: &mut SizeCtx) -> Len { - if self.is_blank() + if self.is_empty() && let Some(hint) = &self.hint { ctx.width(hint) @@ -85,7 +85,7 @@ impl TextView { } } pub fn desired_height(&mut self, ctx: &mut SizeCtx) -> Len { - if self.is_blank() + if self.is_empty() && let Some(hint) = &self.hint { ctx.height(hint) @@ -96,7 +96,7 @@ impl TextView { pub fn draw(&mut self, painter: &mut Painter) -> UiRegion { let tex = self.render(&mut painter.size_ctx()); let region = tex.size.align(self.align); - if self.is_blank() + if self.is_empty() && let Some(hint) = &self.hint { painter.widget(hint);