ui: the selection filter follows what the selection holds (#341, #371)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 10:17:28 -04:00
1 parent 2908a77850
commit f9c1c3cb24
2 files changed
+41

No files matched your search

+5
View File
@@ -1264,6 +1264,11 @@ impl ModelApp {
if self.pick.selection.apply(items, mode) {
self.pick.generation = self.pick.generation.wrapping_add(1);
}
// The filter label follows what the selection holds (a seed picked in the browser selects
// its edge whatever the filter was, #341).
if let Some(f) = self.pick.selection.filter() {
self.pick.filter = f;
}
let mut text = format!("Selected: {}", self.pick.selection.summary());
if self.pick.selection.capped() {
text.push_str(&format!(" (at most {} items)", selection::MAX_SELECTION));
+36
View File
@@ -72,6 +72,21 @@ impl Filter {
}
}
/// The filter that picks `item`.
pub fn of(item: &Item) -> Filter {
match item {
Item::Geometry(g) => match g.entity {
Entity::Body => Filter::Bodies,
Entity::Face(_) => Filter::Faces,
Entity::Edge(_) => Filter::Edges,
Entity::Vertex(_) => Filter::Vertices,
},
Item::Node(_) => Filter::Nodes,
Item::Element(_) => Filter::Elements,
Item::Face(_) => Filter::ElementFaces,
}
}
/// Geometry (named) rather than mesh (labelled) entities.
pub fn geometry(self) -> bool {
matches!(self, Filter::Faces | Filter::Edges | Filter::Vertices | Filter::Bodies)
@@ -142,6 +157,13 @@ impl Selection {
&self.items
}
/// The one filter that picks every selected item (`None` when empty or mixed).
pub fn filter(&self) -> Option<Filter> {
let mut kinds = self.items.iter().map(Filter::of);
let first = kinds.next()?;
kinds.all(|k| k == first).then_some(first)
}
pub fn len(&self) -> usize {
self.items.len()
}
@@ -974,6 +996,20 @@ mod tests {
use super::*;
/// The filter a selection holds: one kind names it, a mix or nothing names none (#341).
#[test]
fn a_selection_names_the_filter_of_what_it_holds() {
let edge = Item::Geometry(GeometryRef::new("Bar", Entity::Edge("top".into())).unwrap());
let mut sel = Selection::default();
assert_eq!(sel.filter(), None);
sel.apply([edge], Mode::Replace);
assert_eq!(sel.filter(), Some(Filter::Edges));
sel.apply([Item::Node(3)], Mode::Add);
assert_eq!(sel.filter(), None);
sel.apply([Item::Node(4)], Mode::Replace);
assert_eq!(sel.filter(), Some(Filter::Nodes));
}
/// `nx × ny × nz` unit hex8 cells, the faces at x = nx tagged as face `end` of body `Bar`, the
/// solids as the body, the edge along x = nx, z = nz as edge `top` and the corner node at
/// (nx, 0, 0) as vertex `v`.