IMX500-Object-Detection-UI/ui/textlayout.py
2026-02-04 20:30:15 +01:00

82 lines
2.8 KiB
Python

# imx500_gui/ui/textlayout.py
from typing import List, Tuple
import pygame
class TextLayout:
"""Word-Wrap + Font-Fitting fuer Step-Beschreibungen."""
@staticmethod
def wrap_lines(text: str, font: pygame.font.Font, max_w: int) -> List[str]:
text = text.replace("\r\n", "\n").replace("\r", "\n")
paragraphs = text.split("\n")
lines: List[str] = []
for p in paragraphs:
if p.strip() == "":
lines.append("")
continue
words = p.split(" ")
cur = ""
for w in words:
test = (cur + " " + w).strip()
if font.size(test)[0] <= max_w: # [web:177]
cur = test
else:
if cur:
lines.append(cur)
cur = w
if cur:
lines.append(cur)
return lines
@staticmethod
def draw_wrapped_lines(surface, lines, font, color, x, y, line_spacing=4) -> int:
line_h = font.get_linesize() + line_spacing # [web:177]
for ln in lines:
if ln == "":
y += line_h
continue
surface.blit(font.render(ln, True, color), (x, y)) # [web:177]
y += line_h
return y
@staticmethod
def split_title_body(title: str, body: str) -> Tuple[str, str]:
# In der neuen Struktur bekommst du Titel und Body getrennt aus STEP_TEXT.
return title.strip(), body.strip()
@staticmethod
def fit_title_and_body(title: str, body: str, rect: pygame.Rect,
min_body=18, max_body=40, title_ratio=1.30, line_spacing=4):
title = title.strip()
body = body.strip()
best_body = pygame.font.Font(None, min_body)
best_title = pygame.font.Font(None, int(min_body * title_ratio))
lo, hi = min_body, max_body
while lo <= hi:
body_size = (lo + hi) // 2
title_size = max(body_size + 4, int(body_size * title_ratio))
f_body = pygame.font.Font(None, body_size)
f_title = pygame.font.Font(None, title_size)
title_lines = TextLayout.wrap_lines(title, f_title, rect.w)
body_lines = TextLayout.wrap_lines(body, f_body, rect.w) if body else []
needed_h = 0
needed_h += len(title_lines) * (f_title.get_linesize() + line_spacing) # [web:177]
if body_lines:
needed_h += (f_body.get_linesize() + line_spacing)
needed_h += len(body_lines) * (f_body.get_linesize() + line_spacing)
if needed_h <= rect.h:
best_body, best_title = f_body, f_title
lo = body_size + 1
else:
hi = body_size - 1
return best_title, best_body