mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-29 13:24:48 +00:00
Fix multi-byte handling hit testing
Return a byte offset within the string for the hit test in TextInput.
This commit is contained in:
parent
adfadd12fa
commit
49edd69a3a
3 changed files with 16 additions and 15 deletions
|
@ -27,17 +27,17 @@ impl Font {
|
|||
text_metrics.width() as _
|
||||
}
|
||||
|
||||
pub fn text_index_for_x_position(&self, text: &str, x: f32) -> usize {
|
||||
pub fn text_offset_for_x_position(&self, text: &str, x: f32) -> usize {
|
||||
// This is pretty cruel ...
|
||||
let mut last_width = 0.;
|
||||
for index in 1..text.len() {
|
||||
let new_width = self.text_width(&text[0..index]);
|
||||
for offset in text.char_indices().map(|(offset, _)| offset) {
|
||||
let new_width = self.text_width(&text[0..offset]);
|
||||
|
||||
if new_width > last_width {
|
||||
let advance = new_width - last_width;
|
||||
|
||||
if last_width + advance / 2. >= x {
|
||||
return index;
|
||||
return offset;
|
||||
}
|
||||
|
||||
last_width = new_width;
|
||||
|
|
|
@ -48,18 +48,19 @@ impl Font {
|
|||
.fold(0., |width, glyph| width + glyph.advance)
|
||||
}
|
||||
|
||||
pub fn text_index_for_x_position(&self, text: &str, x: f32) -> usize {
|
||||
let mut index = 0;
|
||||
pub fn text_offset_for_x_position<'a>(&self, text: &'a str, x: f32) -> usize {
|
||||
let mut char_offset_it = text.char_indices().map(|(offset, _)| offset);
|
||||
|
||||
let mut current_x = 0.;
|
||||
let mut current_offset = 0;
|
||||
// This assumes a 1:1 mapping between glyphs and characters right now -- this is wrong.
|
||||
for (_, glyph_id) in self.string_to_glyphs(text) {
|
||||
let metrics = self.glyph_metrics(glyph_id);
|
||||
|
||||
if current_x + metrics.advance / 2. >= x {
|
||||
return index;
|
||||
return current_offset;
|
||||
}
|
||||
index += 1;
|
||||
current_offset = char_offset_it.next().unwrap();
|
||||
current_x += metrics.advance;
|
||||
}
|
||||
|
||||
|
|
|
@ -835,8 +835,8 @@ pub struct TextInput {
|
|||
pub y: Property<f32>,
|
||||
pub width: Property<f32>,
|
||||
pub height: Property<f32>,
|
||||
pub cursor_position: Property<i32>,
|
||||
pub anchor_position: Property<i32>,
|
||||
pub cursor_position: Property<i32>, // byte offset,
|
||||
pub anchor_position: Property<i32>, // byte offset
|
||||
pub text_cursor_width: Property<f32>,
|
||||
pub cursor_visible: Property<bool>,
|
||||
pub accepted: Signal<()>,
|
||||
|
@ -952,16 +952,16 @@ impl Item for TextInput {
|
|||
InputEventResult::GrabMouse
|
||||
};
|
||||
|
||||
let clicked_index = TextInput::with_font(self, window, |font| {
|
||||
let clicked_offset = TextInput::with_font(self, window, |font| {
|
||||
let text = Self::FIELD_OFFSETS.text.apply_pin(self).get();
|
||||
font.text_index_for_x_position(&text, event.pos.x)
|
||||
font.text_offset_for_x_position(&text, event.pos.x)
|
||||
}) as i32;
|
||||
|
||||
if matches!(event.what, MouseEventType::MousePressed) {
|
||||
self.as_ref().pressed.set(true);
|
||||
self.as_ref().show_cursor(window);
|
||||
self.as_ref().anchor_position.set(clicked_index);
|
||||
self.as_ref().cursor_position.set(clicked_index);
|
||||
self.as_ref().anchor_position.set(clicked_offset);
|
||||
self.as_ref().cursor_position.set(clicked_offset);
|
||||
}
|
||||
|
||||
match event.what {
|
||||
|
@ -969,7 +969,7 @@ impl Item for TextInput {
|
|||
self.as_ref().pressed.set(false);
|
||||
}
|
||||
MouseEventType::MouseMoved if self.as_ref().pressed.get() => {
|
||||
self.as_ref().cursor_position.set(clicked_index);
|
||||
self.as_ref().cursor_position.set(clicked_offset);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue