Skip to content

Commit

Permalink
fix: Edge labels and label padding control
Browse files Browse the repository at this point in the history
  • Loading branch information
ewuerger committed Mar 19, 2024
1 parent db4b54f commit 1ba655a
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 60 deletions.
47 changes: 22 additions & 25 deletions capellambse_context_diagrams/collectors/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,30 +126,21 @@ def exchange_data_collector(
if data.is_hierarchical:
target, source = source, target

label = collect_label(data.exchange)
for filter in data.filter_iterable:
try:
label = filters.FILTER_LABEL_ADJUSTERS[filter](
data.exchange, label
)
except KeyError:
logger.exception(
"There is no filter labelled: '%s' in filters.FILTER_LABEL_ADJUSTERS",
filter,
)

params = (data.params or {}).copy()
# Remove simple render parameters from params
no_edgelabels: bool = params.pop("no_edgelabels", False)
params.pop("transparent_background", False)
font_family = params.pop("font_family", "Open Sans")
font_size = params.pop("font_size", 12)

render_adj: dict[str, t.Any] = {}
for name, value in params.items():
try:
filters.RENDER_ADJUSTERS[name](value, data.exchange, render_adj)
except KeyError:
logger.exception(
"There is no render parameter solver labelled: '%s' in filters.RENDER_ADJUSTERS",
"There is no render parameter solver labelled: '%s' "
"in filters.RENDER_ADJUSTERS",
name,
)

Expand All @@ -160,19 +151,25 @@ def exchange_data_collector(
"targets": [render_adj.get("targets", target.uuid)],
},
)

label = collect_label(data.exchange)
for filter in data.filter_iterable:
try:
label = filters.FILTER_LABEL_ADJUSTERS[filter](
data.exchange, label
)
except KeyError:
logger.exception(
"There is no filter labelled: '%s' in "
"filters.FILTER_LABEL_ADJUSTERS",
filter,
)

if label and not no_edgelabels:
width, height = helpers.extent_func(label)
data.elkdata["edges"][-1]["labels"] = [
{
"text": render_adj.get("labels_text", label),
"width": render_adj.get(
"labels_width", width + 2 * makers.LABEL_HPAD
),
"height": render_adj.get(
"labels_height", height + 2 * makers.LABEL_VPAD
),
}
]
data.elkdata["edges"][-1]["labels"] = makers.make_label(
render_adj.get("labels_text", label),
max_width=makers.MAX_LABEL_WIDTH,
)

return source, target

Expand Down
11 changes: 6 additions & 5 deletions capellambse_context_diagrams/collectors/makers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@
"""Default size of ports in pixels."""
PORT_PADDING = 2
"""Default padding of ports in pixels."""
LABEL_HPAD = 5
LABEL_HPAD = 3
"""Horizontal padding left and right of the label."""
LABEL_VPAD = 1
"""Vertical padding above and below the label."""
MAX_LABEL_WIDTH = 200
"""Maximum width for edge labels."""
NEIGHBOR_VMARGIN = 20
"""Vertical space between two neighboring boxes."""
EOI_WIDTH = 100
Expand Down Expand Up @@ -87,7 +89,7 @@ def make_label(
[`ELKInputLabel`][capellambse_context_diagrams._elkjs.ELKInputLabel].
"""
label_width, label_height = chelpers.get_text_extent(text)
icon_width, icon_height = icon
icon_width, _ = icon
lines = [text]
if max_width is not None and label_width > max_width:
lines, _, _ = svghelpers.check_for_horizontal_overflow(
Expand All @@ -105,11 +107,10 @@ def make_label(
{
"text": line,
"width": icon_width + label_width + 2 * LABEL_HPAD,
"height": icon_height + label_height + 2 * LABEL_VPAD,
"height": label_height + 2 * LABEL_VPAD,
"layoutOptions": layout_options,
}
)
icon_height *= 0
return labels


Expand Down Expand Up @@ -178,7 +179,7 @@ def calculate_height_and_width(
"""Calculate the size (width and height) from given labels for a box."""
icon = icon_size + icon_padding * 2
_height = sum(label["height"] + 2 * LABEL_VPAD for label in labels) + icon
min_width = max(label["width"] + 2 * LABEL_HPAD for label in labels) + icon
min_width = max(label["width"] + 2 * LABEL_HPAD for label in labels)
width = min_width if slim_width else max(width, min_width)
return width, max(height, _height)

Expand Down
37 changes: 20 additions & 17 deletions capellambse_context_diagrams/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,28 +180,31 @@ class type that stores all previously named classes.
self._cache[child["id"]] = element
elif child["type"] == "label":
assert parent is not None
if isinstance(parent, diagram.Box) and not parent.port:
if not parent.port:
if parent.JSON_TYPE != "symbol":
parent.styleoverrides |= self.get_styleoverrides(child)

parent.labels.append(
diagram.Box(
ref + (child["position"]["x"], child["position"]["y"]),
(child["size"]["width"], child["size"]["height"]),
labels=[child["text"]],
styleoverrides=self.get_styleoverrides(child),
if parent.labels:
label_box = parent.labels[-1]
label_box.labels.append(child["text"])
label_box.size = diagram.Vector2D(
max(label_box.size.x, child["size"]["width"]),
label_box.size.y + child["size"]["height"],
)
)
else:
assert isinstance(parent, diagram.Edge)
parent.labels.append(
diagram.Box(
ref + (child["position"]["x"], child["position"]["y"]),
(child["size"]["width"], child["size"]["height"]),
labels=[child["text"]],
styleoverrides=self.get_styleoverrides(child),
label_box.pos = diagram.Vector2D(
min(label_box.pos.x, ref.x + child["position"]["x"]),
label_box.pos.y,
)
else:
parent.labels.append(
diagram.Box(
ref
+ (child["position"]["x"], child["position"]["y"]),
(child["size"]["width"], child["size"]["height"]),
labels=[child["text"]],
styleoverrides=self.get_styleoverrides(child),
)
)
)

element = parent
elif child["type"] == "junction":
Expand Down
16 changes: 10 additions & 6 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ def start_filter_apply_test(


def get_ExchangeItems(edge: diagram.Edge) -> list[str]:
assert isinstance(edge.labels[0].labels[0], str)
match = EX_PTRN.match(edge.labels[0].labels[0])
label = " ".join(edge.labels[0].labels)
assert isinstance(label, str)
match = EX_PTRN.match(label)
assert match is not None
return match.group(1).split(", ")

Expand Down Expand Up @@ -128,8 +129,8 @@ def test_context_diagrams_FEX_EX_ITEMS_is_applied(

assert isinstance(aedge, diagram.Edge)
assert len(aedge.labels) == 1
assert isinstance(aedge.labels[0].labels[0], str)
assert aedge.labels[0].labels[0] == expected_label
assert isinstance(aedge.labels[0].labels, list)
assert [" ".join(aedge.labels[0].labels)] == [expected_label]


@pytest.mark.parametrize("uuid", (FNC_UUID, INTERF_UUID))
Expand All @@ -145,7 +146,7 @@ def test_context_diagrams_FEX_OR_EX_ITEMS_is_applied(

assert isinstance(aedge, diagram.Edge)

label = aedge.labels[0].labels[0]
label = " ".join(aedge.labels[0].labels)
if edge.exchange_items:
eitem_label_frag = ", ".join(
(exi.name for exi in edge.exchange_items)
Expand Down Expand Up @@ -189,7 +190,10 @@ def test_context_diagrams_NO_UUID_is_applied(model: MelodyModel) -> None:
aedge = aird_diag[CAP_EXPLOIT]

assert isinstance(aedge, diagram.Edge)
assert aedge.labels[0].labels == ["[CapabilityExploitation] to Capability"]
assert (
" ".join(aedge.labels[0].labels)
== "[CapabilityExploitation] to Capability"
)


def test_context_diagrams_no_edgelabels_render_param_is_applied(
Expand Down
15 changes: 8 additions & 7 deletions tests/test_labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
pytest.param(
"d817767f-68b7-49a5-aa47-13419d41df0a",
[
["Really long label"],
["that needs"],
["wrapping else"],
["its parent box is"],
["also very long!"],
"Really long",
"label that",
"needs",
"wrapping else",
"its parent box",
"is also very",
"long!",
],
id="LogicalFunction",
),
Expand All @@ -27,6 +29,5 @@ def test_context_diagrams(
obj = model.by_uuid(uuid)

diagram = obj.context_diagram.render(None)
labels = [label.labels for label in diagram[uuid].labels]

assert labels == expected_labels
assert diagram[uuid].labels[0].labels == expected_labels

0 comments on commit 1ba655a

Please sign in to comment.