//! Implements storage for Component instances, in a way that allows us to //! short-circuit the rendering process so we don't have to re-scan entire //! tree structures when updating state. use std::collections::HashMap; pub use alchemy_styles::Appearance; use crate::reconciler::error::{RenderEngineError as Error}; use crate::reconciler::instance::Instance; use crate::reconciler::key::{Allocator, Id, INSTANCE_ALLOCATOR, ComponentKey}; /// This is a clone of a structure you'll also find over in stretch. We do this separately /// here for two reasons. /// /// - First, a Component may have children that don't require styles or layout passes. These nodes /// should not have `Style` or `Appearance` nodes created, but we do need the correct parent/child /// relationships in place. /// - The `Storage` pieces of stretch are realistically an implementation detail that we shouldn't /// rely on. struct Storage(HashMap); impl Storage { pub fn new() -> Self { Storage(HashMap::new()) } pub fn get(&self, key: ComponentKey) -> Result<&T, Error> { match self.0.get(&key) { Some(v) => Ok(v), None => Err(Error::InvalidComponentKey(key)), } } pub fn get_mut(&mut self, key: ComponentKey) -> Result<&mut T, Error> { match self.0.get_mut(&key) { Some(v) => Ok(v), None => Err(Error::InvalidComponentKey(key)), } } pub fn remove(&mut self, key: ComponentKey) -> Result { match self.0.remove(&key) { Some(v) => Ok(v), None => Err(Error::InvalidComponentKey(key)) } } pub fn insert(&mut self, key: ComponentKey, value: T) -> Option { self.0.insert(key, value) } } impl std::ops::Index<&ComponentKey> for Storage { type Output = T; fn index(&self, idx: &ComponentKey) -> &T { &(self.0)[idx] } } pub(crate) struct ComponentStore { id: Id, nodes: Allocator, components: Storage, parents: Storage>, children: Storage> } impl ComponentStore { pub fn new() -> Self { ComponentStore { id: INSTANCE_ALLOCATOR.lock().unwrap().allocate(), nodes: Allocator::new(), components: Storage::new(), parents: Storage::new(), children: Storage::new() } } pub fn new_key(&mut self) -> ComponentKey { let local = self.nodes.allocate(); ComponentKey { instance: self.id, local } } pub fn insert( &mut self, key: ComponentKey, instance: Instance ) -> Result<(), Error> { /*for child in &children { self.parents.get_mut(*child)?.push(key); }*/ self.components.insert(key, instance); self.parents.insert(key, Vec::with_capacity(1)); self.children.insert(key, vec![]); //children); Ok(()) } pub fn remove(&mut self, key: ComponentKey) -> Result { self.parents.remove(key)?; self.children.remove(key)?; self.components.remove(key) } pub fn add_child(&mut self, key: ComponentKey, child: ComponentKey) -> Result<(), Error> { self.parents.get_mut(child)?.push(key); self.children.get_mut(key)?.push(child); Ok(()) } pub fn set_children(&mut self, key: ComponentKey, children: Vec) -> Result<(), Error> { // Remove node as parent from all its current children. for child in self.children.get(key)? { self.parents.get_mut(*child)?.retain(|p| *p != key); } *self.children.get_mut(key)? = Vec::with_capacity(children.len()); // Build up relation node <-> child for child in children { self.parents.get_mut(child)?.push(key); self.children.get_mut(key)?.push(child); } Ok(()) } pub fn remove_child(&mut self, key: ComponentKey, child: ComponentKey) -> Result { match self.children(key)?.iter().position(|n| *n == child) { Some(index) => self.remove_child_at_index(key, index), None => Err(Error::InvalidComponentKey(child)), } } pub fn remove_child_at_index(&mut self, key: ComponentKey, index: usize) -> Result { let child = self.children.get_mut(key)?.remove(index); self.parents.get_mut(child)?.retain(|p| *p != key); Ok(child) } pub fn replace_child_at_index(&mut self, key: ComponentKey, index: usize, child: ComponentKey) -> Result { self.parents.get_mut(child)?.push(key); let old_child = std::mem::replace(&mut self.children.get_mut(key)?[index], child); self.parents.get_mut(old_child)?.retain(|p| *p != key); Ok(old_child) } pub fn children(&self, key: ComponentKey) -> Result, Error> { self.children.get(key).map(Clone::clone) } pub fn child_count(&self, key: ComponentKey) -> Result { self.children.get(key).map(Vec::len) } pub fn get(&self, key: ComponentKey) -> Result<&Instance, Error> { self.components.get(key) } pub fn get_mut(&mut self, key: ComponentKey) -> Result<&mut Instance, Error> { self.components.get_mut(key) } }