fix(layers): VP glyph and filter-aware shift ranges

VP-freeze columns used the global-freeze glyph; shift-ranges swept filtered-out rows into bulk ops. Glyph swapped to layer_vp_freeze (ribbon precedent); new visible_indices helper shared by the view loop and the shift arm. Test: shift_select_skips_filtered_out_rows (RED: hidden row in range). Full suite: 2028 passed / 0 failed / 25 ignored.
This commit is contained in:
Karim Jerbi committed 2026-10-10 20:41:28 +01:00
1 parent ea7e79bfab
commit 6c3cfb55b5
3 files changed
+53 -8

No files matched your search

+29
View File
@@ -4787,6 +4787,35 @@ mod layer_name_target_tests {
);
}
#[test]
fn shift_select_skips_filtered_out_rows() {
// #50: rows hidden by the live filter must not join a shift-range.
// Sorted panel: A1(0), B9(1), C1(2); filter "1" hides B9.
let mut app = OpenCADStudio::new_for_test();
app.automation_op(r#"{"op":"new"}"#);
for new in ["C1", "B9", "A1"] {
let _ = app.on_layer_new();
let fresh = app.tabs[app.active_tab].layers.edit_buf.clone();
rename_layer(&mut app, &fresh, new);
}
let i = app.active_tab;
app.tabs[i].layers.filter = "1".to_string();
let _ = app.update(Message::LayerSelect("A1".to_string()));
app.shift_down = true;
let _ = app.update(Message::LayerSelect("C1".to_string()));
app.shift_down = false;
let multi = app.tabs[i].layers.selected_multi.clone();
let names: Vec<String> = multi
.iter()
.filter_map(|&x| app.tabs[i].layers.layers.get(x).map(|l| l.name.clone()))
.collect();
assert!(
!names.contains(&"B9".to_string()),
"hidden row must not join the range, got {names:?}"
);
assert!(names.contains(&"A1".to_string()) && names.contains(&"C1".to_string()));
}
#[test]
fn layer_toggle_visible_unknown_name_is_noop() {
let mut app = app_with_zulu_alpha();
+6 -2
View File
@@ -3590,10 +3590,14 @@ impl OpenCADStudio {
panel.selected_multi.push(idx);
}
} else if shift {
// Shift-click selects the range from the anchor to here.
// Shift-click selects the range from the anchor to here —
// visible rows only, so filtered-out rows between them
// cannot join bulk edits/deletes (#50).
let anchor = panel.selected.unwrap_or(idx);
let (lo, hi) = (anchor.min(idx), anchor.max(idx));
panel.selected_multi = (lo..=hi).collect();
let visible: std::collections::HashSet<usize> =
panel.visible_indices().into_iter().collect();
panel.selected_multi = (lo..=hi).filter(|r| visible.contains(r)).collect();
} else if !panel.selected_multi.contains(&idx) {
// Plain click collapses to this row — but NOT when it is
// already part of a multi-selection, so clicking a property