This document describes the internal architecture of the Boundless Stack package, explaining how the various components work together to provide infinite scrolling and scaling capabilities.
The package is organized into the following directory structure:
lib/
├── boundless_stack.dart # Main library file
└── src/
├── backgrounds/ # Background builders
│ └── grid.dart # Grid background implementation
├── core/ # Core components
│ ├── boundless_stack.dart
│ ├── boundless_stack_delegate.dart
│ ├── boundless_stack_scroll_view.dart
│ ├── boundless_stack_viewport.dart
│ ├── render_boundless_stack_viewport.dart
│ └── stack_position.dart
├── gestures/ # Gesture handling
│ └── zoom_stack_gesture_detector.dart
└── utils/ # Utility classes
└── vicinity_manager.dart
ZoomStackGestureDetector
├── BoundlessStack
├── BoundlessStackScrollView
│ └── BoundlessStackViewport
│ └── RenderBoundlessStackViewport
└── Background/Foreground Builders
- User Input → ZoomStackGestureDetector
- Gesture Processing → Scale/Pan calculations
- State Updates → BoundlessStack state changes
- Viewport Updates → BoundlessStackViewport rendering
- Child Management → StackPosition widgets
Purpose: Handles all user input gestures including zoom, pan, and scroll.
Responsibilities:
- Detect and process scale gestures (pinch-to-zoom)
- Handle mouse wheel zoom with Ctrl key
- Manage pan gestures for moving the viewport
- Coordinate with keyboard input for modifier keys
Key Methods:
onScaleStart(): Initialize scaling operationonScaleUpdate(): Update scale and viewport positiononScaleEnd(): Finalize scaling operation
Purpose: Main widget that orchestrates the infinite scrollable area.
Responsibilities:
- Manage scroll controllers for both axes
- Coordinate background/foreground rendering
- Handle scale factor changes
- Provide viewport configuration
State Management:
- Maintains horizontal and vertical scroll controllers
- Listens to scale factor changes
- Manages scroll behavior overrides during gestures
Purpose: Abstract interface for providing children to the stack.
Implementations:
BoundlessStackListDelegate: Static list of children- Custom delegates can be created for dynamic content
Key Features:
- Layer-based sorting support
- Viewport-aware child building
- Efficient child management
Purpose: Individual positioned widget within the stack.
Capabilities:
- Movement with optional snap-to-grid
- Resizing with custom handles
- Scale-aware rendering
- Keep-alive functionality
Interaction Handling:
- Pan gestures for movement
- Resize gestures with custom thumbs
- Automatic state management
// Calculate visible area based on scroll positions and scale
Rect viewport = Rect.fromLTWH(
horizontalOffset / scaleFactor,
verticalOffset / scaleFactor,
viewportWidth / scaleFactor,
viewportHeight / scaleFactor,
);The system determines which children are visible or near-visible based on:
- Current viewport bounds
- Cache extent settings
- Child positions and sizes
Children are rendered in layer order:
- Background builder (if provided)
- Stack children (sorted by layer)
- Foreground builder (if provided)
Each child receives appropriate transforms:
- Scale transformation based on current zoom level
- Position transformation based on viewport offset
- Hit-test adjustments for interaction
- Viewport Culling: Only visible items are rendered
- Cache Extent: Configurable pre-rendering of nearby items
- Keep Alive: Optional persistent rendering for specific items
- ValueNotifier Pattern: Efficient reactive updates
- Automatic Disposal: Proper cleanup of listeners and controllers
- Minimal Rebuilds: Targeted updates using RepaintBoundary
The infinite 2D space where items are positioned:
- Origin at (0, 0)
- Unlimited bounds in all directions
- Item positions stored in world coordinates
The visible area on screen:
- Affected by scroll position
- Scaled by zoom factor
- Used for rendering calculations
Final pixel positions on device:
- Result of world → viewport → screen transformations
- Used for hit testing and gesture handling
- Children built only when needed
- Delegate pattern allows for dynamic content
- Efficient memory usage for large datasets
- Hardware-accelerated transformations
- Minimal state updates during gestures
- Efficient coordinate calculations
- RepaintBoundary usage to isolate repaints
- Custom painters for backgrounds
- Efficient layer management
Implement BoundlessStackDelegate for:
- Dynamic content loading
- Database-backed items
- Infinite procedural generation
Implement TwoDimensionalViewportBuilder for:
- Custom grid patterns
- Image backgrounds
- Dynamic visual effects
Extend gesture handling for:
- Multi-touch interactions
- Custom input devices
- Specialized interaction patterns
The package is designed for single-threaded use within Flutter's main isolate:
- All state changes occur on the main thread
- Gesture handling is synchronous
- Background computations should use separate isolates
- Individual component behavior
- Coordinate transformations
- State management logic
- User interaction scenarios
- Gesture handling
- Visual rendering
- End-to-end workflows
- Performance characteristics
- Memory usage patterns