Badges : retour à la ligne et créneaux en tableau par jour
Le texte des champs passe à la ligne pour tenir dans la largeur de son cadre (wrap_text) au lieu de déborder. Les créneaux affectés s'affichent en tableau : le jour de festival en en-tête, puis une colonne horaire et une colonne poste (plus de référent sur le badge) ; même tableau dans l'aperçu de l'éditeur. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
cfed76c239
commit
1a23881e81
@@ -3,6 +3,8 @@
|
||||
import io
|
||||
|
||||
from PIL import Image
|
||||
from reportlab.lib.units import mm
|
||||
from reportlab.pdfbase.pdfmetrics import stringWidth
|
||||
|
||||
from app.badges.pdf import (
|
||||
ASSUMED_DPI,
|
||||
@@ -10,11 +12,15 @@ from app.badges.pdf import (
|
||||
DEFAULT_BADGE_WIDTH_MM,
|
||||
BadgeFieldSpec,
|
||||
BadgeSpec,
|
||||
BadgeTable,
|
||||
BadgeTableSection,
|
||||
_cell_origin,
|
||||
_column_widths,
|
||||
_fit_photo,
|
||||
_grid_size,
|
||||
generate_badge_sheets_pdf,
|
||||
image_size_mm,
|
||||
wrap_text,
|
||||
)
|
||||
|
||||
|
||||
@@ -151,3 +157,82 @@ def test_unreadable_photo_does_not_crash_generation():
|
||||
[_photo_badge(b"pas une image")], front_image=None, back_image=None
|
||||
)
|
||||
assert pdf.startswith(b"%PDF")
|
||||
|
||||
|
||||
def test_wrap_text_keeps_a_short_text_on_one_line():
|
||||
assert wrap_text("Alex Martin", "Helvetica", 12, 60 * mm) == ["Alex Martin"]
|
||||
|
||||
|
||||
def test_wrap_text_breaks_between_words_to_fit_the_width():
|
||||
# Assez large pour « Marie-Christine » seul, trop étroit pour le tout.
|
||||
width = 40 * mm
|
||||
lines = wrap_text("Marie-Christine de La Fontaine", "Helvetica-Bold", 12, width)
|
||||
|
||||
assert len(lines) > 1
|
||||
assert " ".join(lines) == "Marie-Christine de La Fontaine"
|
||||
assert all(stringWidth(line, "Helvetica-Bold", 12) <= width for line in lines)
|
||||
|
||||
|
||||
def test_wrap_text_keeps_explicit_line_breaks_and_wraps_each_line():
|
||||
text = "Bar central 19:00–22:00 (Référent : Sam Nuit)\nAccueil 09:00–13:00"
|
||||
width = 40 * mm
|
||||
lines = wrap_text(text, "Helvetica", 8, width)
|
||||
|
||||
assert lines[0].startswith("Bar central 19:00–22:00")
|
||||
assert "Accueil 09:00–13:00" in lines
|
||||
assert all(stringWidth(line, "Helvetica", 8) <= width for line in lines)
|
||||
|
||||
|
||||
def test_wrap_text_cuts_a_single_word_too_long_for_the_frame():
|
||||
width = 10 * mm
|
||||
lines = wrap_text("Anticonstitutionnellement", "Helvetica", 12, width)
|
||||
|
||||
assert "".join(lines) == "Anticonstitutionnellement"
|
||||
assert all(stringWidth(line, "Helvetica", 12) <= width for line in lines)
|
||||
|
||||
|
||||
def _table_badge(rows: int, height_mm: float = 30) -> BadgeSpec:
|
||||
return BadgeSpec(
|
||||
fields=(
|
||||
BadgeFieldSpec(
|
||||
text="", x_mm=5, y_mm=5, width_mm=60, height_mm=height_mm,
|
||||
font_size=7, align="LEFT", bold=False, color="#000000",
|
||||
table=BadgeTable(
|
||||
sections=(
|
||||
BadgeTableSection(
|
||||
title="Samedi 11",
|
||||
rows=tuple(
|
||||
("19:00–22:00", "Bar central très très long")
|
||||
for _ in range(rows)
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def test_column_widths_keep_short_columns_and_share_the_rest():
|
||||
widths = _column_widths([20, 30, 200, 100], available=200)
|
||||
|
||||
assert widths[:2] == [20, 30]
|
||||
assert widths[2] == widths[3] == 75
|
||||
assert sum(widths) == 200
|
||||
|
||||
|
||||
def test_column_widths_give_the_spare_room_to_the_last_column():
|
||||
assert _column_widths([20, 30, 40], available=150) == [20, 30, 100]
|
||||
|
||||
|
||||
def test_table_field_generates_a_valid_pdf():
|
||||
pdf = generate_badge_sheets_pdf([_table_badge(3)], front_image=None, back_image=None)
|
||||
assert pdf.startswith(b"%PDF")
|
||||
|
||||
|
||||
def test_table_rows_beyond_the_frame_are_not_drawn():
|
||||
# Cadre trop petit pour 50 lignes : celles qui débordent sont omises,
|
||||
# la planche fait la même taille qu'avec quelques lignes seulement.
|
||||
few = generate_badge_sheets_pdf([_table_badge(4, height_mm=12)], None, None)
|
||||
many = generate_badge_sheets_pdf([_table_badge(50, height_mm=12)], None, None)
|
||||
assert abs(len(many) - len(few)) < 50
|
||||
|
||||
Reference in New Issue
Block a user