225 lines
7.4 KiB
Python
225 lines
7.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Demo script showing the viewport system in action.
|
|
|
|
This demonstrates how the viewport provides a movable window into large content,
|
|
enabling efficient scrolling without rendering the entire content at once.
|
|
"""
|
|
|
|
import os
|
|
from PIL import Image
|
|
from pyWebLayout.concrete import (
|
|
Viewport, ScrollablePageContent, Text, Box, RenderableImage
|
|
)
|
|
from pyWebLayout.style.fonts import Font, FontWeight
|
|
from pyWebLayout.style.layout import Alignment
|
|
|
|
|
|
def create_large_document_content():
|
|
"""Create a large document to demonstrate viewport scrolling"""
|
|
|
|
# Create scrollable content container
|
|
content = ScrollablePageContent(content_width=800, initial_height=100)
|
|
|
|
# Add a title
|
|
title_font = Font(font_size=24, weight=FontWeight.BOLD)
|
|
title = Text("Large Document Demo", title_font)
|
|
content.add_child(title)
|
|
|
|
# Add spacing
|
|
content.add_child(Box((0, 0), (1, 20)))
|
|
|
|
# Add many paragraphs to create a long document
|
|
paragraph_font = Font(font_size=14)
|
|
|
|
for i in range(50):
|
|
# Section header
|
|
section_font = Font(font_size=18, weight=FontWeight.BOLD)
|
|
header = Text(f"Section {i+1}", section_font)
|
|
content.add_child(header)
|
|
|
|
# Add some spacing
|
|
content.add_child(Box((0, 0), (1, 10)))
|
|
|
|
# Add paragraph content
|
|
paragraphs = [
|
|
f"This is paragraph {i+1}, line 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
f"This is paragraph {i+1}, line 2. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
|
f"This is paragraph {i+1}, line 3. Ut enim ad minim veniam, quis nostrud exercitation ullamco.",
|
|
f"This is paragraph {i+1}, line 4. Duis aute irure dolor in reprehenderit in voluptate velit esse.",
|
|
f"This is paragraph {i+1}, line 5. Excepteur sint occaecat cupidatat non proident, sunt in culpa."
|
|
]
|
|
|
|
for para_text in paragraphs:
|
|
para = Text(para_text, paragraph_font)
|
|
content.add_child(para)
|
|
content.add_child(Box((0, 0), (1, 5))) # Line spacing
|
|
|
|
# Add section spacing
|
|
content.add_child(Box((0, 0), (1, 15)))
|
|
|
|
return content
|
|
|
|
|
|
def demo_viewport_rendering():
|
|
"""Demonstrate viewport rendering at different scroll positions"""
|
|
|
|
print("Creating large document content...")
|
|
content = create_large_document_content()
|
|
|
|
print(f"Content size: {content.get_content_height()} pixels tall")
|
|
|
|
# Create viewport
|
|
viewport = Viewport(viewport_size=(800, 600), background_color=(255, 255, 255))
|
|
|
|
# Add content to viewport
|
|
viewport.add_content(content)
|
|
|
|
print(f"Viewport content size: {viewport.content_size}")
|
|
print(f"Max scroll Y: {viewport.max_scroll_y}")
|
|
|
|
# Create output directory
|
|
os.makedirs("output/viewport_demo", exist_ok=True)
|
|
|
|
# Render viewport at different scroll positions
|
|
scroll_positions = [
|
|
(0, "top"),
|
|
(viewport.max_scroll_y // 4, "quarter"),
|
|
(viewport.max_scroll_y // 2, "middle"),
|
|
(viewport.max_scroll_y * 3 // 4, "three_quarters"),
|
|
(viewport.max_scroll_y, "bottom")
|
|
]
|
|
|
|
for scroll_y, label in scroll_positions:
|
|
print(f"Rendering viewport at scroll position {scroll_y} ({label})...")
|
|
|
|
# Scroll to position
|
|
viewport.scroll_to(0, scroll_y)
|
|
|
|
# Get scroll info
|
|
scroll_info = viewport.get_scroll_info()
|
|
print(f" Scroll progress: {scroll_info['scroll_progress_y']:.2%}")
|
|
print(f" Visible elements: {len(viewport.get_visible_elements())}")
|
|
|
|
# Render viewport
|
|
viewport_img = viewport.render()
|
|
|
|
# Save image
|
|
output_path = f"output/viewport_demo/viewport_{label}.png"
|
|
viewport_img.save(output_path)
|
|
print(f" Saved: {output_path}")
|
|
|
|
print("\nViewport demo complete!")
|
|
return viewport
|
|
|
|
|
|
def demo_hit_testing():
|
|
"""Demonstrate hit testing in the viewport"""
|
|
|
|
print("\nTesting hit detection...")
|
|
|
|
# Create simple content for hit testing
|
|
content = ScrollablePageContent(content_width=800, initial_height=100)
|
|
|
|
# Add clickable elements
|
|
for i in range(10):
|
|
text = Text(f"Clickable text item {i}", Font(font_size=16))
|
|
content.add_child(text)
|
|
content.add_child(Box((0, 0), (1, 20))) # Spacing
|
|
|
|
# Create viewport
|
|
viewport = Viewport(viewport_size=(800, 300))
|
|
viewport.add_content(content)
|
|
|
|
# Test hit detection at different scroll positions
|
|
test_points = [(100, 50), (200, 100), (300, 150)]
|
|
|
|
for scroll_y in [0, 100, 200]:
|
|
viewport.scroll_to(0, scroll_y)
|
|
print(f"\nAt scroll position {scroll_y}:")
|
|
|
|
for point in test_points:
|
|
hit_element = viewport.hit_test(point)
|
|
if hit_element:
|
|
element_text = getattr(hit_element, '_text', 'Unknown element')
|
|
print(f" Point {point}: Hit '{element_text}'")
|
|
else:
|
|
print(f" Point {point}: No element")
|
|
|
|
|
|
def demo_scroll_methods():
|
|
"""Demonstrate different scrolling methods"""
|
|
|
|
print("\nTesting scroll methods...")
|
|
|
|
# Create content
|
|
content = ScrollablePageContent(content_width=800, initial_height=100)
|
|
|
|
for i in range(20):
|
|
text = Text(f"Line {i+1}: This is some sample text for scrolling demo", Font(font_size=14))
|
|
content.add_child(text)
|
|
content.add_child(Box((0, 0), (1, 5)))
|
|
|
|
# Create viewport
|
|
viewport = Viewport(viewport_size=(800, 200))
|
|
viewport.add_content(content)
|
|
|
|
print(f"Content height: {viewport.content_size[1]}")
|
|
print(f"Viewport height: {viewport.viewport_size[1]}")
|
|
print(f"Max scroll Y: {viewport.max_scroll_y}")
|
|
|
|
# Test different scroll methods
|
|
print("\nTesting scroll methods:")
|
|
|
|
# Scroll by lines
|
|
print("Scrolling down 5 lines...")
|
|
for i in range(5):
|
|
viewport.scroll_line_down(20)
|
|
print(f" After line {i+1}: offset = {viewport.viewport_offset}")
|
|
|
|
# Scroll by pages
|
|
print("Scrolling down 1 page...")
|
|
viewport.scroll_page_down()
|
|
print(f" After page down: offset = {viewport.viewport_offset}")
|
|
|
|
# Scroll to bottom
|
|
print("Scrolling to bottom...")
|
|
viewport.scroll_to_bottom()
|
|
print(f" At bottom: offset = {viewport.viewport_offset}")
|
|
|
|
# Scroll to top
|
|
print("Scrolling to top...")
|
|
viewport.scroll_to_top()
|
|
print(f" At top: offset = {viewport.viewport_offset}")
|
|
|
|
|
|
def main():
|
|
"""Run all viewport demos"""
|
|
print("=== Viewport System Demo ===")
|
|
|
|
# Demo 1: Basic viewport rendering
|
|
viewport = demo_viewport_rendering()
|
|
|
|
# Demo 2: Hit testing
|
|
demo_hit_testing()
|
|
|
|
# Demo 3: Scroll methods
|
|
demo_scroll_methods()
|
|
|
|
print("\n=== Demo Complete ===")
|
|
print("Check the output/viewport_demo/ directory for rendered images.")
|
|
|
|
# Show final scroll info
|
|
scroll_info = viewport.get_scroll_info()
|
|
print(f"\nFinal viewport state:")
|
|
print(f" Content size: {scroll_info['content_size']}")
|
|
print(f" Viewport size: {scroll_info['viewport_size']}")
|
|
print(f" Current offset: {scroll_info['offset']}")
|
|
print(f" Scroll progress: {scroll_info['scroll_progress_y']:.1%}")
|
|
print(f" Can scroll up: {scroll_info['can_scroll_up']}")
|
|
print(f" Can scroll down: {scroll_info['can_scroll_down']}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|