From 362dc2631f04e5ed194faf15b71b5579831c864e Mon Sep 17 00:00:00 2001 From: Piotr <114903054+elevenhsoft@users.noreply.github.com> Date: Fri, 17 May 2024 00:07:44 +0200 Subject: [PATCH 1/5] feat: add validate_input widget --- src/widget/text_input/input.rs | 37 +++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index 0ddbd567..596051be 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -160,6 +160,20 @@ where .padding([spacing, spacing, spacing, spacing]) } +/// Creates a new validate input [`TextInput`]. +/// +/// [`TextInput`]: widget::TextInput +pub fn validate_input<'a, Message>( + placeholder: impl Into>, + value: impl Into>, + validate_condition: bool, +) -> TextInput<'a, Message> +where + Message: Clone + 'static, +{ + TextInput::new(placeholder, value).validation_condition(validate_condition) +} + #[cfg(feature = "wayland")] pub(crate) const SUPPORTED_TEXT_MIME_TYPES: &[&str; 6] = &[ "text/plain;charset=utf-8", @@ -185,6 +199,7 @@ pub struct TextInput<'a, Message> { is_secure: bool, is_editable: bool, is_read_only: bool, + is_validated: Option, font: Option<::Font>, width: Length, padding: Padding, @@ -228,6 +243,7 @@ where is_secure: false, is_editable: false, is_read_only: false, + is_validated: None, font: None, width: Length::Fill, padding: [spacing, spacing, spacing, spacing].into(), @@ -298,6 +314,11 @@ where self } + fn validation_condition(mut self, validation_condition: bool) -> Self { + self.is_validated = Some(validation_condition); + self + } + /// Sets the message that should be produced when some text is typed into /// the [`TextInput`]. /// @@ -415,6 +436,7 @@ where self.font, self.on_input.is_none(), self.is_secure, + self.is_validated, self.leading_icon.as_ref(), self.trailing_icon.as_ref(), &self.style, @@ -804,6 +826,7 @@ where self.font, self.on_input.is_none(), self.is_secure, + self.is_validated, self.leading_icon.as_ref(), self.trailing_icon.as_ref(), &self.style, @@ -1959,6 +1982,7 @@ pub fn draw<'a, Message>( font: Option<::Font>, is_disabled: bool, is_secure: bool, + is_validated: Option, icon: Option<&Element<'a, Message, crate::Theme, crate::Renderer>>, trailing_icon: Option<&Element<'a, Message, crate::Theme, crate::Renderer>>, style: &::Style, @@ -2020,6 +2044,7 @@ pub fn draw<'a, Message>( let mut icon_color = appearance.icon_color.unwrap_or(renderer_style.icon_color); let mut text_color = appearance.text_color.unwrap_or(renderer_style.text_color); + let mut border_color = appearance.border_color; // TODO: iced will not render alpha itself on text or icon colors. if is_disabled { @@ -2028,6 +2053,16 @@ pub fn draw<'a, Message>( text_color = text_color.blend_alpha(background, 0.5); } + if is_validated.is_some() { + if !is_validated.unwrap() { + border_color = Color::from_rgb( + 0.95, + 0.30, + 0.30 + ); + } + } + // draw background and its border if let Some(border_offset) = appearance.border_offset { let offset_bounds = Rectangle { @@ -2056,7 +2091,7 @@ pub fn draw<'a, Message>( bounds: offset_bounds, border: Border { width: appearance.border_width, - color: appearance.border_color, + color: border_color, radius: appearance.border_radius, }, shadow: Shadow { From f76ae9b019dffa65b1dba052466d1fad39306fcd Mon Sep 17 00:00:00 2001 From: Piotr <114903054+elevenhsoft@users.noreply.github.com> Date: Fri, 17 May 2024 00:08:03 +0200 Subject: [PATCH 2/5] add input_validation example --- examples/input_validation/Cargo.toml | 8 +++ examples/input_validation/src/main.rs | 83 +++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 examples/input_validation/Cargo.toml create mode 100644 examples/input_validation/src/main.rs diff --git a/examples/input_validation/Cargo.toml b/examples/input_validation/Cargo.toml new file mode 100644 index 00000000..732bfe32 --- /dev/null +++ b/examples/input_validation/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "input_validation" +version = "0.1.0" +edition = "2021" + +[dependencies] +libcosmic = { path = "../..", features = ["wayland", "wgpu"] } +regex = "1.10.4" diff --git a/examples/input_validation/src/main.rs b/examples/input_validation/src/main.rs new file mode 100644 index 00000000..d98db1a7 --- /dev/null +++ b/examples/input_validation/src/main.rs @@ -0,0 +1,83 @@ +use cosmic::app::{Application, Command, Core, Settings}; +use cosmic::iced; +use cosmic::iced::executor; +use cosmic::iced_core::Size; +use cosmic::widget::{column, text_input, validate_input}; +use cosmic::Element; +use regex::Regex; + +#[derive(Debug, Clone)] +pub enum Message { + InputName(String), + InputEmail(String), +} + +struct Window { + core: Core, + name: String, + email: String, +} + +impl Application for Window { + type Executor = executor::Default; + type Flags = (); + type Message = Message; + const APP_ID: &'static str = "com.system76.InputValidation"; + + fn core(&self) -> &Core { + &self.core + } + + fn core_mut(&mut self) -> &mut Core { + &mut self.core + } + + fn init(core: Core, _flags: Self::Flags) -> (Self, Command) { + ( + Self { + core, + name: String::new(), + email: String::new(), + }, + Command::none(), + ) + } + + fn update( + &mut self, + message: Self::Message, + ) -> iced::Command> { + match message { + Message::InputName(name) => self.name = name, + Message::InputEmail(email) => self.email = email, + } + Command::none() + } + + fn view(&self) -> Element { + let emailregex = Regex::new(r#"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"#).unwrap(); + let validation_condition = emailregex.is_match(&self.email); + + let name_input = text_input("Name", &self.name).on_input(Message::InputName); + let email_input = validate_input("E-mail", &self.email, validation_condition) + .on_input(Message::InputEmail); + + column() + .push(name_input) + .push(email_input) + .spacing(10) + .into() + } +} + +fn main() -> std::io::Result<()> { + let mut settings = Settings::default(); + settings = settings.size(Size { + width: 480., + height: 480., + }); + + let _ = cosmic::app::run::(settings, ()); + + Ok(()) +} From 624989d0390f7328d4fb5e075c17e3342be6897d Mon Sep 17 00:00:00 2001 From: Piotr <114903054+elevenhsoft@users.noreply.github.com> Date: Fri, 17 May 2024 00:17:44 +0200 Subject: [PATCH 3/5] run cargo fmt --- src/widget/text_input/input.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index 596051be..738d0fa3 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -2055,11 +2055,7 @@ pub fn draw<'a, Message>( if is_validated.is_some() { if !is_validated.unwrap() { - border_color = Color::from_rgb( - 0.95, - 0.30, - 0.30 - ); + border_color = Color::from_rgb(0.95, 0.30, 0.30); } } From ad8f1a43cc14f5ae627ddab3acdc1099d9c8b190 Mon Sep 17 00:00:00 2001 From: Piotr <114903054+elevenhsoft@users.noreply.github.com> Date: Fri, 17 May 2024 00:55:53 +0200 Subject: [PATCH 4/5] remove validate_input widget --- examples/input_validation/src/main.rs | 11 ++++------- src/widget/text_input/input.rs | 21 ++++----------------- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/examples/input_validation/src/main.rs b/examples/input_validation/src/main.rs index d98db1a7..aaba2b8c 100644 --- a/examples/input_validation/src/main.rs +++ b/examples/input_validation/src/main.rs @@ -1,8 +1,7 @@ use cosmic::app::{Application, Command, Core, Settings}; -use cosmic::iced; use cosmic::iced::executor; use cosmic::iced_core::Size; -use cosmic::widget::{column, text_input, validate_input}; +use cosmic::widget::{column, text_input}; use cosmic::Element; use regex::Regex; @@ -43,10 +42,7 @@ impl Application for Window { ) } - fn update( - &mut self, - message: Self::Message, - ) -> iced::Command> { + fn update(&mut self, message: Self::Message) -> Command { match message { Message::InputName(name) => self.name = name, Message::InputEmail(email) => self.email = email, @@ -59,7 +55,8 @@ impl Application for Window { let validation_condition = emailregex.is_match(&self.email); let name_input = text_input("Name", &self.name).on_input(Message::InputName); - let email_input = validate_input("E-mail", &self.email, validation_condition) + let email_input = text_input("E-mail", &self.email) + .validation_condition(validation_condition) .on_input(Message::InputEmail); column() diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index 738d0fa3..a703dcb3 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -160,20 +160,6 @@ where .padding([spacing, spacing, spacing, spacing]) } -/// Creates a new validate input [`TextInput`]. -/// -/// [`TextInput`]: widget::TextInput -pub fn validate_input<'a, Message>( - placeholder: impl Into>, - value: impl Into>, - validate_condition: bool, -) -> TextInput<'a, Message> -where - Message: Clone + 'static, -{ - TextInput::new(placeholder, value).validation_condition(validate_condition) -} - #[cfg(feature = "wayland")] pub(crate) const SUPPORTED_TEXT_MIME_TYPES: &[&str; 6] = &[ "text/plain;charset=utf-8", @@ -314,7 +300,7 @@ where self } - fn validation_condition(mut self, validation_condition: bool) -> Self { + pub fn validation_condition(mut self, validation_condition: bool) -> Self { self.is_validated = Some(validation_condition); self } @@ -2054,8 +2040,9 @@ pub fn draw<'a, Message>( } if is_validated.is_some() { - if !is_validated.unwrap() { - border_color = Color::from_rgb(0.95, 0.30, 0.30); + if !is_validated.unwrap_or_default() { + border_color = + Color::from(palette::Srgb::new(0.890, 0.145, 0.420)); } } From 1acbd81c0030eeb1f8b3cfefec56f0fcebfc67e1 Mon Sep 17 00:00:00 2001 From: Piotr <114903054+elevenhsoft@users.noreply.github.com> Date: Fri, 17 May 2024 00:57:29 +0200 Subject: [PATCH 5/5] run cargo fmt --- src/widget/text_input/input.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widget/text_input/input.rs b/src/widget/text_input/input.rs index a703dcb3..a46a86a2 100644 --- a/src/widget/text_input/input.rs +++ b/src/widget/text_input/input.rs @@ -2041,8 +2041,7 @@ pub fn draw<'a, Message>( if is_validated.is_some() { if !is_validated.unwrap_or_default() { - border_color = - Color::from(palette::Srgb::new(0.890, 0.145, 0.420)); + border_color = Color::from(palette::Srgb::new(0.890, 0.145, 0.420)); } }