Show which cell a shift-click is measuring from

The gesture had a hidden operand. A range runs from the anchor — the last cell
plainly clicked — to the cell shift-clicked, and nothing on screen said which
one the anchor was. A user who could not tell where the range was being measured
from had no way to predict what it would take and no clue why a wrong one came
out wrong; often the anchor is not on screen at all, which is itself the answer
to "why did that select so much".

The anchor is marked with an inner ring, drawn inside the selection ring rather
than in a colour of its own: it has to stay legible against a thumbnail of any
brightness, and a hue would read as a second kind of selection. It is an
ordinal, so it marks a row only while the photograph it names is in the loaded
window — off screen it marks nothing, which is the honest answer, and `anchor`
rides in the cell model beside `selected` so both are pushed by the one pass
that already keeps the grid in step with the selection.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-24 19:50:46 +02:00
co-authored by Claude Opus 5
parent 54f9cb54fb
commit dce1e66746
3 changed files with 36 additions and 4 deletions
+4 -3
View File
@@ -2129,10 +2129,11 @@ fn load_window(window: &AppWindow, ctl: &Rc<LibraryController>) {
thumbnail: carried.map(|h| h.thumbnail.clone()).unwrap_or_default(),
has_thumb: carried.is_some_and(|h| h.has_thumb),
unavailable: carried.is_some_and(|h| h.unavailable),
// Both are filled straight after by `collections_ui`, which owns
// the selection and queries the badge counts for the whole window
// in one statement rather than one per cell.
// All three are filled straight after by `collections_ui`,
// which owns the selection and queries the badge counts for the
// whole window in one statement rather than one per cell.
selected: false,
anchor: false,
collection_count: 0,
// Likewise filled by `sync_ratings` below — one query for the
// window, not one per cell.