#!/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()