style: Add methods to iterate a subtree in preorder.

Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
Emilio Cobos Álvarez 2017-10-22 01:18:44 +02:00
parent 6ae8bdee61
commit 4f997bf333
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 65 additions and 2 deletions

View file

@ -110,9 +110,32 @@ where
}
}
/// An iterator over the DOM descendants of a node in pre-order.
pub struct DomDescendants<N> {
previous: Option<N>,
scope: N,
}
impl<N> Iterator for DomDescendants<N>
where
N: TNode
{
type Item = N;
fn next(&mut self) -> Option<N> {
let prev = match self.previous.take() {
None => return None,
Some(n) => n,
};
self.previous = prev.next_in_preorder(Some(self.scope));
self.previous
}
}
/// The `TNode` trait. This is the main generic trait over which the style
/// system can be implemented.
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo + PartialEq {
/// The concrete `TElement` type.
type ConcreteElement: TElement<ConcreteNode = Self>;
@ -131,11 +154,45 @@ pub trait TNode : Sized + Copy + Clone + Debug + NodeInfo {
/// Get this node's next sibling.
fn next_sibling(&self) -> Option<Self>;
/// Iterate over the DOM children of an element.
/// Iterate over the DOM children of a node.
fn dom_children(&self) -> DomChildren<Self> {
DomChildren(self.first_child())
}
/// Iterate over the DOM children of a node, in preorder.
fn dom_descendants(&self) -> DomDescendants<Self> {
DomDescendants {
previous: Some(*self),
scope: *self,
}
}
/// Returns the next children in pre-order, optionally scoped to a subtree
/// root.
fn next_in_preorder(&self, scoped_to: Option<Self>) -> Option<Self> {
if let Some(c) = self.first_child() {
return Some(c);
}
if Some(*self) == scoped_to {
return None;
}
let mut current = *self;
loop {
if let Some(s) = current.next_sibling() {
return Some(s);
}
let parent = current.parent_node();
if parent == scoped_to {
return None;
}
current = parent.expect("Not a descendant of the scope?");
}
}
/// Get this node's parent element from the perspective of a restyle
/// traversal.
fn traversal_parent(&self) -> Option<Self::ConcreteElement>;

View file

@ -104,6 +104,12 @@ use stylist::Stylist;
#[derive(Clone, Copy)]
pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
impl<'ln> PartialEq for GeckoNode<'ln> {
fn eq(&self, other: &Self) -> bool {
self.0 as *const _ == other.0 as *const _
}
}
impl<'ln> fmt::Debug for GeckoNode<'ln> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(el) = self.as_element() {