Skip to content

_makers

BOX_TO_SYMBOL module-attribute 🔗

BOX_TO_SYMBOL = (
    __name__,
    __name__,
    __name__,
    __name__,
    "SystemHumanActor",
    "SystemActor",
)

Types that need to be converted to symbols during serialization if display_symbols_as_boxes attribute is False.

CENTRIC_LABEL_LAYOUT_OPTIONS module-attribute 🔗

CENTRIC_LABEL_LAYOUT_OPTIONS: LayoutOptions = {
    "nodeLabels.placement": "INSIDE, V_CENTER, H_CENTER"
}

Layout options for a centric label.

DEFAULT_LABEL_LAYOUT_OPTIONS module-attribute 🔗

DEFAULT_LABEL_LAYOUT_OPTIONS: LayoutOptions = {
    "nodeLabels.placement": "INSIDE, V_TOP, H_CENTER"
}

Default layout options for a label.

EOI_WIDTH module-attribute 🔗

EOI_WIDTH = 100

The width of the element of interest.

FAULT_PAD module-attribute 🔗

FAULT_PAD = 10

Height adjustment for labels.

ICON_HEIGHT module-attribute 🔗

ICON_HEIGHT = icon_size

Default icon height from capellambse.

ICON_WIDTH module-attribute 🔗

ICON_WIDTH = icon_size + icon_padding * 2

Default icon width from capellambse including the padding around it.

LABEL_HPAD module-attribute 🔗

LABEL_HPAD = 3

Horizontal padding left and right of the label.

LABEL_VPAD module-attribute 🔗

LABEL_VPAD = 1

Vertical padding above and below the label.

MAX_BOX_WIDTH module-attribute 🔗

MAX_BOX_WIDTH = 150

Maximum width of boxes.

MAX_LABEL_WIDTH module-attribute 🔗

MAX_LABEL_WIDTH = 200

Maximum width for edge labels.

MAX_SYMBOL_HEIGHT module-attribute 🔗

MAX_SYMBOL_HEIGHT = 135

Maximum height of symbols.

MAX_SYMBOL_WIDTH module-attribute 🔗

MAX_SYMBOL_WIDTH = 150

Maximum width of symbols.

MIN_SYMBOL_HEIGHT module-attribute 🔗

MIN_SYMBOL_HEIGHT = 17

Minimum height of symbols.

MIN_SYMBOL_WIDTH module-attribute 🔗

MIN_SYMBOL_WIDTH = 30

Minimum width of symbols.

NEIGHBOR_VMARGIN module-attribute 🔗

NEIGHBOR_VMARGIN = 20

Vertical space between two neighboring boxes.

PORT_PADDING module-attribute 🔗

PORT_PADDING = 2

Default padding of ports in pixels.

PORT_SIZE module-attribute 🔗

PORT_SIZE = 10

Default size of ports in pixels.

SYMBOL_LAYOUT_OPTIONS module-attribute 🔗

SYMBOL_LAYOUT_OPTIONS: LayoutOptions = {
    "nodeLabels.placement": "OUTSIDE, V_BOTTOM, H_CENTER"
}

Layout options for a symbol label.

SYMBOL_RATIO module-attribute 🔗

SYMBOL_RATIO = MIN_SYMBOL_WIDTH / MIN_SYMBOL_HEIGHT

Width and height ratio of symbols.

adjust_box_height_for_ports 🔗

adjust_box_height_for_ports(box: ELKInputChild) -> None

Adjust box height based on number of ports.

Source code in src/capellambse_context_diagrams/builders/_makers.py
290
291
292
def adjust_box_height_for_ports(box: _elkjs.ELKInputChild) -> None:
    """Adjust box height based on number of ports."""
    box.height = (PORT_SIZE + 2 * PORT_PADDING) * (len(box.ports) + 1)

calculate_height_and_width 🔗

calculate_height_and_width(
    labels: list[ELKInputLabel],
    *,
    width: int | float = 0,
    height: int | float = 0,
    slim_width: bool = False
) -> tuple[int | float, int | float]

Calculate the size (width and height) from given labels for a box.

Source code in src/capellambse_context_diagrams/builders/_makers.py
200
201
202
203
204
205
206
207
208
209
210
211
212
def calculate_height_and_width(
    labels: list[_elkjs.ELKInputLabel],
    *,
    width: int | float = 0,
    height: int | float = 0,
    slim_width: bool = False,
) -> tuple[int | float, int | float]:
    """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)
    width = min_width if slim_width else max(width, min_width)
    return width, max(height, _height)

is_symbol 🔗

is_symbol(obj: str | ModelElement | None) -> bool

Check if given obj is rendered as a Symbol instead of a Box.

Source code in src/capellambse_context_diagrams/builders/_makers.py
215
216
217
218
219
220
221
def is_symbol(obj: str | m.ModelElement | None) -> bool:
    """Check if given `obj` is rendered as a Symbol instead of a Box."""
    if obj is None:
        return False
    if isinstance(obj, str):
        return obj in BOX_TO_SYMBOL
    return type(obj).__name__ in BOX_TO_SYMBOL

make_box 🔗

make_box(
    obj: ModelElement,
    *,
    width: int | float = 0,
    height: int | float = 0,
    no_symbol: bool = False,
    slim_width: bool = True,
    label_getter: Callable[
        [ModelElement], Iterable[_LabelBuilder]
    ] = lambda i: [
        {"text": i.name, "icon": (ICON_WIDTH, 0), "layout_options": {}}
    ],
    max_label_width: int | float = MAX_BOX_WIDTH,
    layout_options: LayoutOptions | None = None
) -> _elkjs.ELKInputChild

Return a box.

See Also

ELKInputChild : Input data for an ELK box.

Source code in src/capellambse_context_diagrams/builders/_makers.py
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
def make_box(
    obj: m.ModelElement,
    *,
    width: int | float = 0,
    height: int | float = 0,
    no_symbol: bool = False,
    slim_width: bool = True,
    label_getter: cabc.Callable[
        [m.ModelElement], cabc.Iterable[_LabelBuilder]
    ] = lambda i: [
        {
            "text": i.name,
            "icon": (ICON_WIDTH, 0),
            "layout_options": {},
        }
    ],
    max_label_width: int | float = MAX_BOX_WIDTH,
    layout_options: _elkjs.LayoutOptions | None = None,
) -> _elkjs.ELKInputChild:
    """Return a box.

    See Also
    --------
    [`ELKInputChild`][capellambse_context_diagrams._elkjs.ELKInputChild] :
        Input data for an ELK box.
    """
    layout_options = layout_options or CENTRIC_LABEL_LAYOUT_OPTIONS
    if symbol := not no_symbol and is_symbol(obj):
        max_label_width = 200

    labels: list[_elkjs.ELKInputLabel] = []
    for label_builder in label_getter(obj):
        if not label_builder.get("layout_options"):
            label_builder.setdefault("layout_options", {}).update(
                layout_options
            )

        labels.extend(make_label(**label_builder, max_width=max_label_width))

    if symbol:
        if height < MIN_SYMBOL_HEIGHT:
            height = MIN_SYMBOL_HEIGHT
        elif height > MAX_SYMBOL_HEIGHT:
            height = MAX_SYMBOL_HEIGHT
        width = height * SYMBOL_RATIO
        for label in labels:
            label.layoutOptions.update(SYMBOL_LAYOUT_OPTIONS)
    else:
        width, height = calculate_height_and_width(
            labels, width=width, height=height, slim_width=slim_width
        )
    return _elkjs.ELKInputChild(
        id=obj.uuid,
        labels=labels,
        width=width,
        height=height,
    )

make_diagram 🔗

make_diagram(diagram: ContextDiagram) -> _elkjs.ELKInputData

Return basic skeleton for ContextDiagrams.

Source code in src/capellambse_context_diagrams/builders/_makers.py
82
83
84
85
86
87
88
89
def make_diagram(diagram: context.ContextDiagram) -> _elkjs.ELKInputData:
    """Return basic skeleton for ``ContextDiagram``s."""
    return _elkjs.ELKInputData(
        id=diagram.uuid,
        layoutOptions=_elkjs.get_global_layered_layout_options(),
        children=[],
        edges=[],
    )

make_label 🔗

make_label(
    text: str,
    icon: tuple[int | float, int | float] = (ICON_WIDTH, ICON_HEIGHT),
    layout_options: LayoutOptions | None = None,
    max_width: int | float | None = None,
) -> list[_elkjs.ELKInputLabel]

Return a label.

See Also

ELKInputLabel : Input data for an ELK label.

Source code in src/capellambse_context_diagrams/builders/_makers.py
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
def make_label(
    text: str,
    icon: tuple[int | float, int | float] = (ICON_WIDTH, ICON_HEIGHT),
    layout_options: _elkjs.LayoutOptions | None = None,
    max_width: int | float | None = None,
) -> list[_elkjs.ELKInputLabel]:
    """Return a label.

    See Also
    --------
    [`ELKInputLabel`][capellambse_context_diagrams._elkjs.ELKInputLabel] :
        Input data for an ELK label.
    """
    label_width, label_height = chelpers.get_text_extent(text)
    icon_width, _ = icon
    lines: cabc.Sequence[str] = [text]
    if max_width is not None and label_width > max_width:
        lines, _, _ = svghelpers.check_for_horizontal_overflow(
            text,
            max_width,
            icon_padding,
            icon_width,
        )

    layout_options = layout_options or CENTRIC_LABEL_LAYOUT_OPTIONS
    labels: list[_elkjs.ELKInputLabel] = []
    for line in lines:
        label_width, label_height = chelpers.get_text_extent(line)
        labels.append(
            _elkjs.ELKInputLabel(
                text=line,
                width=(
                    (icon_width + label_width + 2 * LABEL_HPAD) if line else 0
                ),
                height=(label_height + 2 * LABEL_VPAD) if line else 0,
                layoutOptions=layout_options,
            )
        )
    return labels

make_owner_boxes 🔗

make_owner_boxes(
    obj: ModelElement,
    excluded: list[str],
    make_box_func: Callable,
    boxes: dict[str, ELKInputChild],
    boxes_to_delete: set[str],
    max_depth: int = sys.maxsize,
) -> str

Create owner boxes for all owners of obj.

Source code in src/capellambse_context_diagrams/builders/_makers.py
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
def make_owner_boxes(
    obj: m.ModelElement,
    excluded: list[str],
    make_box_func: cabc.Callable,
    boxes: dict[str, _elkjs.ELKInputChild],
    boxes_to_delete: set[str],
    max_depth: int = sys.maxsize,
) -> str:
    """Create owner boxes for all owners of ``obj``."""
    current = obj
    depth: int = 0
    while (
        current
        and current.uuid not in excluded
        and getattr(current, "owner", None) is not None
        and not isinstance(current.owner, PackageTypes)
        and depth < max_depth
    ):
        current = make_owner_box(
            current, make_box_func, boxes, boxes_to_delete
        )
        depth += 1
    return current.uuid

make_port 🔗

make_port(uuid: str, label: str = '') -> _elkjs.ELKInputPort

Return a port.

See Also

ELKInputPort : Input data for an ELK port.

Source code in src/capellambse_context_diagrams/builders/_makers.py
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
def make_port(uuid: str, label: str = "") -> _elkjs.ELKInputPort:
    """Return a port.

    See Also
    --------
    [`ELKInputPort`][capellambse_context_diagrams._elkjs.ELKInputPort] :
        Input data for an ELK port.
    """
    labels = make_label(label) if label else []
    return _elkjs.ELKInputPort(
        id=uuid,
        width=PORT_SIZE,
        height=PORT_SIZE,
        labels=labels,
        layoutOptions={"borderOffset": -4 * PORT_PADDING},
    )