From da130f785255be0ad89d97f2152bbbea5d490c01 Mon Sep 17 00:00:00 2001 From: Fedor Logachev Date: Sun, 1 Sep 2024 16:23:14 -0600 Subject: [PATCH] First attempt on editbox utf8 fix --- examples/basic_shapes.rs | 10 ++++--- src/ui/widgets/editbox.rs | 13 +++++---- src/ui/widgets/editbox/text_editor.rs | 38 +++++++++++++-------------- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/examples/basic_shapes.rs b/examples/basic_shapes.rs index c81fb5e7..64b60579 100644 --- a/examples/basic_shapes.rs +++ b/examples/basic_shapes.rs @@ -5,11 +5,13 @@ async fn main() { loop { clear_background(LIGHTGRAY); - draw_line(40.0, 40.0, 100.0, 200.0, 15.0, BLUE); - draw_rectangle(screen_width() / 2.0 - 60.0, 100.0, 120.0, 60.0, GREEN); - draw_circle(screen_width() - 30.0, screen_height() - 30.0, 15.0, YELLOW); + if is_key_pressed(KeyCode::Q) + && (is_key_down(KeyCode::LeftControl) || is_key_down(KeyCode::RightControl)) + { + println!("ctrl-q") + } - draw_text("HELLO", 20.0, 20.0, 30.0, DARKGRAY); + // draw_text("HELLO", 20.0, 20.0, 30.0, DARKGRAY); next_frame().await } diff --git a/src/ui/widgets/editbox.rs b/src/ui/widgets/editbox.rs index 36b4bc61..b6f64f94 100644 --- a/src/ui/widgets/editbox.rs +++ b/src/ui/widgets/editbox.rs @@ -90,8 +90,7 @@ impl<'a> Editbox<'a> { .. } => { // Don't insert spaces for control characters - if character.is_ascii() - && !character.is_ascii_control() + if !(character.is_control() || character.is_ascii_control()) && self.filter.as_ref().map_or(true, |f| f(character)) { if state.selection.is_some() { @@ -240,7 +239,7 @@ impl<'a> Editbox<'a> { let to_line_end = state.find_line_end(text) as i32; state.move_cursor(text, to_line_end, modifier_shift); - if text.len() != 0 && state.cursor < text.len() as u32 - 1 { + if text.chars().count() != 0 && state.cursor < text.chars().count() as u32 - 1 { state.move_cursor(text, 1, modifier_shift); state.move_cursor_within_line(text, to_line_begin, modifier_shift); } @@ -289,8 +288,8 @@ impl<'a> Editbox<'a> { *context.clipboard_selection = selected.to_owned(); } // in case the string was updated outside of editbox - if state.cursor > text.len() as u32 { - state.cursor = text.len() as u32; + if state.cursor > text.chars().count() as u32 { + state.cursor = text.chars().count() as u32; } let input_focused = @@ -439,12 +438,12 @@ impl<'a> Editbox<'a> { let cursor_on_current_line = (context.input.mouse_position.y - (pos.y + y + line_height / 2.)).abs() < line_height / 2. + 0.1; - let line_end = character == '\n' || n == text.len(); + let line_end = character == '\n' || n == text.chars().count(); let cursor_after_line_end = context.input.mouse_position.x > (pos.x + x); let clickable_character = character != '\n'; let cursor_on_character = (context.input.mouse_position.x - (pos.x + x)).abs() < advance / 2.; - let last_character = n == text.len(); + let last_character = n == text.chars().count(); let cursor_below_line = (context.input.mouse_position.y - (pos.y + y + line_height)) > 0.; diff --git a/src/ui/widgets/editbox/text_editor.rs b/src/ui/widgets/editbox/text_editor.rs index 3fb09834..a98f885a 100644 --- a/src/ui/widgets/editbox/text_editor.rs +++ b/src/ui/widgets/editbox/text_editor.rs @@ -20,14 +20,14 @@ impl InsertCharacter { impl Command for InsertCharacter { fn apply(&self, text_cursor: &mut u32, text: &mut String) { *text_cursor = self.cursor; - if self.cursor <= text.len() as u32 { + if self.cursor <= text.chars().count() as u32 { text.insert(self.cursor as usize, self.character); } *text_cursor += 1; } fn unapply(&self, text_cursor: &mut u32, text: &mut String) { *text_cursor = self.cursor; - if self.cursor < text.len() as u32 { + if self.cursor < text.chars().count() as u32 { text.remove(self.cursor as usize); } } @@ -50,16 +50,16 @@ impl InsertString { impl Command for InsertString { fn apply(&self, text_cursor: &mut u32, text: &mut String) { *text_cursor = self.cursor; - if self.cursor <= text.len() as u32 { + if self.cursor <= text.chars().count() as u32 { text.insert_str(self.cursor as usize, &self.data); } - *text_cursor += self.data.len() as u32; + *text_cursor += self.data.chars().count() as u32; } fn unapply(&self, text_cursor: &mut u32, text: &mut String) { *text_cursor = self.cursor; - if self.cursor < text.len() as u32 { - let end = (self.cursor as usize + self.data.len()).min(text.len()); + if self.cursor < text.chars().count() as u32 { + let end = (self.cursor as usize + self.data.chars().count()).min(text.chars().count()); text.replace_range(self.cursor as usize..end, ""); } @@ -85,14 +85,14 @@ impl DeleteCharacter { impl Command for DeleteCharacter { fn apply(&self, text_cursor: &mut u32, text: &mut String) { *text_cursor = self.cursor; - if self.cursor < text.len() as u32 { + if self.cursor < text.chars().count() as u32 { text.remove(self.cursor as usize); } } fn unapply(&self, text_cursor: &mut u32, text: &mut String) { *text_cursor = self.cursor + 1; - if self.cursor <= text.len() as u32 { + if self.cursor <= text.chars().count() as u32 { text.insert(self.cursor as usize, self.character); } } @@ -109,7 +109,7 @@ impl DeleteRange { let max = start.max(end) as usize; DeleteRange { - data: text[min..max].to_string(), + data: text.chars().skip(min).take(max - min).collect(), range: (start, end), } } @@ -165,11 +165,11 @@ pub struct EditboxState { impl EditboxState { pub fn clamp_selection<'a>(&mut self, text: &'a str) { if let Some((ref mut start, ref mut end)) = &mut self.selection { - if *start >= text.len() as u32 { - *start = text.len() as _; + if *start >= text.chars().count() as u32 { + *start = text.chars().count() as _; } - if *end >= text.len() as u32 { - *end = text.len() as _; + if *end >= text.chars().count() as u32 { + *end = text.chars().count() as _; } } } @@ -180,7 +180,7 @@ impl EditboxState { let max = start.max(end) as usize; assert!(min <= max); - assert!(max <= text.len()); + assert!(max <= text.chars().count()); Some(&text[min..max]) } else { @@ -207,7 +207,7 @@ impl EditboxState { pub fn find_line_end(&self, text: &str) -> u32 { let mut cursor_tmp = self.cursor; - while cursor_tmp < text.len() as u32 + while cursor_tmp < text.chars().count() as u32 && text.chars().nth(cursor_tmp as usize).unwrap_or('x') != '\n' { cursor_tmp += 1; @@ -244,7 +244,7 @@ impl EditboxState { let mut offset = 0; let mut space_skipping = false; - while cursor_tmp < text.len() as u32 { + while cursor_tmp < text.chars().count() as u32 { let current_char = text.chars().nth(cursor_tmp as usize).unwrap_or(' '); if Self::word_delimiter(current_char) || current_char == '\n' { space_skipping = true; @@ -321,7 +321,7 @@ impl EditboxState { let start_cursor = self.cursor; let mut end_cursor = start_cursor; - if self.cursor as i32 + dx <= text.len() as i32 && self.cursor as i32 + dx >= 0 { + if self.cursor as i32 + dx <= text.chars().count() as i32 && self.cursor as i32 + dx >= 0 { end_cursor = (self.cursor as i32 + dx) as u32; self.cursor = end_cursor; } @@ -344,7 +344,7 @@ impl EditboxState { for _ in 0..dx { if text.chars().nth(self.cursor as usize).unwrap_or('x') == '\n' - || self.cursor == text.len() as u32 + || self.cursor == text.chars().count() as u32 { break; } @@ -353,7 +353,7 @@ impl EditboxState { } pub fn select_all(&mut self, text: &str) { - self.selection = Some((0, text.len() as u32)); + self.selection = Some((0, text.chars().count() as u32)); self.click_state = ClickState::None; }