From f10e936f00d4b83dcacfdebd2727b1a5cd1add95 Mon Sep 17 00:00:00 2001 From: Dan Mishin Date: Fri, 3 Mar 2023 10:01:49 +0300 Subject: Introduce disabled state for `TextInput` --- native/src/widget/helpers.rs | 3 +- native/src/widget/text_input.rs | 365 +++++++++++++++++++++------------------- 2 files changed, 196 insertions(+), 172 deletions(-) (limited to 'native') diff --git a/native/src/widget/helpers.rs b/native/src/widget/helpers.rs index d13eca75..0363fc99 100644 --- a/native/src/widget/helpers.rs +++ b/native/src/widget/helpers.rs @@ -171,14 +171,13 @@ where pub fn text_input<'a, Message, Renderer>( placeholder: &str, value: &str, - on_change: impl Fn(String) -> Message + 'a, ) -> widget::TextInput<'a, Message, Renderer> where Message: Clone, Renderer: crate::text::Renderer, Renderer::Theme: widget::text_input::StyleSheet, { - widget::TextInput::new(placeholder, value, on_change) + widget::TextInput::new(placeholder, value) } /// Creates a new [`Slider`]. diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index fd61a849..65897a68 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -46,8 +46,8 @@ pub use iced_style::text_input::{Appearance, StyleSheet}; /// let input = TextInput::new( /// "This is the placeholder...", /// value, -/// Message::TextInputChanged, /// ) +/// .on_change(|_| Message::TextInputChanged) /// .padding(10); /// ``` /// ![Text input drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text_input.png?raw=true) @@ -65,7 +65,7 @@ where width: Length, padding: Padding, size: Option, - on_change: Box Message + 'a>, + on_change: Option Message + 'a>>, on_paste: Option Message + 'a>>, on_submit: Option, icon: Option>, @@ -82,12 +82,8 @@ where /// /// It expects: /// - a placeholder, - /// - the current value, and - /// - a function that produces a message when the [`TextInput`] changes. - pub fn new(placeholder: &str, value: &str, on_change: F) -> Self - where - F: 'a + Fn(String) -> Message, - { + /// - the current value + pub fn new(placeholder: &str, value: &str) -> Self { TextInput { id: None, placeholder: String::from(placeholder), @@ -97,7 +93,7 @@ where width: Length::Fill, padding: Padding::new(5.0), size: None, - on_change: Box::new(on_change), + on_change: None, on_paste: None, on_submit: None, icon: None, @@ -175,6 +171,16 @@ where self } + /// Sets the callback which is called when the text gets changed + /// If not specified, the widget will be disabled + pub fn on_change(mut self, callback: F) -> Self + where + F: 'a + Fn(String) -> Message, + { + self.on_change = Some(Box::new(callback)); + self + } + /// Draws the [`TextInput`] with the given [`Renderer`], overriding its /// [`Value`] if provided. /// @@ -201,6 +207,7 @@ where self.is_secure, self.icon.as_ref(), &self.style, + self.on_change.is_none(), ) } } @@ -277,7 +284,7 @@ where self.size, &self.font, self.is_secure, - self.on_change.as_ref(), + self.on_change.as_deref(), self.on_paste.as_deref(), &self.on_submit, || tree.state.downcast_mut::(), @@ -307,6 +314,7 @@ where self.is_secure, self.icon.as_ref(), &self.style, + self.on_change.is_none(), ) } @@ -492,7 +500,7 @@ pub fn update<'a, Message, Renderer>( size: Option, font: &Renderer::Font, is_secure: bool, - on_change: &dyn Fn(String) -> Message, + on_change: Option<&dyn Fn(String) -> Message>, on_paste: Option<&dyn Fn(String) -> Message>, on_submit: &Option, state: impl FnOnce() -> &'a mut State, @@ -501,11 +509,14 @@ where Message: Clone, Renderer: text::Renderer, { + let is_disabled = on_change.is_none(); + match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { let state = state(); let is_clicked = layout.bounds().contains(cursor_position); + let is_clicked = is_clicked && !is_disabled; state.is_focused = if is_clicked { state.is_focused.or_else(|| { @@ -635,20 +646,22 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - if state.is_pasting.is_none() - && !state.keyboard_modifiers.command() - && !c.is_control() - { - let mut editor = Editor::new(value, &mut state.cursor); + if let Some(on_change) = on_change { + if state.is_pasting.is_none() + && !state.keyboard_modifiers.command() + && !c.is_control() + { + let mut editor = Editor::new(value, &mut state.cursor); - editor.insert(c); + editor.insert(c); - let message = (on_change)(editor.contents()); - shell.publish(message); + let message = (on_change)(editor.contents()); + shell.publish(message); - focus.updated_at = Instant::now(); + focus.updated_at = Instant::now(); - return event::Status::Captured; + return event::Status::Captured; + } } } } @@ -656,181 +669,188 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - let modifiers = state.keyboard_modifiers; - focus.updated_at = Instant::now(); + if let Some(on_change) = on_change { + let modifiers = state.keyboard_modifiers; + focus.updated_at = Instant::now(); - match key_code { - keyboard::KeyCode::Enter - | keyboard::KeyCode::NumpadEnter => { - if let Some(on_submit) = on_submit.clone() { - shell.publish(on_submit); + match key_code { + keyboard::KeyCode::Enter + | keyboard::KeyCode::NumpadEnter => { + if let Some(on_submit) = on_submit.clone() { + shell.publish(on_submit); + } } - } - keyboard::KeyCode::Backspace => { - if platform::is_jump_modifier_pressed(modifiers) - && state.cursor.selection(value).is_none() - { - if is_secure { - let cursor_pos = state.cursor.end(value); - state.cursor.select_range(0, cursor_pos); - } else { - state.cursor.select_left_by_words(value); + keyboard::KeyCode::Backspace => { + if platform::is_jump_modifier_pressed(modifiers) + && state.cursor.selection(value).is_none() + { + if is_secure { + let cursor_pos = state.cursor.end(value); + state.cursor.select_range(0, cursor_pos); + } else { + state.cursor.select_left_by_words(value); + } } + + let mut editor = + Editor::new(value, &mut state.cursor); + editor.backspace(); + + let message = (on_change)(editor.contents()); + shell.publish(message); } + keyboard::KeyCode::Delete => { + if platform::is_jump_modifier_pressed(modifiers) + && state.cursor.selection(value).is_none() + { + if is_secure { + let cursor_pos = state.cursor.end(value); + state + .cursor + .select_range(cursor_pos, value.len()); + } else { + state.cursor.select_right_by_words(value); + } + } - let mut editor = Editor::new(value, &mut state.cursor); - editor.backspace(); + let mut editor = + Editor::new(value, &mut state.cursor); + editor.delete(); - let message = (on_change)(editor.contents()); - shell.publish(message); - } - keyboard::KeyCode::Delete => { - if platform::is_jump_modifier_pressed(modifiers) - && state.cursor.selection(value).is_none() - { - if is_secure { - let cursor_pos = state.cursor.end(value); - state - .cursor - .select_range(cursor_pos, value.len()); + let message = (on_change)(editor.contents()); + shell.publish(message); + } + keyboard::KeyCode::Left => { + if platform::is_jump_modifier_pressed(modifiers) + && !is_secure + { + if modifiers.shift() { + state.cursor.select_left_by_words(value); + } else { + state.cursor.move_left_by_words(value); + } + } else if modifiers.shift() { + state.cursor.select_left(value) } else { - state.cursor.select_right_by_words(value); + state.cursor.move_left(value); } } - - let mut editor = Editor::new(value, &mut state.cursor); - editor.delete(); - - let message = (on_change)(editor.contents()); - shell.publish(message); - } - keyboard::KeyCode::Left => { - if platform::is_jump_modifier_pressed(modifiers) - && !is_secure - { - if modifiers.shift() { - state.cursor.select_left_by_words(value); + keyboard::KeyCode::Right => { + if platform::is_jump_modifier_pressed(modifiers) + && !is_secure + { + if modifiers.shift() { + state.cursor.select_right_by_words(value); + } else { + state.cursor.move_right_by_words(value); + } + } else if modifiers.shift() { + state.cursor.select_right(value) } else { - state.cursor.move_left_by_words(value); + state.cursor.move_right(value); } - } else if modifiers.shift() { - state.cursor.select_left(value) - } else { - state.cursor.move_left(value); } - } - keyboard::KeyCode::Right => { - if platform::is_jump_modifier_pressed(modifiers) - && !is_secure - { + keyboard::KeyCode::Home => { if modifiers.shift() { - state.cursor.select_right_by_words(value); + state + .cursor + .select_range(state.cursor.start(value), 0); } else { - state.cursor.move_right_by_words(value); + state.cursor.move_to(0); } - } else if modifiers.shift() { - state.cursor.select_right(value) - } else { - state.cursor.move_right(value); - } - } - keyboard::KeyCode::Home => { - if modifiers.shift() { - state - .cursor - .select_range(state.cursor.start(value), 0); - } else { - state.cursor.move_to(0); } - } - keyboard::KeyCode::End => { - if modifiers.shift() { - state.cursor.select_range( - state.cursor.start(value), - value.len(), - ); - } else { - state.cursor.move_to(value.len()); + keyboard::KeyCode::End => { + if modifiers.shift() { + state.cursor.select_range( + state.cursor.start(value), + value.len(), + ); + } else { + state.cursor.move_to(value.len()); + } } - } - keyboard::KeyCode::C - if state.keyboard_modifiers.command() => - { - if let Some((start, end)) = - state.cursor.selection(value) + keyboard::KeyCode::C + if state.keyboard_modifiers.command() => { - clipboard - .write(value.select(start, end).to_string()); + if let Some((start, end)) = + state.cursor.selection(value) + { + clipboard.write( + value.select(start, end).to_string(), + ); + } } - } - keyboard::KeyCode::X - if state.keyboard_modifiers.command() => - { - if let Some((start, end)) = - state.cursor.selection(value) + keyboard::KeyCode::X + if state.keyboard_modifiers.command() => { - clipboard - .write(value.select(start, end).to_string()); - } - - let mut editor = Editor::new(value, &mut state.cursor); - editor.delete(); - - let message = (on_change)(editor.contents()); - shell.publish(message); - } - keyboard::KeyCode::V => { - if state.keyboard_modifiers.command() { - let content = match state.is_pasting.take() { - Some(content) => content, - None => { - let content: String = clipboard - .read() - .unwrap_or_default() - .chars() - .filter(|c| !c.is_control()) - .collect(); - - Value::new(&content) - } - }; + if let Some((start, end)) = + state.cursor.selection(value) + { + clipboard.write( + value.select(start, end).to_string(), + ); + } let mut editor = Editor::new(value, &mut state.cursor); + editor.delete(); - editor.paste(content.clone()); - - let message = if let Some(paste) = &on_paste { - (paste)(editor.contents()) - } else { - (on_change)(editor.contents()) - }; + let message = (on_change)(editor.contents()); shell.publish(message); - - state.is_pasting = Some(content); - } else { - state.is_pasting = None; } - } - keyboard::KeyCode::A - if state.keyboard_modifiers.command() => - { - state.cursor.select_all(value); - } - keyboard::KeyCode::Escape => { - state.is_focused = None; - state.is_dragging = false; - state.is_pasting = None; + keyboard::KeyCode::V => { + if state.keyboard_modifiers.command() { + let content = match state.is_pasting.take() { + Some(content) => content, + None => { + let content: String = clipboard + .read() + .unwrap_or_default() + .chars() + .filter(|c| !c.is_control()) + .collect(); + + Value::new(&content) + } + }; + + let mut editor = + Editor::new(value, &mut state.cursor); + + editor.paste(content.clone()); + + let message = if let Some(paste) = &on_paste { + (paste)(editor.contents()) + } else { + (on_change)(editor.contents()) + }; + shell.publish(message); + + state.is_pasting = Some(content); + } else { + state.is_pasting = None; + } + } + keyboard::KeyCode::A + if state.keyboard_modifiers.command() => + { + state.cursor.select_all(value); + } + keyboard::KeyCode::Escape => { + state.is_focused = None; + state.is_dragging = false; + state.is_pasting = None; - state.keyboard_modifiers = - keyboard::Modifiers::default(); - } - keyboard::KeyCode::Tab - | keyboard::KeyCode::Up - | keyboard::KeyCode::Down => { - return event::Status::Ignored; + state.keyboard_modifiers = + keyboard::Modifiers::default(); + } + keyboard::KeyCode::Tab + | keyboard::KeyCode::Up + | keyboard::KeyCode::Down => { + return event::Status::Ignored; + } + _ => {} } - _ => {} } return event::Status::Captured; @@ -900,6 +920,7 @@ pub fn draw( is_secure: bool, icon: Option<&Icon>, style: &::Style, + is_disabled: bool, ) where Renderer: text::Renderer, Renderer::Theme: StyleSheet, @@ -914,7 +935,9 @@ pub fn draw( let is_mouse_over = bounds.contains(cursor_position); - let appearance = if state.is_focused() { + let appearance = if is_disabled { + theme.disabled(style) + } else if state.is_focused() { theme.focused(style) } else if is_mouse_over { theme.hovered(style) @@ -968,7 +991,7 @@ pub fn draw( % 2 == 0; - let cursor = if is_cursor_visible { + let cursor = if is_cursor_visible && !is_disabled { Some(( renderer::Quad { bounds: Rectangle { @@ -1057,6 +1080,8 @@ pub fn draw( content: if text.is_empty() { placeholder } else { &text }, color: if text.is_empty() { theme.placeholder_color(style) + } else if is_disabled { + theme.disabled_color(style) } else { theme.value_color(style) }, -- cgit From e6a93e960c3ac71a74f11555fd2d225c185f6e8c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 12 Apr 2023 04:13:36 +0200 Subject: Rename `on_change` to `on_input` for `TextInput` --- native/src/widget/text_input.rs | 383 ++++++++++++++++++++-------------------- 1 file changed, 188 insertions(+), 195 deletions(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 65897a68..0cbc65db 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -47,7 +47,7 @@ pub use iced_style::text_input::{Appearance, StyleSheet}; /// "This is the placeholder...", /// value, /// ) -/// .on_change(|_| Message::TextInputChanged) +/// .on_input(Message::TextInputChanged) /// .padding(10); /// ``` /// ![Text input drawn by `iced_wgpu`](https://github.com/iced-rs/iced/blob/7760618fb112074bc40b148944521f312152012a/docs/images/text_input.png?raw=true) @@ -65,7 +65,7 @@ where width: Length, padding: Padding, size: Option, - on_change: Option Message + 'a>>, + on_input: Option Message + 'a>>, on_paste: Option Message + 'a>>, on_submit: Option, icon: Option>, @@ -93,7 +93,7 @@ where width: Length::Fill, padding: Padding::new(5.0), size: None, - on_change: None, + on_input: None, on_paste: None, on_submit: None, icon: None, @@ -113,6 +113,23 @@ where self } + /// Sets the callback which is called when the text gets changed + /// If not specified, the widget will be disabled + pub fn on_input(mut self, callback: F) -> Self + where + F: 'a + Fn(String) -> Message, + { + self.on_input = Some(Box::new(callback)); + self + } + + /// Sets the message that should be produced when the [`TextInput`] is + /// focused and the enter key is pressed. + pub fn on_submit(mut self, message: Message) -> Self { + self.on_submit = Some(message); + self + } + /// Sets the message that should be produced when some text is pasted into /// the [`TextInput`]. pub fn on_paste( @@ -155,13 +172,6 @@ where self } - /// Sets the message that should be produced when the [`TextInput`] is - /// focused and the enter key is pressed. - pub fn on_submit(mut self, message: Message) -> Self { - self.on_submit = Some(message); - self - } - /// Sets the style of the [`TextInput`]. pub fn style( mut self, @@ -171,16 +181,6 @@ where self } - /// Sets the callback which is called when the text gets changed - /// If not specified, the widget will be disabled - pub fn on_change(mut self, callback: F) -> Self - where - F: 'a + Fn(String) -> Message, - { - self.on_change = Some(Box::new(callback)); - self - } - /// Draws the [`TextInput`] with the given [`Renderer`], overriding its /// [`Value`] if provided. /// @@ -204,10 +204,10 @@ where &self.placeholder, self.size, &self.font, + self.on_input.is_none(), self.is_secure, self.icon.as_ref(), &self.style, - self.on_change.is_none(), ) } } @@ -284,7 +284,7 @@ where self.size, &self.font, self.is_secure, - self.on_change.as_deref(), + self.on_input.as_deref(), self.on_paste.as_deref(), &self.on_submit, || tree.state.downcast_mut::(), @@ -311,10 +311,10 @@ where &self.placeholder, self.size, &self.font, + self.on_input.is_none(), self.is_secure, self.icon.as_ref(), &self.style, - self.on_change.is_none(), ) } @@ -500,7 +500,7 @@ pub fn update<'a, Message, Renderer>( size: Option, font: &Renderer::Font, is_secure: bool, - on_change: Option<&dyn Fn(String) -> Message>, + on_input: Option<&dyn Fn(String) -> Message>, on_paste: Option<&dyn Fn(String) -> Message>, on_submit: &Option, state: impl FnOnce() -> &'a mut State, @@ -509,14 +509,12 @@ where Message: Clone, Renderer: text::Renderer, { - let is_disabled = on_change.is_none(); - match event { Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) | Event::Touch(touch::Event::FingerPressed { .. }) => { let state = state(); - let is_clicked = layout.bounds().contains(cursor_position); - let is_clicked = is_clicked && !is_disabled; + let is_clicked = + layout.bounds().contains(cursor_position) && on_input.is_some(); state.is_focused = if is_clicked { state.is_focused.or_else(|| { @@ -646,22 +644,22 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - if let Some(on_change) = on_change { - if state.is_pasting.is_none() - && !state.keyboard_modifiers.command() - && !c.is_control() - { - let mut editor = Editor::new(value, &mut state.cursor); + let Some(on_input) = on_input else { return event::Status::Ignored }; - editor.insert(c); + if state.is_pasting.is_none() + && !state.keyboard_modifiers.command() + && !c.is_control() + { + let mut editor = Editor::new(value, &mut state.cursor); - let message = (on_change)(editor.contents()); - shell.publish(message); + editor.insert(c); - focus.updated_at = Instant::now(); + let message = (on_input)(editor.contents()); + shell.publish(message); - return event::Status::Captured; - } + focus.updated_at = Instant::now(); + + return event::Status::Captured; } } } @@ -669,188 +667,183 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { - if let Some(on_change) = on_change { - let modifiers = state.keyboard_modifiers; - focus.updated_at = Instant::now(); + let Some(on_input) = on_input else { return event::Status::Ignored }; - match key_code { - keyboard::KeyCode::Enter - | keyboard::KeyCode::NumpadEnter => { - if let Some(on_submit) = on_submit.clone() { - shell.publish(on_submit); - } - } - keyboard::KeyCode::Backspace => { - if platform::is_jump_modifier_pressed(modifiers) - && state.cursor.selection(value).is_none() - { - if is_secure { - let cursor_pos = state.cursor.end(value); - state.cursor.select_range(0, cursor_pos); - } else { - state.cursor.select_left_by_words(value); - } - } - - let mut editor = - Editor::new(value, &mut state.cursor); - editor.backspace(); - - let message = (on_change)(editor.contents()); - shell.publish(message); - } - keyboard::KeyCode::Delete => { - if platform::is_jump_modifier_pressed(modifiers) - && state.cursor.selection(value).is_none() - { - if is_secure { - let cursor_pos = state.cursor.end(value); - state - .cursor - .select_range(cursor_pos, value.len()); - } else { - state.cursor.select_right_by_words(value); - } - } + let modifiers = state.keyboard_modifiers; + focus.updated_at = Instant::now(); - let mut editor = - Editor::new(value, &mut state.cursor); - editor.delete(); - - let message = (on_change)(editor.contents()); - shell.publish(message); + match key_code { + keyboard::KeyCode::Enter + | keyboard::KeyCode::NumpadEnter => { + if let Some(on_submit) = on_submit.clone() { + shell.publish(on_submit); } - keyboard::KeyCode::Left => { - if platform::is_jump_modifier_pressed(modifiers) - && !is_secure - { - if modifiers.shift() { - state.cursor.select_left_by_words(value); - } else { - state.cursor.move_left_by_words(value); - } - } else if modifiers.shift() { - state.cursor.select_left(value) + } + keyboard::KeyCode::Backspace => { + if platform::is_jump_modifier_pressed(modifiers) + && state.cursor.selection(value).is_none() + { + if is_secure { + let cursor_pos = state.cursor.end(value); + state.cursor.select_range(0, cursor_pos); } else { - state.cursor.move_left(value); + state.cursor.select_left_by_words(value); } } - keyboard::KeyCode::Right => { - if platform::is_jump_modifier_pressed(modifiers) - && !is_secure - { - if modifiers.shift() { - state.cursor.select_right_by_words(value); - } else { - state.cursor.move_right_by_words(value); - } - } else if modifiers.shift() { - state.cursor.select_right(value) + + let mut editor = Editor::new(value, &mut state.cursor); + editor.backspace(); + + let message = (on_input)(editor.contents()); + shell.publish(message); + } + keyboard::KeyCode::Delete => { + if platform::is_jump_modifier_pressed(modifiers) + && state.cursor.selection(value).is_none() + { + if is_secure { + let cursor_pos = state.cursor.end(value); + state + .cursor + .select_range(cursor_pos, value.len()); } else { - state.cursor.move_right(value); + state.cursor.select_right_by_words(value); } } - keyboard::KeyCode::Home => { + + let mut editor = Editor::new(value, &mut state.cursor); + editor.delete(); + + let message = (on_input)(editor.contents()); + shell.publish(message); + } + keyboard::KeyCode::Left => { + if platform::is_jump_modifier_pressed(modifiers) + && !is_secure + { if modifiers.shift() { - state - .cursor - .select_range(state.cursor.start(value), 0); + state.cursor.select_left_by_words(value); } else { - state.cursor.move_to(0); + state.cursor.move_left_by_words(value); } + } else if modifiers.shift() { + state.cursor.select_left(value) + } else { + state.cursor.move_left(value); } - keyboard::KeyCode::End => { + } + keyboard::KeyCode::Right => { + if platform::is_jump_modifier_pressed(modifiers) + && !is_secure + { if modifiers.shift() { - state.cursor.select_range( - state.cursor.start(value), - value.len(), - ); + state.cursor.select_right_by_words(value); } else { - state.cursor.move_to(value.len()); + state.cursor.move_right_by_words(value); } + } else if modifiers.shift() { + state.cursor.select_right(value) + } else { + state.cursor.move_right(value); } - keyboard::KeyCode::C - if state.keyboard_modifiers.command() => + } + keyboard::KeyCode::Home => { + if modifiers.shift() { + state + .cursor + .select_range(state.cursor.start(value), 0); + } else { + state.cursor.move_to(0); + } + } + keyboard::KeyCode::End => { + if modifiers.shift() { + state.cursor.select_range( + state.cursor.start(value), + value.len(), + ); + } else { + state.cursor.move_to(value.len()); + } + } + keyboard::KeyCode::C + if state.keyboard_modifiers.command() => + { + if let Some((start, end)) = + state.cursor.selection(value) { - if let Some((start, end)) = - state.cursor.selection(value) - { - clipboard.write( - value.select(start, end).to_string(), - ); - } + clipboard + .write(value.select(start, end).to_string()); } - keyboard::KeyCode::X - if state.keyboard_modifiers.command() => + } + keyboard::KeyCode::X + if state.keyboard_modifiers.command() => + { + if let Some((start, end)) = + state.cursor.selection(value) { - if let Some((start, end)) = - state.cursor.selection(value) - { - clipboard.write( - value.select(start, end).to_string(), - ); - } + clipboard + .write(value.select(start, end).to_string()); + } + + let mut editor = Editor::new(value, &mut state.cursor); + editor.delete(); + + let message = (on_input)(editor.contents()); + shell.publish(message); + } + keyboard::KeyCode::V => { + if state.keyboard_modifiers.command() { + let content = match state.is_pasting.take() { + Some(content) => content, + None => { + let content: String = clipboard + .read() + .unwrap_or_default() + .chars() + .filter(|c| !c.is_control()) + .collect(); + + Value::new(&content) + } + }; let mut editor = Editor::new(value, &mut state.cursor); - editor.delete(); - let message = (on_change)(editor.contents()); - shell.publish(message); - } - keyboard::KeyCode::V => { - if state.keyboard_modifiers.command() { - let content = match state.is_pasting.take() { - Some(content) => content, - None => { - let content: String = clipboard - .read() - .unwrap_or_default() - .chars() - .filter(|c| !c.is_control()) - .collect(); - - Value::new(&content) - } - }; - - let mut editor = - Editor::new(value, &mut state.cursor); - - editor.paste(content.clone()); - - let message = if let Some(paste) = &on_paste { - (paste)(editor.contents()) - } else { - (on_change)(editor.contents()) - }; - shell.publish(message); - - state.is_pasting = Some(content); + editor.paste(content.clone()); + + let message = if let Some(paste) = &on_paste { + (paste)(editor.contents()) } else { - state.is_pasting = None; - } - } - keyboard::KeyCode::A - if state.keyboard_modifiers.command() => - { - state.cursor.select_all(value); - } - keyboard::KeyCode::Escape => { - state.is_focused = None; - state.is_dragging = false; - state.is_pasting = None; + (on_input)(editor.contents()) + }; + shell.publish(message); - state.keyboard_modifiers = - keyboard::Modifiers::default(); - } - keyboard::KeyCode::Tab - | keyboard::KeyCode::Up - | keyboard::KeyCode::Down => { - return event::Status::Ignored; + state.is_pasting = Some(content); + } else { + state.is_pasting = None; } - _ => {} } + keyboard::KeyCode::A + if state.keyboard_modifiers.command() => + { + state.cursor.select_all(value); + } + keyboard::KeyCode::Escape => { + state.is_focused = None; + state.is_dragging = false; + state.is_pasting = None; + + state.keyboard_modifiers = + keyboard::Modifiers::default(); + } + keyboard::KeyCode::Tab + | keyboard::KeyCode::Up + | keyboard::KeyCode::Down => { + return event::Status::Ignored; + } + _ => {} } return event::Status::Captured; @@ -917,10 +910,10 @@ pub fn draw( placeholder: &str, size: Option, font: &Renderer::Font, + is_disabled: bool, is_secure: bool, icon: Option<&Icon>, style: &::Style, - is_disabled: bool, ) where Renderer: text::Renderer, Renderer::Theme: StyleSheet, -- cgit From 7e69cb4b18cde29eceb57e3712c0630d279e7984 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 12 Apr 2023 04:20:04 +0200 Subject: Unfocus `TextInput` if it becomes disabled --- native/src/widget/text_input.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 0cbc65db..4c10f5bb 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -227,6 +227,18 @@ where tree::State::new(State::new()) } + fn diff(&self, tree: &mut Tree) { + let state = tree.state.downcast_mut::(); + + // Unfocus text input if it becomes disabled + if self.on_input.is_none() { + state.last_click = None; + state.is_focused = None; + state.is_pasting = None; + state.is_dragging = false; + } + } + fn width(&self) -> Length { self.width } -- cgit From 70e4af46aaa9f0750bad2b8b6ed676dd841d6401 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 12 Apr 2023 04:21:58 +0200 Subject: Improve consistency of `on_input` documentation --- native/src/widget/text_input.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 4c10f5bb..63751b4d 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -113,8 +113,10 @@ where self } - /// Sets the callback which is called when the text gets changed - /// If not specified, the widget will be disabled + /// Sets the message that should be produced when some text is typed into + /// the [`TextInput`]. + /// + /// If this method is not called, the [`TextInput`] will be disabled. pub fn on_input(mut self, callback: F) -> Self where F: 'a + Fn(String) -> Message, -- cgit From 6b8548869ea25ad7bb7a49fad77adfa3b43cc87d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 12 Apr 2023 04:25:02 +0200 Subject: Remove unnecessary `is_disabled` check in `text_input::draw` A disabled `TextInput` cannot be focused. --- native/src/widget/text_input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index 63751b4d..d704692d 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -998,7 +998,7 @@ pub fn draw( % 2 == 0; - let cursor = if is_cursor_visible && !is_disabled { + let cursor = if is_cursor_visible { Some(( renderer::Quad { bounds: Rectangle { -- cgit From 7e7e66586d990788ffd77b17e98357e74252f497 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 12 Apr 2023 04:37:39 +0200 Subject: Show `NotAllowed` as mouse icon when hovering a disabled `TextInput` --- native/src/widget/text_input.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'native') diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs index d704692d..8627aa98 100644 --- a/native/src/widget/text_input.rs +++ b/native/src/widget/text_input.rs @@ -340,7 +340,7 @@ where _viewport: &Rectangle, _renderer: &Renderer, ) -> mouse::Interaction { - mouse_interaction(layout, cursor_position) + mouse_interaction(layout, cursor_position, self.on_input.is_none()) } } @@ -1117,9 +1117,14 @@ pub fn draw( pub fn mouse_interaction( layout: Layout<'_>, cursor_position: Point, + is_disabled: bool, ) -> mouse::Interaction { if layout.bounds().contains(cursor_position) { - mouse::Interaction::Text + if is_disabled { + mouse::Interaction::NotAllowed + } else { + mouse::Interaction::Text + } } else { mouse::Interaction::default() } -- cgit