diff options
author | 2023-04-12 04:51:19 +0200 | |
---|---|---|
committer | 2023-04-12 04:51:19 +0200 | |
commit | ce8e92ca7a4ed0f4fe284c9042f863f7c83ba03a (patch) | |
tree | f9be0c6e0d8f9e2af6170f4370677918c4b43a2a /native/src | |
parent | ca828f03f5aab9efacc9d63d4149363333035a0c (diff) | |
parent | 7e7e66586d990788ffd77b17e98357e74252f497 (diff) | |
download | iced-ce8e92ca7a4ed0f4fe284c9042f863f7c83ba03a.tar.gz iced-ce8e92ca7a4ed0f4fe284c9042f863f7c83ba03a.tar.bz2 iced-ce8e92ca7a4ed0f4fe284c9042f863f7c83ba03a.zip |
Merge pull request #1744 from JungleTryne/disable-text-input
Add functionality to make `TextInput` disabled
Diffstat (limited to 'native/src')
-rw-r--r-- | native/src/widget/helpers.rs | 3 | ||||
-rw-r--r-- | native/src/widget/text_input.rs | 91 |
2 files changed, 65 insertions, 29 deletions
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..8627aa98 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_input(Message::TextInputChanged) /// .padding(10); /// ``` ///  @@ -65,7 +65,7 @@ where width: Length, padding: Padding, size: Option<f32>, - on_change: Box<dyn Fn(String) -> Message + 'a>, + on_input: Option<Box<dyn Fn(String) -> Message + 'a>>, on_paste: Option<Box<dyn Fn(String) -> Message + 'a>>, on_submit: Option<Message>, icon: Option<Icon<Renderer::Font>>, @@ -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<F>(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_input: None, on_paste: None, on_submit: None, icon: None, @@ -117,6 +113,25 @@ where self } + /// 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<F>(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( @@ -159,13 +174,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, @@ -198,6 +206,7 @@ where &self.placeholder, self.size, &self.font, + self.on_input.is_none(), self.is_secure, self.icon.as_ref(), &self.style, @@ -220,6 +229,18 @@ where tree::State::new(State::new()) } + fn diff(&self, tree: &mut Tree) { + let state = tree.state.downcast_mut::<State>(); + + // 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 } @@ -277,7 +298,7 @@ where self.size, &self.font, self.is_secure, - self.on_change.as_ref(), + self.on_input.as_deref(), self.on_paste.as_deref(), &self.on_submit, || tree.state.downcast_mut::<State>(), @@ -304,6 +325,7 @@ where &self.placeholder, self.size, &self.font, + self.on_input.is_none(), self.is_secure, self.icon.as_ref(), &self.style, @@ -318,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()) } } @@ -492,7 +514,7 @@ pub fn update<'a, Message, Renderer>( size: Option<f32>, font: &Renderer::Font, is_secure: bool, - on_change: &dyn Fn(String) -> Message, + on_input: Option<&dyn Fn(String) -> Message>, on_paste: Option<&dyn Fn(String) -> Message>, on_submit: &Option<Message>, state: impl FnOnce() -> &'a mut State, @@ -505,7 +527,8 @@ where 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 = + layout.bounds().contains(cursor_position) && on_input.is_some(); state.is_focused = if is_clicked { state.is_focused.or_else(|| { @@ -635,6 +658,8 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { + let Some(on_input) = on_input else { return event::Status::Ignored }; + if state.is_pasting.is_none() && !state.keyboard_modifiers.command() && !c.is_control() @@ -643,7 +668,7 @@ where editor.insert(c); - let message = (on_change)(editor.contents()); + let message = (on_input)(editor.contents()); shell.publish(message); focus.updated_at = Instant::now(); @@ -656,6 +681,8 @@ where let state = state(); if let Some(focus) = &mut state.is_focused { + let Some(on_input) = on_input else { return event::Status::Ignored }; + let modifiers = state.keyboard_modifiers; focus.updated_at = Instant::now(); @@ -681,7 +708,7 @@ where let mut editor = Editor::new(value, &mut state.cursor); editor.backspace(); - let message = (on_change)(editor.contents()); + let message = (on_input)(editor.contents()); shell.publish(message); } keyboard::KeyCode::Delete => { @@ -701,7 +728,7 @@ where let mut editor = Editor::new(value, &mut state.cursor); editor.delete(); - let message = (on_change)(editor.contents()); + let message = (on_input)(editor.contents()); shell.publish(message); } keyboard::KeyCode::Left => { @@ -776,7 +803,7 @@ where let mut editor = Editor::new(value, &mut state.cursor); editor.delete(); - let message = (on_change)(editor.contents()); + let message = (on_input)(editor.contents()); shell.publish(message); } keyboard::KeyCode::V => { @@ -803,7 +830,7 @@ where let message = if let Some(paste) = &on_paste { (paste)(editor.contents()) } else { - (on_change)(editor.contents()) + (on_input)(editor.contents()) }; shell.publish(message); @@ -897,6 +924,7 @@ pub fn draw<Renderer>( placeholder: &str, size: Option<f32>, font: &Renderer::Font, + is_disabled: bool, is_secure: bool, icon: Option<&Icon<Renderer::Font>>, style: &<Renderer::Theme as StyleSheet>::Style, @@ -914,7 +942,9 @@ pub fn draw<Renderer>( 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) @@ -1057,6 +1087,8 @@ pub fn draw<Renderer>( 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) }, @@ -1085,9 +1117,14 @@ pub fn draw<Renderer>( 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() } |