Closes #19902: add clip path to avoid overflow of device name, truncate text to improve centering (#19913)
Some checks failed
CI / build (20.x, 3.10) (push) Has been cancelled
CI / build (20.x, 3.11) (push) Has been cancelled
CI / build (20.x, 3.12) (push) Has been cancelled

This commit is contained in:
Marco Spizzuoco 2025-07-22 18:44:14 +02:00 committed by GitHub
parent 2129355c30
commit d571cb4867
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -3,6 +3,7 @@ import svgwrite
from svgwrite.container import Hyperlink from svgwrite.container import Hyperlink
from svgwrite.image import Image from svgwrite.image import Image
from svgwrite.gradients import LinearGradient from svgwrite.gradients import LinearGradient
from svgwrite.masking import ClipPath
from svgwrite.shapes import Rect from svgwrite.shapes import Rect
from svgwrite.text import Text from svgwrite.text import Text
@ -67,6 +68,20 @@ def get_device_description(device):
return description return description
def truncate_text(text, width, font_size=15):
"""
Truncate text to fit within the width of a rectangle.
:param text: The text to truncate
:param width: Width of rectangle
:param font_size: Font size (default is 15, ~0.875rem)
"""
char_width = font_size * 0.6 # 0.6 is an approximation of the average character width in pixels
max_char = int(width / char_width)
return text if len(text) <= max_char else text[:max_char] + '...'
class RackElevationSVG: class RackElevationSVG:
""" """
Use this class to render a rack elevation as an SVG image. Use this class to render a rack elevation as an SVG image.
@ -177,12 +192,26 @@ class RackElevationSVG:
link = Hyperlink(href=f'{self.base_url}{device.get_absolute_url()}', target="_parent") link = Hyperlink(href=f'{self.base_url}{device.get_absolute_url()}', target="_parent")
link.set_desc(description) link.set_desc(description)
# Create clipPath element
# This is necessary as fallback because the truncate_text method is an approximation
clip_id = f"clip-{device.id}"
clip_path = ClipPath(id=clip_id)
clip_path.add(Rect(coords, size))
self.drawing.defs.add(clip_path)
# Name to display
display_name = truncate_text(name, size[0])
# Add rect element to hyperlink # Add rect element to hyperlink
if color: if color:
link.add(Rect(coords, size, style=f'fill: #{color}', class_=f'slot{css_extra}')) link.add(Rect(coords, size, style=f'fill: #{color}', class_=f'slot{css_extra}'))
else: else:
link.add(Rect(coords, size, class_=f'slot blocked{css_extra}')) link.add(Rect(coords, size, class_=f'slot blocked{css_extra}'))
link.add(Text(name, insert=text_coords, fill=text_color, class_=f'label{css_extra}')) link.add(
Text(display_name, insert=text_coords, fill=text_color, clip_path=f"url(#{clip_id})",
class_=f'label{css_extra}')
)
# Embed device type image if provided # Embed device type image if provided
if self.include_images and image: if self.include_images and image: