Say so when a crop leaves a mask outside the frame

Cropping tighter past a mask layer made it invisible without a word:
the layer stayed in the panel and the sidecar, and its adjustment went
on landing on pixels nobody would see again.

When a crop is let go, develop now measures what the gesture did to the
mask stack (dr_pipeline::orphan) and, if any layer is now entirely or
mostly outside the frame, shows a notice over the photograph: how many
layers, their names, "Undo crop" and "Keep crop". The crop is already
applied and nothing waits on the answer.

The crop overlay gains a release callback carrying the rect the press
began from, so the measurement runs once per gesture and never on the
drag's per-frame changes. Choosing a ratio is measured the same way,
being a crop committed in one click.

"Undo crop" is the ordinary undo, and the notice is tied to the history
revision it was raised at: the redraw that follows any history move
clears it, so the crop and its warning go back as one step. A second
drag folded into the same step is measured from where that step began.
A crop that strands nothing shows nothing.
This commit is contained in:
2026-09-24 21:52:03 -04:00
parent fc0ea8824d
commit c3d1f83b96
9 changed files with 432 additions and 46 deletions
+16
View File
@@ -679,6 +679,22 @@ export global Framing {
callback portrait-toggled();
/// Crop, angle, rotation and flips back to neutral, leaving colour alone.
callback reset();
/// TRACES: FR-DEV-17
/// A crop gesture was let go; the rect it was pressed from. See
/// `CropOverlay.crop-released`.
callback crop-released(float, float, float, float);
/// TRACES: FR-DEV-17
/// How many mask layers the crop just let go took out of the frame, and
/// their names, already joined. Zero, and the notice is not drawn — the
/// common case says nothing.
///
/// Rust clears it when the history moves off that crop, so an undo takes
/// the notice away with the crop it was about.
in property <int> hidden-masks: 0;
in property <string> hidden-mask-names: "";
/// Keep the crop anyway: the notice has been read.
callback hidden-masks-kept();
}
// Crop, rotation, flips and straightening — the framing controls.