From 9453085cef2cfae323fade4f82f650c5aea1ae56 Mon Sep 17 00:00:00 2001 From: Nathaniel Ledford Date: Fri, 9 Oct 2026 12:07:59 -0400 Subject: [PATCH] LR-CROP-STRAIGHTEN: the Angle field writes a turned angle with its sign MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The readout and the slider said "+2.50" where the field said "2.50"; it now writes the angle through crop_angle_label too. The test that said the readout's "0.00°" matched the slider at rest (it shows "0") says what it does match. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/panels/detail.rs | 3 ++- crates/ui-egui/src/panels/right.rs | 2 ++ crates/ui-egui/src/tests_crop_rotate.rs | 15 ++++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/ui-egui/src/panels/detail.rs b/crates/ui-egui/src/panels/detail.rs index 2b0989e3..d6e4b60b 100644 --- a/crates/ui-egui/src/panels/detail.rs +++ b/crates/ui-egui/src/panels/detail.rs @@ -1348,7 +1348,8 @@ fn crop_overlay(app: &mut LightcraftApp, ui: &mut egui::Ui, resp: &egui::Respons pub(crate) fn crop_angle_label(angle: f64) -> String { let shown = lightcraft_develop::controls::find("crop.angle").map_or_else(|| format!("{angle:.2}"), |spec| crate::widgets::shown_value(spec, angle)); - // the slider's format turns a rounded −0.00 into "0": every zero reads as the slider at rest + // the slider's format turns a rounded −0.00 into "0": every zero reads "0.00", the angle's + // usual two decimals let shown = if shown == "0" { "0.00".to_string() } else { shown }; format!("{shown}°") } diff --git a/crates/ui-egui/src/panels/right.rs b/crates/ui-egui/src/panels/right.rs index bf7c400e..a06e1733 100644 --- a/crates/ui-egui/src/panels/right.rs +++ b/crates/ui-egui/src/panels/right.rs @@ -197,6 +197,8 @@ fn crop(app: &mut LightcraftApp, ui: &mut egui::Ui, id: PhotoId) { .clamp_existing_to_range(false) .speed(0.05) .fixed_decimals(2) + // as the readout writes it: "+2.50", and every zero "0.00" + .custom_formatter(|v, _| super::detail::crop_angle_label(v).trim_end_matches('°').to_string()) .suffix("°") // read as the Straighten value reads a typed one: "-3,25" too .custom_parser(|text| crate::widgets::typed_value(&spec, text.trim().trim_end_matches('°'))) diff --git a/crates/ui-egui/src/tests_crop_rotate.rs b/crates/ui-egui/src/tests_crop_rotate.rs index 5313ff0f..cfbfbde6 100644 --- a/crates/ui-egui/src/tests_crop_rotate.rs +++ b/crates/ui-egui/src/tests_crop_rotate.rs @@ -94,7 +94,7 @@ fn the_straighten_value_takes_an_exact_angle() { #[test] fn the_angle_reads_like_the_straighten_value() { use crate::panels::detail::crop_angle_label; - assert_eq!(crop_angle_label(0.0), "0.00°", "as the slider shows it at rest"); + assert_eq!(crop_angle_label(0.0), "0.00°", "as the Angle field shows it at rest"); assert_eq!(crop_angle_label(2.5), "+2.50°"); assert_eq!(crop_angle_label(-12.254), "-12.25°"); assert_eq!(crop_angle_label(-0.001), "0.00°", "no minus zero, and every zero the same"); @@ -351,3 +351,16 @@ fn the_angle_field_reads_angles_as_people_type_them() { assert!((angle(&h) - want).abs() < 1e-9, "{typed:?}: want {want}, got {}", angle(&h)); } } + +/// The Angle field writes an angle as the readout does: a sign on a turned angle. +#[test] +fn the_angle_field_writes_the_angle_like_the_readout() { + let mut h = crop_tool(); + let r = h.request("engine.execute", json!({"command": "crop.straighten", "params": {"angle": 2.5}}), T); + assert_eq!(r["ok"], true, "{r}"); + h.settle(SETTLE); + let texts = h.painted_text(); + // the field's number follows its label (its "°" is painted on its own) + let field = texts.iter().position(|t| t == "Angle").and_then(|i| texts.get(i + 1)); + assert_eq!(field.map(String::as_str), Some("+2.50"), "{texts:?}"); +}