Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #ifndef nsXBLChildrenElement_h___
8 : #define nsXBLChildrenElement_h___
9 :
10 : #include "nsIDOMElement.h"
11 : #include "nsINodeList.h"
12 : #include "nsBindingManager.h"
13 : #include "mozilla/dom/nsXMLElement.h"
14 :
15 : class nsAnonymousContentList;
16 :
17 : namespace mozilla {
18 : namespace dom {
19 :
20 : class XBLChildrenElement : public nsXMLElement
21 : {
22 : public:
23 163 : explicit XBLChildrenElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
24 163 : : nsXMLElement(aNodeInfo)
25 : {
26 163 : }
27 71 : explicit XBLChildrenElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
28 71 : : nsXMLElement(aNodeInfo)
29 : {
30 71 : }
31 :
32 : // nsISupports
33 : NS_DECL_ISUPPORTS_INHERITED
34 :
35 : // nsINode interface methods
36 : virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
37 : bool aPreallocateChildren) const override;
38 :
39 0 : virtual nsIDOMNode* AsDOMNode() override { return this; }
40 :
41 413 : void AppendInsertedChild(nsIContent* aChild)
42 : {
43 413 : mInsertedChildren.AppendElement(aChild);
44 413 : aChild->SetXBLInsertionParent(GetParent());
45 :
46 : // Appending an inserted child causes the inserted
47 : // children to be projected instead of default content.
48 413 : MaybeRemoveDefaultContent();
49 413 : }
50 :
51 17 : void InsertInsertedChildAt(nsIContent* aChild, uint32_t aIndex)
52 : {
53 17 : mInsertedChildren.InsertElementAt(aIndex, aChild);
54 17 : aChild->SetXBLInsertionParent(GetParent());
55 :
56 : // Inserting an inserted child causes the inserted
57 : // children to be projected instead of default content.
58 17 : MaybeRemoveDefaultContent();
59 17 : }
60 :
61 2 : void RemoveInsertedChild(nsIContent* aChild)
62 : {
63 : // Can't use this assertion as we cheat for dynamic insertions and
64 : // only insert in the innermost insertion point.
65 : //NS_ASSERTION(mInsertedChildren.Contains(aChild),
66 : // "Removing child that's not there");
67 2 : mInsertedChildren.RemoveElement(aChild);
68 :
69 : // After removing the inserted child, default content
70 : // may be projected into this insertion point.
71 2 : MaybeSetupDefaultContent();
72 2 : }
73 :
74 12 : void ClearInsertedChildren()
75 : {
76 21 : for (uint32_t c = 0; c < mInsertedChildren.Length(); ++c) {
77 9 : mInsertedChildren[c]->SetXBLInsertionParent(nullptr);
78 : }
79 12 : mInsertedChildren.Clear();
80 :
81 : // After clearing inserted children, default content
82 : // will be projected into this insertion point.
83 12 : MaybeSetupDefaultContent();
84 12 : }
85 :
86 175 : void MaybeSetupDefaultContent()
87 : {
88 175 : if (!HasInsertedChildren()) {
89 98 : for (nsIContent* child = static_cast<nsINode*>(this)->GetFirstChild();
90 98 : child;
91 5 : child = child->GetNextSibling()) {
92 5 : child->SetXBLInsertionParent(GetParent());
93 : }
94 : }
95 175 : }
96 :
97 430 : void MaybeRemoveDefaultContent()
98 : {
99 430 : if (!HasInsertedChildren()) {
100 0 : for (nsIContent* child = static_cast<nsINode*>(this)->GetFirstChild();
101 0 : child;
102 0 : child = child->GetNextSibling()) {
103 0 : child->SetXBLInsertionParent(nullptr);
104 : }
105 : }
106 430 : }
107 :
108 162 : uint32_t InsertedChildrenLength()
109 : {
110 162 : return mInsertedChildren.Length();
111 : }
112 :
113 794 : bool HasInsertedChildren()
114 : {
115 794 : return !mInsertedChildren.IsEmpty();
116 : }
117 :
118 13 : int32_t IndexOfInsertedChild(nsIContent* aChild)
119 : {
120 13 : return mInsertedChildren.IndexOf(aChild);
121 : }
122 :
123 89 : bool Includes(nsIContent* aChild)
124 : {
125 89 : NS_ASSERTION(!mIncludes.IsEmpty(),
126 : "Shouldn't check for includes on default insertion point");
127 89 : return mIncludes.Contains(aChild->NodeInfo()->NameAtom());
128 : }
129 :
130 173 : bool IsDefaultInsertion()
131 : {
132 173 : return mIncludes.IsEmpty();
133 : }
134 :
135 130 : nsIContent* InsertedChild(uint32_t aIndex)
136 : {
137 130 : return mInsertedChildren[aIndex];
138 : }
139 :
140 : protected:
141 : ~XBLChildrenElement();
142 : virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
143 : const nsAttrValueOrString* aValue,
144 : bool aNotify) override;
145 :
146 : private:
147 : nsTArray<nsIContent*> mInsertedChildren; // WEAK
148 : nsTArray<nsCOMPtr<nsIAtom> > mIncludes;
149 : };
150 :
151 : } // namespace dom
152 : } // namespace mozilla
153 :
154 : class nsAnonymousContentList : public nsINodeList
155 : {
156 : public:
157 9 : explicit nsAnonymousContentList(nsIContent* aParent)
158 9 : : mParent(aParent)
159 : {
160 9 : }
161 :
162 : NS_DECL_CYCLE_COLLECTING_ISUPPORTS
163 18 : NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsAnonymousContentList)
164 : // nsIDOMNodeList interface
165 : NS_DECL_NSIDOMNODELIST
166 :
167 : // nsINodeList interface
168 : virtual int32_t IndexOf(nsIContent* aContent) override;
169 0 : virtual nsINode* GetParentObject() override { return mParent; }
170 : virtual nsIContent* Item(uint32_t aIndex) override;
171 :
172 : virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
173 :
174 : bool IsListFor(nsIContent* aContent) {
175 : return mParent == aContent;
176 : }
177 :
178 : private:
179 0 : virtual ~nsAnonymousContentList()
180 0 : {
181 0 : }
182 :
183 : nsCOMPtr<nsIContent> mParent;
184 : };
185 :
186 : #endif // nsXBLChildrenElement_h___
|