diff --git a/capellambse_context_diagrams/context.py b/capellambse_context_diagrams/context.py index 6833115a..722b3b41 100644 --- a/capellambse_context_diagrams/context.py +++ b/capellambse_context_diagrams/context.py @@ -422,24 +422,10 @@ def _create_diagram(self, params: dict[str, t.Any]) -> cdiagram.Diagram: "search_direction", params.get("search_direction", "ALL") ) params.setdefault("show_owners", params.get("show_owners", True)) + params.setdefault("layer_sizing", params.get("layer_sizing", "UNION")) data, edges = realization_view.collector(self, params) layout = try_to_layout(data) - min_width = max(child["size"]["width"] for child in layout["children"]) # type: ignore[typeddict-item] - min_width += 15.0 - for layer in data["children"]: - min_height: int | float = 0 - for layout_layer in layout["children"]: - if layer["id"] != layout_layer["id"]: - continue - assert layout_layer["type"] != "edge" - min_height = layout_layer["size"]["height"] - - assert min_height > 0 - layer["width"] = min_width - layer["layoutOptions"][ - "nodeSize.minimum" - ] = f"({min_width},{min_height})" - + adjust_layer_sizing(data, layout, params["layer_sizing"]) layout = try_to_layout(data) for edge in edges: layout["children"].append( @@ -490,6 +476,42 @@ def try_to_layout(data: _elkjs.ELKInputData) -> _elkjs.ELKOutputData: raise error +def adjust_layer_sizing( + data: _elkjs.ELKInputData, + layout: _elkjs.ELKOutputData, + layer_sizing: t.Literal["UNION", "WIDTH", "HEIGHT"], +) -> None: + """Set `nodeSize.minimum` config in the layoutOptions.""" + + def calculate_min_width() -> float: + return max(child["size"]["width"] for child in layout["children"]) + 15.0 # type: ignore[typeddict-item] + + def find_layer_height(layer_id: str) -> float: + for layout_layer in layout["children"]: + if ( + layer_id == layout_layer["id"] + and layout_layer["type"] != "edge" + ): + return layout_layer["size"]["height"] + return 0.0 + + if layer_sizing not in {"UNION", "WIDTH", "HEIGHT"}: + raise NotImplementedError( + "For ``layer_sizing`` only UNION, WIDTH or HEIGHT is supported" + ) + + min_w = calculate_min_width() if layer_sizing in ["UNION", "WIDTH"] else 0 + for layer in data["children"]: + min_h = ( + find_layer_height(layer["id"]) + if layer_sizing in {"UNION", "HEIGHT"} + else 0 + ) + layer["layoutOptions"]["nodeSize.minimum"] = f"({min_w},{min_h})" + if layer_sizing in {"UNION", "WIDTH"}: + layer["width"] = min_w + + def stack_diagrams( first: cdiagram.Diagram, second: cdiagram.Diagram, diff --git a/docs/realization_view.md b/docs/realization_view.md index e32ce2c2..cb42359f 100644 --- a/docs/realization_view.md +++ b/docs/realization_view.md @@ -32,6 +32,7 @@ implement currently. The diagram elements are collected from the depth=3, # 1-3 search_direction="ALL", # BELOW; ABOVE and ALL show_owners=True, + layer_sizing="UNION", # UNION; WIDTH and HEIGHT ).save_drawing(pretty=True) ```
@@ -51,6 +52,7 @@ implement currently. The diagram elements are collected from the depth=3, search_direction="ALL", show_owners=True, + layer_sizing="UNION", ).save_drawing(pretty=True) ```
@@ -59,8 +61,9 @@ implement currently. The diagram elements are collected from the
Additional rendering parameters enable showing owning functions or components, -as well as the depth of traversion (i.e. `1`-`3`). They are put to display the -maximum amount of diagram elements per default. +as well as the depth of traversion (i.e. `1`-`3`) and control on sizing of the +layer boxes. They are put to display the maximum amount of diagram elements per +default. ??? bug "Alignment of diagram elements" diff --git a/tests/test_realization_views.py b/tests/test_realization_views.py index 5439fbb9..826c30b3 100644 --- a/tests/test_realization_views.py +++ b/tests/test_realization_views.py @@ -27,11 +27,13 @@ def test_tree_view_gets_rendered_successfully( @pytest.mark.parametrize("depth", list(range(1, 4))) @pytest.mark.parametrize("search_direction", ["ABOVE", "BELOW"]) @pytest.mark.parametrize("show_owners", [True, False]) +@pytest.mark.parametrize("layer_sizing", ["UNION", "WIDTH", "HEIGHT"]) def test_tree_view_renders_with_additional_params( model: capellambse.MelodyModel, depth: int, search_direction: str, show_owners: bool, + layer_sizing: str, uuid: str, ) -> None: obj = model.by_uuid(uuid) @@ -43,4 +45,5 @@ def test_tree_view_renders_with_additional_params( depth=depth, search_direction=search_direction, show_owners=show_owners, + layer_sizing=layer_sizing, )