Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      7  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
     11  * Copyright (C) 2012, Google, Inc. All rights reserved.
     12  *
     13  * This library is free software; you can redistribute it and/or
     14  * modify it under the terms of the GNU Library General Public
     15  * License as published by the Free Software Foundation; either
     16  * version 2 of the License, or (at your option) any later version.
     17  *
     18  * This library is distributed in the hope that it will be useful,
     19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21  * Library General Public License for more details.
     22  *
     23  * You should have received a copy of the GNU Library General Public License
     24  * along with this library; see the file COPYING.LIB.  If not, write to
     25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     26  * Boston, MA 02110-1301, USA.
     27  */
     28 
     29 #ifndef SiblingTraversalStrategies_h
     30 #define SiblingTraversalStrategies_h
     31 
     32 #include "core/dom/Element.h"
     33 #include "core/dom/ElementTraversal.h"
     34 #include "core/rendering/style/RenderStyle.h"
     35 
     36 namespace blink {
     37 
     38 class DOMSiblingTraversalStrategy {
     39 public:
     40     bool isFirstChild(Element&) const;
     41     bool isLastChild(Element&) const;
     42     bool isFirstOfType(Element&, const QualifiedName&) const;
     43     bool isLastOfType(Element&, const QualifiedName&) const;
     44 
     45     int countElementsBefore(Element&) const;
     46     int countElementsAfter(Element&) const;
     47     int countElementsOfTypeBefore(Element&, const QualifiedName&) const;
     48     int countElementsOfTypeAfter(Element&, const QualifiedName&) const;
     49 
     50 private:
     51     class HasTagName {
     52     public:
     53         explicit HasTagName(const QualifiedName& tagName) : m_tagName(tagName) { }
     54         bool operator() (const Element& element) const { return element.hasTagName(m_tagName); }
     55     private:
     56         const QualifiedName& m_tagName;
     57     };
     58 };
     59 
     60 inline bool DOMSiblingTraversalStrategy::isFirstChild(Element& element) const
     61 {
     62     return !ElementTraversal::previousSibling(element);
     63 }
     64 
     65 inline bool DOMSiblingTraversalStrategy::isLastChild(Element& element) const
     66 {
     67     return !ElementTraversal::nextSibling(element);
     68 }
     69 
     70 inline bool DOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const
     71 {
     72     return !ElementTraversal::previousSibling(element, HasTagName(type));
     73 }
     74 
     75 inline bool DOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const
     76 {
     77     return !ElementTraversal::nextSibling(element, HasTagName(type));
     78 }
     79 
     80 inline int DOMSiblingTraversalStrategy::countElementsBefore(Element& element) const
     81 {
     82     int count = 0;
     83     for (const Element* sibling = ElementTraversal::previousSibling(element); sibling; sibling = ElementTraversal::previousSibling(*sibling))
     84         count++;
     85 
     86     return count;
     87 }
     88 
     89 inline int DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element& element, const QualifiedName& type) const
     90 {
     91     int count = 0;
     92     for (const Element* sibling = ElementTraversal::previousSibling(element, HasTagName(type)); sibling; sibling = ElementTraversal::previousSibling(*sibling, HasTagName(type)))
     93         ++count;
     94     return count;
     95 }
     96 
     97 inline int DOMSiblingTraversalStrategy::countElementsAfter(Element& element) const
     98 {
     99     int count = 0;
    100     for (const Element* sibling = ElementTraversal::nextSibling(element); sibling; sibling = ElementTraversal::nextSibling(*sibling))
    101         ++count;
    102     return count;
    103 }
    104 
    105 inline int DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element& element, const QualifiedName& type) const
    106 {
    107     int count = 0;
    108     for (const Element* sibling = ElementTraversal::nextSibling(element, HasTagName(type)); sibling; sibling = ElementTraversal::nextSibling(*sibling, HasTagName(type)))
    109         ++count;
    110     return count;
    111 }
    112 
    113 class ShadowDOMSiblingTraversalStrategy FINAL {
    114     STACK_ALLOCATED();
    115 public:
    116     ShadowDOMSiblingTraversalStrategy(const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& siblings, int nth)
    117         : m_siblings(siblings)
    118         , m_nth(nth)
    119     {
    120     }
    121 
    122     bool isFirstChild(Element&) const;
    123     bool isLastChild(Element&) const;
    124     bool isFirstOfType(Element&, const QualifiedName&) const;
    125     bool isLastOfType(Element&, const QualifiedName&) const;
    126 
    127     int countElementsBefore(Element&) const;
    128     int countElementsAfter(Element&) const;
    129     int countElementsOfTypeBefore(Element&, const QualifiedName&) const;
    130     int countElementsOfTypeAfter(Element&, const QualifiedName&) const;
    131 
    132 private:
    133     const WillBeHeapVector<RawPtrWillBeMember<Node>, 32>& m_siblings;
    134     int m_nth;
    135 };
    136 
    137 inline bool ShadowDOMSiblingTraversalStrategy::isFirstChild(Element& element) const
    138 {
    139     ASSERT(element == toElement(m_siblings[m_nth]));
    140 
    141     for (int i = m_nth - 1; i >= 0; --i) {
    142         if (m_siblings[i]->isElementNode())
    143             return false;
    144     }
    145 
    146     return true;
    147 }
    148 
    149 inline bool ShadowDOMSiblingTraversalStrategy::isLastChild(Element& element) const
    150 {
    151     ASSERT(element == toElement(m_siblings[m_nth]));
    152 
    153     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    154         if (m_siblings[i]->isElementNode())
    155             return false;
    156     }
    157 
    158     return true;
    159 }
    160 
    161 inline bool ShadowDOMSiblingTraversalStrategy::isFirstOfType(Element& element, const QualifiedName& type) const
    162 {
    163     ASSERT(element == toElement(m_siblings[m_nth]));
    164 
    165     for (int i = m_nth - 1; i >= 0; --i) {
    166         if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type))
    167             return false;
    168     }
    169 
    170     return true;
    171 }
    172 
    173 inline bool ShadowDOMSiblingTraversalStrategy::isLastOfType(Element& element, const QualifiedName& type) const
    174 {
    175     ASSERT(element == toElement(m_siblings[m_nth]));
    176 
    177     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    178         if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type))
    179             return false;
    180     }
    181 
    182     return true;
    183 }
    184 
    185 inline int ShadowDOMSiblingTraversalStrategy::countElementsBefore(Element& element) const
    186 {
    187     ASSERT(element == toElement(m_siblings[m_nth]));
    188 
    189     int count = 0;
    190     for (int i = m_nth - 1; i >= 0; --i) {
    191         if (m_siblings[i]->isElementNode())
    192             ++count;
    193     }
    194 
    195     return count;
    196 }
    197 
    198 inline int ShadowDOMSiblingTraversalStrategy::countElementsAfter(Element& element) const
    199 {
    200     ASSERT(element == toElement(m_siblings[m_nth]));
    201 
    202     int count = 0;
    203     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    204         if (m_siblings[i]->isElementNode())
    205             return ++count;
    206     }
    207 
    208     return count;
    209 }
    210 
    211 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element& element, const QualifiedName& type) const
    212 {
    213     ASSERT(element == toElement(m_siblings[m_nth]));
    214 
    215     int count = 0;
    216     for (int i = m_nth - 1; i >= 0; --i) {
    217         if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type))
    218             ++count;
    219     }
    220 
    221     return count;
    222 }
    223 
    224 inline int ShadowDOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element& element, const QualifiedName& type) const
    225 {
    226     ASSERT(element == toElement(m_siblings[m_nth]));
    227 
    228     int count = 0;
    229     for (size_t i = m_nth + 1; i < m_siblings.size(); ++i) {
    230         if (m_siblings[i]->isElementNode() && toElement(m_siblings[i])->hasTagName(type))
    231             return ++count;
    232     }
    233 
    234     return count;
    235 }
    236 
    237 }
    238 
    239 #endif
    240