Skip to content

makers

BOX_TO_SYMBOL = (layers.ctx.Capability.__name__, layers.oa.OperationalCapability.__name__, layers.ctx.Mission.__name__, layers.ctx.SystemComponent.__name__, 'SystemHumanActor', 'SystemActor') module-attribute 🔗

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

CENTRIC_LABEL_LAYOUT_OPTIONS: _elkjs.LayoutOptions = {'nodeLabels.placement': 'INSIDE, V_CENTER, H_CENTER'} module-attribute 🔗

Layout options for a centric label.

DEFAULT_LABEL_LAYOUT_OPTIONS: _elkjs.LayoutOptions = {'nodeLabels.placement': 'INSIDE, V_TOP, H_CENTER'} module-attribute 🔗

Default layout options for a label.

EOI_WIDTH = 100 module-attribute 🔗

The width of the element of interest.

FAULT_PAD = 10 module-attribute 🔗

Height adjustment for labels.

ICON_HEIGHT = icon_size module-attribute 🔗

Default icon height from capellambse.

ICON_WIDTH = icon_size + icon_padding * 2 module-attribute 🔗

Default icon width from capellambse including the padding around it.

LABEL_HPAD = 3 module-attribute 🔗

Horizontal padding left and right of the label.

LABEL_VPAD = 1 module-attribute 🔗

Vertical padding above and below the label.

MAX_BOX_WIDTH = 150 module-attribute 🔗

Maximum width of boxes.

MAX_LABEL_WIDTH = 200 module-attribute 🔗

Maximum width for edge labels.

MAX_SYMBOL_HEIGHT = 135 module-attribute 🔗

Maximum height of symbols.

MAX_SYMBOL_WIDTH = 150 module-attribute 🔗

Maximum width of symbols.

MIN_SYMBOL_HEIGHT = 17 module-attribute 🔗

Minimum height of symbols.

MIN_SYMBOL_WIDTH = 30 module-attribute 🔗

Minimum width of symbols.

NEIGHBOR_VMARGIN = 20 module-attribute 🔗

Vertical space between two neighboring boxes.

PORT_PADDING = 2 module-attribute 🔗

Default padding of ports in pixels.

PORT_SIZE = 10 module-attribute 🔗

Default size of ports in pixels.

SYMBOL_LAYOUT_OPTIONS: _elkjs.LayoutOptions = {'nodeLabels.placement': 'OUTSIDE, V_BOTTOM, H_CENTER'} module-attribute 🔗

Layout options for a symbol label.

SYMBOL_RATIO = MIN_SYMBOL_WIDTH / MIN_SYMBOL_HEIGHT module-attribute 🔗

Width and height ratio of symbols.

calculate_height_and_width(labels, *, width=0, height=0, slim_width=False) 🔗

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

Source code in capellambse_context_diagrams/collectors/makers.py
179
180
181
182
183
184
185
186
187
188
189
190
191
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(obj) 🔗

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

Source code in capellambse_context_diagrams/collectors/makers.py
194
195
196
197
198
199
200
def is_symbol(obj: str | common.GenericElement | None) -> bool:
    """Check if given `obj` is rendered as a Symbol instead of a Box."""
    if obj is None:
        return False
    elif isinstance(obj, str):
        return obj in BOX_TO_SYMBOL
    return type(obj).__name__ in BOX_TO_SYMBOL

make_box(obj, *, width=0, height=0, no_symbol=False, slim_width=True, label_getter=lambda i: [{'text': i.name, 'icon': (ICON_WIDTH, 0), 'layout_options': {}}], max_label_width=MAX_BOX_WIDTH, layout_options=None) 🔗

Return an ELKInputChild.

Source code in capellambse_context_diagrams/collectors/makers.py
129
130
131
132
133
134
135
136
137
138
139
140
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
def make_box(
    obj: common.GenericElement,
    *,
    width: int | float = 0,
    height: int | float = 0,
    no_symbol: bool = False,
    slim_width: bool = True,
    label_getter: cabc.Callable[
        [common.GenericElement], cabc.Iterable[_LabelBuilder]
    ] = lambda i: [
        {
            "text": i.name,
            "icon": (ICON_WIDTH, 0),
            "layout_options": {},
        }
    ],  # type: ignore
    max_label_width: int | float = MAX_BOX_WIDTH,
    layout_options: _elkjs.LayoutOptions | None = None,
) -> _elkjs.ELKInputChild:
    """Return an
    [`ELKInputChild`][capellambse_context_diagrams._elkjs.ELKInputChild].
    """
    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.setdefault("layoutOptions", {}).update(SYMBOL_LAYOUT_OPTIONS)
    else:
        width, height = calculate_height_and_width(
            labels, width=width, height=height, slim_width=slim_width
        )
    return {"id": obj.uuid, "labels": labels, "width": width, "height": height}

make_diagram(diagram) 🔗

Return basic skeleton for ContextDiagrams.

Source code in capellambse_context_diagrams/collectors/makers.py
74
75
76
77
78
79
80
81
def make_diagram(diagram: context.ContextDiagram) -> _elkjs.ELKInputData:
    """Return basic skeleton for ``ContextDiagram``s."""
    return {
        "id": diagram.uuid,
        "layoutOptions": _elkjs.get_global_layered_layout_options(),
        "children": [],
        "edges": [],
    }

make_label(text, icon=(ICON_WIDTH, ICON_HEIGHT), layout_options=None, max_width=None) 🔗

Return an ELKInputLabel.

Source code in capellambse_context_diagrams/collectors/makers.py
 84
 85
 86
 87
 88
 89
 90
 91
 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
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 an
    [`ELKInputLabel`][capellambse_context_diagrams._elkjs.ELKInputLabel].
    """
    label_width, label_height = chelpers.get_text_extent(text)
    icon_width, _ = icon
    lines = [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(
            {
                "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_port(uuid) 🔗

Return an ELKInputPort.

Source code in capellambse_context_diagrams/collectors/makers.py
203
204
205
206
207
208
209
210
211
212
def make_port(uuid: str) -> _elkjs.ELKInputPort:
    """Return an
    [`ELKInputPort`][capellambse_context_diagrams._elkjs.ELKInputPort].
    """
    return {
        "id": uuid,
        "width": 10,
        "height": 10,
        "layoutOptions": {"borderOffset": -8},
    }