diff --git a/crates/ui-egui/src/widgets.rs b/crates/ui-egui/src/widgets.rs index c74a78a0f..4c5891c1a 100644 --- a/crates/ui-egui/src/widgets.rs +++ b/crates/ui-egui/src/widgets.rs @@ -486,6 +486,20 @@ mod field_number_tests { assert_eq!(field_number("45*2°", "°", false), Some(90.0)); assert_eq!(field_number("50% / 2", "%", false), Some(25.0)); } + + /// A thousands comma is refused inside Kerning's pair of parentheses and before `%` or the + /// suffix, as it is in plain text, rather than read as a decimal comma (`(1,000)` as 1). + #[test] + fn a_thousands_comma_is_refused_inside_parentheses_and_before_a_suffix() { + for text in ["(1,000)", " (-1,000) ", "(12,500)"] { + assert_eq!(field_number(text, "", true), None, "{text}"); + } + assert_eq!(field_number("1,000%", "%", false), None); + assert_eq!(field_number("1,000°", "°", false), None); + assert_eq!(field_number("(1,5)", "", true), Some(1.5)); + assert_eq!(field_number("(0,125)", "", true), Some(0.125)); + assert_eq!(field_number("12,5%", "%", false), Some(12.5)); + } } #[cfg(test)] diff --git a/crates/ui-egui/src/widgets/look_tests.rs b/crates/ui-egui/src/widgets/look_tests.rs index 1f9275008..582833127 100644 --- a/crates/ui-egui/src/widgets/look_tests.rs +++ b/crates/ui-egui/src/widgets/look_tests.rs @@ -494,5 +494,7 @@ fn kerning_reads_parentheses_around_its_text_with_a_manual_value_too() { for automatic in [false, true] { assert_eq!(typed(automatic, "(10+5)"), Some(SpinPick::Value(15.0)), "automatic: {automatic}"); assert_eq!(typed(automatic, "(10+5)*2"), None, "automatic: {automatic}"); + assert_eq!(typed(automatic, "(1,000)"), None, "a thousands comma, automatic: {automatic}"); + assert_eq!(typed(automatic, "(1,5)"), Some(SpinPick::Value(1.5)), "a decimal comma, automatic: {automatic}"); } } diff --git a/crates/ui-egui/src/widgets/numeric.rs b/crates/ui-egui/src/widgets/numeric.rs index 847b3b0ea..a1a0433ae 100644 --- a/crates/ui-egui/src/widgets/numeric.rs +++ b/crates/ui-egui/src/widgets/numeric.rs @@ -511,15 +511,15 @@ fn bounded_field_reading( /// may follow any operand: `45*2°`, `50% / 2`. With `parentheses` (Kerning, which shows its /// automatic value as `(12)`), one pair of parentheses around the whole text is dropped first, so /// `(12)` reads as 12. Any other parentheses are refused: `(10+5)*2` reads as nothing, not as -/// `10+5*2`. +/// `10+5*2`. A decimal comma is read ([`decimal_point`]) after the suffix, `%`, `°` and that pair +/// are dropped, so `(1,000)` and `1,000%` are refused as thousands rather than read as 1. pub(super) fn field_number(buf: &str, suffix: &str, parentheses: bool) -> Option { let suffix = suffix.trim(); - let buf = decimal_point(buf); let bare = if suffix.is_empty() { buf.to_string() } else { buf.replace(suffix, "") }; let bare = bare.replace(['%', '°'], ""); let bare = bare.trim(); let bare = if parentheses { bare.strip_prefix('(').and_then(|b| b.strip_suffix(')')).unwrap_or(bare) } else { bare }; - vectorcraft_doc::parse_number(bare) + vectorcraft_doc::parse_number(&decimal_point(bare)) } /// The text [`plain_field`] shows for `value`: at most `decimals` places, without trailing zeros,