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:
@@ -48,6 +48,14 @@ export component CropOverlay inherits Rectangle {
|
||||
/// written here — Rust takes the opposite corner.
|
||||
callback crop-changed(float, float, float, float, float, float);
|
||||
|
||||
/// TRACES: FR-DEV-17
|
||||
/// A drag of the rect or a handle was let go. Carries the rect as it was
|
||||
/// when the press began, so Rust can measure what the whole gesture did.
|
||||
///
|
||||
/// The one boundary a crop gesture reports. `crop-changed` fires on
|
||||
/// every pointer move and a handle passing over a mask on its way
|
||||
/// somewhere else is not an event; only the release is a decision.
|
||||
callback crop-released(float, float, float, float);
|
||||
|
||||
property <length> rx: root.crop-x * self.width;
|
||||
property <length> ry: root.crop-y * self.height;
|
||||
@@ -135,6 +143,8 @@ export component CropOverlay inherits Rectangle {
|
||||
|
||||
property <float> start-x;
|
||||
property <float> start-y;
|
||||
property <float> start-w;
|
||||
property <float> start-h;
|
||||
property <float> from-x;
|
||||
property <float> from-y;
|
||||
|
||||
@@ -149,9 +159,16 @@ export component CropOverlay inherits Rectangle {
|
||||
if (ev.kind == PointerEventKind.down) {
|
||||
self.start-x = root.crop-x;
|
||||
self.start-y = root.crop-y;
|
||||
self.start-w = root.crop-w;
|
||||
self.start-h = root.crop-h;
|
||||
self.from-x = self.fraction-x(self.pressed-x);
|
||||
self.from-y = self.fraction-y(self.pressed-y);
|
||||
}
|
||||
if (ev.kind == PointerEventKind.up || ev.kind == PointerEventKind.cancel) {
|
||||
// The extent too, not only the origin: Rust clamps a rect
|
||||
// moved past an edge, and that can narrow it.
|
||||
root.crop-released(self.start-x, self.start-y, self.start-w, self.start-h);
|
||||
}
|
||||
}
|
||||
|
||||
moved => {
|
||||
@@ -224,6 +241,9 @@ export component CropOverlay inherits Rectangle {
|
||||
self.from-x = self.fraction-x(self.pressed-x);
|
||||
self.from-y = self.fraction-y(self.pressed-y);
|
||||
}
|
||||
if (ev.kind == PointerEventKind.up || ev.kind == PointerEventKind.cancel) {
|
||||
root.crop-released(self.ox, self.oy, self.ow, self.oh);
|
||||
}
|
||||
}
|
||||
|
||||
// Movement as a fraction of the frame, live while
|
||||
|
||||
Reference in New Issue
Block a user