Dim the histogram while the canvas shows a draft

The histogram is measured on settled frames only, so during a drag it
describes the frame from before the gesture while the canvas shows
something newer, and nothing said so. The draft flag stopped at the
render closure.

It now reaches the interface: `canvas-draft` on the window and
`Levels.provisional` for the readouts, both set on every canvas render
from the flag that chose the frame's resolution, and cleared when a
render fails. The histogram panel dims its display reading to half
while a draft is up and brings it back when the frame settles. Dimmed
rather than captioned, because a caption appearing on every drag would
move the column; the raw reading has no frame to lag and is left alone.
This commit is contained in:
2026-09-24 21:52:23 -04:00
parent 7d0870c3fb
commit 4642c77e18
5 changed files with 120 additions and 35 deletions
+10
View File
@@ -2292,7 +2292,15 @@ fn build_render_now(
match rendered {
Ok(image) => {
// TRACES: FR-DSP-4
// **The draft flag goes past the render**, to the places
// that have to know which kind of frame is up: the canvas,
// and the histogram, which is measured on settled frames
// only and so describes an older frame while a draft is
// showing.
window.set_canvas(image);
window.set_canvas_draft(draft);
window.global::<Levels>().set_provisional(draft);
window.set_load_error("".into());
// The readout and the "Fit" button follow the session
// rather than the gesture, so a clamped zoom shows the
@@ -2383,6 +2391,8 @@ fn build_render_now(
Err(e) => {
log::warn!("render failed: {e}");
window.set_load_error(e.into());
window.set_canvas_draft(false);
window.global::<Levels>().set_provisional(false);
// No frame, so nothing to describe. The stale plot would
// otherwise sit beside the error message looking current.
window.global::<Levels>().set_data(histogram::empty());
+3
View File
@@ -99,6 +99,9 @@ export component AppWindow inherits Window {
// Set from Rust each frame: the compute output, delivered as a texture.
in property <image> canvas;
/// TRACES: FR-DSP-4
/// Whether `canvas` is a draft: half resolution, rendered mid-gesture.
in property <bool> canvas-draft;
in property <string> adapter: "detecting…";
in property <string> backend: "—";
in property <string> inference-backend: "detecting…";
+16
View File
@@ -179,6 +179,13 @@ export global Levels {
in property <HistogramView> data;
/// The sensor data the file holds (FR-CULL-3).
in property <HistogramView> raw-data;
/// TRACES: FR-DSP-4
/// The canvas is showing a draft, so `data` describes the last *settled*
/// frame rather than the one on screen: it is measured on settled frames
/// only (FR-DSP-7's budget). Set on every canvas render, from the same
/// flag that chose the frame's resolution, so the two cannot disagree.
/// `raw-data` is untouched by it — the sensor reading has no frame.
in property <bool> provisional;
}
// TRACES: FR-DSP-7
@@ -240,6 +247,15 @@ export component HistogramPanel inherits Rectangle {
}
Rectangle {
// TRACES: FR-DSP-4
// **Held back while the canvas is a draft**, because the display
// reading then describes the frame before the one under the
// finger. Dimmed rather than emptied or captioned: it is still the
// best reading there is, the gesture is seconds long, and a
// caption appearing and vanishing on every drag would move the
// column. The raw reading has no frame to lag behind.
opacity: root.mode == 0 && Levels.provisional ? 0.5 : 1;
animate opacity { duration: 120ms; }
// Tall enough to read a shape off and no taller. The column is the
// photographer's instrument panel, and every pixel this takes is a
// slider pushed below the fold.