diff --git a/src/algo.rs b/src/algo.rs
index e814e8545..18bb933d6 100644
--- a/src/algo.rs
+++ b/src/algo.rs
@@ -6,8 +6,8 @@ use libm::F32Ext;
use core::any::Any;
use core::f32;
+use crate::forest::{Forest, NodeData};
use crate::id::NodeId;
-use crate::node::{Forest, NodeData};
use crate::result;
use crate::style::*;
diff --git a/src/forest.rs b/src/forest.rs
new file mode 100644
index 000000000..289cb08d8
--- /dev/null
+++ b/src/forest.rs
@@ -0,0 +1,100 @@
+//! Forest - ECS like datastructure for storing node trees.
+//!
+//! Backing datastructure for `Stretch` structs.
+
+use crate::geometry::Size;
+use crate::id::NodeId;
+use crate::node::MeasureFunc;
+use crate::number::Number;
+use crate::result::{Cache, Layout};
+use crate::style::Style;
+use crate::Error;
+
+pub(crate) struct NodeData {
+ pub(crate) style: Style,
+ pub(crate) measure: Option<MeasureFunc>,
+ pub(crate) layout: Layout,
+ pub(crate) layout_cache: Option<Cache>,
+ pub(crate) is_dirty: bool,
+}
+
+impl NodeData {
+ fn new_leaf(style: Style, measure: MeasureFunc) -> Self {
+ NodeData { style, measure: Some(measure), layout_cache: None, layout: Layout::new(), is_dirty: true }
+ }
+
+ fn new(style: Style) -> Self {
+ NodeData { style, measure: None, layout_cache: None, layout: Layout::new(), is_dirty: true }
+ }
+}
+
+pub(crate) struct Forest {
+ pub(crate) nodes: Vec<NodeData>,
+ pub(crate) children: Vec<Vec<NodeId>>,
+ pub(crate) parents: Vec<Vec<NodeId>>,
+}
+
+impl Forest {
+ pub fn with_capacity(capacity: usize) -> Self {
+ Forest {
+ nodes: Vec::with_capacity(capacity),
+ children: Vec::with_capacity(capacity),
+ parents: Vec::with_capacity(capacity),
+ }
+ }
+
+ pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> NodeId {
+ let id = self.nodes.len();
+ self.nodes.push(NodeData::new_leaf(style, measure));
+ self.children.push(Vec::with_capacity(0));
+ self.parents.push(Vec::with_capacity(1));
+ id
+ }
+
+ pub fn new_node(&mut self, style: Style, children: Vec<NodeId>) -> NodeId {
+ let id = self.nodes.len();
+ for child in &children {
+ self.parents[*child].push(id);
+ }
+ self.nodes.push(NodeData::new(style));
+ self.children.push(children);
+ self.parents.push(Vec::with_capacity(1));
+ id
+ }
+
+ pub fn add_child(&mut self, node: NodeId, child: NodeId) {
+ self.parents[child].push(node);
+ self.children[node].push(child);
+ self.mark_dirty(node)
+ }
+
+ pub unsafe fn remove_child(&mut self, node: NodeId, child: NodeId) -> NodeId {
+ let index = self.children[node].iter().position(|n| *n == child).unwrap();
+ self.remove_child_at_index(node, index)
+ }
+
+ pub fn remove_child_at_index(&mut self, node: NodeId, index: usize) -> NodeId {
+ let child = self.children[node].remove(index);
+ self.parents[child].retain(|p| *p != node);
+ self.mark_dirty(node);
+ child
+ }
+
+ pub fn mark_dirty(&mut self, node: NodeId) {
+ fn mark_dirty_impl(nodes: &mut Vec<NodeData>, parents: &Vec<Vec<NodeId>>, node_id: NodeId) {
+ let node = &mut nodes[node_id];
+ node.layout_cache = None;
+ node.is_dirty = true;
+
+ for parent in &parents[node_id] {
+ mark_dirty_impl(nodes, parents, *parent);
+ }
+ }
+
+ mark_dirty_impl(&mut self.nodes, &self.parents, node);
+ }
+
+ pub fn compute_layout(&mut self, node: NodeId, size: Size<Number>) -> Result<(), Error> {
+ self.compute(node, size).map_err(|err| Error::Measure(err))
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 97fef7abb..c9f0b4542 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,6 +13,7 @@ pub mod result;
pub mod style;
mod algo;
+mod forest;
mod id;
pub use crate::node::Stretch;
diff --git a/src/node.rs b/src/node.rs
index 6a0ebadda..bf6175c13 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -7,14 +7,15 @@ use std::collections::HashMap;
use std::ops::Drop;
use std::sync::Mutex;
+use crate::forest::Forest;
use crate::geometry::Size;
use crate::id::{self, NodeId};
use crate::number::Number;
-use crate::result::{Cache, Layout};
+use crate::result::Layout;
use crate::style::*;
use crate::Error;
-type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>, Box<Any>>>;
+pub type MeasureFunc = Box<Fn(Size<Number>) -> Result<Size<f32>, Box<Any>>>;
lazy_static! {
/// Global stretch instance id allocator.
@@ -70,6 +71,13 @@ impl Stretch {
}
}
+ /// Removes all nodes.
+ ///
+ /// All associated nodes will be invalid.
+ pub fn clear(&mut self) {
+ unimplemented!()
+ }
+
pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> Node {
let node = self.allocate_node();
let id = self.forest.new_leaf(style, measure);
@@ -189,7 +197,7 @@ impl Stretch {
pub fn compute_layout(&mut self, node: Node, size: Size<Number>) -> Result<(), Error> {
let id = self.find_node(node)?;
- self.forest.compute(id, size).map_err(|err| Error::Measure(err))
+ self.forest.compute_layout(id, size)
}
}
@@ -198,92 +206,3 @@ impl Drop for Stretch {
INSTANCE_ALLOCATOR.lock().unwrap().free(&[self.id]);
}
}
-
-pub(crate) struct NodeData {
- pub(crate) style: Style,
- pub(crate) measure: Option<MeasureFunc>,
- pub(crate) layout: Layout,
- pub(crate) layout_cache: Option<Cache>,
- pub(crate) is_dirty: bool,
-}
-
-impl NodeData {
- fn new_leaf(style: Style, measure: MeasureFunc) -> Self {
- NodeData { style, measure: Some(measure), layout_cache: None, layout: Layout::new(), is_dirty: true }
- }
-
- fn new(style: Style) -> Self {
- NodeData { style, measure: None, layout_cache: None, layout: Layout::new(), is_dirty: true }
- }
-}
-
-pub(crate) struct Forest {
- pub(crate) nodes: Vec<NodeData>,
- pub(crate) children: Vec<Vec<id::NodeId>>,
- pub(crate) parents: Vec<Vec<id::NodeId>>,
-}
-
-impl Forest {
- pub fn with_capacity(capacity: usize) -> Self {
- Forest {
- nodes: Vec::with_capacity(capacity),
- children: Vec::with_capacity(capacity),
- parents: Vec::with_capacity(capacity),
- }
- }
-
- pub fn new_leaf(&mut self, style: Style, measure: MeasureFunc) -> NodeId {
- let id = self.nodes.len();
- self.nodes.push(NodeData::new_leaf(style, measure));
- self.children.push(Vec::with_capacity(0));
- self.parents.push(Vec::with_capacity(1));
- id
- }
-
- pub fn new_node(&mut self, style: Style, children: Vec<NodeId>) -> NodeId {
- let id = self.nodes.len();
- for child in &children {
- self.parents[*child].push(id);
- }
- self.nodes.push(NodeData::new(style));
- self.children.push(children);
- self.parents.push(Vec::with_capacity(1));
- id
- }
-
- pub fn add_child(&mut self, node: NodeId, child: NodeId) {
- self.parents[child].push(node);
- self.children[node].push(child);
- self.mark_dirty(node)
- }
-
- pub unsafe fn remove_child(&mut self, node: NodeId, child: NodeId) -> NodeId {
- let index = self.children[node].iter().position(|n| *n == child).unwrap();
- self.remove_child_at_index(node, index)
- }
-
- pub fn remove_child_at_index(&mut self, node: NodeId, index: usize) -> NodeId {
- let child = self.children[node].remove(index);
- self.parents[child].retain(|p| *p != node);
- self.mark_dirty(node);
- child
- }
-
- pub fn mark_dirty(&mut self, node: NodeId) {
- fn mark_dirty_impl(nodes: &mut Vec<NodeData>, parents: &Vec<Vec<NodeId>>, node_id: NodeId) {
- let node = &mut nodes[node_id];
- node.layout_cache = None;
- node.is_dirty = true;
-
- for parent in &parents[node_id] {
- mark_dirty_impl(nodes, parents, *parent);
- }
- }
-
- mark_dirty_impl(&mut self.nodes, &self.parents, node);
- }
-
- pub fn compute_layout(&mut self, node: NodeId, size: Size<Number>) -> Result<(), Error> {
- self.compute(node, size).map_err(|err| Error::Measure(err))
- }
-}