mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
132 lines
4.2 KiB
C++
132 lines
4.2 KiB
C++
/*
|
|
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
|
|
* (C) 1999 Antti Koivisto (koivisto@kde.org)
|
|
* (C) 2001 Dirk Mueller (mueller@kde.org)
|
|
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
|
|
* Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "sky/engine/core/dom/NodeTraversal.h"
|
|
|
|
#include "sky/engine/core/dom/ContainerNode.h"
|
|
|
|
namespace blink {
|
|
|
|
Node* NodeTraversal::nextAncestorSibling(const Node& current)
|
|
{
|
|
ASSERT(!current.nextSibling());
|
|
for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
|
|
if (parent->nextSibling())
|
|
return parent->nextSibling();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Node* NodeTraversal::nextAncestorSibling(const Node& current, const Node* stayWithin)
|
|
{
|
|
ASSERT(!current.nextSibling());
|
|
ASSERT(current != stayWithin);
|
|
for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
|
|
if (parent == stayWithin)
|
|
return 0;
|
|
if (parent->nextSibling())
|
|
return parent->nextSibling();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Node* NodeTraversal::lastWithin(const ContainerNode& current)
|
|
{
|
|
Node* descendant = current.lastChild();
|
|
for (Node* child = descendant; child; child = child->lastChild())
|
|
descendant = child;
|
|
return descendant;
|
|
}
|
|
|
|
Node& NodeTraversal::lastWithinOrSelf(Node& current)
|
|
{
|
|
Node* lastDescendant = current.isContainerNode() ? NodeTraversal::lastWithin(toContainerNode(current)) : 0;
|
|
return lastDescendant ? *lastDescendant : current;
|
|
}
|
|
|
|
Node* NodeTraversal::previous(const Node& current, const Node* stayWithin)
|
|
{
|
|
if (current == stayWithin)
|
|
return 0;
|
|
if (current.previousSibling()) {
|
|
Node* previous = current.previousSibling();
|
|
while (Node* child = previous->lastChild())
|
|
previous = child;
|
|
return previous;
|
|
}
|
|
return current.parentNode();
|
|
}
|
|
|
|
Node* NodeTraversal::previousSkippingChildren(const Node& current, const Node* stayWithin)
|
|
{
|
|
if (current == stayWithin)
|
|
return 0;
|
|
if (current.previousSibling())
|
|
return current.previousSibling();
|
|
for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
|
|
if (parent == stayWithin)
|
|
return 0;
|
|
if (parent->previousSibling())
|
|
return parent->previousSibling();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Node* NodeTraversal::nextPostOrder(const Node& current, const Node* stayWithin)
|
|
{
|
|
if (current == stayWithin)
|
|
return 0;
|
|
if (!current.nextSibling())
|
|
return current.parentNode();
|
|
Node* next = current.nextSibling();
|
|
while (Node* child = next->firstChild())
|
|
next = child;
|
|
return next;
|
|
}
|
|
|
|
static Node* previousAncestorSiblingPostOrder(const Node& current, const Node* stayWithin)
|
|
{
|
|
ASSERT(!current.previousSibling());
|
|
for (Node* parent = current.parentNode(); parent; parent = parent->parentNode()) {
|
|
if (parent == stayWithin)
|
|
return 0;
|
|
if (parent->previousSibling())
|
|
return parent->previousSibling();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Node* NodeTraversal::previousPostOrder(const Node& current, const Node* stayWithin)
|
|
{
|
|
if (Node* lastChild = current.lastChild())
|
|
return lastChild;
|
|
if (current == stayWithin)
|
|
return 0;
|
|
if (current.previousSibling())
|
|
return current.previousSibling();
|
|
return previousAncestorSiblingPostOrder(current, stayWithin);
|
|
}
|
|
|
|
} // namespace blink
|