M8: an icon double-click becomes the range anchor

A Shift-double-click on a layer's icon leaves only that layer selected, but the range anchor stayed on the layer clicked before, which was no longer selected, so the next Shift-click toggled instead of selecting a range. The icon branch now makes its layer the anchor.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove; Fable 5.2 queued; Sonnet 5.5 measured and wrote at medium
This commit is contained in:
Trevor BrownandClaude Sonnet 5.5 committed 2026-11-12 13:43:50 -05:00
1 parent cf80dc1afa
commit 6785be8a3e
2 files changed
+26

No files matched your search

@@ -914,3 +914,27 @@ fn an_icon_double_click_keeps_its_selection_when_a_modifier_is_held() {
let v = &u.app.session.ds().unwrap().view;
assert_ne!((v.cx, v.zoom), before, "the view frames the layer");
}
/// A Shift-double-click on an icon leaves just that layer selected, and it becomes the anchor: the
/// next Shift-click selects the range from it, not a toggle.
#[test]
fn an_icon_double_click_becomes_the_range_anchor() {
let (mut u, [a, b, c, d]) = four();
u.frame(vec![]);
let a_row = u.row_at(a);
click(&mut u, a_row, Modifiers::NONE);
let icon = icon_of(&mut u, b);
for _ in 0..2 {
for pressed in [true, false] {
let e = Event::PointerButton { pos: icon, button: egui::PointerButton::Primary, pressed, modifiers: SHIFT };
u.frame_with(vec![Event::PointerMoved(icon), e], SHIFT);
}
}
for _ in 0..30 {
u.frame(vec![]);
}
assert_eq!(u.app.session.selection(), vec![b], "the icon's layer is all that is selected");
let d_row = u.row_at(d);
click(&mut u, d_row, SHIFT);
assert_eq!(sorted(u.app.session.selection()), sorted(vec![b, c, d]), "the range from the icon's layer");
}
+2
View File
@@ -1271,6 +1271,8 @@ fn layers(app: &mut FigApp, ui: &mut Ui) {
app.run("view.zoomSelection", json!({}));
// The release is also a click: it must not toggle or extend the selection.
clicked = None;
// The layer is the anchor of the next Shift-click's range.
app.ui.layer_anchor = Some(row.id);
} else if !crate::menus::dev_mode_refuses(app, "object.rename") {
app.ui.rename = Some(Rename { id: row.id, start: true });
}