Add double click to select word support for Input. (#38)

Continue #27
This commit is contained in:
Jason Lee 2024-07-17 11:41:04 +08:00 committed by GitHub
parent 36411750ee
commit 3467522714
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 48 additions and 11 deletions

View file

@ -11,11 +11,11 @@ A UI components for building desktop application by using [GPUI](https://gpui.rs
- [ ] TextField
- [x] Ctrl+a, e to move cursor to start/end
- [x] Copy, Cut, Paste by keyboard
- [ ] ContextMenu to let user copy, cut, paste
- [x] Selection by mouse, drag to select text
- [x] Cursor blinking
- [ ] Textarea
- [x] Input icon
- [ ] Textarea
- [ ] ContextMenu to let user copy, cut, paste
- [ ] InputOTP
- [x] Button
- [x] Button with Icon
@ -66,13 +66,7 @@ A UI components for building desktop application by using [GPUI](https://gpui.rs
## Showcase
<https://github.com/huacnlee/gpui-app/assets/5518/ad103f02-697a-40ed-a876-8b13e4242a72>
<https://github.com/huacnlee/gpui-app/assets/5518/5316f9f0-58c8-4b99-bd79-eafffb38c3fc>
<https://github.com/huacnlee/gpui-app/assets/5518/0273e031-4426-4ab5-a41c-f7cbbb0e55bc>
<https://github.com/huacnlee/gpui-component/assets/5518/51622a5e-f51d-4ede-8cae-04cae703f8aa>
<https://github.com/user-attachments/assets/23766bb2-ffc3-4878-b5ad-7a08a0657f26>
## Demo

View file

@ -297,11 +297,18 @@ impl TextInput {
fn on_mouse_down(&mut self, event: &MouseDownEvent, cx: &mut ViewContext<Self>) {
self.is_selecting = true;
let offset = self.index_for_mouse_position(event.position);
// Double click to select word
if event.button == MouseButton::Left && event.click_count == 2 {
self.select_word(offset, cx);
return;
}
if event.modifiers.shift {
self.select_to(self.index_for_mouse_position(event.position), cx);
self.select_to(offset, cx);
} else {
self.move_to(self.index_for_mouse_position(event.position), cx)
self.move_to(offset, cx)
}
}
@ -391,6 +398,42 @@ impl TextInput {
cx.notify()
}
/// Select the word at the given offset.
fn select_word(&mut self, offset: usize, cx: &mut ViewContext<Self>) {
fn is_word(c: char) -> bool {
c.is_alphanumeric() || matches!(c, '_')
}
let mut start = self.offset_to_utf16(offset);
let mut end = start;
let prev_text = self.text_for_range(0..start, cx).unwrap_or_default();
let next_text = self
.text_for_range(end..self.text.len(), cx)
.unwrap_or_default();
let prev_chars = prev_text.chars().rev().peekable();
let next_chars = next_text.chars().peekable();
for (_, c) in prev_chars.enumerate() {
if !is_word(c) {
break;
}
start -= c.len_utf16();
}
for (_, c) in next_chars.enumerate() {
if !is_word(c) {
break;
}
end += c.len_utf16();
}
self.selected_range = self.range_from_utf16(&(start..end));
cx.notify()
}
fn unselect(&mut self, cx: &mut ViewContext<Self>) {
self.selected_range = self.cursor_offset()..self.cursor_offset();
cx.notify()