Dampen Iced
Iced backend implementation for the Dampen declarative UI framework.
Overview
Dampen Iced provides automatic interpretation of parsed Dampen markup into Iced widgets, eliminating manual conversion boilerplate. It handles bindings, events, styles, and layouts automatically through the DampenWidgetBuilder.
Features
- ✅ Automatic Widget Building: Convert XML markup to Iced widgets with one line
- ✅ Binding Support: Evaluate expressions like
{count}or{user.name} - ✅ Event Handling: Connect handlers via
on_click,on_input, etc. - ✅ Style & Layout: Apply padding, spacing, colors, borders automatically
- ✅ Recursive Processing: Handles nested widget trees automatically
- ✅ Verbose Logging: Debug mode for development
Quick Start
Basic Usage
use ;
use ;
use UiModel;
use ;
use ;
use Any;
type Message = HandlerMessage;
UI File (ui/main.dampen)
API Reference
DampenWidgetBuilder
Constructor
// Using HandlerMessage (recommended for most cases)
new // From complete document
from_document // With custom message factory
new_with_factory where F: Fn + 'a
Configuration
// Enable verbose logging for debugging
builder.with_verbose
// Add style classes for theme support
builder.with_style_classes
// Access state manager for event handlers
let manager = builder.state_manager;
Execution
// Build the widget tree
let element: = builder.build;
Supported Widgets
| Widget | XML Tag | Key Attributes |
|---|---|---|
| Text | <text /> |
value, size, weight, color |
| Button | <button /> |
label, on_click, enabled |
| Column | <column /> |
spacing, padding |
| Row | <row /> |
spacing, padding |
| Container | <container /> |
width, height, padding |
| TextInput | <text_input /> |
value, placeholder, on_input |
| Checkbox | <checkbox /> |
label, checked, on_toggle |
| Slider | <slider /> |
min, max, value, on_change |
| PickList | <pick_list /> |
options, selected, on_select |
| Toggler | <toggler /> |
label, active, on_toggle |
| Image | <image /> |
src |
| Scrollable | <scrollable /> |
(wraps children) |
| Stack | <stack /> |
(layered children) |
| Space | <space /> |
(flexible spacer) |
| Rule | <rule /> |
(horizontal/vertical line) |
Binding Expressions
<!-- Simple field access -->
<!-- Nested fields -->
<!-- Method calls -->
<!-- Binary operations -->
<!-- Conditionals -->
<!-- Interpolated strings -->
Event Handlers
// Simple handler (no payload)
// Handler with value
// Handler with command (async)
Examples
See the examples/ directory for complete working applications:
- hello-world: Minimal example showing basic usage
- counter: Interactive counter with event handlers
- todo-app: Full CRUD application with bindings
- styling: Theme and style class examples
Architecture
Design Principles
- Centralized Interpretation: All widget rendering logic lives in the builder
- Type Safety: No runtime type erasure, compile-time verified
- Backend Agnostic: Core logic separate from Iced-specific widgets
- Zero Duplication: Reuses existing style mapping and evaluation functions
File Structure
crates/dampen-iced/
├── src/
│ ├── lib.rs # Public API, IcedBackend trait
│ ├── builder.rs # DampenWidgetBuilder implementation
│ ├── convert.rs # IR → Iced type conversions
│ ├── state.rs # Widget state management
│ ├── style_mapping.rs # Style and layout mapping
│ ├── theme_adapter.rs # Theme conversion
│ └── widgets/ # Widget-specific helpers
└── tests/ # Integration tests
Performance
Benchmarks
- 100 widgets: ~0.027ms (37x faster than 1ms target)
- 1000 widgets: ~0.284ms (175x faster than 50ms target)
- Binding evaluation: ~713ns per widget
- Event connection: ~784ns per widget
Optimization Tips
- Reuse builders: Builder instances are single-use, but cheap to create
- Minimize bindings: Each binding adds ~700ns overhead
- Use style classes: Reuse styles instead of inline attributes
- Profile with verbose: Use
with_verbose(true)to identify bottlenecks
Error Handling
Verbose Mode
let widget = new
.with_verbose // Enable debug logging
.build;
Common Errors
- Missing handler: Logs warning if verbose enabled, event ignored
- Binding error: Returns empty string, logs error if verbose
- Invalid attribute: Uses default value, logs warning if verbose
- Unsupported widget: Returns empty placeholder, logs error
Integration
With Hot-Reload
use ;
let mut interpreter = new;
interpreter.load_document?;
// File watcher triggers reload on changes
With CLI
# Development mode
# Validate XML
# Inspect IR
Best Practices
1. Model Design
2. Handler Registration
// Register all handlers at once
let registry = new;
registry.register_simple;
registry.register_simple;
registry.register_with_value;
3. XML Structure
<!-- Good: Clear hierarchy -->
<!-- Avoid: Deep nesting without layout -->
Troubleshooting
Builder doesn't update on changes
- Ensure you're using hot-reload mode
- Check file permissions
- Verify XML is valid
Bindings not evaluating
- Check field names match exactly (case-sensitive)
- Verify model implements
UiBindable - Enable verbose mode to see evaluation errors
Events not firing
- Verify handler is registered in
HandlerRegistry - Check handler name matches XML attribute
- Ensure handler is registered in HandlerRegistry
Contributing
See the main repository CONTRIBUTING.md for guidelines.
License
This project is licensed under either of:
- Apache License, Version 2.0
- MIT license
at your option.
Status
Current Version: 0.1.0 (MVP)
Phase: Phase 6 - Polish & Documentation
All Tests: ✅ Passing (28/28)
Examples: ✅ Working (hello-world, counter, todo-app, styling)