Simplify text editing state changes
This commit is contained in:
1 parent
5fe7c3b6df
commit
dc008441e4
2 files changed
+51
-61
No files matched your search
+47
-57
@@ -111,7 +111,7 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
self.text.view.buf.layout()
|
self.text.view.buf.layout()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh(&mut self) {
|
fn clamp_selection_to_layout(&mut self) {
|
||||||
if let Some(sel) = self.text.selection {
|
if let Some(sel) = self.text.selection {
|
||||||
let layout = self.layout();
|
let layout = self.layout();
|
||||||
self.text.selection = Some(sel.refresh(layout));
|
self.text.selection = Some(sel.refresh(layout));
|
||||||
@@ -119,8 +119,8 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn take(&mut self) -> String {
|
pub fn take(&mut self) -> String {
|
||||||
let text = self.text.view.buf.text().to_string();
|
let text = std::mem::take(self.text.view.buf.edit());
|
||||||
self.set("");
|
self.text.selection = None;
|
||||||
text
|
text
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,23 +219,21 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
if end == 0 {
|
if end == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let start = {
|
let layout = self.layout();
|
||||||
let layout = self.layout();
|
let start = if word {
|
||||||
if word {
|
sel.focus().previous_logical_word(layout).index()
|
||||||
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 {
|
} else {
|
||||||
let Some(cluster) = sel.focus().logical_clusters(layout)[0] else {
|
self.text.view.buf.text()[..range.end]
|
||||||
return;
|
.char_indices()
|
||||||
};
|
.next_back()
|
||||||
let range = cluster.text_range();
|
.map_or(range.start, |(start, _)| start)
|
||||||
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.delete_range(start, end);
|
self.delete_range(start, end);
|
||||||
@@ -252,27 +250,20 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
if start >= self.text.view.buf.text().len() {
|
if start >= self.text.view.buf.text().len() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let end = {
|
let layout = self.layout();
|
||||||
let layout = self.layout();
|
let end = if word {
|
||||||
if word {
|
sel.focus().next_logical_word(layout).index()
|
||||||
sel.focus().next_logical_word(layout).index()
|
} else {
|
||||||
} else {
|
let clusters = sel.focus().logical_clusters(layout);
|
||||||
let clusters = sel.focus().logical_clusters(layout);
|
let Some(cluster) = clusters[1].as_ref() else {
|
||||||
let Some(cluster) = clusters[1].as_ref() else {
|
return;
|
||||||
return;
|
};
|
||||||
};
|
cluster.text_range().end
|
||||||
cluster.text_range().end
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
self.delete_range(start, end);
|
self.delete_range(start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_range(&mut self, start: usize, end: usize) {
|
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.edit().replace_range(start..end, "");
|
||||||
self.text.view.buf.changed = true;
|
self.text.view.buf.changed = true;
|
||||||
self.set_caret(start);
|
self.set_caret(start);
|
||||||
@@ -294,31 +285,30 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
let prev_sel = self.text.selection;
|
let prev_sel = self.text.selection;
|
||||||
let prev_hit = self.text.double_hit;
|
let prev_hit = self.text.double_hit;
|
||||||
|
|
||||||
let outcome = {
|
let layout = self.layout();
|
||||||
let layout = self.layout();
|
let (selection, double_hit) = if drag {
|
||||||
if drag {
|
let Some(selection) = prev_sel else {
|
||||||
prev_sel.map(|sel| (Some(sel.extend_to_point(layout, pos.x, pos.y)), prev_hit))
|
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 {
|
} else {
|
||||||
let hit = Selection::from_point(layout, pos.x, pos.y);
|
(hit, None)
|
||||||
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)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some((selection, double_hit)) = outcome {
|
self.text.selection = Some(selection);
|
||||||
self.text.selection = selection;
|
self.text.double_hit = double_hit;
|
||||||
self.text.double_hit = double_hit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deselect(&mut self) {
|
pub fn deselect(&mut self) {
|
||||||
@@ -334,7 +324,7 @@ impl<'a> TextEditCtx<'a> {
|
|||||||
if let Some((old, selection)) = self.text.history.pop() {
|
if let Some((old, selection)) = self.text.history.pop() {
|
||||||
self.set(&old);
|
self.set(&old);
|
||||||
self.text.selection = selection;
|
self.text.selection = selection;
|
||||||
self.refresh();
|
self.clamp_selection_to_layout();
|
||||||
}
|
}
|
||||||
} else if self.text.view.buf.text() != old.0 {
|
} else if self.text.view.buf.text() != old.0 {
|
||||||
self.text.history.push(old);
|
self.text.history.push(old);
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ pub struct TextView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TextView {
|
impl TextView {
|
||||||
fn is_blank(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
self.buf.is_empty()
|
self.buf.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ impl TextView {
|
|||||||
self.tex.as_ref()
|
self.tex.as_ref()
|
||||||
}
|
}
|
||||||
pub fn desired_width(&mut self, ctx: &mut SizeCtx) -> Len {
|
pub fn desired_width(&mut self, ctx: &mut SizeCtx) -> Len {
|
||||||
if self.is_blank()
|
if self.is_empty()
|
||||||
&& let Some(hint) = &self.hint
|
&& let Some(hint) = &self.hint
|
||||||
{
|
{
|
||||||
ctx.width(hint)
|
ctx.width(hint)
|
||||||
@@ -85,7 +85,7 @@ impl TextView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn desired_height(&mut self, ctx: &mut SizeCtx) -> Len {
|
pub fn desired_height(&mut self, ctx: &mut SizeCtx) -> Len {
|
||||||
if self.is_blank()
|
if self.is_empty()
|
||||||
&& let Some(hint) = &self.hint
|
&& let Some(hint) = &self.hint
|
||||||
{
|
{
|
||||||
ctx.height(hint)
|
ctx.height(hint)
|
||||||
@@ -96,7 +96,7 @@ impl TextView {
|
|||||||
pub fn draw(&mut self, painter: &mut Painter) -> UiRegion {
|
pub fn draw(&mut self, painter: &mut Painter) -> UiRegion {
|
||||||
let tex = self.render(&mut painter.size_ctx());
|
let tex = self.render(&mut painter.size_ctx());
|
||||||
let region = tex.size.align(self.align);
|
let region = tex.size.align(self.align);
|
||||||
if self.is_blank()
|
if self.is_empty()
|
||||||
&& let Some(hint) = &self.hint
|
&& let Some(hint) = &self.hint
|
||||||
{
|
{
|
||||||
painter.widget(hint);
|
painter.widget(hint);
|
||||||
|
|||||||
Reference in new issue
Block a user