23dad8dca7081231821f97d8bf304d77333276f7
[WebKit-https.git] / Source / WebCore / html / shadow / InsertionPoint.h
1 /*
2  * Copyright (C) 2012 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #ifndef InsertionPoint_h
32 #define InsertionPoint_h
33
34 #include "CSSSelectorList.h"
35 #include "ContentDistributor.h"
36 #include "ElementShadow.h"
37 #include "HTMLElement.h"
38 #include "HTMLNames.h"
39 #include "ShadowRoot.h"
40 #include <wtf/Forward.h>
41
42 namespace WebCore {
43
44 class InsertionPoint : public HTMLElement {
45 public:
46     virtual ~InsertionPoint();
47
48     bool hasDistribution() const { return !m_distribution.isEmpty(); }
49     void setDistribution(ContentDistribution& distribution) { m_distribution.swap(distribution); }
50     void clearDistribution() { m_distribution.clear(); }
51     bool isShadowBoundary() const;
52     bool isActive() const;
53
54     PassRefPtr<NodeList> getDistributedNodes() const;
55
56     virtual const AtomicString& select() const = 0;
57     virtual bool isSelectValid() = 0;
58     virtual const CSSSelectorList& selectorList() = 0;
59
60     bool resetStyleInheritance() const;
61     void setResetStyleInheritance(bool);
62
63     virtual void attach();
64     virtual void detach();
65     virtual bool isInsertionPoint() const OVERRIDE { return true; }
66
67     bool shouldUseFallbackElements() const;
68
69     size_t indexOf(Node* node) const { return m_distribution.find(node); }
70     bool contains(const Node* node) const { return m_distribution.contains(const_cast<Node*>(node)) || (node->isShadowRoot() && toShadowRoot(node)->assignedTo() == this); }
71     size_t size() const { return m_distribution.size(); }
72     Node* at(size_t index)  const { return m_distribution.at(index).get(); }
73     Node* first() const { return m_distribution.isEmpty() ? 0 : m_distribution.first().get(); }
74     Node* last() const { return m_distribution.isEmpty() ? 0 : m_distribution.last().get(); }
75     Node* nextTo(const Node*) const;
76     Node* previousTo(const Node*) const;
77
78 protected:
79     InsertionPoint(const QualifiedName&, Document*);
80     virtual bool rendererIsNeeded(const NodeRenderingContext&) OVERRIDE;
81     virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE;
82     virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
83     virtual void removedFrom(ContainerNode*) OVERRIDE;
84
85 private:
86     ContentDistribution m_distribution;
87     bool m_shouldResetStyleInheritance : 1;
88 };
89
90 inline bool isInsertionPoint(const Node* node)
91 {
92     if (node->isHTMLElement() && toHTMLElement(node)->isInsertionPoint())
93         return true;
94
95     return false;
96 }
97
98 inline InsertionPoint* toInsertionPoint(Node* node)
99 {
100     ASSERT(!node || isInsertionPoint(node));
101     return static_cast<InsertionPoint*>(node);
102 }
103
104 inline const InsertionPoint* toInsertionPoint(const Node* node)
105 {
106     ASSERT(!node || isInsertionPoint(node));
107     return static_cast<const InsertionPoint*>(node);
108 }
109
110 inline bool isActiveInsertionPoint(const Node* node)
111 {
112     return isInsertionPoint(node) && toInsertionPoint(node)->isActive();
113 }
114
115 inline bool isLowerEncapsulationBoundary(Node* node)
116 {
117     if (!node || !isInsertionPoint(node))
118         return false;
119     return toInsertionPoint(node)->isShadowBoundary();
120 }
121
122 inline Node* parentNodeForDistribution(const Node* node)
123 {
124     ASSERT(node);
125
126     if (Node* parent = node->parentNode()) {
127         if (isInsertionPoint(parent) && toInsertionPoint(parent)->shouldUseFallbackElements())
128             return parent->parentNode();
129         return parent;
130     }
131
132     return 0;
133 }
134
135 inline Element* parentElementForDistribution(const Node* node)
136 {
137     if (Node* parent = parentNodeForDistribution(node)) {
138         if (parent->isElementNode())
139             return toElement(parent);
140     }
141
142     return 0;
143 }
144
145 inline ElementShadow* shadowOfParentForDistribution(const Node* node)
146 {
147     if (!node)
148         return 0;
149
150     if (Element* parent = parentElementForDistribution(node))
151         return parent->shadow();
152
153     return 0;
154 }
155
156 inline InsertionPoint* resolveReprojection(const Node* projectedNode)
157 {
158     InsertionPoint* insertionPoint = 0;
159     const Node* current = projectedNode;
160
161     while (true) {
162         if (ElementShadow* shadow = shadowOfParentForDistribution(current)) {
163             shadow->ensureDistribution();
164             if (InsertionPoint* insertedTo = shadow->distributor().findInsertionPointFor(projectedNode)) {
165                 current = insertedTo;
166                 insertionPoint = insertedTo;
167                 continue;
168             }
169         }
170
171         if (Node* parent = parentNodeForDistribution(current)) {
172             if (InsertionPoint* insertedTo = parent->isShadowRoot() ? toShadowRoot(parent)->assignedTo() : 0) {
173                 current = insertedTo;
174                 insertionPoint = insertedTo;
175                 continue;
176             }
177         }
178
179         break;
180     }
181
182     return insertionPoint;
183 }
184
185 } // namespace WebCore
186
187 #endif // InsertionPoint_h