Skip to content

Commit

Permalink
feat: Add left_aligned text rendering from capstyle
Browse files Browse the repository at this point in the history
Before text placement was always centric. Now based on a new
`text_style` keyed `text_align` in `diagram.capstyle.STYLES` it is
decided when text is placed with a default margin (5) or bigger for
centric position.

- Additionally all text stylings were moved from `decorations` into
`diagram.capstyle.STYLES`.
- Additionally `helpers.check_for_horizontal_overflow` was changed to do
only what its name suggests. Margin calculation were moved outside into
`render_hbounded_lines`.
  • Loading branch information
ewuerger committed Jan 19, 2023
1 parent 9ab6f60 commit 47ceef4
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 23 deletions.
15 changes: 15 additions & 0 deletions capellambse/diagram/capstyle.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ class in the form::
"fill": RGB(255, 255, 203),
"stroke": RGB(255, 204, 102),
"text_fill": RGB(0, 0, 0),
"text_position": "always_top",
},
"Box.Requirement": { # ReqVP_Requirement
"fill": COLORS["light_purple"],
Expand Down Expand Up @@ -326,6 +327,7 @@ class in the form::
"ry": "10px",
"stroke": COLORS["_CAP_Class_Border_Brown"],
"text_fill": COLORS["black"],
"text_position": "always_top",
},
"Box.DataPkg": { # DT_DataPkg
"fill": [
Expand All @@ -339,6 +341,7 @@ class in the form::
"fill": COLORS["_CAP_Class_Brown"],
"stroke": COLORS["_CAP_Datatype_Border_Gray"],
"text_fill": COLORS["black"],
"text_position": "always_top",
},
"Box.ExchangeItem": { # DT_ExchangeItem
"fill": COLORS["_CAP_ExchangeItem_Pinkkish"],
Expand Down Expand Up @@ -439,6 +442,7 @@ class in the form::
"Box.LogicalActor": { # Logical Actors
"fill": [COLORS["_CAP_Actor_Blue_min"], COLORS["_CAP_Actor_Blue"]],
"stroke": COLORS["_CAP_Actor_Border_Blue"],
"text_anchor": "start",
"text_fill": COLORS["_CAP_Actor_Blue_label"],
},
"Box.LogicalComponent": { # LAB Logical Component
Expand All @@ -447,6 +451,7 @@ class in the form::
COLORS["_CAP_Component_Blue"],
],
"stroke": COLORS["_CAP_Component_Border_Blue"],
"text_anchor": "start",
"text_fill": COLORS["_CAP_Component_Label_Blue"],
},
"Box.LogicalHumanActor": { # LAB Logical Human Actor
Expand All @@ -455,6 +460,7 @@ class in the form::
COLORS["_CAP_Component_Blue"],
],
"stroke": COLORS["_CAP_Component_Border_Blue"],
"text_anchor": "start",
"text_fill": COLORS["_CAP_Component_Label_Blue"],
},
"Box.LogicalHumanComponent": { # LAB Logical Human Component
Expand All @@ -463,6 +469,7 @@ class in the form::
COLORS["_CAP_Component_Blue"],
],
"stroke": COLORS["_CAP_Component_Border_Blue"],
"text_anchor": "start",
"text_fill": COLORS["_CAP_Component_Label_Blue"],
},
"Box.LogicalFunction": { # LAB Logical Function
Expand Down Expand Up @@ -584,6 +591,8 @@ class in the form::
COLORS["_CAP_MSM_Mode_Gray"],
],
"stroke": COLORS["dark_gray"],
"text_align": "left",
"text_anchor": "start",
},
"Box.State": {
"fill": COLORS["_CAP_MSM_State_Gray_min"],
Expand All @@ -595,6 +604,8 @@ class in the form::
COLORS["_CAP_MSM_State_Gray"],
],
"stroke": COLORS["dark_gray"],
"text_align": "left",
"text_anchor": "start",
},
"Edge.StateTransition": {
"marker-end": "FineArrowMark",
Expand Down Expand Up @@ -653,6 +664,7 @@ class in the form::
"fill": COLORS["_CAP_Activity_Orange"],
"stroke": COLORS["_CAP_Activity_Border_Orange"],
"text_fill": COLORS["_CAP_xAB_Activity_Label_Orange"],
"text_position": "always_top",
},
"Box.OperationalActor": {
"fill": [
Expand Down Expand Up @@ -695,6 +707,7 @@ class in the form::
"Box.OperationalActivity": {
"fill": COLORS["_CAP_Activity_Orange"],
"stroke": COLORS["_CAP_Activity_Border_Orange"],
"text_position": "always_top",
},
"Edge.OperationalExchange": {
"marker-end": "FineArrowMark",
Expand All @@ -713,6 +726,7 @@ class in the form::
"ry": "10px",
"stroke": COLORS["_CAP_Activity_Border_Orange"],
"text_fill": COLORS["_CAP_xAB_Activity_Label_Orange"],
"text_position": "always_top",
},
"Box.OperationalProcess": {
"stroke": COLORS["black"],
Expand Down Expand Up @@ -751,6 +765,7 @@ class in the form::
],
"stroke": COLORS["_CAP_Node_Yellow_Border"],
"text_fill": COLORS["_CAP_Node_Yellow_Label"],
"text_position": "always_top",
},
"Box.PhysicalFunction": {
"fill": COLORS["_CAP_xAB_Function_Green"],
Expand Down
15 changes: 2 additions & 13 deletions capellambse/svg/decorations.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,18 @@
"""Default icon padding (left/right side)."""
feature_space = 24
"""Default margins/padding (top/bot and left/right) for feature text."""
text_margin = 5
"""Default margins/padding (left and right) for label text."""

function_ports = {"FIP", "FOP"}
directed_component_ports = {"CP_IN", "CP_OUT"}
component_ports = directed_component_ports | {"PP", "CP_INOUT", "CP_UNSET"}
all_ports = function_ports | component_ports
all_directed_ports = directed_component_ports | function_ports
start_aligned = {
"LogicalComponent",
"LogicalActor",
"LogicalHumanActor",
"LogicalHumanComponent",
}
only_icons = {"Requirement"}
DiagramClass = str
FaultyClass = str
PatchClass = str
always_top_label = {
"Class",
"Enumeration",
"Note",
"OperationalActivity",
"PhysicalComponent",
}
needs_feature_line = {"Class", "Enumeration"}


Expand Down
21 changes: 15 additions & 6 deletions capellambse/svg/drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,12 @@ def add_rect(
)

if label:
text_anchor = (
"start" if class_ in decorations.start_aligned else "middle"
defaultstyles = diagram.get_style(
self.diagram_class, text_style._class
)
text_anchor = defaultstyles.get("text_anchor", "middle")
y_margin = None
if children or class_ in decorations.always_top_label:
if children or defaultstyles.get("text_position") == "always_top":
y_margin = 5

self._draw_box_label(
Expand Down Expand Up @@ -324,7 +325,10 @@ def _draw_label(
f"{builder.class_}Symbol" in decorations.deco_factories
and builder.icon
)
lines = render_hbounded_lines(builder, render_icon)
defaultstyles = diagram.get_style(
self.diagram_class, builder.labelstyle._class
)
lines = render_hbounded_lines(builder, defaultstyles, render_icon)
x, icon_x = get_label_position_x(builder, lines, render_icon)
y = get_label_position_y(builder, lines)
for line in lines.lines:
Expand Down Expand Up @@ -873,18 +877,23 @@ class LinesData(t.NamedTuple):


def render_hbounded_lines(
builder: LabelBuilder, render_icon: bool
builder: LabelBuilder, defaultstyles: dict[str, t.Any], render_icon: bool
) -> LinesData:
(
lines,
label_margin,
label_width,
max_text_width,
) = helpers.check_for_horizontal_overflow(
str(builder.label["text"]),
builder.label["width"],
decorations.icon_padding if render_icon else 0,
builder.icon_size if render_icon else 0,
)
if defaultstyles.get("text_align") == "left":
label_margin: int | float = decorations.text_margin
else:
label_margin = (builder.label["width"] - label_width) / 2

lines_to_render = helpers.check_for_vertical_overflow(
lines, builder.label["height"], max_text_width
)
Expand Down
3 changes: 1 addition & 2 deletions capellambse/svg/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ def check_for_horizontal_overflow(
label_width = text_width + icon_size + 2 * icon_padding
assert text_width <= max_text_width
assert label_width <= width
label_margin = (width - label_width) / 2
return (lines, label_margin, max_text_width)
return (lines, label_width, max_text_width)


def check_for_vertical_overflow(
Expand Down
4 changes: 2 additions & 2 deletions tests/test_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,10 +494,10 @@ class TestSVGHelpers:
def test_check_for_horizontal_overflow_recognizes_tabs_and_breaks(
self,
) -> None:
lines, margin, max_text_width = helpers.check_for_horizontal_overflow(
lines, width, max_text_width = helpers.check_for_horizontal_overflow(
" • item 1\n • item 2", 100, 0, 0
)
assert lines == [" • item 1", " • item 2"]
assert 10 <= margin < 13
assert 75 <= width <= 100
for line in lines:
assert capellambse.helpers.extent_func(line)[0] <= max_text_width

0 comments on commit 47ceef4

Please sign in to comment.