Come back from develop on the photograph you were editing
Leaving develop returned to where the *grid* was, which after a walk along the photo roll can be a thousand rows from the frame you had just finished. So the one photograph you were certainly interested in was the one the grid came back without. Two positions, and the rule is not to pick one of them. The grid seeks to the remembered position, then reveals the keyboard cursor -- which is now put on the open photograph, and which moves the viewport as little as will bring its row into view. A frame inside the remembered screenful moves nothing at all; one outside it scrolls exactly far enough. One rule, both behaviours. The cursor rather than the selection, deliberately: `place_cursor` also rewrites the selection, and a set of forty photographs assembled in the grid must survive having one of them opened. `reveal()` now also runs on the grid's `init`, since `cursor-row` is initialised rather than changed when the subtree is rebuilt and no handler would otherwise fire. Both it and the roll's centring defer while the element has no height yet -- `init` runs before layout, where a height of zero makes every row look off screen -- and a latch brings the first real height back to the cursor without letting every later resize haul the viewport around. The capture-time marker follows the same move, for the same reason: `load_window` rebuilds the axis only when the scope, the filter or the total has changed, and none of them has. It is the same library seen from a different row. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2737,6 +2737,15 @@ export component LibraryGrid inherits Rectangle {
|
||||
if (root.cursor < 0) {
|
||||
return;
|
||||
}
|
||||
// Nothing to reveal *into* before layout has run, and this
|
||||
// is now called from `init` as well as on a cursor move —
|
||||
// where a height of zero would make every row look off
|
||||
// screen and scroll the grid to the cursor when `seek` had
|
||||
// just put it somewhere deliberate.
|
||||
if (self.height <= 0px) {
|
||||
return;
|
||||
}
|
||||
self.revealed = true;
|
||||
let top = Theme.gap + self.cursor-row * self.pitch;
|
||||
let shown = -self.viewport-y;
|
||||
let bottom = max(0px, self.viewport-height - self.height);
|
||||
@@ -2747,13 +2756,38 @@ export component LibraryGrid inherits Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether a reveal has run against real geometry yet.
|
||||
///
|
||||
/// The safety net for the deferral above, and deliberately a
|
||||
/// latch rather than a plain `changed height` handler: the first
|
||||
/// height a rebuilt grid is given must bring the cursor into
|
||||
/// view, and every height *after* that is a window being
|
||||
/// resized, where dragging a corner should not keep hauling the
|
||||
/// viewport back to a cursor the user is not looking at.
|
||||
property <bool> revealed: false;
|
||||
changed height => {
|
||||
if (!self.revealed) {
|
||||
self.reveal();
|
||||
}
|
||||
}
|
||||
|
||||
// Also on creation, which is what returning from the develop
|
||||
// view needs. `show-library` gates an `if`, so the grid is built
|
||||
// anew and `token` is *initialised* to the already-bumped value
|
||||
// view needs. The grid is gated on an `if`, so it is built anew
|
||||
// and `token` is *initialised* to the already-bumped value
|
||||
// rather than changing to it — no `changed` handler fires, and
|
||||
// without this the restored position would be dropped and the
|
||||
// view would sit at the top.
|
||||
init => { self.seek(); }
|
||||
//
|
||||
// `reveal()` after `seek()`, and the order is the point: seek
|
||||
// puts the viewport where the grid was left, reveal then moves
|
||||
// it as little as will bring the cursor's row into view. Coming
|
||||
// back from develop the cursor is on the photograph that was
|
||||
// open, so a frame inside the remembered screenful moves
|
||||
// nothing at all and one outside it is scrolled just far enough
|
||||
// to be seen. `cursor-row` is *initialised* here too, so its own
|
||||
// `changed` handler never fires and this is the only thing that
|
||||
// can do it.
|
||||
init => { self.seek(); self.reveal(); }
|
||||
|
||||
// Sized to the **whole library**, not the loaded window. The
|
||||
// scrollbar has to represent 23,971 images or there is no way to
|
||||
|
||||
Reference in New Issue
Block a user