diff --git a/AUTHORS b/AUTHORS index a748c7fe56..dfa6b9f233 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,3 +20,4 @@ Marcin ZajÄ…c Laura Gallo Tim Murison Manmeet Singh +Simon Fell diff --git a/CHANGELOG.md b/CHANGELOG.md index e4bb6d9c77..e6f8b2d9b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ You can find its changes [documented below](#070---2021-01-01). - `ClipBox` and `Tabs` handle SCROLL_TO_VIEW ([#2141] by [@xarvic]) - `EventCtx::submit_notification_without_warning` ([#2141] by [@xarvic]) - `WidgetPod::requested_layout` ([#2145] by [@xarvic]) +- Make `Parse` work better with floats and similar types ([#2148] by [@superfell]) ### Changed @@ -546,6 +547,7 @@ Last release without a changelog :( [@zedseven]: https://github.com/zedseven [@Pavel-N]: https://github.com/Pavel-N [@maurerdietmar]: https://github.com/maurerdietmar +[@superfell]: https://github.com/superfell [#599]: https://github.com/linebender/druid/pull/599 [#611]: https://github.com/linebender/druid/pull/611 @@ -834,6 +836,7 @@ Last release without a changelog :( [#2117]: https://github.com/linebender/druid/pull/2117 [#2117]: https://github.com/linebender/druid/pull/2141 [#2145]: https://github.com/linebender/druid/pull/2145 +[#2148]: https://github.com/linebender/druid/pull/2148 [Unreleased]: https://github.com/linebender/druid/compare/v0.7.0...master [0.7.0]: https://github.com/linebender/druid/compare/v0.6.0...v0.7.0 diff --git a/druid/src/widget/parse.rs b/druid/src/widget/parse.rs index 41c75a4abf..8be108755c 100644 --- a/druid/src/widget/parse.rs +++ b/druid/src/widget/parse.rs @@ -64,9 +64,27 @@ impl> Widget> for Parse fn update(&mut self, ctx: &mut UpdateCtx, _old_data: &Option, data: &Option, env: &Env) { let old = match *data { None => return, // Don't clobber the input - Some(ref x) => mem::replace(&mut self.state, x.to_string()), + Some(ref x) => { + // Its possible that the current self.state already represents the data value + // in that case we shouldn't clobber the self.state. This helps deal + // with types where parse()/to_string() round trips can lose information + // e.g. with floating point numbers, text of "1.0" becomes "1" in the + // round trip, and this makes it impossible to type in the . otherwise + match self.state.parse() { + Err(_) => Some(mem::replace(&mut self.state, x.to_string())), + Ok(v) => { + if !Data::same(&v, x) { + Some(mem::replace(&mut self.state, x.to_string())) + } else { + None + } + } + } + } }; - self.widget.update(ctx, &old, &self.state, env) + // if old is None here, that means that self.state hasn't changed + let old_data = old.as_ref().unwrap_or(&self.state); + self.widget.update(ctx, old_data, &self.state, env) } #[instrument(name = "Parse", level = "trace", skip(self, ctx, bc, _data, env))]