pub struct DifferentialRenderer { /* private fields */ }Expand description
The main differential rendering manager.
This is the central component that orchestrates the differential rendering system. It tracks component states, manages dirty regions, and provides the API for determining what needs to be re-rendered.
§Architecture
┌────────────────────┐
│ DifferentialRenderer │
├──────────┬─────────┤
│ Components│DirtyRegions│
│ HashMap │ Vec │
│ │ │
│ - States │ - Areas │
│ - Deps │ - Priority │
│ - Versions│ - Metadata │
└──────────┴──────────┘§Memory Complexity
- Components: O(n) where n is the number of registered components
- Dirty Regions: O(k) where k is bounded by
max_dirty_regions - Total: O(n + k) with configurable upper bounds
§Performance Guarantees
- Component lookup: O(1) average, O(n) worst case (HashMap)
- Region intersection: O(k) where k is current dirty regions
- Memory bounded: Hard limits prevent unbounded growth
- Cleanup: Automatic eviction of stale data
§Thread Safety
Not thread-safe. Designed for single-threaded UI event loops. Use external synchronization if multi-threaded access is needed.
§Invariants
The following invariants are maintained and checked in debug builds:
- All dirty regions have positive area
- Component dependency graph is acyclic (DAG)
- Version numbers are monotonic within each component
- Memory usage stays within configured limits
Implementations§
Source§impl DifferentialRenderer
impl DifferentialRenderer
Sourcepub fn with_config(config: DifferentialConfig) -> Self
pub fn with_config(config: DifferentialConfig) -> Self
Create a new differential renderer with custom config
Sourcepub fn register_component(&mut self, id: String, area: Rect)
pub fn register_component(&mut self, id: String, area: Rect)
Register a component
Sourcepub fn unregister_component(&mut self, id: &str)
pub fn unregister_component(&mut self, id: &str)
Unregister a component
Sourcepub fn update_component_area(&mut self, id: &str, area: Rect)
pub fn update_component_area(&mut self, id: &str, area: Rect)
Update component area
Sourcepub fn mark_component_dirty(&mut self, id: &str)
pub fn mark_component_dirty(&mut self, id: &str)
Mark a component as dirty
Sourcepub fn mark_region_dirty(&mut self, rect: Rect, component_id: Option<String>)
pub fn mark_region_dirty(&mut self, rect: Rect, component_id: Option<String>)
Mark a region as dirty for re-rendering.
This is the core API for indicating that a rectangular area needs to be updated. The system will automatically handle region merging and memory management.
§Parameters
rect: The rectangular area that needs updatingcomponent_id: Optional ID of the component that owns this region
§Behavior
- Size Filtering: Skips regions smaller than
min_region_area - Region Merging: Attempts to merge with existing regions if enabled
- Memory Management: Enforces
max_dirty_regionslimit via LRU eviction - Validation: Ensures region has positive area and valid coordinates
§Performance
- Best case: O(1) if no merging occurs
- Average case: O(k) where k is existing dirty regions
- Worst case: O(k*log(k)) when sorting for eviction
§Examples
use hojicha_rendering::differential::DifferentialRenderer;
use ratatui::layout::Rect;
let mut renderer = DifferentialRenderer::new();
// Mark a region for a specific component
renderer.mark_region_dirty(
Rect::new(10, 10, 20, 20),
Some("my_component".to_string())
);
// Mark a generic region
renderer.mark_region_dirty(Rect::new(0, 0, 100, 100), None);Sourcepub fn needs_render(&self, rect: Rect) -> bool
pub fn needs_render(&self, rect: Rect) -> bool
Check if a rectangular region needs rendering.
This is the primary API for determining whether a given area needs to be re-rendered based on dirty region tracking.
§Algorithm
- Return
trueif differential rendering is disabled - Return
trueif full refresh interval has elapsed - Return
trueif region intersects any dirty regions - Return
falseotherwise (region is clean)
§Performance
- Time Complexity: O(k) where k is the number of dirty regions
- Space Complexity: O(1)
- Early termination: Stops on first intersection found
§Parameters
rect: The rectangular area to check
§Returns
true if the region should be re-rendered, false if it can be skipped.
§Examples
use hojicha_rendering::differential::DifferentialRenderer;
use ratatui::layout::Rect;
let mut renderer = DifferentialRenderer::new();
let check_area = Rect::new(0, 0, 50, 50);
// Initially clean
assert!(!renderer.needs_render(check_area));
// Mark overlapping area dirty
renderer.mark_region_dirty(Rect::new(25, 25, 50, 50), None);
assert!(renderer.needs_render(check_area)); // Now needs renderSourcepub fn component_needs_render(&self, id: &str) -> bool
pub fn component_needs_render(&self, id: &str) -> bool
Check if a component needs rendering
Sourcepub fn mark_component_rendered(&mut self, id: &str, checksum: Option<Checksum>)
pub fn mark_component_rendered(&mut self, id: &str, checksum: Option<Checksum>)
Mark a component as rendered
Sourcepub fn clear_dirty_regions(&mut self, rect: Rect)
pub fn clear_dirty_regions(&mut self, rect: Rect)
Clear dirty regions for a specific area
Sourcepub fn force_full_refresh(&mut self)
pub fn force_full_refresh(&mut self)
Force a full refresh
Sourcepub fn get_dirty_regions(&self) -> &[DirtyRegion]
pub fn get_dirty_regions(&self) -> &[DirtyRegion]
Get the list of dirty regions
Sourcepub fn get_stats(&self) -> &RenderStats
pub fn get_stats(&self) -> &RenderStats
Get rendering statistics
Sourcepub fn reset_stats(&mut self)
pub fn reset_stats(&mut self)
Reset statistics
Sourcepub fn record_render(&mut self, differential: bool, skipped: bool)
pub fn record_render(&mut self, differential: bool, skipped: bool)
Record a render operation
Sourcepub fn set_enabled(&mut self, enabled: bool)
pub fn set_enabled(&mut self, enabled: bool)
Enable or disable differential rendering
Sourcepub fn is_enabled(&self) -> bool
pub fn is_enabled(&self) -> bool
Check if differential rendering is enabled
Sourcepub fn config(&self) -> &DifferentialConfig
pub fn config(&self) -> &DifferentialConfig
Get the current configuration
Sourcepub fn update_config(&mut self, config: DifferentialConfig)
pub fn update_config(&mut self, config: DifferentialConfig)
Update configuration
Sourcepub fn dirty_region_count(&self) -> usize
pub fn dirty_region_count(&self) -> usize
Get the number of dirty regions (for testing/debugging)
Sourcepub fn has_component(&self, id: &str) -> bool
pub fn has_component(&self, id: &str) -> bool
Check if a component exists (for testing)
Sourcepub fn add_component_dependency(
&mut self,
component_id: &str,
dependency_id: &str,
)
pub fn add_component_dependency( &mut self, component_id: &str, dependency_id: &str, )
Add a dependency between components (for testing)
Trait Implementations§
Auto Trait Implementations§
impl Freeze for DifferentialRenderer
impl RefUnwindSafe for DifferentialRenderer
impl Send for DifferentialRenderer
impl Sync for DifferentialRenderer
impl Unpin for DifferentialRenderer
impl UnsafeUnpin for DifferentialRenderer
impl UnwindSafe for DifferentialRenderer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more