# `osui::state` The `state` module provides OSUI's built-in reactivity system, allowing widgets to automatically update when their associated data changes. This is achieved through the `State` struct and the `DependencyHandler` trait. ## `DependencyHandler` Trait A trait for types that can signal changes, triggering reactive updates in `DynWidget`s. `State` is the primary implementer. ```rust pub trait DependencyHandler: std::fmt::Debug + Send + Sync { /// Called when a dependent widget registers itself with this dependency. /// This typically increments an internal counter of dependents. fn add(&self); /// Returns `true` if the state has changed since the last `check()`. /// If `true`, it typically "consumes" one change notification. fn check(&self) -> bool; } ``` ## `State` `State` is a reactive data container. It wraps a value of type `T` and provides methods to get/set the value and signal changes to dependent widgets. ```rust #[derive(Debug, Clone)] pub struct State { inner: Arc>>, } #[derive(Debug)] pub struct Inner { value: T, dependencies: usize, // Count of widgets depending on this state changed: usize, // Count of pending changes to be processed by dependents } ``` ### Associated Functions #### `use_state(v: T) -> State` Creates a new `State` instance, initialized with the provided value `v`. This is the recommended way to create reactive state variables. **Arguments:** * `v`: The initial value for the state. **Returns:** A new `State` instance. **Example:** ```rust use osui::prelude::*; let my_counter = use_state(0); let my_text = use_state(String::from("Initial Text")); ``` ### Associated Methods #### `State::get_dl(&self) -> T` Returns a cloned copy of the inner value `T`. This method is recommended for preventing potential deadlocks if you only need to read the value and don't need to hold a lock for extended periods. It does *not* mark the state as changed. **Returns:** A `T` (clone of the inner value). **Example:** ```rust use osui::prelude::*; let my_state = use_state(42); let value = my_state.get_dl(); // value is 42 ``` #### `State::get(&self) -> MutexGuard<'_, Inner>` Acquires a `MutexGuard` for the inner `Inner` struct, providing mutable (or immutable) access to the `value` within `Inner`. This method *will* block if another thread or part of the application is currently holding the lock. **Returns:** A `MutexGuard` that dereferences to `Inner`. Since `Inner` implements `Deref` and `DerefMut` for `T`, you can often treat `state.get()` as a direct reference to `T`. **Example (modifying value and marking as changed):** ```rust use osui::prelude::*; let my_state = use_state(0); { let mut inner_guard = my_state.get(); // Acquire lock *inner_guard += 1; // Modify value using DerefMut; automatically marks as changed } // Lock is released here ``` #### `State::set(&self, v: T)` Sets the inner value of the state to `v` and explicitly marks it as changed. This is an alternative to acquiring a `get()` lock and reassigning. **Arguments:** * `v`: The new value for the state. **Example:** ```rust use osui::prelude::*; let my_state = use_state("hello".to_string()); my_state.set("world".to_string()); // State is updated and marked changed ``` #### `State::update(&self)` Explicitly marks the state as updated without changing its value. This is useful if you've modified the inner `T` through a method that doesn't trigger `DerefMut` on `Inner` (e.g., if `T` is a complex mutable struct and you called a method on it while holding the `MutexGuard` without reassigning the `T` itself). **Example:** ```rust use osui::prelude::*; #[derive(Debug, Clone)] struct MyData { count: i32 } let my_data_state = use_state(MyData { count: 0 }); { let mut data_guard = my_data_state.get(); data_guard.count += 1; // Directly modify field within the guard } my_data_state.update(); // Manually signal that the state has changed ``` ### Implementations #### `impl DependencyHandler for State` `State` implements `DependencyHandler`. * `add()`: Increments `inner.dependencies`. * `check()`: Returns `true` if `inner.changed > 0`, then decrements `inner.changed`. This ensures each dependent consumes one change notification. #### `impl Display for State` `State` implements `Display`, allowing it to be formatted directly (e.g., in `format!` strings or debug output), by displaying its inner `value`. **Example:** ```rust use osui::prelude::*; let count = use_state(10); println!("Current count: {}", count); // Output: "Current count: 10" ``` #### `impl Deref for Inner` Allows immutable dereferencing of `Inner` to `T`. This means `state.get().value` can be simply `*state.get()`. #### `impl DerefMut for Inner` Allows mutable dereferencing of `Inner` to `T`. Crucially, when this is used, the `changed` counter within `Inner` is set to `dependencies`, marking the state as changed for all its dependents. This means `*state.get() = new_value;` will trigger the change notification.