Fix cursor positioning in TextInput
on overflow
This commit is contained in:
parent
453d2d5bb0
commit
36e7ac2048
@ -93,6 +93,16 @@ impl text_input::Renderer for Null {
|
|||||||
0.0
|
0.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn offset(
|
||||||
|
&self,
|
||||||
|
_text_bounds: Rectangle,
|
||||||
|
_size: u16,
|
||||||
|
_value: &text_input::Value,
|
||||||
|
_state: &text_input::State,
|
||||||
|
) -> f32 {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
|
||||||
fn draw(
|
fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
_bounds: Rectangle,
|
_bounds: Rectangle,
|
||||||
|
@ -179,35 +179,40 @@ where
|
|||||||
button: mouse::Button::Left,
|
button: mouse::Button::Left,
|
||||||
state: ButtonState::Pressed,
|
state: ButtonState::Pressed,
|
||||||
}) => {
|
}) => {
|
||||||
self.state.is_focused =
|
let is_clicked = layout.bounds().contains(cursor_position);
|
||||||
layout.bounds().contains(cursor_position);
|
|
||||||
|
|
||||||
if self.state.is_focused {
|
if is_clicked {
|
||||||
let text_layout = layout.children().next().unwrap();
|
let text_layout = layout.children().next().unwrap();
|
||||||
let target = cursor_position.x - text_layout.bounds().x;
|
let target = cursor_position.x - text_layout.bounds().x;
|
||||||
|
|
||||||
if target < 0.0 {
|
if target > 0.0 {
|
||||||
self.state.cursor_position = 0;
|
let value = if self.is_secure {
|
||||||
} else if self.is_secure {
|
self.value.secure()
|
||||||
self.state.cursor_position = find_cursor_position(
|
|
||||||
renderer,
|
|
||||||
target,
|
|
||||||
&self.value.secure(),
|
|
||||||
self.size.unwrap_or(renderer.default_size()),
|
|
||||||
0,
|
|
||||||
self.value.len(),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
|
self.value.clone()
|
||||||
|
};
|
||||||
|
|
||||||
|
let size = self.size.unwrap_or(renderer.default_size());
|
||||||
|
|
||||||
|
let offset = renderer.offset(
|
||||||
|
text_layout.bounds(),
|
||||||
|
size,
|
||||||
|
&value,
|
||||||
|
&self.state,
|
||||||
|
);
|
||||||
|
|
||||||
self.state.cursor_position = find_cursor_position(
|
self.state.cursor_position = find_cursor_position(
|
||||||
renderer,
|
renderer,
|
||||||
target,
|
target + offset,
|
||||||
&self.value,
|
&value,
|
||||||
self.size.unwrap_or(renderer.default_size()),
|
size,
|
||||||
0,
|
0,
|
||||||
self.value.len(),
|
self.value.len(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.state.is_focused = is_clicked;
|
||||||
}
|
}
|
||||||
Event::Keyboard(keyboard::Event::CharacterReceived(c))
|
Event::Keyboard(keyboard::Event::CharacterReceived(c))
|
||||||
if self.state.is_focused
|
if self.state.is_focused
|
||||||
@ -392,6 +397,22 @@ pub trait Renderer: crate::Renderer + Sized {
|
|||||||
/// [`TextInput`]: struct.TextInput.html
|
/// [`TextInput`]: struct.TextInput.html
|
||||||
fn measure_value(&self, value: &str, size: u16) -> f32;
|
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`].
|
/// Draws a [`TextInput`].
|
||||||
///
|
///
|
||||||
/// It receives:
|
/// It receives:
|
||||||
|
@ -30,6 +30,28 @@ impl text_input::Renderer for Renderer {
|
|||||||
width
|
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(
|
fn draw(
|
||||||
&mut self,
|
&mut self,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
@ -91,11 +113,13 @@ impl text_input::Renderer for Renderer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let (contents_primitive, offset) = if state.is_focused() {
|
let (contents_primitive, offset) = if state.is_focused() {
|
||||||
let text_before_cursor =
|
let (text_value_width, offset) = measure_cursor_and_scroll_offset(
|
||||||
value.until(state.cursor_position(value)).to_string();
|
self,
|
||||||
|
text_bounds,
|
||||||
let text_value_width =
|
value,
|
||||||
self.measure_value(&text_before_cursor, size);
|
size,
|
||||||
|
state.cursor_position(value),
|
||||||
|
);
|
||||||
|
|
||||||
let cursor = Primitive::Quad {
|
let cursor = Primitive::Quad {
|
||||||
bounds: Rectangle {
|
bounds: Rectangle {
|
||||||
@ -112,11 +136,7 @@ impl text_input::Renderer for Renderer {
|
|||||||
Primitive::Group {
|
Primitive::Group {
|
||||||
primitives: vec![text_value, cursor],
|
primitives: vec![text_value, cursor],
|
||||||
},
|
},
|
||||||
Vector::new(
|
Vector::new(offset as u32, 0),
|
||||||
((text_value_width + 5.0) - text_bounds.width).max(0.0)
|
|
||||||
as u32,
|
|
||||||
0,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(text_value, Vector::new(0, 0))
|
(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)
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user