use std::cell::Ref;
use std::iter::Filter;
use {
Node,
NodeType,
};
use super::node_data::WeakLink;
macro_rules! filter_svg {
($name:ty) => (
impl $name {
pub fn svg(self) -> Filter<$name, fn(&Node) -> bool> {
fn is_svg(n: &Node) -> bool { n.is_svg_element() }
self.filter(is_svg)
}
}
)
}
#[derive(Clone)]
pub enum NodeEdge {
Start(Node),
End(Node),
}
#[derive(Clone)]
pub struct Traverse {
root: Node,
next: Option<NodeEdge>,
}
impl Traverse {
pub fn new(node: &Node) -> Traverse {
Traverse {
root: node.clone(),
next: Some(NodeEdge::Start(node.clone())),
}
}
}
impl Iterator for Traverse {
type Item = NodeEdge;
fn next(&mut self) -> Option<NodeEdge> {
match self.next.take() {
Some(item) => {
self.next = match item {
NodeEdge::Start(ref node) => {
match node.first_child() {
Some(first_child) => Some(NodeEdge::Start(first_child)),
None => Some(NodeEdge::End(node.clone()))
}
}
NodeEdge::End(ref node) => {
if *node == self.root {
None
} else {
match node.next_sibling() {
Some(next_sibling) => Some(NodeEdge::Start(next_sibling)),
None => match node.parent() {
Some(parent) => Some(NodeEdge::End(parent)),
None => None
}
}
}
}
};
Some(item)
}
None => None
}
}
}
pub struct Descendants(Traverse);
impl Descendants {
pub fn new(node: &Node) -> Descendants {
Descendants(node.traverse())
}
}
impl Iterator for Descendants {
type Item = Node;
fn next(&mut self) -> Option<Node> {
loop {
match self.0.next() {
Some(NodeEdge::Start(node)) => return Some(node),
Some(NodeEdge::End(_)) => {}
None => return None
}
}
}
}
filter_svg!(Descendants);
pub struct Children(Option<Node>);
impl Children {
pub fn new(node: Option<Node>) -> Children {
Children(node)
}
}
impl Iterator for Children {
type Item = Node;
fn next(&mut self) -> Option<Node> {
match self.0.take() {
Some(node) => {
self.0 = node.next_sibling();
Some(node)
}
None => None
}
}
}
filter_svg!(Children);
pub struct Parents(Option<Node>);
impl Parents {
pub fn new(node: Option<Node>) -> Parents {
Parents(node)
}
}
impl Iterator for Parents {
type Item = Node;
fn next(&mut self) -> Option<Node> {
match self.0.take() {
Some(node) => {
if node.node_type() == NodeType::Root {
return None;
}
self.0 = node.parent();
Some(node)
}
None => None
}
}
}
filter_svg!(Parents);
pub struct LinkedNodes<'a> {
data: Ref<'a, Vec<WeakLink>>,
idx: usize,
}
impl<'a> LinkedNodes<'a> {
pub fn new(data: Ref<'a, Vec<WeakLink>>) -> LinkedNodes<'a> {
LinkedNodes {
data: data,
idx: 0,
}
}
}
impl<'a> Iterator for LinkedNodes<'a> {
type Item = Node;
fn next(&mut self) -> Option<Node> {
let i = self.idx;
self.idx += 1;
if i < self.data.len() {
match self.data[i].upgrade() {
Some(n) => Some(Node(n)),
None => None,
}
} else {
None
}
}
}