From 6222e031b580be49b61ee499a50cb9da8f179734 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sun, 30 Jun 2024 14:34:36 +0200 Subject: [PATCH] The default parser for `DragValue` and `Slider` now ignores whitespace (#4739) It's easy to include whitespace when copy-pasting values. Also, some formatters use half-spaces as thousands separators. --- crates/egui/src/widgets/drag_value.rs | 42 ++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/crates/egui/src/widgets/drag_value.rs b/crates/egui/src/widgets/drag_value.rs index e46a454f..509dc5f9 100644 --- a/crates/egui/src/widgets/drag_value.rs +++ b/crates/egui/src/widgets/drag_value.rs @@ -491,10 +491,7 @@ impl<'a> Widget for DragValue<'a> { if let Some(value_text) = value_text { // We were editing the value as text last frame, but lost focus. // Make sure we applied the last text value: - let parsed_value = match &custom_parser { - Some(parser) => parser(&value_text), - None => value_text.parse().ok(), - }; + let parsed_value = parse(&custom_parser, &value_text); if let Some(mut parsed_value) = parsed_value { if clamp_to_range { parsed_value = clamp_value_to_range(parsed_value, range.clone()); @@ -530,10 +527,7 @@ impl<'a> Widget for DragValue<'a> { response.lost_focus() && !ui.input(|i| i.key_pressed(Key::Escape)) }; if update { - let parsed_value = match &custom_parser { - Some(parser) => parser(&value_text), - None => value_text.parse().ok(), - }; + let parsed_value = parse(&custom_parser, &value_text); if let Some(mut parsed_value) = parsed_value { if clamp_to_range { parsed_value = clamp_value_to_range(parsed_value, range.clone()); @@ -675,6 +669,19 @@ impl<'a> Widget for DragValue<'a> { } } +fn parse(custom_parser: &Option>, value_text: &str) -> Option { + match &custom_parser { + Some(parser) => parser(value_text), + None => default_parser(value_text), + } +} + +fn default_parser(value_text: &str) -> Option { + // Ignore whitespace (trailing, leading, and thousands separators): + let value_text: String = value_text.chars().filter(|c| !c.is_whitespace()).collect(); + value_text.parse().ok() +} + fn clamp_value_to_range(x: f64, range: RangeInclusive) -> f64 { let (mut min, mut max) = (*range.start(), *range.end()); @@ -719,4 +726,23 @@ mod tests { total_assert_eq!(5.0_f64, clamp_value_to_range(15.0, 5.0..=1.0)); total_assert_eq!(1.0_f64, clamp_value_to_range(-5.0, 5.0..=1.0)); } + + #[test] + fn test_default_parser() { + assert_eq!(super::default_parser("123"), Some(123.0)); + + assert_eq!(super::default_parser("1.23"), Some(1.230)); + + assert_eq!( + super::default_parser(" 1.23 "), + Some(1.230), + "We should handle leading and trailing spaces" + ); + + assert_eq!( + super::default_parser("1 234 567"), + Some(1_234_567.0), + "We should handle thousands separators using half-space" + ); + } }