diff options
author | 2019-12-05 03:09:39 +0100 | |
---|---|---|
committer | 2019-12-05 03:09:39 +0100 | |
commit | 14fb7e13fb272a43b9924d5d2823b0c105d781b0 (patch) | |
tree | cbc9a7acc00e96179c9dfb99da10db8e72490d10 /native | |
parent | e92ea48e8814b42fc566017db085ca9bdaf3c272 (diff) | |
download | iced-14fb7e13fb272a43b9924d5d2823b0c105d781b0.tar.gz iced-14fb7e13fb272a43b9924d5d2823b0c105d781b0.tar.bz2 iced-14fb7e13fb272a43b9924d5d2823b0c105d781b0.zip |
Place `TextInput` cursor position on click
Diffstat (limited to 'native')
-rw-r--r-- | native/src/renderer/null.rs | 4 | ||||
-rw-r--r-- | native/src/widget/text_input.rs | 78 |
2 files changed, 79 insertions, 3 deletions
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index da0e5159..02f033a5 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -89,6 +89,10 @@ impl text_input::Renderer for Null { 20 } + fn measure_value(&self, _value: &str, _size: u16) -> f32 { + 0.0 + } + fn draw( &mut self, _bounds: Rectangle, diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index f97ed424..764f87cf 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -160,7 +160,7 @@ where layout: Layout<'_>, cursor_position: Point, messages: &mut Vec<Message>, - _renderer: &Renderer, + renderer: &Renderer, ) { match event { Event::Mouse(mouse::Event::Input { @@ -170,8 +170,22 @@ where self.state.is_focused = layout.bounds().contains(cursor_position); - if self.state.cursor_position(&self.value) == 0 { - self.state.move_cursor_to_end(&self.value); + if self.state.is_focused { + let text_layout = layout.children().next().unwrap(); + let target = cursor_position.x - text_layout.bounds().x; + + if target < 0.0 { + self.state.cursor_position = 0; + } else { + self.state.cursor_position = find_cursor_position( + renderer, + target, + &self.value, + self.size.unwrap_or(renderer.default_size()), + 0, + self.value.len(), + ); + } } } Event::Keyboard(keyboard::Event::CharacterReceived(c)) @@ -275,6 +289,11 @@ pub trait Renderer: crate::Renderer + Sized { /// [`TextInput`]: struct.TextInput.html fn default_size(&self) -> u16; + /// Returns the width of the value of the [`TextInput`]. + /// + /// [`TextInput`]: struct.TextInput.html + fn measure_value(&self, value: &str, size: u16) -> f32; + /// Draws a [`TextInput`]. /// /// It receives: @@ -437,3 +456,56 @@ impl Value { let _ = self.0.remove(index); } } + +// TODO: Reduce allocations +fn find_cursor_position<Renderer: self::Renderer>( + renderer: &Renderer, + target: f32, + value: &Value, + size: u16, + start: usize, + end: usize, +) -> usize { + if start >= end { + if start == 0 { + return 0; + } + + let prev = value.until(start - 1); + let next = value.until(start); + + let prev_width = renderer.measure_value(&prev.to_string(), size); + let next_width = renderer.measure_value(&next.to_string(), size); + + if (target - next_width).abs() > (target - prev_width).abs() { + return start - 1; + } else { + return start; + } + } + + let index = (end - start) / 2; + let subvalue = value.until(start + index); + + let width = renderer.measure_value(&subvalue.to_string(), size); + + if width > target { + find_cursor_position( + renderer, + target, + value, + size, + start, + start + index, + ) + } else { + find_cursor_position( + renderer, + target, + value, + size, + start + index + 1, + end, + ) + } +} |