diff --git a/capellambse_context_diagrams/__init__.py b/capellambse_context_diagrams/__init__.py index f0d52bd6..3d496816 100644 --- a/capellambse_context_diagrams/__init__.py +++ b/capellambse_context_diagrams/__init__.py @@ -152,9 +152,9 @@ def register_functional_context() -> None: def register_class_tree() -> None: - """Add the `class_tree_diagram` attribute to `ModelObject`s.""" + """Add the `tree_diagram` attribute to ``Class``es.""" common.set_accessor( information.Class, - "class_tree_diagram", + "tree_diagram", context.ClassTreeAccessor(DiagramType.CDB.value), ) diff --git a/capellambse_context_diagrams/collectors/class_tree.py b/capellambse_context_diagrams/collectors/class_tree.py index 64b93653..009913de 100644 --- a/capellambse_context_diagrams/collectors/class_tree.py +++ b/capellambse_context_diagrams/collectors/class_tree.py @@ -12,29 +12,26 @@ from .. import _elkjs, context from . import generic, makers -LAYOUT_OPTIONS: _elkjs.LayoutOptions = { - "algorithm": "layered", - "edgeRouting": "ORTHOGONAL", - "elk.direction": "DOWN", - "partitioning.activate": True, - "edgeLabels.sideSelection": "ALWAYS_DOWN", -} - def collector( - diagram: context.ContextDiagram, params: dict[str, t.Any] | None = None + diagram: context.ContextDiagram, params: dict[str, t.Any] ) -> _elkjs.ELKInputData: """Return the class tree data for ELK.""" - params = params or {} assert isinstance(diagram.target, information.Class) data = generic.collector(diagram, no_symbol=True) if params.get("partitioning", False): + data["layoutOptions"]["partitioning.activate"] = True data["children"][0]["layoutOptions"] = {} data["children"][0]["layoutOptions"]["elk.partitioning.partition"] = 0 - data["layoutOptions"] = LAYOUT_OPTIONS - data["layoutOptions"]["algorithm"] = (params or {})["algorithm"] - data["layoutOptions"]["elk.direction"] = (params or {})["direction"] - data["layoutOptions"]["edgeRouting"] = (params or {})["edgeRouting"] + + data["layoutOptions"]["edgeLabels.sideSelection"] = params.get( + "edgeLabelsSide", "ALWAYS_DOWN" + ) + data["layoutOptions"]["algorithm"] = params.get("algorithm", "layered") + data["layoutOptions"]["elk.direction"] = params.get("direction", "DOWN") + data["layoutOptions"]["edgeRouting"] = params.get( + "edgeRouting", "ORTHOGONAL" + ) made_boxes: set[str] = set() for _, (source, prop, target, partition) in get_all_classes( diff --git a/capellambse_context_diagrams/context.py b/capellambse_context_diagrams/context.py index 53ca7ce8..536f888a 100644 --- a/capellambse_context_diagrams/context.py +++ b/capellambse_context_diagrams/context.py @@ -351,5 +351,6 @@ def _create_diagram(self, params: dict[str, t.Any]) -> cdiagram.Diagram: params.setdefault("direction", "DOWN") params.setdefault("edgeRouting", "POLYLINE") params.setdefault("partitioning", True) + params.setdefault("edgeLabelsSide", "SMART_DOWN") params["elkdata"] = class_tree.collector(self, params) return super()._create_diagram(params) diff --git a/docs/class-tree.md b/docs/class-tree.md index 13ba69ed..4c55d44b 100644 --- a/docs/class-tree.md +++ b/docs/class-tree.md @@ -6,8 +6,9 @@ # Class Tree Diagram With release [`v0.5.35`](https://github.com/DSD-DBS/py-capellambse/releases/tag/v0.5.35) of [py-capellambse](https://github.com/DSD-DBS/py-capellambse) you can access the -`.class_tree_diagram` on `Class` objects. A class tree diagram shows a tree -made from all properties of the parent class. +`.tree_diagram` on [`Class`][capellambse.model.crosslayer.information.Class] +objects. A class tree diagram shows a tree made from all properties of the +parent class. ??? example "Class Tree of Root" @@ -15,7 +16,7 @@ made from all properties of the parent class. import capellambse model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("b7c7f442-377f-492c-90bf-331e66988bda").class_tree_diagram + diag = model.by_uuid("b7c7f442-377f-492c-90bf-331e66988bda").tree_diagram diag.render("svgdiagram").save_drawing(pretty=True) ```
@@ -43,6 +44,13 @@ ELK. The available options are: classes is its own partition. - True (default) - False +5. edgeLabelSide - Controls edge label placement. + - SMART_DOWN (default) + - SMART_UP + - ALWAYS_UP + - ALWAYS_DOWN + - DIRECTION_UP + - DIRECTION_DOWN Here is an example that shows how convenient these parameters can be passed before rendering: @@ -53,12 +61,13 @@ before rendering: import capellambse model = capellambse.MelodyModel("tests/data/ContextDiagram.aird") - diag = model.by_uuid("b7c7f442-377f-492c-90bf-331e66988bda").class_tree_diagram + diag = model.by_uuid("b7c7f442-377f-492c-90bf-331e66988bda").tree_diagram diag.render( "svgdiagram", edgeRouting="ORTHOGONAL", direction="Right", partitioning=False, + edgeLabelsSide="ALWAYS_DOWN", ).save_drawing(pretty=True) ```
diff --git a/docs/gen_images.py b/docs/gen_images.py index ed2ed843..f9004f57 100644 --- a/docs/gen_images.py +++ b/docs/gen_images.py @@ -94,7 +94,7 @@ def generate_hierarchy_image() -> None: def generate_class_tree_images() -> None: obj = model.by_uuid(class_tree_uuid) - diag = obj.class_tree_diagram + diag = obj.tree_diagram with mkdocs_gen_files.open(f"{str(dest / diag.name)}.svg", "w") as fd: print(diag.render("svg"), file=fd) with mkdocs_gen_files.open( @@ -106,6 +106,7 @@ def generate_class_tree_images() -> None: edgeRouting="ORTHOGONAL", direction="Right", partitioning=False, + edgeLabelsSide="ALWAYS_DOWN", ), file=fd, ) diff --git a/tests/test_class_tree_diagrams.py b/tests/test_class_tree_diagrams.py index 98a2b48f..66e20866 100644 --- a/tests/test_class_tree_diagrams.py +++ b/tests/test_class_tree_diagrams.py @@ -8,12 +8,12 @@ @pytest.mark.parametrize("fmt", ["svgdiagram", "svg", None]) -def test_class_tree_diagram_gets_rendered_successfully( +def test_tree_diagram_gets_rendered_successfully( model: capellambse.MelodyModel, fmt: str ) -> None: obj = model.by_uuid(CLASS_UUID) - diag = obj.class_tree_diagram + diag = obj.tree_diagram assert diag.render(fmt) @@ -21,19 +21,24 @@ def test_class_tree_diagram_gets_rendered_successfully( @pytest.mark.parametrize("edgeRouting", ["SPLINE", "ORTHOGONAL", "POLYLINE"]) @pytest.mark.parametrize("direction", ["DOWN", "RIGHT"]) @pytest.mark.parametrize("partitioning", [True, False]) -def test_class_tree_diagram_renders_with_additional_params( +@pytest.mark.parametrize( + "edgeLabelsSide", ["ALWAYS_DOWN", "DIRECTION_DOWN", "SMART_DOWN"] +) +def test_tree_diagram_renders_with_additional_params( model: capellambse.MelodyModel, edgeRouting: str, direction: str, partitioning: bool, + edgeLabelsSide: str, ) -> None: obj = model.by_uuid(CLASS_UUID) - diag = obj.class_tree_diagram + diag = obj.tree_diagram assert diag.render( "svgdiagram", edgeRouting=edgeRouting, direction=direction, partitioning=partitioning, + edgeLabelsSide=edgeLabelsSide, )