From e237536dd549bea6da2f4ead23e24492eede5473 Mon Sep 17 00:00:00 2001 From: chompaa Date: Sun, 18 Feb 2024 13:08:06 -0500 Subject: [PATCH 1/5] Add cursor timer reset on input --- src/lib.rs | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index bbf0361..ed4a604 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,9 +127,29 @@ impl<'w, 's> InnerText<'w, 's> { } } +/// Used to set the visibility of the cursor based on the `active` parameter. +#[macro_export] +macro_rules! set_cursor { + ($active:expr, $active_color:expr, $text:expr, $timer:expr) => { + if $active { + $text.sections[1].style.color = $active_color; + } else { + $text.sections[1].style.color = Color::NONE; + } + + $timer.0.reset(); + }; +} + fn keyboard( mut events: EventReader, - mut text_input_query: Query<(Entity, &TextInputInactive, &mut TextInput)>, + mut text_input_query: Query<( + Entity, + &TextInputInactive, + &TextInputTextStyle, + &mut TextInput, + &mut TextInputCursorTimer, + )>, mut inner_text: InnerText, mut submit_writer: EventWriter, ) { @@ -137,7 +157,7 @@ fn keyboard( return; } - for (input_entity, inactive, mut text_input) in &mut text_input_query { + for (input_entity, inactive, style, mut text_input, mut timer) in &mut text_input_query { if inactive.0 { continue; } @@ -158,22 +178,18 @@ fn keyboard( if let Some(behind) = text.sections[0].value.pop() { text.sections[2].value.insert(0, behind); } - continue; } KeyCode::ArrowRight => { if !text.sections[2].value.is_empty() { let ahead = text.sections[2].value.remove(0); text.sections[0].value.push(ahead); } - continue; } KeyCode::Backspace => { text.sections[0].value.pop(); - continue; } KeyCode::Delete => { text.sections[2].value = text.sections[2].value.chars().skip(1).collect(); - continue; } KeyCode::Enter => { submitted_value = Some(format!( @@ -187,7 +203,6 @@ fn keyboard( } KeyCode::Space => { text.sections[0].value.push(' '); - continue; } _ => {} } @@ -195,6 +210,8 @@ fn keyboard( if let Key::Character(ref s) = event.logical_key { text.sections[0].value.push_str(s.as_str()); } + + set_cursor!(true, style.0.color, text, timer); } let value = format!("{}{}", text.sections[0].value, text.sections[2].value); @@ -291,13 +308,7 @@ fn blink_cursor( continue; }; - text.sections[1].style.color = if inactive.0 { - Color::NONE - } else { - style.0.color - }; - - timer.0.reset(); + set_cursor!(!inactive.0, style.0.color, text, timer); } } @@ -324,11 +335,9 @@ fn show_hide_cursor( continue; }; - if text.sections[1].style.color != Color::NONE { - text.sections[1].style.color = Color::NONE; - } else { - text.sections[1].style.color = style.0.color; - } + let active = text.sections[1].style.color == Color::NONE; + + set_cursor!(active, style.0.color, text, timer); } } From 6906e4e877fbce2728e45d7df48c0e1127b66a0c Mon Sep 17 00:00:00 2001 From: chompaa Date: Sun, 18 Feb 2024 13:28:18 -0500 Subject: [PATCH 2/5] Add rustdoc links --- src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ed4a604..b8ee049 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ const CURSOR_HANDLE: Handle = Handle::weak_from_u128(10482756907980398621) /// A bundle providing the additional components required for a text input. /// -/// Add this to a `NodeBundle`. +/// Add this to a [`NodeBundle`]. /// /// Examples: /// ```rust @@ -60,7 +60,7 @@ pub struct TextInputBundle { } impl TextInputBundle { - /// Creates a new `TextInputBundle` with the specified `TextStyle`. + /// Creates a new [`TextInputBundle`] with the specified [`TextStyle`]. pub fn new(text_style: TextStyle) -> Self { Self { text_style: TextInputTextStyle(text_style), @@ -68,7 +68,7 @@ impl TextInputBundle { } } - /// Creates a new `TextInputBundle` with the specified `TextStyle` and starting text. + /// Creates a new [`TextInputBundle`] with the specified [`TextStyle`] and starting text. pub fn with_starting_text(text_style: TextStyle, starting_text: String) -> Self { Self { text_style: TextInputTextStyle(text_style), @@ -78,7 +78,7 @@ impl TextInputBundle { } } -/// The `TextStyle` that will be used when creating the text input's inner `TextBundle`. +/// The [`TextStyle`] that will be used when creating the text input's inner [`TextBundle`]. #[derive(Component, Default)] pub struct TextInputTextStyle(pub TextStyle); @@ -112,7 +112,7 @@ pub struct TextInputSubmitEvent { pub value: String, } -/// A convenience parameter for dealing with a `TextInput`'s inner `Text` entity. +/// A convenience parameter for dealing with a [`TextInput`]'s inner [`Text`] entity. #[derive(SystemParam)] struct InnerText<'w, 's> { text_query: Query<'w, 's, &'static mut Text, With>, From af73bf3b9377a4e82351eb81d5e8b39384771a50 Mon Sep 17 00:00:00 2001 From: chompaa Date: Sun, 18 Feb 2024 13:44:54 -0500 Subject: [PATCH 3/5] Revert "Add cursor timer reset on input" This reverts commit e237536dd549bea6da2f4ead23e24492eede5473. --- src/lib.rs | 47 +++++++++++++++++++---------------------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b8ee049..fb9e827 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,29 +127,9 @@ impl<'w, 's> InnerText<'w, 's> { } } -/// Used to set the visibility of the cursor based on the `active` parameter. -#[macro_export] -macro_rules! set_cursor { - ($active:expr, $active_color:expr, $text:expr, $timer:expr) => { - if $active { - $text.sections[1].style.color = $active_color; - } else { - $text.sections[1].style.color = Color::NONE; - } - - $timer.0.reset(); - }; -} - fn keyboard( mut events: EventReader, - mut text_input_query: Query<( - Entity, - &TextInputInactive, - &TextInputTextStyle, - &mut TextInput, - &mut TextInputCursorTimer, - )>, + mut text_input_query: Query<(Entity, &TextInputInactive, &mut TextInput)>, mut inner_text: InnerText, mut submit_writer: EventWriter, ) { @@ -157,7 +137,7 @@ fn keyboard( return; } - for (input_entity, inactive, style, mut text_input, mut timer) in &mut text_input_query { + for (input_entity, inactive, mut text_input) in &mut text_input_query { if inactive.0 { continue; } @@ -178,18 +158,22 @@ fn keyboard( if let Some(behind) = text.sections[0].value.pop() { text.sections[2].value.insert(0, behind); } + continue; } KeyCode::ArrowRight => { if !text.sections[2].value.is_empty() { let ahead = text.sections[2].value.remove(0); text.sections[0].value.push(ahead); } + continue; } KeyCode::Backspace => { text.sections[0].value.pop(); + continue; } KeyCode::Delete => { text.sections[2].value = text.sections[2].value.chars().skip(1).collect(); + continue; } KeyCode::Enter => { submitted_value = Some(format!( @@ -203,6 +187,7 @@ fn keyboard( } KeyCode::Space => { text.sections[0].value.push(' '); + continue; } _ => {} } @@ -210,8 +195,6 @@ fn keyboard( if let Key::Character(ref s) = event.logical_key { text.sections[0].value.push_str(s.as_str()); } - - set_cursor!(true, style.0.color, text, timer); } let value = format!("{}{}", text.sections[0].value, text.sections[2].value); @@ -308,7 +291,13 @@ fn blink_cursor( continue; }; - set_cursor!(!inactive.0, style.0.color, text, timer); + text.sections[1].style.color = if inactive.0 { + Color::NONE + } else { + style.0.color + }; + + timer.0.reset(); } } @@ -335,9 +324,11 @@ fn show_hide_cursor( continue; }; - let active = text.sections[1].style.color == Color::NONE; - - set_cursor!(active, style.0.color, text, timer); + if text.sections[1].style.color != Color::NONE { + text.sections[1].style.color = Color::NONE; + } else { + text.sections[1].style.color = style.0.color; + } } } From 4637ddd7606cf5458bf7c67e41e3772607b7c0fd Mon Sep 17 00:00:00 2001 From: chompaa Date: Sun, 18 Feb 2024 14:07:56 -0500 Subject: [PATCH 4/5] Add requested implementation --- src/lib.rs | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fb9e827..5f4ba31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,13 +86,20 @@ pub struct TextInputTextStyle(pub TextStyle); #[derive(Component, Default)] pub struct TextInputInactive(pub bool); -/// The timer controlling the blinking cursor. The cursor is toggled when the timer is finished. +/// A component that manages the cursor's blinking. #[derive(Component)] -pub struct TextInputCursorTimer(pub Timer); +pub struct TextInputCursorTimer { + /// The timer that blinks the cursor on and off, and resets when the user types. + pub timer: Timer, + should_reset: bool, +} impl Default for TextInputCursorTimer { fn default() -> Self { - Self(Timer::from_seconds(0.5, TimerMode::Repeating)) + Self { + timer: Timer::from_seconds(0.5, TimerMode::Repeating), + should_reset: false, + } } } @@ -129,7 +136,12 @@ impl<'w, 's> InnerText<'w, 's> { fn keyboard( mut events: EventReader, - mut text_input_query: Query<(Entity, &TextInputInactive, &mut TextInput)>, + mut text_input_query: Query<( + Entity, + &TextInputInactive, + &mut TextInput, + &mut TextInputCursorTimer, + )>, mut inner_text: InnerText, mut submit_writer: EventWriter, ) { @@ -137,7 +149,7 @@ fn keyboard( return; } - for (input_entity, inactive, mut text_input) in &mut text_input_query { + for (input_entity, inactive, mut text_input, mut cursor_timer) in &mut text_input_query { if inactive.0 { continue; } @@ -150,6 +162,8 @@ fn keyboard( for event in events.read() { if !event.state.is_pressed() { + // Resume blinking the cursor when the user releases a key. + cursor_timer.should_reset = false; continue; }; @@ -158,22 +172,18 @@ fn keyboard( if let Some(behind) = text.sections[0].value.pop() { text.sections[2].value.insert(0, behind); } - continue; } KeyCode::ArrowRight => { if !text.sections[2].value.is_empty() { let ahead = text.sections[2].value.remove(0); text.sections[0].value.push(ahead); } - continue; } KeyCode::Backspace => { text.sections[0].value.pop(); - continue; } KeyCode::Delete => { text.sections[2].value = text.sections[2].value.chars().skip(1).collect(); - continue; } KeyCode::Enter => { submitted_value = Some(format!( @@ -187,7 +197,6 @@ fn keyboard( } KeyCode::Space => { text.sections[0].value.push(' '); - continue; } _ => {} } @@ -195,6 +204,9 @@ fn keyboard( if let Key::Character(ref s) = event.logical_key { text.sections[0].value.push_str(s.as_str()); } + + // Reset the cursor timer when the user types. + cursor_timer.should_reset = true; } let value = format!("{}{}", text.sections[0].value, text.sections[2].value); @@ -282,7 +294,7 @@ fn blink_cursor( )>, mut inner_text: InnerText, ) { - for (entity, style, mut timer, inactive) in &mut input_query { + for (entity, style, mut cursor_timer, inactive) in &mut input_query { if !inactive.is_changed() { continue; } @@ -297,7 +309,7 @@ fn blink_cursor( style.0.color }; - timer.0.reset(); + cursor_timer.timer.reset(); } } @@ -311,18 +323,23 @@ fn show_hide_cursor( mut inner_text: InnerText, time: Res