From 8e9c5aff7ee1fa46097312a99e74fe40450fc8ac Mon Sep 17 00:00:00 2001 From: PiMinusMax <121135695+PiMinusMax@users.noreply.github.com> Date: Sat, 10 Oct 2026 15:07:11 +0200 Subject: [PATCH] LR-EDIT-COLOR-WB-PICKER: the selector button does what W does The White Balance Selector button in the Edit panel only armed the tool, so in Compare (which doesn't handle on-image tools) it did nothing while W opened the photo in Detail with the selector armed. The button now runs tool.wbPicker like W; a second click still disarms it. New headless test tests_wb_selector.rs clicks the button in Compare and expects Detail with the selector armed on the photo that was active; it fails without the fix (the view stays Compare). Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/lib.rs | 2 ++ crates/ui-egui/src/panels/edit.rs | 7 +++- crates/ui-egui/src/tests_wb_selector.rs | 44 +++++++++++++++++++++++++ docs/parity-checklist.md | 2 +- 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 crates/ui-egui/src/tests_wb_selector.rs diff --git a/crates/ui-egui/src/lib.rs b/crates/ui-egui/src/lib.rs index 6b5033e0c..cd55116d0 100644 --- a/crates/ui-egui/src/lib.rs +++ b/crates/ui-egui/src/lib.rs @@ -89,6 +89,8 @@ mod tests_titlebar; #[cfg(test)] mod tests_unsaved; #[cfg(test)] +mod tests_wb_selector; +#[cfg(test)] mod tests_zoom; #[cfg(test)] mod tests_zoom_keys; diff --git a/crates/ui-egui/src/panels/edit.rs b/crates/ui-egui/src/panels/edit.rs index 56f405ea3..5567c8beb 100644 --- a/crates/ui-egui/src/panels/edit.rs +++ b/crates/ui-egui/src/panels/edit.rs @@ -216,7 +216,12 @@ pub fn show(app: &mut LightcraftApp, ui: &mut egui::Ui, id: PhotoId) { if crate::widgets::icon_button(ui, "wbPicker", Icon::Picker, vec2(28.0, 28.0), active, true, "White Balance Selector (W)") .clicked() { - app.ui.tool = if active { String::new() } else { "wbPicker".into() }; + if active { + app.ui.tool.clear(); + } else if let Err(e) = app.run("tool.wbPicker", json!({})) { + // the same as W: from Compare, Survey or the grid it opens the photo in Detail + app.toast(ui.ctx(), e); + } } }); }); diff --git a/crates/ui-egui/src/tests_wb_selector.rs b/crates/ui-egui/src/tests_wb_selector.rs new file mode 100644 index 000000000..32a881acd --- /dev/null +++ b/crates/ui-egui/src/tests_wb_selector.rs @@ -0,0 +1,44 @@ +//! Headless tests of the White Balance Selector's button. + +use std::time::Duration; + +use serde_json::json; + +use crate::headless::Headless; +use crate::state::ViewMode; +use crate::{LightcraftApp, Services}; + +const T: Duration = Duration::from_secs(20); +const SETTLE: Duration = Duration::from_secs(120); + +/// The White Balance Selector button in the Edit panel does what W does: from Compare it opens +/// the active photo in Detail with the selector armed (it used to arm a tool Compare ignores). +/// Clicking it again disarms it. +#[test] +fn wb_selector_button_in_compare_opens_detail_like_w() { + let app = LightcraftApp::new(lightcraft_engine::Session::with_demo(), Services { png: None, ..Default::default() }); + let mut h = Headless::new(app, [1400.0, 900.0], 1.0); + let vis: Vec = h.app.session.visible_cloned().iter().map(|p| p.0).collect(); + h.request("engine.execute", json!({"command": "library.select", "params": {"ids": [vis[0], vis[1]], "active": vis[0]}}), T); + let r = h.request("engine.execute", json!({"command": "view.compare"}), T); + assert_eq!(r["ok"], true, "{r}"); + h.app.ui.right = crate::state::RightPanel::Edit; + h.settle(SETTLE); + // open the Color section, where the selector sits + if !h.app.widgets.iter().any(|(w, _)| w == "icon:wbPicker") { + h.request("ui.clickWidget", json!({"id": "section:color"}), T); + h.settle(SETTLE); + } + assert_eq!(h.app.ui.view, ViewMode::Compare); + let active = h.app.session.selection.active; + let r = h.request("ui.clickWidget", json!({"id": "icon:wbPicker"}), T); + assert_eq!(r["ok"], true, "{r}"); + h.settle(SETTLE); + assert_eq!(h.app.ui.view, ViewMode::Detail, "the button leaves Compare like W"); + assert_eq!(h.app.ui.tool, "wbPicker"); + assert_eq!(h.app.session.selection.active, active, "on the photo that was active in Compare"); + let r = h.request("ui.clickWidget", json!({"id": "icon:wbPicker"}), T); + assert_eq!(r["ok"], true, "{r}"); + h.settle(SETTLE); + assert_eq!(h.app.ui.tool, "", "a second click disarms it"); +} diff --git a/docs/parity-checklist.md b/docs/parity-checklist.md index 099411089..67ba5aca3 100644 --- a/docs/parity-checklist.md +++ b/docs/parity-checklist.md @@ -188,7 +188,7 @@ differences and missing bindings are in [ui-parity.md](ui-parity.md#shortcuts). | LR-EDIT-LIGHT-CURVE-REFINESAT | Curve saturation compensation | P1 | ✅ | `ctl:curve.refineSaturation` | | | LR-EDIT-LIGHT-CURVE-TAT | Drag-on-image curve adjust | P1 | ✅ | `cmd:develop.targeted` (`target: curve`) | | | LR-EDIT-COLOR-WB-PRESET | White-balance presets | P0 | ✅ | `cmd:develop.wb` | | -| LR-EDIT-COLOR-WB-PICKER | White-balance eyedropper | P0 | ✅ | `cmd:tool.wbPicker`, `cmd:develop.wbPick` | no magnified loupe while picking | +| LR-EDIT-COLOR-WB-PICKER | White-balance eyedropper | P0 | ✅ | `cmd:tool.wbPicker`, `cmd:develop.wbPick`, `crates/ui-egui/src/tests_wb_selector.rs` | the Edit panel's selector button does what W does (from Compare, Survey or the grid it opens the photo in Detail); no magnified loupe while picking | | LR-EDIT-COLOR-TEMP | Temperature | P0 | ✅ | `ctl:wb.temp`, `crates/pipeline/src/local.rs` (`wb_matrix_for`), `crates/raw/src/color.rs` (`rebalance`) | relative scale for non-raw in the UI; raws with a colour matrix (DNG and other raws without a file-local look) are re-developed for the chosen white through the camera's own matrices (camera-space white balance, as Lightroom), and the eyedropper / Auto invert the same model; other photos are adapted (Bradford) | | LR-EDIT-COLOR-TINT | Tint | P0 | ✅ | `ctl:wb.tint`, `docs/tint-direction.md` | DNG / Lightroom sign: negative (left) adds green, positive (right) magenta; XMP `crs:Tint` values render as in Lightroom (issue #188); CPU/GPU regression tests | | LR-EDIT-COLOR-VIBRANCE | Vibrance | P0 | ✅ | `ctl:color.vibrance` | |