egui_mobius_reactive/lib.rs
1//! Thread-safe reactive state management system for egui_mobius.
2//!
3//! This crate provides a reactive state management system designed specifically for
4//! thread-safe, real-time UI updates in egui applications. It is built on three main
5//! concepts:
6//!
7//! 1. **Values**: Thread-safe containers for state that can notify listeners of changes
8//! 2. **Derived Values**: Automatically updating computed values that depend on other values
9//! 3. **Signal Registry**: A system for managing signal-slot connections between components
10//!
11//! # Quick Start
12//!
13//! ```rust
14//! use egui_mobius_reactive::{Value, Derived};
15//! use std::thread::sleep;
16//! use std::time::Duration;
17//!
18//! // Create a basic value
19//! let count = Value::new(0);
20//!
21//! // Create a derived value that automatically updates
22//! let count_clone = count.clone();
23//! use std::sync::Arc;
24//! let doubled = Derived::new(&[Arc::new(count.clone())], move || {
25//! let val = *count_clone.lock();
26//! val * 2
27//! });
28//!
29//! // Update the original value and see automatic updates
30//! count.set(5);
31//! sleep(Duration::from_millis(50));
32//! assert_eq!(doubled.get(), 10);
33//! ```
34//!
35//! # Architecture
36//!
37//! The reactive system is built on three key architectural components that work together
38//! to provide thread-safe, real-time UI updates:
39//!
40//! ## Key Components
41//!
42//! 1. **Thread-Safe Values**:
43//! - `Value<T>` wraps state in `Arc<Mutex<T>>`
44//! - Safe concurrent access across UI and worker threads
45//! - Change notification through `ValueExt` trait
46//!
47//! 2. **Automatic Dependency Tracking**:
48//! - `Derived<T>` computes values from dependencies
49//! - Auto-updates when dependencies change
50//! - Thread-safe computation in background
51//!
52//! 3. **Signal Management**:
53//! - `SignalRegistry` manages reactive context
54//! - Handles signal-slot connections
55//! - Prevents memory leaks
56//! - Type-safe message passing
57//!
58//! ## Complete Example
59//!
60//! ```rust
61//! use std::sync::Arc;
62//! use egui_mobius_reactive::{Value, Derived, SignalRegistry};
63//!
64//! // Define your application state
65//! pub struct AppState {
66//! pub registry: SignalRegistry,
67//! count: Value<i32>,
68//! label: Value<String>,
69//! doubled: Derived<i32>,
70//! }
71//!
72//! impl AppState {
73//! pub fn new(registry: SignalRegistry) -> Self {
74//! let count = Value::new(0);
75//! let count_ref = count.clone();
76//! let doubled = Derived::new(&[Arc::new(count.clone())], move || {
77//! let val = *count_ref.lock();
78//! val * 2
79//! });
80//! let label = Value::new("Click to increment".to_string());
81//!
82//! registry.register_named_signal("count", Arc::new(count.clone()));
83//! registry.register_named_signal("doubled", Arc::new(doubled.clone()));
84//!
85//! Self {
86//! registry,
87//! count,
88//! label,
89//! doubled,
90//! }
91//! }
92//!
93//! pub fn increment(&self) {
94//! let new_count = *self.count.lock() + 1;
95//! self.count.set(new_count);
96//! // Doubled value updates automatically!
97//! }
98//! }
99//! ```
100//!
101//! # Features & Best Practices
102//!
103//! ## Thread Safety & Performance
104//!
105//! - All values protected by `Arc<Mutex<T>>`
106//! - Each slot runs in its own thread for true async operation
107//! - Clean thread separation for background tasks
108//! - Type-safe message passing between threads
109//!
110//! ## Automatic Updates
111//!
112//! - Derived values update when dependencies change
113//! - No manual synchronization needed
114//! - UI updates trigger reactive updates
115//! - Seamless integration with egui
116//!
117//! ## Memory Management
118//!
119//! - SignalRegistry handles registration and cleanup
120//! - Prevents memory leaks from orphaned signals
121//! - Automatic cleanup of unused values
122//! - Manual cleanup available when needed
123//!
124//! ## Best Practices
125//!
126//! 1. **State Organization**:
127//! - Keep SignalRegistry at app level
128//! - Group related values in structs
129//! - Register all dependent values
130//!
131//! 2. **Thread Safety**:
132//! - Use Value::lock() for access
133//! - Clone before moving to closures
134//! - Let each slot handle its thread
135//!
136
137pub mod reactive;
138pub use crate::reactive::{Value, ValueExt, Derived, ReactiveList, ReactiveValue, SignalRegistry};
139
140// Re-export commonly used types for convenience
141//pub use reactive::{Value, ValueExt, Derived, SignalRegistry, ReactiveValue, ReactiveList};