hyperchad_renderer_egui 0.2.0

HyperChad egui renderer package
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
# HyperChad Egui Renderer

Native desktop UI renderer for HyperChad using the egui immediate mode GUI framework.

## Overview

The HyperChad Egui Renderer provides:

- **Native Desktop UI**: Render HyperChad components as native desktop applications
- **Immediate Mode GUI**: Built on egui's immediate mode architecture
- **Hardware Acceleration**: Optional WGPU backend for GPU-accelerated rendering
- **Cross-platform**: Works on Windows, macOS, and Linux
- **Layout Engine**: Complete CSS-like layout system with flexbox support
- **Interactive Elements**: Full support for forms, buttons, and user interactions
- **Image Loading**: Async image loading with caching
- **Viewport Management**: Scrolling and viewport-aware rendering
- **Event System**: Complete action and event handling

## Features

### Rendering Capabilities

- **Container Rendering**: Full HyperChad container hierarchy support
- **Element Types**: All HTML-equivalent elements (div, span, input, button, image, etc.)
- **Layout Systems**: Flexbox, positioning, margins, padding, borders
- **Typography**: Font sizing, text alignment, headings (H1-H6)
- **Styling**: Colors, backgrounds, borders, opacity, visibility
- **Responsive Design**: Conditional styling and responsive breakpoints

### Interactive Features

- **Form Elements**: Text inputs, checkboxes, buttons with validation
- **Event Handling**: Click, hover, focus, resize, and custom events
- **Action System**: Comprehensive action framework with effects
- **State Management**: Component state and data binding
- **Navigation**: Route handling and page navigation
- **Canvas Support**: Canvas rendering for graphics (available in v1 renderer)

### Performance Features

- **Efficient Rendering**: Immediate mode rendering with minimal overhead
- **Layout Caching**: Cached layout calculations for performance
- **Image Caching**: Smart image loading and caching system
- **Viewport Culling**: Only render visible elements
- **Profiling Support**: Optional profiling with puffin and tracing

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
hyperchad_renderer_egui = { path = "../hyperchad/renderer/egui" }

# Or with GPU acceleration
# hyperchad_renderer_egui = { path = "../hyperchad/renderer/egui", features = ["wgpu"] }

# Or with profiling
# hyperchad_renderer_egui = { path = "../hyperchad/renderer/egui", features = ["profiling", "profiling-puffin"] }
```

## Usage

### Basic Desktop Application

```rust
use hyperchad_renderer_egui::EguiRenderer;
use hyperchad_renderer::{Handle, Renderer, ToRenderRunner};
use hyperchad_router::Router;
use hyperchad_actions::logic::Value;
use flume::unbounded;
use std::sync::Arc;

// You need to implement a custom calculator that implements both
// hyperchad_transformer::layout::Calc and hyperchad_renderer_egui::layout::EguiCalc
// See packages/hyperchad/app/src/renderer.rs for a complete example

#[derive(Clone)]
struct MyCalculator;

impl hyperchad_transformer::layout::Calc for MyCalculator {
    fn calc(&self, container: &mut hyperchad_transformer::Container) -> bool {
        // Your layout calculation logic
        true
    }
}

impl hyperchad_renderer_egui::layout::EguiCalc for MyCalculator {
    fn with_context(self, context: eframe::egui::Context) -> Self {
        // Initialize with egui context
        self
    }
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create async runtime
    let runtime = switchy::unsync::runtime::Builder::new().build()?;

    runtime.block_on(async {
        // Create communication channels
        let (action_tx, action_rx) = unbounded();
        let (resize_tx, resize_rx) = unbounded();

        // Create router
        let router = Router::new();

        // Create client info
        let client_info = Arc::new(hyperchad_router::ClientInfo::default());

        // Create layout calculator
        let calculator = MyCalculator;

        // Create renderer
        let mut renderer = EguiRenderer::new(
            router,
            action_tx,
            resize_tx,
            client_info,
            calculator,
        );

        // Initialize window
        renderer.init(
            800.0,    // width
            600.0,    // height
            None,     // x position
            None,     // y position
            None,     // background color
            Some("My App"), // title
            Some("My HyperChad App"), // description
            None,     // viewport
        ).await?;

        // Create and run the application
        let mut runner = renderer.to_runner(Handle::current())?;
        runner.run()?;

        Ok(())
    })
}
```

### Navigation Events

`EguiRenderer` also exposes `wait_for_navigation()` for handling link navigation
events generated by rendered anchors:

```rust
use switchy_async::runtime::Handle;

let renderer = renderer.clone();
Handle::current().spawn(async move {
    while let Some(path) = renderer.wait_for_navigation().await {
        // Route or handle the requested path
        println!("Navigate to: {path}");
    }
});
```

### Rendering HyperChad Components

```rust
use hyperchad_template::container;
use hyperchad_renderer::{View, Renderer};

// Create HyperChad components
let view = container! {
    div
        width=800
        height=600
        background="#f0f0f0"
        direction="column"
        padding=20
    {
        h1
            color="blue"
            margin-bottom=20
        {
            "Welcome to HyperChad!"
        }

        div
            direction="row"
            gap=10
        {
            button
                background="green"
                color="white"
                padding=10
                fx-click=fx { show("message") }
            {
                "Show Message"
            }

            button
                background="red"
                color="white"
                padding=10
                fx-click=fx { hide("message") }
            {
                "Hide Message"
            }
        }

        div
            str_id="message"
            background="yellow"
            padding=15
            margin-top=20
            visibility="hidden"
        {
            "Hello from HyperChad!"
        }
    }
};

// Render the view
renderer.render(View::from(view)).await?;
```

### Form Handling

```rust
use hyperchad_template::container;

let form_view = container! {
    div
        width=400
        background="white"
        padding=20
        border="1px solid #ccc"
        direction="column"
        gap=15
    {
        h2 { "User Registration" }

        input
            type="text"
            name="username"
            placeholder="Enter username"
            fx-change=fx { set_data_attr("username", event_value()) }
        {}

        input
            type="password"
            name="password"
            placeholder="Enter password"
            fx-change=fx { set_data_attr("password", event_value()) }
        {}

        input
            type="checkbox"
            name="agree"
            fx-change=fx { set_data_attr("agreed", event_value()) }
        {}

        span { "I agree to the terms" }

        button
            background="blue"
            color="white"
            padding="10px 20px"
            fx-click=fx { request_action("submit_form", data_attrs()) }
        {
            "Register"
        }
    }
};

renderer.render(View::from(form_view)).await?;
```

### Image Display

```rust
use hyperchad_template::container;

let image_view = container! {
    div
        width=600
        height=400
        direction="column"
        align-items="center"
        gap=20
    {
        h2 { "Image Gallery" }

        img
            src="https://example.com/image.jpg"
            alt="Example Image"
            width=400
            height=300
            fit="cover"
            loading="lazy"
        {}

        div
            direction="row"
            gap=10
        {
            img
                src="/assets/thumb1.jpg"
                width=100
                height=100
                fit="cover"
                fx-click=fx { set_attr("main-image", "src", "/assets/image1.jpg") }
            {}

            img
                src="/assets/thumb2.jpg"
                width=100
                height=100
                fit="cover"
                fx-click=fx { set_attr("main-image", "src", "/assets/image2.jpg") }
            {}
        }
    }
};

renderer.render(View::from(image_view)).await?;
```

### Custom Layout Calculator

For a complete working example of implementing a custom layout calculator with font metrics
and default sizing, see `packages/hyperchad/app/src/renderer.rs` which demonstrates:

- Creating a calculator that implements both `Calc` and `EguiCalc` traits
- Using `Calculator` with `CalculatorDefaults` for font sizes and margins
- Integrating `EguiFontMetrics` for accurate text measurement
- Setting up H1-H6 heading sizes and margins

The calculator is initialized with the egui context via the `with_context` method
when the renderer starts.

### Event Handling

```rust
use hyperchad_actions::{ActionType, ActionEffect};
use switchy_async::runtime::Handle;

// Handle action events
Handle::current().spawn(async move {
    while let Ok((action_name, value)) = action_rx.recv_async().await {
        match action_name.as_str() {
            "submit_form" => {
                println!("Form submitted: {:?}", value);
                // Process form data
            }
            "navigate" => {
                if let Some(Value::String(url)) = value {
                    println!("Navigate to: {}", url);
                    // Handle navigation
                }
            }
            _ => {
                println!("Unknown action: {}", action_name);
            }
        }
    }
});

// Handle resize events
Handle::current().spawn(async move {
    while let Ok((width, height)) = resize_rx.recv_async().await {
        println!("Window resized: {}x{}", width, height);
        // Handle window resize
    }
});
```

### Canvas Rendering

**Note**: Canvas rendering is implemented in the v1 renderer only. The v2 renderer has canvas
rendering stubbed but not yet implemented.

```rust
use hyperchad_renderer::canvas::{CanvasUpdate, CanvasAction, Pos};
use hyperchad_renderer::Color;

let canvas_update = CanvasUpdate {
    target: "my-canvas".to_string(),
    canvas_actions: vec![
        CanvasAction::Clear,
        CanvasAction::StrokeColor(Color { r: 255, g: 0, b: 0, a: Some(255) }),
        CanvasAction::StrokeSize(2.0),
        CanvasAction::Line(Pos(10.0, 10.0), Pos(110.0, 10.0)),
        CanvasAction::FillRect(Pos(10.0, 20.0), Pos(110.0, 70.0)),
    ],
};

renderer.render_canvas(canvas_update).await?;
```

## Feature Flags

- **`wgpu`**: Enable WGPU backend for GPU acceleration (enabled by default)
- **`glow`**: Enable OpenGL backend
- **`wayland`**: Enable Wayland support on Linux
- **`x11`**: Enable X11 support on Linux
- **`profiling`**: Enable performance profiling support
- **`profiling-puffin`**: Enable puffin profiler integration
- **`profiling-tracing`**: Enable tracing profiler integration
- **`profiling-tracy`**: Enable Tracy profiler integration
- **`debug`**: Enable debug rendering features (enabled by default)
- **`v1`**: Use v1 renderer implementation (enabled by default) - Full-featured renderer with complete canvas support, comprehensive action handling, and mature viewport management. This is the production-ready implementation (~3800 lines).
- **`v2`**: Use v2 renderer implementation (enabled by default) - Refactored renderer with modular action handling using the new `ActionHandler` API from `hyperchad_actions`. This version uses simplified, more maintainable code architecture (~1000 lines). Canvas rendering and some advanced features are stubbed but not yet fully implemented. When both features are enabled, v2 takes precedence.

## Performance Considerations

- **Immediate Mode**: UI is rebuilt every frame for maximum flexibility
- **Layout Caching**: Layout calculations are cached when possible
- **Image Caching**: Images are cached to avoid repeated loading
- **Viewport Culling**: Only visible elements are processed
- **GPU Acceleration**: Use WGPU backend for better performance

## Dependencies

- **eframe**: egui application framework
- **egui**: Immediate mode GUI library
- **HyperChad Core**: Template, transformer, and action systems
- **switchy_async**: Runtime abstraction for async operations
- **Image**: Image processing and loading

## Integration

This renderer is designed for:

- **Desktop Applications**: Native desktop apps with rich UI
- **Development Tools**: IDE-like applications and editors
- **Games**: Game UI and tools with immediate mode benefits
- **Prototyping**: Rapid UI prototyping and development
- **Cross-platform Apps**: Applications targeting multiple desktop platforms

## Limitations

- **Mobile Support**: Not designed for mobile platforms
- **Web Deployment**: Cannot run in web browsers
- **Immediate Mode**: UI state must be managed externally
- **Memory Usage**: Higher memory usage due to immediate mode architecture