diff --git a/capellambse_context_diagrams/collectors/custom.py b/capellambse_context_diagrams/collectors/custom.py index 06d2e14..f4d35c7 100644 --- a/capellambse_context_diagrams/collectors/custom.py +++ b/capellambse_context_diagrams/collectors/custom.py @@ -92,7 +92,9 @@ def __call__(self) -> _elkjs.ELKInputData: and not isinstance(current.owner, generic.PackageTypes) ): self.common_owners.discard(current.uuid) - current = self._make_owner_box(current) + current = generic.make_owner_box( + current, self._make_box, self.boxes, self.boxes_to_delete + ) self.common_owners.discard(current.uuid) for edge_uuid, box_uuid in self.edge_owners.items(): if box := self.boxes.get(box_uuid): @@ -293,34 +295,15 @@ def _make_box( if self.diagram._display_parent_relation: self.common_owners.add( generic.make_owner_boxes( - obj, self.diagram_target_owners, self._make_owner_box + obj, + self.diagram_target_owners, + self._make_box, + self.boxes, + self.boxes_to_delete, ) ) return box - def _make_owner_box( - self, - obj: t.Any, - ) -> t.Any: - parent_box = self._make_box( - obj.owner, - layout_options=makers.DEFAULT_LABEL_LAYOUT_OPTIONS, - ) - assert (obj_box := self.boxes.get(obj.uuid)) - for box in (children := parent_box.children): - if box.id == obj.uuid: - break - else: - children.append(obj_box) - obj_box.width = max( - obj_box.width, - parent_box.width, - ) - for label in parent_box.labels: - label.layoutOptions = makers.DEFAULT_LABEL_LAYOUT_OPTIONS - self.boxes_to_delete.add(obj.uuid) - return obj.owner - def _make_edge_and_ports( self, edge_obj: m.ModelElement, diff --git a/capellambse_context_diagrams/collectors/default.py b/capellambse_context_diagrams/collectors/default.py index edf4f4d..53874af 100644 --- a/capellambse_context_diagrams/collectors/default.py +++ b/capellambse_context_diagrams/collectors/default.py @@ -67,7 +67,6 @@ def process_context(self): ): box = self._make_box( self.diagram.target.owner, - no_symbol=self.diagram._display_symbols_as_boxes, layout_options=makers.DEFAULT_LABEL_LAYOUT_OPTIONS, ) box.children = [self.centerbox] @@ -83,8 +82,11 @@ def process_context(self): and hasattr(current, "owner") and not isinstance(current.owner, generic.PackageTypes) ): - current = self._make_owner_box( + current = generic.make_owner_box( current, + self._make_box, + self.global_boxes, + self.boxes_to_delete, ) self.common_owners.discard(current.uuid) @@ -248,7 +250,6 @@ def _process_ports(self) -> None: box = self._make_box( owner, height=height, - no_symbol=self.diagram._display_symbols_as_boxes, ) box.ports = local_port_objs @@ -257,7 +258,11 @@ def _process_ports(self) -> None: if self.diagram._display_parent_relation: self.common_owners.add( generic.make_owner_boxes( - owner, self.diagram_target_owners, self._make_owner_box + owner, + self.diagram_target_owners, + self._make_box, + self.global_boxes, + self.boxes_to_delete, ) ) @@ -284,33 +289,13 @@ def _make_box( return box box = makers.make_box( obj, + no_symbol=self.diagram._display_symbols_as_boxes, **kwargs, ) self.global_boxes[obj.uuid] = box self.made_boxes[obj.uuid] = box return box - def _make_owner_box( - self, - obj: t.Any, - ) -> t.Any: - parent_box = self._make_box( - obj.owner, - no_symbol=self.diagram._display_symbols_as_boxes, - layout_options=makers.DEFAULT_LABEL_LAYOUT_OPTIONS, - ) - assert (obj_box := self.global_boxes.get(obj.uuid)) - for box in (children := parent_box.children): - if box.id == obj.uuid: - break - else: - children.append(obj_box) - for label in parent_box.labels: - label.layoutOptions = makers.DEFAULT_LABEL_LAYOUT_OPTIONS - - self.boxes_to_delete.add(obj.uuid) - return obj.owner - def collector( diagram: context.ContextDiagram, params: dict[str, t.Any] | None = None diff --git a/capellambse_context_diagrams/collectors/generic.py b/capellambse_context_diagrams/collectors/generic.py index faf8512..f6cc992 100644 --- a/capellambse_context_diagrams/collectors/generic.py +++ b/capellambse_context_diagrams/collectors/generic.py @@ -269,8 +269,38 @@ def get_all_owners(obj: m.ModelElement) -> cabc.Iterator[str]: current = getattr(current, "owner", None) +def make_owner_box( + obj: t.Any, + make_box_func: t.Callable, + boxes: dict[str, _elkjs.ELKInputChild], + boxes_to_delete: set[str], +) -> t.Any: + parent_box = make_box_func( + obj.owner, + layout_options=makers.DEFAULT_LABEL_LAYOUT_OPTIONS, + ) + assert (obj_box := boxes.get(obj.uuid)) + for box in (children := parent_box.children): + if box.id == obj.uuid: + break + else: + children.append(obj_box) + obj_box.width = max( + obj_box.width, + parent_box.width, + ) + for label in parent_box.labels: + label.layoutOptions = makers.DEFAULT_LABEL_LAYOUT_OPTIONS + boxes_to_delete.add(obj.uuid) + return obj.owner + + def make_owner_boxes( - obj: m.ModelElement, excluded: list[str], make_func: t.Callable + obj: m.ModelElement, + excluded: list[str], + make_box_func: t.Callable, + boxes: dict[str, _elkjs.ELKInputChild], + boxes_to_delete: set[str], ) -> str: """Create owner boxes for all owners of ``obj``.""" current = obj @@ -280,5 +310,7 @@ def make_owner_boxes( and getattr(current, "owner", None) is not None and not isinstance(current.owner, PackageTypes) ): - current = make_func(current) + current = make_owner_box( + current, make_box_func, boxes, boxes_to_delete + ) return current.uuid diff --git a/docs/custom_diagram.md b/docs/custom_diagram.md index 0a49da5..43193ae 100644 --- a/docs/custom_diagram.md +++ b/docs/custom_diagram.md @@ -17,17 +17,17 @@ At every step of the collection, you can either `get` or `include` elements. `ge ```yaml get: - name: inputs - include: - - name: exchanges - - name: links + include: + - name: exchanges + - name: links - name: outputs - include: - - name: exchanges - - name: links + include: + - name: exchanges + - name: links - name: ports - include: - - name: exchanges - - name: links + include: + - name: exchanges + - name: links ``` In the example above, we first `get` all the inputs of our target element and iterate over them. For each input, we include all the exchanges and links in the resulting diagram. We do the same for outputs and ports. Note that `get` does not include the element in the diagram, it just gets the element, but calling `include` on an edge will also include the edge's source and target ports. diff --git a/docs/index.md b/docs/index.md index 8f6f3a2..af85294 100644 --- a/docs/index.md +++ b/docs/index.md @@ -202,7 +202,7 @@ Available via `.context_diagram` on a [`ModelObject`][capellambse.model.ModelObj diag.render("svgdiagram").save(pretty=True) ```
- +
Context of PP 1 [PAB]
diff --git a/tests/test_context_diagrams.py b/tests/test_context_diagrams.py index a9e62a1..9209a95 100644 --- a/tests/test_context_diagrams.py +++ b/tests/test_context_diagrams.py @@ -300,10 +300,6 @@ def test_context_diagram_display_unused_ports( obj = model.by_uuid("446d3f9f-644d-41ee-bd57-8ae0f7662db2") unused_port_uuid = "5cbc4d2d-1b9c-4e10-914e-44d4526e4a2f" - obj.context_diagram.render("svgdiagram", display_unused_ports=True).save( - pretty=True - ) - adiag = obj.context_diagram.render(None, display_unused_ports=False) bdiag = obj.context_diagram.render(None, display_unused_ports=True)