feat(select): invert selection from the right-click menu
Add an Invert Selection entry to the selection context menu (below Select Similar): it replaces the current selection with every other selectable object in the active layout. Candidates come from the visible wire set, so objects on off/frozen layers stay excluded. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
e562738d9e
commit
fd15dd0aac
4 changed files with 38 additions and 0 deletions
|
|
@ -1289,6 +1289,9 @@ pub enum Message {
|
||||||
/// Extend the current selection with every entity in the active
|
/// Extend the current selection with every entity in the active
|
||||||
/// layout that matches a selected entity by (type, layer).
|
/// layout that matches a selected entity by (type, layer).
|
||||||
SelectSimilar,
|
SelectSimilar,
|
||||||
|
/// Replace the current selection with every other selectable object in
|
||||||
|
/// the active layout (the complement of what's selected now).
|
||||||
|
InvertSelection,
|
||||||
/// Keyboard modifier state changed — tracks whether Shift is held so the
|
/// Keyboard modifier state changed — tracks whether Shift is held so the
|
||||||
/// pick path can do subtractive (Shift+click) selection.
|
/// pick path can do subtractive (Shift+click) selection.
|
||||||
SetShiftDown(bool),
|
SetShiftDown(bool),
|
||||||
|
|
|
||||||
|
|
@ -4971,6 +4971,16 @@ impl OpenCADStudio {
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::InvertSelection => {
|
||||||
|
let i = self.active_tab;
|
||||||
|
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
|
||||||
|
let count = self.tabs[i].scene.invert_selection();
|
||||||
|
self.command_line
|
||||||
|
.push_output(&format!("Invert Selection: {} object(s) selected.", count));
|
||||||
|
self.refresh_properties();
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
|
||||||
Message::QSelectOpen => {
|
Message::QSelectOpen => {
|
||||||
let i = self.active_tab;
|
let i = self.active_tab;
|
||||||
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
|
self.tabs[i].scene.selection.borrow_mut().context_menu = None;
|
||||||
|
|
|
||||||
|
|
@ -2907,6 +2907,10 @@ fn viewport_context_menu_overlay(
|
||||||
));
|
));
|
||||||
items.push(sep());
|
items.push(sep());
|
||||||
items.push(item("Select Similar".to_string(), Message::SelectSimilar));
|
items.push(item("Select Similar".to_string(), Message::SelectSimilar));
|
||||||
|
items.push(item(
|
||||||
|
"Invert Selection".to_string(),
|
||||||
|
Message::InvertSelection,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if isolation_active {
|
if isolation_active {
|
||||||
items.push(item(
|
items.push(item(
|
||||||
|
|
|
||||||
|
|
@ -4896,6 +4896,27 @@ impl Scene {
|
||||||
added
|
added
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Replace the selection with its complement: every selectable object
|
||||||
|
/// in the active layout that isn't currently selected. The candidate
|
||||||
|
/// set is the visible wire set, so objects on off/frozen layers (which
|
||||||
|
/// can't be picked anyway) are excluded. Returns the new count.
|
||||||
|
pub fn invert_selection(&mut self) -> usize {
|
||||||
|
let prev: rustc_hash::FxHashSet<Handle> = self.selected.iter().copied().collect();
|
||||||
|
let all: Vec<Handle> = self
|
||||||
|
.entity_wires()
|
||||||
|
.iter()
|
||||||
|
.filter_map(|w| Self::handle_from_wire_name(&w.name))
|
||||||
|
.collect();
|
||||||
|
self.selected.clear();
|
||||||
|
for h in all {
|
||||||
|
if !prev.contains(&h) {
|
||||||
|
self.selected.insert(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.bump_selection();
|
||||||
|
self.selected.len()
|
||||||
|
}
|
||||||
|
|
||||||
/// Replaces (or extends, when `append` is true) the current
|
/// Replaces (or extends, when `append` is true) the current
|
||||||
/// selection with every entity in the active layout that matches
|
/// selection with every entity in the active layout that matches
|
||||||
/// the filter. Returns the number of newly-matching entities.
|
/// the filter. Returns the number of newly-matching entities.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue