diff --git a/capellambse_context_diagrams/_elkjs.py b/capellambse_context_diagrams/_elkjs.py
index 7a7bc2c1..337588b1 100644
--- a/capellambse_context_diagrams/_elkjs.py
+++ b/capellambse_context_diagrams/_elkjs.py
@@ -56,6 +56,7 @@
"hierarchyHandling": "INCLUDE_CHILDREN",
"layered.edgeLabels.sideSelection": "ALWAYS_DOWN",
"layered.nodePlacement.strategy": "BRANDES_KOEPF",
+ "layered.considerModelOrder.strategy": "NODES_AND_EDGES",
"spacing.labelNode": "0.0",
}
"""
diff --git a/capellambse_context_diagrams/collectors/exchanges.py b/capellambse_context_diagrams/collectors/exchanges.py
index f4eaab46..83f64933 100644
--- a/capellambse_context_diagrams/collectors/exchanges.py
+++ b/capellambse_context_diagrams/collectors/exchanges.py
@@ -9,6 +9,7 @@
import typing as t
from capellambse.model import common
+from capellambse.model.crosslayer import cs
from capellambse.model.modeltypes import DiagramType as DT
from .. import _elkjs, context
@@ -65,31 +66,60 @@ def get_functions_and_exchanges(
self, comp: common.GenericElement, interface: common.GenericElement
) -> tuple[
list[common.GenericElement],
- list[common.GenericElement],
- list[common.GenericElement],
+ dict[str, common.GenericElement],
+ dict[str, common.GenericElement],
]:
"""Return `Function`s, incoming and outgoing
`FunctionalExchange`s for given `Component` and `interface`.
"""
- functions, outgoings, incomings = [], [], []
+ functions, incomings, outgoings = [], {}, {}
alloc_functions = self.get_alloc_functions(comp)
for fex in self.get_alloc_fex(interface):
source = self.get_source(fex)
if source in alloc_functions:
- if fex not in outgoings:
- outgoings.append(fex)
+ if fex.uuid not in outgoings:
+ outgoings[fex.uuid] = fex
if source not in functions:
functions.append(source)
target = self.get_target(fex)
if target in alloc_functions:
- if fex not in incomings:
- incomings.append(fex)
+ if fex.uuid not in incomings:
+ incomings[fex.uuid] = fex
if target not in functions:
functions.append(target)
return functions, incomings, outgoings
+ def collect_context(
+ self, comp: common.GenericElement, interface: common.GenericElement
+ ) -> tuple[
+ dict[str, t.Any],
+ dict[str, common.GenericElement],
+ dict[str, common.GenericElement],
+ ]:
+ functions, incomings, outgoings = self.get_functions_and_exchanges(
+ comp, interface
+ )
+ components = []
+ for cmp in comp.components:
+ fncs, _, _ = self.get_functions_and_exchanges(cmp, interface)
+ functions.extend(fncs)
+ if fncs:
+ c, incs, outs = self.collect_context(cmp, interface)
+ components.append(c)
+ incomings |= incs
+ outgoings |= outs
+ return (
+ {
+ "element": comp,
+ "functions": functions,
+ "components": components,
+ },
+ incomings,
+ outgoings,
+ )
+
def make_ports_and_update_children_size(
self,
data: _elkjs.ELKInputChild,
@@ -100,6 +130,9 @@ def make_ports_and_update_children_size(
for child in data["children"]:
inputs, outputs = [], []
obj = self.obj._model.by_uuid(child["id"])
+ if isinstance(obj, cs.Component):
+ self.make_ports_and_update_children_size(child, exchanges)
+ return
port_ids = {p.uuid for p in obj.inputs + obj.outputs}
for ex in exchanges:
source, target = ex["sources"][0], ex["targets"][0]
@@ -153,12 +186,12 @@ class InterfaceContextCollector(ExchangeCollector):
for building the interface context.
"""
- left: common.GenericElement
- """Source or target Component of the interface."""
- right: common.GenericElement
- """Source or target Component of the interface."""
- outgoing_edges: list[common.GenericElement]
- incoming_edges: list[common.GenericElement]
+ left: _elkjs.ELKInputChild | None
+ """Left (source) Component Box of the interface."""
+ right: _elkjs.ELKInputChild | None
+ """Right (target) Component Box of the interface."""
+ outgoing_edges: dict[str, common.GenericElement]
+ incoming_edges: dict[str, common.GenericElement]
def __init__(
self,
@@ -166,8 +199,16 @@ def __init__(
data: _elkjs.ELKInputData,
params: dict[str, t.Any],
) -> None:
+ self.left = None
+ self.right = None
+ self.incoming_edges = {}
+ self.outgoing_edges = {}
+
super().__init__(diagram, data, params)
+
self.get_left_and_right()
+ if diagram.include_interface:
+ self.add_interface()
def get_left_and_right(self) -> None:
made_children: set[str] = set()
@@ -178,15 +219,19 @@ def get_capella_order(
alloc_functions = self.get_alloc_functions(comp)
return [fnc for fnc in alloc_functions if fnc in functions]
- def make_boxes(
- comp: common.GenericElement, functions: list[common.GenericElement]
- ) -> None:
+ def make_boxes(cntxt: dict[str, t.Any]) -> _elkjs.ELKInputChild | None:
+ comp = cntxt["element"]
+ functions = cntxt["functions"]
+ components = cntxt["components"]
if comp.uuid not in made_children:
children = [
- makers.make_box(c)
- for c in functions
- if c in self.get_alloc_functions(comp)
+ makers.make_box(fnc)
+ for fnc in functions
+ if fnc in self.get_alloc_functions(comp)
]
+ for cmp in components:
+ if child := make_boxes(cmp):
+ children.append(child)
if children:
layout_options = makers.DEFAULT_LABEL_LAYOUT_OPTIONS
else:
@@ -196,52 +241,68 @@ def make_boxes(
comp, no_symbol=True, layout_options=layout_options
)
box["children"] = children
- self.data["children"].append(box)
made_children.add(comp.uuid)
+ return box
+ return None
try:
comp = self.get_source(self.obj)
- functions, incs, outs = self.get_functions_and_exchanges(
- comp, self.obj
- )
- inc_port_ids = set(ex.target.uuid for ex in incs)
- out_port_ids = set(ex.source.uuid for ex in outs)
+ left_context, incs, outs = self.collect_context(comp, self.obj)
+ inc_port_ids = set(ex.target.uuid for ex in incs.values())
+ out_port_ids = set(ex.source.uuid for ex in outs.values())
port_spread = len(out_port_ids) - len(inc_port_ids)
_comp = self.get_target(self.obj)
- _functions, _, _ = self.get_functions_and_exchanges(
- _comp, self.obj
- )
- _inc_port_ids = set(ex.target.uuid for ex in outs)
- _out_port_ids = set(ex.source.uuid for ex in incs)
+ right_context, _, _ = self.collect_context(_comp, self.obj)
+ _inc_port_ids = set(ex.target.uuid for ex in outs.values())
+ _out_port_ids = set(ex.source.uuid for ex in incs.values())
_port_spread = len(_out_port_ids) - len(_inc_port_ids)
- functions = get_capella_order(comp, functions)
- _functions = get_capella_order(_comp, _functions)
+ left_context["functions"] = get_capella_order(
+ comp, left_context["functions"]
+ )
+ right_context["functions"] = get_capella_order(
+ _comp, right_context["functions"]
+ )
if port_spread >= _port_spread:
- self.left = comp
- self.right = _comp
- self.outgoing_edges = outs
self.incoming_edges = incs
- left_functions = functions
- right_functions = _functions
+ self.outgoing_edges = outs
else:
- self.left = _comp
- self.right = comp
- self.outgoing_edges = incs
self.incoming_edges = outs
- left_functions = _functions
- right_functions = functions
-
- make_boxes(self.left, left_functions)
- make_boxes(self.right, right_functions)
+ self.outgoing_edges = incs
+ left_context, right_context = right_context, left_context
+
+ if left_child := make_boxes(left_context):
+ self.data["children"].append(left_child)
+ self.left = left_child
+ if right_child := make_boxes(right_context):
+ self.data["children"].append(right_child)
+ self.right = right_child
except AttributeError:
pass
+ def add_interface(self) -> None:
+ ex_data = generic.ExchangeData(
+ self.obj,
+ self.data,
+ self.diagram.filters,
+ self.params,
+ is_hierarchical=False,
+ )
+ src, tgt = generic.exchange_data_collector(ex_data)
+ assert self.right is not None
+ if self.get_source(self.obj).uuid == self.right["id"]:
+ self.data["edges"][-1]["sources"] = [tgt.uuid]
+ self.data["edges"][-1]["targets"] = [src.uuid]
+
+ assert self.left is not None
+ self.left.setdefault("ports", []).append(makers.make_port(src.uuid))
+ self.right.setdefault("ports", []).append(makers.make_port(tgt.uuid))
+
def collect(self) -> None:
- """Return all allocated `FunctionalExchange`s in the context."""
+ """Collect all allocated `FunctionalExchange`s in the context."""
try:
- for ex in self.incoming_edges + self.outgoing_edges:
+ for ex in (self.incoming_edges | self.outgoing_edges).values():
ex_data = generic.ExchangeData(
ex,
self.data,
@@ -251,7 +312,7 @@ def collect(self) -> None:
)
src, tgt = generic.exchange_data_collector(ex_data)
- if ex in self.incoming_edges:
+ if ex in self.incoming_edges.values():
self.data["edges"][-1]["sources"] = [tgt.uuid]
self.data["edges"][-1]["targets"] = [src.uuid]
@@ -300,7 +361,7 @@ def collect(self) -> None:
made_children.add(comp.uuid)
all_functions.extend(functions)
- functional_exchanges.extend(inc + outs)
+ functional_exchanges.extend(inc | outs)
self.data["children"][0]["children"] = [
makers.make_box(c)
diff --git a/capellambse_context_diagrams/context.py b/capellambse_context_diagrams/context.py
index 419574cb..a672d365 100644
--- a/capellambse_context_diagrams/context.py
+++ b/capellambse_context_diagrams/context.py
@@ -368,7 +368,14 @@ class InterfaceContextDiagram(ContextDiagram):
``ComponentExchange``s.
"""
- def __init__(self, class_: str, obj: common.GenericElement, **kw) -> None:
+ def __init__(
+ self,
+ class_: str,
+ obj: common.GenericElement,
+ include_interface: bool = False,
+ **kw,
+ ) -> None:
+ self.include_interface = include_interface
super().__init__(class_, obj, **kw, display_symbols_as_boxes=True)
@property
diff --git a/docs/data_flow_view.md b/docs/data_flow_view.md
index fa101353..9c9127e2 100644
--- a/docs/data_flow_view.md
+++ b/docs/data_flow_view.md
@@ -24,7 +24,7 @@ The diagram elements are collected from the
diag.as_svgdiagram.save(pretty=True)
```
diff --git a/docs/gen_images.py b/docs/gen_images.py
index b07f7488..d48e173c 100644
--- a/docs/gen_images.py
+++ b/docs/gen_images.py
@@ -5,6 +5,7 @@
import logging
import pathlib
+import typing as t
import mkdocs_gen_files
from capellambse import MelodyModel, diagram
@@ -16,19 +17,23 @@
dest = pathlib.Path("assets") / "images"
model_path = pathlib.Path(__file__).parent.parent / "tests" / "data"
model = MelodyModel(path=model_path, entrypoint="ContextDiagram.aird")
-general_context_diagram_uuids = {
- "Environment": "e37510b9-3166-4f80-a919-dfaac9b696c7",
- "Eat": "8bcb11e6-443b-4b92-bec2-ff1d87a224e7",
- "Middle": "da08ddb6-92ba-4c3b-956a-017424dbfe85",
- "Capability": "9390b7d5-598a-42db-bef8-23677e45ba06",
- "Lost": "a5642060-c9cc-4d49-af09-defaa3024bae",
- "Left": "f632888e-51bc-4c9f-8e81-73e9404de784",
- "educate Wizards": "957c5799-1d4a-4ac0-b5de-33a65bf1519c",
- "Weird guy": "098810d9-0325-4ae8-a111-82202c0d2016",
- "Top secret": "5bf3f1e3-0f5e-4fec-81d5-c113d3a1b3a6",
+general_context_diagram_uuids: dict[str, tuple[str, dict[str, t.Any]]] = {
+ "Environment": ("e37510b9-3166-4f80-a919-dfaac9b696c7", {}),
+ "Eat": ("8bcb11e6-443b-4b92-bec2-ff1d87a224e7", {}),
+ "Middle": ("da08ddb6-92ba-4c3b-956a-017424dbfe85", {}),
+ "Capability": ("9390b7d5-598a-42db-bef8-23677e45ba06", {}),
+ "Lost": ("a5642060-c9cc-4d49-af09-defaa3024bae", {}),
+ "Left": ("f632888e-51bc-4c9f-8e81-73e9404de784", {}),
+ "educate Wizards": ("957c5799-1d4a-4ac0-b5de-33a65bf1519c", {}),
+ "Weird guy": ("098810d9-0325-4ae8-a111-82202c0d2016", {}),
+ "Top secret": ("5bf3f1e3-0f5e-4fec-81d5-c113d3a1b3a6", {}),
}
-interface_context_diagram_uuids = {
- "Left to right": "3ef23099-ce9a-4f7d-812f-935f47e7938d",
+interface_context_diagram_uuids: dict[str, tuple[str, dict[str, t.Any]]] = {
+ "Left to right": ("3ef23099-ce9a-4f7d-812f-935f47e7938d", {}),
+ "Interface": (
+ "fbb7f735-3c1f-48de-9791-179d35ca7b98",
+ {"include_interface": True},
+ ),
}
hierarchy_context = "16b4fcc5-548d-4721-b62a-d3d5b1c1d2eb"
diagram_uuids = general_context_diagram_uuids | interface_context_diagram_uuids
@@ -40,15 +45,16 @@
def generate_index_images() -> None:
- for uuid in diagram_uuids.values():
+ for uuid, render_params in diagram_uuids.values():
diag: context.ContextDiagram = model.by_uuid(uuid).context_diagram
with mkdocs_gen_files.open(f"{str(dest / diag.name)}.svg", "w") as fd:
- print(diag.render("svg", transparent_background=False), file=fd)
+ render_params["transparent_background"] = False # type: ignore[index]
+ print(diag.render("svg", **render_params), file=fd) # type: ignore[arg-type]
def generate_no_symbol_images() -> None:
for name in ("Capability", "Middle"):
- uuid = general_context_diagram_uuids[name]
+ uuid, _ = general_context_diagram_uuids[name]
diag: context.ContextDiagram = model.by_uuid(uuid).context_diagram
diag.display_symbols_as_boxes = True
diag.invalidate_cache()
@@ -170,23 +176,23 @@ def generate_derived_image() -> None:
generate_hierarchy_image()
generate_no_symbol_images()
-wizard = general_context_diagram_uuids["educate Wizards"]
-generate_no_edgelabel_image(wizard)
+wizard_uuid = general_context_diagram_uuids["educate Wizards"][0]
+generate_no_edgelabel_image(wizard_uuid)
-lost = general_context_diagram_uuids["Lost"]
-generate_filter_image(lost, filters.EX_ITEMS, "ex")
-generate_filter_image(lost, filters.FEX_EX_ITEMS, "fex and ex")
-generate_filter_image(lost, filters.FEX_OR_EX_ITEMS, "fex or ex")
+lost_uuid = general_context_diagram_uuids["Lost"][0]
+generate_filter_image(lost_uuid, filters.EX_ITEMS, "ex")
+generate_filter_image(lost_uuid, filters.FEX_EX_ITEMS, "fex and ex")
+generate_filter_image(lost_uuid, filters.FEX_OR_EX_ITEMS, "fex or ex")
generate_styling_image(
- lost,
+ lost_uuid,
dict(
styling.BLUE_ACTOR_FNCS,
junction=lambda o, s: {"stroke": diagram.RGB(220, 20, 60)},
),
"red junction",
)
-generate_styling_image(wizard, {}, "no_styles")
+generate_styling_image(wizard_uuid, {}, "no_styles")
generate_class_tree_images()
generate_realization_view_images()
generate_data_flow_image()
diff --git a/docs/index.md b/docs/index.md
index 93ab4d46..93f44bfb 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -17,8 +17,8 @@ base class with [`ContextDiagram`s][capellambse_context_diagrams.context.Context
Generate **Context Diagrams** from your model data!
## Features
@@ -192,6 +192,21 @@ The data is collected by [get_elkdata_for_exchanges][capellambse_context_diagram
Interface context diagram of Left to right LogicalComponentExchange with type [LAB]
+??? example "Include the interface the ([`fa.ComponentExchange`][capellambse.model.crosslayer.fa.ComponentExchange])"
+
+ ``` py
+ import capellambse
+
+ model = capellambse.MelodyModel("tests/data/ContextDiagram.aird")
+ diag = model.by_uuid("fbb7f735-3c1f-48de-9791-179d35ca7b98").context_diagram
+ diag.render("svgdiagram", include_interface=True).save(pretty=True)
+ ```
+
+
+
!!! warning "Interface context only supported for the LogicalComponentExchanges"
### Customized edge routing
diff --git a/tests/data/ContextDiagram.aird b/tests/data/ContextDiagram.aird
index 61b5b7b3..ca8830e5 100644
--- a/tests/data/ContextDiagram.aird
+++ b/tests/data/ContextDiagram.aird
@@ -54,7 +54,7 @@
-
+
@@ -62,7 +62,7 @@
-
+
@@ -78,7 +78,7 @@
-
+
@@ -102,6 +102,14 @@
+
+
+
+
+
+
+
+
@@ -2041,7 +2049,7 @@
-
+
@@ -2052,7 +2060,7 @@
-
+
@@ -2063,10 +2071,10 @@
-
+
-
+
@@ -2083,7 +2091,7 @@
-
+
@@ -2128,22 +2136,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2162,17 +2154,17 @@
-
+
-
+
-
+
-
+
@@ -2224,22 +2216,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -2258,17 +2234,17 @@
-
+
-
+
-
+
-
+
@@ -2290,17 +2266,17 @@
-
+
-
+
-
+
@@ -2322,17 +2298,17 @@
-
+
-
+
-
+
-
+
@@ -2448,6 +2424,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -2500,7 +2508,7 @@
-
+
@@ -2541,7 +2549,7 @@
-
+
@@ -2671,7 +2679,7 @@
-
+
@@ -2681,7 +2689,7 @@
-
+
@@ -2691,7 +2699,7 @@
-
+
@@ -2755,7 +2763,7 @@
-
+
@@ -2765,7 +2773,7 @@
-
+
@@ -2920,17 +2928,6 @@
-
-
-
-
-
-
-
-
-
-
-
@@ -2968,6 +2965,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3425,15 +3444,6 @@
-
-
-
-
-
-
-
-
-
@@ -3461,6 +3471,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
KEEP_LOCATION
KEEP_SIZE
KEEP_RATIO
@@ -3508,8 +3536,8 @@
KEEP_LOCATION
KEEP_SIZE
KEEP_RATIO
-
-
+
+
@@ -7753,7 +7781,7 @@
-
+
@@ -9451,4 +9479,733 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ KEEP_LOCATION
+ KEEP_SIZE
+ KEEP_RATIO
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/data/ContextDiagram.capella b/tests/data/ContextDiagram.capella
index a20b61b3..1a673425 100644
--- a/tests/data/ContextDiagram.capella
+++ b/tests/data/ContextDiagram.capella
@@ -2971,6 +2971,35 @@ The predator is far away
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -3008,20 +3037,20 @@ The predator is far away
id="0fe9e999-3bd8-4590-9dc2-f51d2c1af173" name="FunctionalExchange 11"
target="#494979bd-d301-419b-8a91-fd1c28dec21c" source="#aaf1f13c-270f-4d67-bc65-37a1c9afb17a"/>
-
+
@@ -3067,6 +3096,18 @@ The predator is far away
+
+
+
+
+
+
+
+
+
+
name="LC 16" abstractType="#749a54c8-1ee6-41ac-851d-08994c5fb403"/>
+
+
@@ -3837,6 +3898,71 @@ The predator is far away
id="b30ee5f7-e2ce-43c5-b8cc-fc0f7335929f" targetElement="#24cfdc5b-918d-4f62-98e3-260d91d635fc"
sourceElement="#84525f1a-a5e5-4ca5-bbe8-7e5c64aa18d0"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
None:
+ obj = model.by_uuid(TEST_INTERFACE_UUID)
+
+ diag = obj.context_diagram
+
+ assert diag.nodes
+
+
+def test_interface_diagram_with_included_interface(
+ model: capellambse.MelodyModel,
+) -> None:
+ obj = model.by_uuid(TEST_INTERFACE_UUID)
+
+ diag = obj.context_diagram.render(None, include_interface=True)
+
+ assert diag[TEST_INTERFACE_UUID]