Implement Renderer::find_cursor_position

This commit is contained in:
Héctor Ramón Jiménez 2020-03-25 13:57:02 +01:00
parent b30ddf90d2
commit 30f02345a8
3 changed files with 61 additions and 50 deletions

View File

@ -114,10 +114,10 @@ impl text_input::Renderer for Null {
fn offset( fn offset(
&self, &self,
_text_bounds: Rectangle, _text_bounds: Rectangle,
_font: Font,
_size: u16, _size: u16,
_value: &text_input::Value, _value: &text_input::Value,
_state: &text_input::State, _state: &text_input::State,
_font: Font,
) -> f32 { ) -> f32 {
0.0 0.0
} }
@ -127,8 +127,8 @@ impl text_input::Renderer for Null {
_bounds: Rectangle, _bounds: Rectangle,
_text_bounds: Rectangle, _text_bounds: Rectangle,
_cursor_position: Point, _cursor_position: Point,
_size: u16,
_font: Font, _font: Font,
_size: u16,
_placeholder: &str, _placeholder: &str,
_value: &text_input::Value, _value: &text_input::Value,
_state: &text_input::State, _state: &text_input::State,

View File

@ -236,29 +236,16 @@ where
self.value.clone() self.value.clone()
}; };
let size = self let position = renderer.find_cursor_position(
.size
.unwrap_or(renderer.default_size());
let offset = renderer.offset(
text_layout.bounds(), text_layout.bounds(),
size, self.font,
self.size,
&value, &value,
&self.state, &self.state,
self.font, target,
); );
self.state.cursor.move_to( self.state.cursor.move_to(position);
find_cursor_position(
renderer,
target + offset,
&value,
size,
0,
self.value.len(),
self.font,
),
);
} else { } else {
self.state.cursor.move_to(0); self.state.cursor.move_to(0);
} }
@ -267,11 +254,18 @@ where
if self.is_secure { if self.is_secure {
self.state.cursor.select_all(&self.value); self.state.cursor.select_all(&self.value);
} else { } else {
let end = self.state.cursor.end(&self.value); let position = renderer.find_cursor_position(
text_layout.bounds(),
self.font,
self.size,
&self.value,
&self.state,
target,
);
self.state.cursor.select_range( self.state.cursor.select_range(
self.value.previous_start_of_word(end), self.value.previous_start_of_word(position),
self.value.next_end_of_word(end), self.value.next_end_of_word(position),
); );
} }
} }
@ -304,24 +298,13 @@ where
self.value.clone() self.value.clone()
}; };
let size = self.size.unwrap_or(renderer.default_size()); let position = renderer.find_cursor_position(
let offset = renderer.offset(
text_layout.bounds(), text_layout.bounds(),
size, self.font,
self.size,
&value, &value,
&self.state, &self.state,
self.font, target,
);
let position = find_cursor_position(
renderer,
target + offset,
&value,
size,
0,
self.value.len(),
self.font,
); );
self.state.cursor.select_range( self.state.cursor.select_range(
@ -493,8 +476,8 @@ where
bounds, bounds,
text_bounds, text_bounds,
cursor_position, cursor_position,
self.size.unwrap_or(renderer.default_size()),
self.font, self.font,
self.size.unwrap_or(renderer.default_size()),
&self.placeholder, &self.placeholder,
&self.value.secure(), &self.value.secure(),
&self.state, &self.state,
@ -505,8 +488,8 @@ where
bounds, bounds,
text_bounds, text_bounds,
cursor_position, cursor_position,
self.size.unwrap_or(renderer.default_size()),
self.font, self.font,
self.size.unwrap_or(renderer.default_size()),
&self.placeholder, &self.placeholder,
&self.value, &self.value,
&self.state, &self.state,
@ -559,10 +542,10 @@ pub trait Renderer: crate::Renderer + Sized {
fn offset( fn offset(
&self, &self,
text_bounds: Rectangle, text_bounds: Rectangle,
font: Font,
size: u16, size: u16,
value: &Value, value: &Value,
state: &State, state: &State,
font: Font,
) -> f32; ) -> f32;
/// Draws a [`TextInput`]. /// Draws a [`TextInput`].
@ -583,13 +566,41 @@ pub trait Renderer: crate::Renderer + Sized {
bounds: Rectangle, bounds: Rectangle,
text_bounds: Rectangle, text_bounds: Rectangle,
cursor_position: Point, cursor_position: Point,
size: u16,
font: Font, font: Font,
size: u16,
placeholder: &str, placeholder: &str,
value: &Value, value: &Value,
state: &State, state: &State,
style: &Self::Style, style: &Self::Style,
) -> Self::Output; ) -> Self::Output;
/// Computes the position of the text cursor at the given X coordinate of
/// a [`TextInput`].
///
/// [`TextInput`]: struct.TextInput.html
fn find_cursor_position(
&self,
text_bounds: Rectangle,
font: Font,
size: Option<u16>,
value: &Value,
state: &State,
x: f32,
) -> usize {
let size = size.unwrap_or(self.default_size());
let offset = self.offset(text_bounds, font, size, &value, &state);
find_cursor_position(
self,
&value,
font,
size,
x + offset,
0,
value.len(),
)
}
} }
impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>> impl<'a, Message, Renderer> From<TextInput<'a, Message, Renderer>>
@ -658,12 +669,12 @@ impl State {
// TODO: Reduce allocations // TODO: Reduce allocations
fn find_cursor_position<Renderer: self::Renderer>( fn find_cursor_position<Renderer: self::Renderer>(
renderer: &Renderer, renderer: &Renderer,
target: f32,
value: &Value, value: &Value,
font: Font,
size: u16, size: u16,
target: f32,
start: usize, start: usize,
end: usize, end: usize,
font: Font,
) -> usize { ) -> usize {
if start >= end { if start >= end {
if start == 0 { if start == 0 {
@ -691,22 +702,22 @@ fn find_cursor_position<Renderer: self::Renderer>(
if width > target { if width > target {
find_cursor_position( find_cursor_position(
renderer, renderer,
target,
value, value,
font,
size, size,
target,
start, start,
start + index, start + index,
font,
) )
} else { } else {
find_cursor_position( find_cursor_position(
renderer, renderer,
target,
value, value,
font,
size, size,
target,
start + index + 1, start + index + 1,
end, end,
font,
) )
} }
} }

View File

@ -36,10 +36,10 @@ impl text_input::Renderer for Renderer {
fn offset( fn offset(
&self, &self,
text_bounds: Rectangle, text_bounds: Rectangle,
font: Font,
size: u16, size: u16,
value: &text_input::Value, value: &text_input::Value,
state: &text_input::State, state: &text_input::State,
font: Font,
) -> f32 { ) -> f32 {
if state.is_focused() { if state.is_focused() {
let cursor = state.cursor(); let cursor = state.cursor();
@ -69,8 +69,8 @@ impl text_input::Renderer for Renderer {
bounds: Rectangle, bounds: Rectangle,
text_bounds: Rectangle, text_bounds: Rectangle,
cursor_position: Point, cursor_position: Point,
size: u16,
font: Font, font: Font,
size: u16,
placeholder: &str, placeholder: &str,
value: &text_input::Value, value: &text_input::Value,
state: &text_input::State, state: &text_input::State,