375 lines
9.9 KiB
Python
375 lines
9.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Comprehensive Forms Example
|
|
|
|
This example demonstrates:
|
|
- All FormFieldType variations (TEXT, PASSWORD, EMAIL, etc.)
|
|
- Form layout with multiple fields
|
|
- Field labels and validation
|
|
- Form submission callbacks
|
|
- Organizing forms on pages
|
|
|
|
This shows how to create interactive forms with all available field types.
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Add pyWebLayout to path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from pyWebLayout.concrete.page import Page
|
|
from pyWebLayout.style.page_style import PageStyle
|
|
from pyWebLayout.style.fonts import Font
|
|
from pyWebLayout.abstract.functional import Form, FormField, FormFieldType
|
|
from pyWebLayout.layout.document_layouter import DocumentLayouter
|
|
from PIL import Image, ImageDraw
|
|
|
|
|
|
# Track form submissions
|
|
form_submissions = []
|
|
|
|
|
|
def form_submit_callback(form_id: str):
|
|
"""Callback for form submissions"""
|
|
def callback(data):
|
|
form_submissions.append((form_id, data))
|
|
print(f" Form submitted: {form_id} with data: {data}")
|
|
return callback
|
|
|
|
|
|
def create_example_1_text_fields():
|
|
"""Example 1: Text input fields"""
|
|
print("\n Creating Example 1: Text input fields...")
|
|
|
|
page_style = PageStyle(
|
|
border_width=2,
|
|
border_color=(150, 150, 200),
|
|
padding=(20, 30, 20, 30),
|
|
background_color=(255, 255, 255)
|
|
)
|
|
|
|
page = Page(size=(500, 600), style=page_style)
|
|
layouter = DocumentLayouter(page)
|
|
|
|
# Create form with text fields
|
|
form = Form(form_id="text_form", html_id="text_form", callback=form_submit_callback("text_form"))
|
|
|
|
# Add various text-based fields
|
|
form.add_field(FormField(
|
|
name="username",
|
|
label="Username",
|
|
field_type=FormFieldType.TEXT,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="email",
|
|
label="Email Address",
|
|
field_type=FormFieldType.EMAIL,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="password",
|
|
label="Password",
|
|
field_type=FormFieldType.PASSWORD,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="website",
|
|
label="Website URL",
|
|
field_type=FormFieldType.URL,
|
|
required=False
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="bio",
|
|
label="Biography",
|
|
field_type=FormFieldType.TEXTAREA,
|
|
required=False
|
|
))
|
|
|
|
# Layout the form
|
|
font = Font(font_size=12, colour=(50, 50, 50))
|
|
success, field_ids = layouter.layout_form(form, font=font)
|
|
|
|
print(f" Laid out {len(field_ids)} text fields")
|
|
return page
|
|
|
|
|
|
def create_example_2_number_fields():
|
|
"""Example 2: Number and date/time fields"""
|
|
print(" Creating Example 2: Number and date/time fields...")
|
|
|
|
page_style = PageStyle(
|
|
border_width=2,
|
|
border_color=(150, 200, 150),
|
|
padding=(20, 30, 20, 30),
|
|
background_color=(255, 255, 255)
|
|
)
|
|
|
|
page = Page(size=(500, 600), style=page_style)
|
|
layouter = DocumentLayouter(page)
|
|
|
|
# Create form with number/date fields
|
|
form = Form(form_id="number_form", html_id="number_form", callback=form_submit_callback("number_form"))
|
|
|
|
form.add_field(FormField(
|
|
name="age",
|
|
label="Age",
|
|
field_type=FormFieldType.NUMBER,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="birth_date",
|
|
label="Birth Date",
|
|
field_type=FormFieldType.DATE,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="appointment",
|
|
label="Appointment Time",
|
|
field_type=FormFieldType.TIME,
|
|
required=False
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="rating",
|
|
label="Rating (1-10)",
|
|
field_type=FormFieldType.RANGE,
|
|
required=False
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="color",
|
|
label="Favorite Color",
|
|
field_type=FormFieldType.COLOR,
|
|
required=False
|
|
))
|
|
|
|
# Layout the form
|
|
font = Font(font_size=12, colour=(50, 50, 50))
|
|
success, field_ids = layouter.layout_form(form, font=font)
|
|
|
|
print(f" Laid out {len(field_ids)} number/date fields")
|
|
return page
|
|
|
|
|
|
def create_example_3_selection_fields():
|
|
"""Example 3: Checkbox, radio, and select fields"""
|
|
print(" Creating Example 3: Selection fields...")
|
|
|
|
page_style = PageStyle(
|
|
border_width=2,
|
|
border_color=(200, 150, 150),
|
|
padding=(20, 30, 20, 30),
|
|
background_color=(255, 255, 255)
|
|
)
|
|
|
|
page = Page(size=(500, 600), style=page_style)
|
|
layouter = DocumentLayouter(page)
|
|
|
|
# Create form with selection fields
|
|
form = Form(form_id="selection_form", html_id="selection_form", callback=form_submit_callback("selection_form"))
|
|
|
|
form.add_field(FormField(
|
|
name="newsletter",
|
|
label="Subscribe to Newsletter",
|
|
field_type=FormFieldType.CHECKBOX,
|
|
required=False
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="terms",
|
|
label="Accept Terms and Conditions",
|
|
field_type=FormFieldType.CHECKBOX,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="gender",
|
|
label="Gender",
|
|
field_type=FormFieldType.RADIO,
|
|
required=False
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="country",
|
|
label="Country",
|
|
field_type=FormFieldType.SELECT,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="hidden_token",
|
|
label="", # Hidden fields don't display labels
|
|
field_type=FormFieldType.HIDDEN,
|
|
required=False
|
|
))
|
|
|
|
# Layout the form
|
|
font = Font(font_size=12, colour=(50, 50, 50))
|
|
success, field_ids = layouter.layout_form(form, font=font)
|
|
|
|
print(f" Laid out {len(field_ids)} selection fields")
|
|
return page
|
|
|
|
|
|
def create_example_4_complete_form():
|
|
"""Example 4: Complete registration form with mixed field types"""
|
|
print(" Creating Example 4: Complete registration form...")
|
|
|
|
page_style = PageStyle(
|
|
border_width=2,
|
|
border_color=(150, 200, 200),
|
|
padding=(20, 30, 20, 30),
|
|
background_color=(255, 255, 255)
|
|
)
|
|
|
|
page = Page(size=(500, 700), style=page_style)
|
|
layouter = DocumentLayouter(page)
|
|
|
|
# Create comprehensive registration form
|
|
form = Form(form_id="registration_form", html_id="registration_form", callback=form_submit_callback("registration"))
|
|
|
|
# Personal information
|
|
form.add_field(FormField(
|
|
name="full_name",
|
|
label="Full Name",
|
|
field_type=FormFieldType.TEXT,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="email",
|
|
label="Email",
|
|
field_type=FormFieldType.EMAIL,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="password",
|
|
label="Password",
|
|
field_type=FormFieldType.PASSWORD,
|
|
required=True
|
|
))
|
|
|
|
form.add_field(FormField(
|
|
name="age",
|
|
label="Age",
|
|
field_type=FormFieldType.NUMBER,
|
|
required=True
|
|
))
|
|
|
|
# Preferences
|
|
form.add_field(FormField(
|
|
name="notifications",
|
|
label="Enable Notifications",
|
|
field_type=FormFieldType.CHECKBOX,
|
|
required=False
|
|
))
|
|
|
|
# Layout the form
|
|
font = Font(font_size=12, colour=(50, 50, 50))
|
|
success, field_ids = layouter.layout_form(form, font=font, field_spacing=15)
|
|
|
|
print(f" Laid out complete form with {len(field_ids)} fields")
|
|
return page
|
|
|
|
|
|
def combine_pages_into_grid(pages, title):
|
|
"""Combine multiple pages into a 2x2 grid."""
|
|
print("\n Combining pages into grid...")
|
|
|
|
# Render all pages
|
|
images = [page.render() for page in pages]
|
|
|
|
# Grid layout
|
|
padding = 20
|
|
title_height = 40
|
|
cols = 2
|
|
rows = 2
|
|
|
|
# Calculate dimensions
|
|
img_width = images[0].size[0]
|
|
img_height = images[0].size[1]
|
|
|
|
total_width = cols * img_width + (cols + 1) * padding
|
|
total_height = rows * img_height + (rows + 1) * padding + title_height
|
|
|
|
# Create combined image
|
|
combined = Image.new('RGB', (total_width, total_height), (240, 240, 240))
|
|
draw = ImageDraw.Draw(combined)
|
|
|
|
# Draw title
|
|
from PIL import ImageFont
|
|
try:
|
|
title_font = ImageFont.truetype(
|
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 18
|
|
)
|
|
except:
|
|
title_font = ImageFont.load_default()
|
|
|
|
bbox = draw.textbbox((0, 0), title, font=title_font)
|
|
text_width = bbox[2] - bbox[0]
|
|
title_x = (total_width - text_width) // 2
|
|
draw.text((title_x, 10), title, fill=(50, 50, 50), font=title_font)
|
|
|
|
# Place pages in grid
|
|
y_offset = title_height + padding
|
|
for row in range(rows):
|
|
x_offset = padding
|
|
for col in range(cols):
|
|
idx = row * cols + col
|
|
if idx < len(images):
|
|
combined.paste(images[idx], (x_offset, y_offset))
|
|
x_offset += img_width + padding
|
|
y_offset += img_height + padding
|
|
|
|
return combined
|
|
|
|
|
|
def main():
|
|
"""Demonstrate comprehensive form field types."""
|
|
global form_submissions
|
|
form_submissions = []
|
|
|
|
print("Comprehensive Forms Example")
|
|
print("=" * 50)
|
|
|
|
# Create examples for different form types
|
|
pages = [
|
|
create_example_1_text_fields(),
|
|
create_example_2_number_fields(),
|
|
create_example_3_selection_fields(),
|
|
create_example_4_complete_form()
|
|
]
|
|
|
|
# Combine into demonstration image
|
|
combined_image = combine_pages_into_grid(
|
|
pages,
|
|
"Form Field Types: Text | Numbers | Selection | Complete"
|
|
)
|
|
|
|
# Save output
|
|
output_dir = Path("docs/images")
|
|
output_dir.mkdir(parents=True, exist_ok=True)
|
|
output_path = output_dir / "example_10_forms.png"
|
|
combined_image.save(output_path)
|
|
|
|
print("\n✓ Example completed!")
|
|
print(f" Output saved to: {output_path}")
|
|
print(f" Image size: {combined_image.size[0]}x{combined_image.size[1]} pixels")
|
|
print(f" Created {len(pages)} form examples")
|
|
print(f" Total form callbacks registered: {len(form_submissions)}")
|
|
|
|
return combined_image, form_submissions
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|