Skip to main content

geop_ops_assembly/
draw.rs

1//! [`AssemblyDrawer`]: the parts placed in a part, drawn as instances of
2//! their components and listed by name.
3
4use geop_core_editor::{
5    registry::{Drawer, StructureItem},
6    view::PartView,
7};
8use geop_core_math::geop_error::GeopResult;
9use geop_core_program::{
10    placed::{Located, split_instance_path},
11    reader::Reader,
12};
13
14use geop_ops_model::placed::{drawn, placed_parts};
15
16use crate::placed::draw_instances;
17
18/// Draws the parts placed in a part, however deep, each as an instance of
19/// its component where the state has it (see [`draw_instances`]), and lists
20/// them all, however deep, by their paths.
21pub struct AssemblyDrawer;
22
23impl Drawer for AssemblyDrawer {
24    fn draw(&self, reader: &Reader, view: &mut PartView) -> GeopResult<()> {
25        draw_instances(reader, view)
26    }
27
28    /// Each part placed in it, however deep — each before those placed in
29    /// it, by its path, `neck/head` — said beside it which file it is from,
30    /// unless its name says so already.
31    fn structure(&self, reader: &Reader) -> GeopResult<Vec<StructureItem>> {
32        let placed = placed_parts(reader).unwrap_or_default();
33        Ok((placed.iter())
34            .map(|p| {
35                let item = StructureItem::drawn("part", "Placed parts", &p.name);
36                let file = p.located.instance.file.as_str();
37                let file = file.rsplit(['/', ':']).next().unwrap_or(file);
38                let stem = file.strip_suffix(".geop").unwrap_or(file);
39                match stem == split_instance_path(&p.name).1 {
40                    true => item,
41                    false => item.detailed(stem.to_string()),
42                }
43            })
44            .collect())
45    }
46
47    /// The datums of the parts placed: theirs, not the part's, shown only
48    /// while a field waits to pick one — a mate's entities.
49    fn hidden(&self, reader: &Reader) -> Vec<String> {
50        let Ok(placed) = placed_parts(reader) else {
51            return Vec::new();
52        };
53        (placed.iter())
54            .filter_map(|part| Some((part, drawn(reader, &part.name).ok()?)))
55            .flat_map(|(part, drawn)| {
56                (drawn.view.datums.iter())
57                    .map(|d| Located::in_instance(part.name.as_str(), d.name.as_str()).key())
58            })
59            .collect()
60    }
61}