diff options
author | 2023-03-03 10:01:49 +0300 | |
---|---|---|
committer | 2023-04-12 03:55:18 +0200 | |
commit | f10e936f00d4b83dcacfdebd2727b1a5cd1add95 (patch) | |
tree | 09f0b4bbfa6446003adebc19c79a1368a89eec6c | |
parent | ca828f03f5aab9efacc9d63d4149363333035a0c (diff) | |
download | iced-f10e936f00d4b83dcacfdebd2727b1a5cd1add95.tar.gz iced-f10e936f00d4b83dcacfdebd2727b1a5cd1add95.tar.bz2 iced-f10e936f00d4b83dcacfdebd2727b1a5cd1add95.zip |
Introduce disabled state for `TextInput`
-rw-r--r-- | examples/component/src/main.rs | 2 | ||||
-rw-r--r-- | examples/integration_wgpu/src/controls.rs | 9 | ||||
-rw-r--r-- | examples/lazy/src/main.rs | 9 | ||||
-rw-r--r-- | examples/modal/src/main.rs | 14 | ||||
-rw-r--r-- | examples/qr_code/src/main.rs | 12 | ||||
-rw-r--r-- | examples/styling/src/main.rs | 11 | ||||
-rw-r--r-- | examples/text_input/Cargo.toml | 11 | ||||
-rw-r--r-- | examples/text_input/README.md | 15 | ||||
-rw-r--r-- | examples/text_input/src/main.rs | 94 | ||||
-rw-r--r-- | examples/toast/src/main.rs | 6 | ||||
-rw-r--r-- | examples/todos/src/main.rs | 29 | ||||
-rw-r--r-- | examples/tour/src/main.rs | 11 | ||||
-rw-r--r-- | examples/websocket/src/main.rs | 9 | ||||
-rw-r--r-- | native/src/widget/helpers.rs | 3 | ||||
-rw-r--r-- | native/src/widget/text_input.rs | 365 | ||||
-rw-r--r-- | style/src/text_input.rs | 6 | ||||
-rw-r--r-- | style/src/theme.rs | 26 |
17 files changed, 394 insertions, 238 deletions
diff --git a/examples/component/src/main.rs b/examples/component/src/main.rs index bbf549e7..8be3f076 100644 --- a/examples/component/src/main.rs +++ b/examples/component/src/main.rs @@ -141,8 +141,8 @@ mod numeric_input { .map(u32::to_string) .as_deref() .unwrap_or(""), - Event::InputChanged, ) + .on_change(Event::InputChanged) .padding(10), button("+", Event::IncrementPressed), ] diff --git a/examples/integration_wgpu/src/controls.rs b/examples/integration_wgpu/src/controls.rs index 533cb6e2..8c42513f 100644 --- a/examples/integration_wgpu/src/controls.rs +++ b/examples/integration_wgpu/src/controls.rs @@ -100,11 +100,10 @@ impl Program for Controls { .size(14) .style(Color::WHITE), ) - .push(text_input( - "Placeholder", - text, - Message::TextChanged, - )), + .push( + text_input("Placeholder", text) + .on_change(Message::TextChanged), + ), ), ) .into() diff --git a/examples/lazy/src/main.rs b/examples/lazy/src/main.rs index 6512106f..6b6dca26 100644 --- a/examples/lazy/src/main.rs +++ b/examples/lazy/src/main.rs @@ -214,12 +214,9 @@ impl Sandbox for App { column![ scrollable(options).height(Length::Fill), row![ - text_input( - "Add a new option", - &self.input, - Message::InputChanged, - ) - .on_submit(Message::AddItem(self.input.clone())), + text_input("Add a new option", &self.input) + .on_change(Message::InputChanged) + .on_submit(Message::AddItem(self.input.clone())), button(text(format!("Toggle Order ({})", self.order))) .on_press(Message::ToggleOrder) ] diff --git a/examples/modal/src/main.rs b/examples/modal/src/main.rs index 54555684..1377f054 100644 --- a/examples/modal/src/main.rs +++ b/examples/modal/src/main.rs @@ -133,18 +133,16 @@ impl Application for App { column![ column![ text("Email").size(12), - text_input( - "abc@123.com", - &self.email, - Message::Email - ) - .on_submit(Message::Submit) - .padding(5), + text_input("abc@123.com", &self.email,) + .on_change(Message::Email) + .on_submit(Message::Submit) + .padding(5), ] .spacing(5), column![ text("Password").size(12), - text_input("", &self.password, Message::Password) + text_input("", &self.password) + .on_change(Message::Password) .on_submit(Message::Submit) .password() .padding(5), diff --git a/examples/qr_code/src/main.rs b/examples/qr_code/src/main.rs index d8041745..0486b068 100644 --- a/examples/qr_code/src/main.rs +++ b/examples/qr_code/src/main.rs @@ -49,13 +49,11 @@ impl Sandbox for QRGenerator { .size(70) .style(Color::from([0.5, 0.5, 0.5])); - let input = text_input( - "Type the data of your QR code here...", - &self.data, - Message::DataChanged, - ) - .size(30) - .padding(15); + let input = + text_input("Type the data of your QR code here...", &self.data) + .on_change(Message::DataChanged) + .size(30) + .padding(15); let mut content = column![title, input] .width(700) diff --git a/examples/styling/src/main.rs b/examples/styling/src/main.rs index 448c9792..58f983df 100644 --- a/examples/styling/src/main.rs +++ b/examples/styling/src/main.rs @@ -90,13 +90,10 @@ impl Sandbox for Styling { }, ); - let text_input = text_input( - "Type something...", - &self.input_value, - Message::InputChanged, - ) - .padding(10) - .size(20); + let text_input = text_input("Type something...", &self.input_value) + .on_change(Message::InputChanged) + .padding(10) + .size(20); let button = button("Submit") .padding(10) diff --git a/examples/text_input/Cargo.toml b/examples/text_input/Cargo.toml new file mode 100644 index 00000000..aead9896 --- /dev/null +++ b/examples/text_input/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "text_input" +authors = ["Dan Mishin <jungletryne@yandex.com>"] +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +iced = { path = "../..", features = ["tokio"] } +tokio = { version = "1.26.0", features = ["time"] } diff --git a/examples/text_input/README.md b/examples/text_input/README.md new file mode 100644 index 00000000..435989cc --- /dev/null +++ b/examples/text_input/README.md @@ -0,0 +1,15 @@ +# Text Input + +This example shows basic usage of text edit. +The button delays the change of the text field state to allow testing of the corner cases. + +<div align="center"> + <a href="https://gfycat.com/everycarelessisabellinewheatear"> + <img src="https://thumbs.gfycat.com/EveryCarelessIsabellinewheatear-max-1mb.gif" height="400px"> + </a> +</div> + +You can run it with cargo run: +```bash +cargo run --package text_input +```
\ No newline at end of file diff --git a/examples/text_input/src/main.rs b/examples/text_input/src/main.rs new file mode 100644 index 00000000..977b5099 --- /dev/null +++ b/examples/text_input/src/main.rs @@ -0,0 +1,94 @@ +use crate::Message::{StartTimer, TextEditModeChange}; +use iced::widget::{button, column, container, row, text, text_input}; +use iced::{ + executor, window, Application, Command, Element, Length, Renderer, + Settings, Theme, +}; +use tokio::time::{sleep, Duration}; + +fn main() -> iced::Result { + let settings = Settings { + window: window::Settings { + size: (700, 100), + ..window::Settings::default() + }, + ..Settings::default() + }; + + Example::run(settings) +} + +#[derive(Default)] +struct Example { + data: String, + text_edit_enabled: bool, +} + +#[derive(Debug, Clone)] +enum Message { + StartTimer, + TextEditModeChange, + TextInputChanged(String), +} + +impl Application for Example { + type Executor = executor::Default; + type Message = Message; + type Theme = Theme; + type Flags = (); + + fn new(_flags: Self::Flags) -> (Self, Command<Self::Message>) { + (Self::default(), Command::none()) + } + + fn title(&self) -> String { + "TextInput example".into() + } + + fn update(&mut self, message: Self::Message) -> Command<Self::Message> { + match message { + Message::TextEditModeChange => { + self.text_edit_enabled = !self.text_edit_enabled; + Command::none() + } + Message::TextInputChanged(updated_text) => { + self.data = updated_text; + Command::none() + } + StartTimer => { + let timer_f = async { + sleep(Duration::from_secs(3)).await; + }; + Command::perform(timer_f, |_| TextEditModeChange) + } + } + } + + fn view(&self) -> Element<'_, Self::Message, Renderer<Self::Theme>> { + let placeholder = if self.text_edit_enabled { + "Enabled TextEdit" + } else { + "Disabled TextEdit" + }; + + let mut txt_input = text_input(placeholder, &self.data); + + if self.text_edit_enabled { + txt_input = txt_input.on_change(Message::TextInputChanged); + } + + let btn = button("Enable/Disable").on_press(StartTimer); + let label = text( + "The mode will be changed after 3s when the button is pressed", + ); + + let content = row![txt_input, btn].spacing(10); + let content = column![content, label].spacing(10); + + container(content) + .width(Length::Shrink) + .height(Length::Shrink) + .padding(20) + .into() + } +} diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index e74b3ee6..765afb8f 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -119,13 +119,15 @@ impl Application for App { column![ subtitle( "Title", - text_input("", &self.editing.title, Message::Title) + text_input("", &self.editing.title) + .on_change(Message::Title) .on_submit(Message::Add) .into() ), subtitle( "Message", - text_input("", &self.editing.body, Message::Body) + text_input("", &self.editing.body) + .on_change(Message::Body) .on_submit(Message::Add) .into() ), diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 6361667e..a6670626 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -204,15 +204,12 @@ impl Application for Todos { .style(Color::from([0.5, 0.5, 0.5])) .horizontal_alignment(alignment::Horizontal::Center); - let input = text_input( - "What needs to be done?", - input_value, - Message::InputChanged, - ) - .id(INPUT_ID.clone()) - .padding(15) - .size(30) - .on_submit(Message::CreateTask); + let input = text_input("What needs to be done?", input_value) + .on_change(Message::InputChanged) + .id(INPUT_ID.clone()) + .padding(15) + .size(30) + .on_submit(Message::CreateTask); let controls = view_controls(tasks, *filter); let filtered_tasks = @@ -375,14 +372,12 @@ impl Task { .into() } TaskState::Editing => { - let text_input = text_input( - "Describe your task...", - &self.description, - TaskMessage::DescriptionEdited, - ) - .id(Self::text_input_id(i)) - .on_submit(TaskMessage::FinishEdition) - .padding(10); + let text_input = + text_input("Describe your task...", &self.description) + .id(Self::text_input_id(i)) + .on_change(TaskMessage::DescriptionEdited) + .on_submit(TaskMessage::FinishEdition) + .padding(10); row![ text_input, diff --git a/examples/tour/src/main.rs b/examples/tour/src/main.rs index 90868877..3b4cfd2d 100644 --- a/examples/tour/src/main.rs +++ b/examples/tour/src/main.rs @@ -570,13 +570,10 @@ impl<'a> Step { bytes: include_bytes!("../fonts/icons.ttf"), }; - let mut text_input = text_input( - "Type something to continue...", - value, - StepMessage::InputChanged, - ) - .padding(10) - .size(30); + let mut text_input = text_input("Type something to continue...", value) + .on_change(StepMessage::InputChanged) + .padding(10) + .size(30); if is_showing_icon { text_input = text_input.icon(text_input::Icon { diff --git a/examples/websocket/src/main.rs b/examples/websocket/src/main.rs index e617b8ce..1fda7f18 100644 --- a/examples/websocket/src/main.rs +++ b/examples/websocket/src/main.rs @@ -125,12 +125,9 @@ impl Application for WebSocket { }; let new_message_input = { - let mut input = text_input( - "Type a message...", - &self.new_message, - Message::NewMessageChanged, - ) - .padding(10); + let mut input = text_input("Type a message...", &self.new_message) + .on_change(Message::NewMessageChanged) + .padding(10); let mut button = button( text("Send") 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); /// ``` ///  @@ -65,7 +65,7 @@ where width: Length, padding: Padding, size: Option<f32>, - on_change: Box<dyn Fn(String) -> Message + 'a>, + on_change: 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_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<F>(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::<State>(), @@ -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<f32>, 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<Message>, 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<Renderer>( is_secure: bool, icon: Option<&Icon<Renderer::Font>>, style: &<Renderer::Theme as StyleSheet>::Style, + is_disabled: bool, ) where Renderer: text::Renderer, Renderer::Theme: StyleSheet, @@ -914,7 +935,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) @@ -968,7 +991,7 @@ pub fn draw<Renderer>( % 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<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) }, diff --git a/style/src/text_input.rs b/style/src/text_input.rs index 73b05852..2616ad5a 100644 --- a/style/src/text_input.rs +++ b/style/src/text_input.rs @@ -33,6 +33,9 @@ pub trait StyleSheet { /// Produces the [`Color`] of the value of a text input. fn value_color(&self, style: &Self::Style) -> Color; + /// Produces the [`Color`] of the value of a disabled text input. + fn disabled_color(&self, style: &Self::Style) -> Color; + /// Produces the [`Color`] of the selection of a text input. fn selection_color(&self, style: &Self::Style) -> Color; @@ -40,4 +43,7 @@ pub trait StyleSheet { fn hovered(&self, style: &Self::Style) -> Appearance { self.focused(style) } + + /// Produces the style of a disabled text input. + fn disabled(&self, style: &Self::Style) -> Appearance; } diff --git a/style/src/theme.rs b/style/src/theme.rs index 0d974a19..e13edb05 100644 --- a/style/src/theme.rs +++ b/style/src/theme.rs @@ -1093,4 +1093,30 @@ impl text_input::StyleSheet for Theme { palette.primary.weak.color } + + fn disabled(&self, style: &Self::Style) -> text_input::Appearance { + if let TextInput::Custom(custom) = style { + return custom.disabled(self); + } + + let palette = self.extended_palette(); + + text_input::Appearance { + background: palette.background.base.color.into(), + border_radius: 2.0, + border_width: 1.0, + border_color: palette.background.weak.color, + icon_color: palette.background.weak.color, + } + } + + fn disabled_color(&self, style: &Self::Style) -> Color { + if let TextInput::Custom(custom) = style { + return custom.value_color(self); + } + + let palette = self.extended_palette(); + + palette.secondary.strong.color + } } |