diff options
-rw-r--r-- | native/src/renderer/null.rs | 10 | ||||
-rw-r--r-- | native/src/widget/text_input.rs | 55 | ||||
-rw-r--r-- | wgpu/src/renderer/widget/text_input.rs | 57 |
3 files changed, 95 insertions, 27 deletions
diff --git a/native/src/renderer/null.rs b/native/src/renderer/null.rs index 02f033a5..43076d61 100644 --- a/native/src/renderer/null.rs +++ b/native/src/renderer/null.rs @@ -93,6 +93,16 @@ impl text_input::Renderer for Null { 0.0 } + fn offset( + &self, + _text_bounds: Rectangle, + _size: u16, + _value: &text_input::Value, + _state: &text_input::State, + ) -> 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 71e3d75a..fe002965 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -179,35 +179,40 @@ where button: mouse::Button::Left, state: ButtonState::Pressed, }) => { - self.state.is_focused = - layout.bounds().contains(cursor_position); + let is_clicked = layout.bounds().contains(cursor_position); - if self.state.is_focused { + if is_clicked { 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 if self.is_secure { - self.state.cursor_position = find_cursor_position( - renderer, - target, - &self.value.secure(), - self.size.unwrap_or(renderer.default_size()), - 0, - self.value.len(), + if target > 0.0 { + let value = if self.is_secure { + self.value.secure() + } else { + self.value.clone() + }; + + let size = self.size.unwrap_or(renderer.default_size()); + + let offset = renderer.offset( + text_layout.bounds(), + size, + &value, + &self.state, ); - } else { + self.state.cursor_position = find_cursor_position( renderer, - target, - &self.value, - self.size.unwrap_or(renderer.default_size()), + target + offset, + &value, + size, 0, self.value.len(), ); } } + + self.state.is_focused = is_clicked; } Event::Keyboard(keyboard::Event::CharacterReceived(c)) if self.state.is_focused @@ -392,6 +397,22 @@ pub trait Renderer: crate::Renderer + Sized { /// [`TextInput`]: struct.TextInput.html fn measure_value(&self, value: &str, size: u16) -> f32; + /// Returns the current horizontal offset of the value of the + /// [`TextInput`]. + /// + /// This is the amount of horizontal scrolling applied when the [`Value`] + /// does not fit the [`TextInput`]. + /// + /// [`TextInput`]: struct.TextInput.html + /// [`Value`]: struct.Value.html + fn offset( + &self, + text_bounds: Rectangle, + size: u16, + value: &Value, + state: &State, + ) -> f32; + /// Draws a [`TextInput`]. /// /// It receives: diff --git a/wgpu/src/renderer/widget/text_input.rs b/wgpu/src/renderer/widget/text_input.rs index c6c64b88..929f94db 100644 --- a/wgpu/src/renderer/widget/text_input.rs +++ b/wgpu/src/renderer/widget/text_input.rs @@ -30,6 +30,28 @@ impl text_input::Renderer for Renderer { width } + fn offset( + &self, + text_bounds: Rectangle, + size: u16, + value: &text_input::Value, + state: &text_input::State, + ) -> f32 { + if state.is_focused() { + let (_, offset) = measure_cursor_and_scroll_offset( + self, + text_bounds, + value, + size, + state.cursor_position(value), + ); + + offset + } else { + 0.0 + } + } + fn draw( &mut self, bounds: Rectangle, @@ -91,11 +113,13 @@ impl text_input::Renderer for Renderer { }; let (contents_primitive, offset) = if state.is_focused() { - let text_before_cursor = - value.until(state.cursor_position(value)).to_string(); - - let text_value_width = - self.measure_value(&text_before_cursor, size); + let (text_value_width, offset) = measure_cursor_and_scroll_offset( + self, + text_bounds, + value, + size, + state.cursor_position(value), + ); let cursor = Primitive::Quad { bounds: Rectangle { @@ -112,11 +136,7 @@ impl text_input::Renderer for Renderer { Primitive::Group { primitives: vec![text_value, cursor], }, - Vector::new( - ((text_value_width + 5.0) - text_bounds.width).max(0.0) - as u32, - 0, - ), + Vector::new(offset as u32, 0), ) } else { (text_value, Vector::new(0, 0)) @@ -140,3 +160,20 @@ impl text_input::Renderer for Renderer { ) } } + +fn measure_cursor_and_scroll_offset( + renderer: &Renderer, + text_bounds: Rectangle, + value: &text_input::Value, + size: u16, + cursor_index: usize, +) -> (f32, f32) { + use iced_native::text_input::Renderer; + + let text_before_cursor = value.until(cursor_index).to_string(); + + let text_value_width = renderer.measure_value(&text_before_cursor, size); + let offset = ((text_value_width + 5.0) - text_bounds.width).max(0.0); + + (text_value_width, offset) +} |