1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Mozilla Public License Version
6
* 1.1 (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/MPL/
10
* Software distributed under the License is distributed on an "AS IS" basis,
11
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
* for the specific language governing rights and limitations under the
15
* The Original Code is mozilla.org code.
17
* The Initial Developer of the Original Code is
18
* Netscape Communications Corporation.
19
* Portions created by the Initial Developer are Copyright (C) 1998
20
* the Initial Developer. All Rights Reserved.
23
* Josh Aas <josh@mozilla.com>
24
* Thomas K. Dyas <tom.dyas@gmail.com>
25
* Chris Coulson <chris.coulson@canonical.com>
27
* Alternatively, the contents of this file may be used under the terms of
28
* either the GNU General Public License Version 2 or later (the "GPL"), or
29
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
* in which case the provisions of the GPL or the LGPL are applicable instead
31
* of those above. If you wish to allow use of your version of this file only
32
* under the terms of either the GPL or the LGPL, and not to allow others to
33
* use your version of this file under the terms of the MPL, indicate your
34
* decision by deleting the provisions above and replace them with the notice
35
* and other provisions required by the GPL or the LGPL. If you do not delete
36
* the provisions above, a recipient may use your version of this file under
37
* the terms of any one of the MPL, the GPL or the LGPL.
39
* ***** END LICENSE BLOCK ***** */
42
#include <nsIDocument.h>
45
#include <mozilla/dom/Element.h>
46
#include <nsIContent.h>
47
#include <nsIDocument.h>
49
#include "uGlobalMenuDocListener.h"
53
NS_IMPL_ISUPPORTS1(uGlobalMenuDocListener, nsIMutationObserver)
56
uGlobalMenuDocListener::Init(nsIContent *rootNode)
58
NS_ENSURE_ARG(rootNode);
60
#if MOZILLA_BRANCH_MAJOR_VERSION >= 10
61
mDocument = rootNode->OwnerDoc();
63
mDocument = rootNode->GetOwnerDoc();
66
return NS_ERROR_FAILURE;
67
mDocument->AddMutationObserver(this);
73
uGlobalMenuDocListener::Destroy()
76
mDocument->RemoveMutationObserver(this);
80
uGlobalMenuDocListener::uGlobalMenuDocListener() :
81
#ifdef DEBUG_chrisccoulson
86
mContentToObserverTable.Init();
89
uGlobalMenuDocListener::~uGlobalMenuDocListener()
91
NS_ASSERTION(mCount == 0, "Some nodes forgot to unregister listeners");
95
uGlobalMenuDocListener::CharacterDataWillChange(nsIDocument *aDocument,
97
CharacterDataChangeInfo *aInfo)
103
uGlobalMenuDocListener::CharacterDataChanged(nsIDocument *aDocument,
104
nsIContent *aContent,
105
CharacterDataChangeInfo *aInfo)
111
uGlobalMenuDocListener::AttributeWillChange(nsIDocument *aDocument,
112
mozilla::dom::Element *aElement,
113
PRInt32 aNameSpaceID,
121
uGlobalMenuDocListener::AttributeChanged(nsIDocument *aDocument,
122
mozilla::dom::Element *aElement,
123
PRInt32 aNameSpaceID,
130
nsTArray<uMenuChangeObserver *> listeners;
131
GetListeners(aElement, listeners);
133
for (PRUint32 i = 0; i < listeners.Length(); i++) {
134
listeners[i]->ObserveAttributeChanged(aDocument, aElement, aAttribute);
139
uGlobalMenuDocListener::ContentAppended(nsIDocument *aDocument,
140
nsIContent *aContainer,
141
nsIContent *aFirstNewContent,
142
PRInt32 aNewIndexInContainer)
144
for (nsIContent* cur = aFirstNewContent; cur; cur = cur->GetNextSibling()) {
145
ContentInserted(aDocument, aContainer, cur, aNewIndexInContainer);
146
aNewIndexInContainer++;
151
uGlobalMenuDocListener::ContentInserted(nsIDocument *aDocument,
152
nsIContent *aContainer,
154
PRInt32 aIndexInContainer)
159
nsTArray<uMenuChangeObserver *> listeners;
160
GetListeners(aContainer, listeners);
162
for (PRUint32 i = 0; i < listeners.Length(); i++) {
163
listeners[i]->ObserveContentInserted(aDocument, aContainer, aChild,
167
if (listeners.Length() == 0) {
168
for (PRUint32 i = 0; i < mGlobalObservers.Length(); i++) {
169
mGlobalObservers[i]->ObserveContentInserted(aDocument, aContainer,
170
aChild, aIndexInContainer);
176
uGlobalMenuDocListener::ContentRemoved(nsIDocument *aDocument,
177
nsIContent *aContainer,
179
PRInt32 aIndexInContainer,
180
nsIContent *aPreviousSibling)
185
nsTArray<uMenuChangeObserver *> listeners;
186
GetListeners(aContainer, listeners);
188
for (PRUint32 i = 0; i < listeners.Length(); i++) {
189
listeners[i]->ObserveContentRemoved(aDocument, aContainer, aChild,
193
if (listeners.Length() == 0) {
194
for (PRUint32 i = 0; i < mGlobalObservers.Length(); i++) {
195
mGlobalObservers[i]->ObserveContentRemoved(aDocument, aContainer, aChild,
202
uGlobalMenuDocListener::NodeWillBeDestroyed(const nsINode *aNode)
208
uGlobalMenuDocListener::ParentChainChanged(nsIContent *aContent)
214
uGlobalMenuDocListener::RegisterForContentChanges(nsIContent *aContent,
215
uMenuChangeObserver *aMenuObject)
217
NS_ENSURE_ARG(aContent);
218
NS_ENSURE_ARG(aMenuObject);
220
nsTArray<uMenuChangeObserver *> *listeners;
221
if (!mContentToObserverTable.Get(aContent, &listeners)) {
222
listeners = new nsTArray<uMenuChangeObserver *>();
223
mContentToObserverTable.Put(aContent, listeners);
226
for (PRUint32 i = 0; i < listeners->Length(); i++) {
227
if (listeners->ElementAt(i) == aMenuObject) {
228
return NS_ERROR_FAILURE;
232
listeners->AppendElement(aMenuObject);
233
#ifdef DEBUG_chrisccoulson
240
uGlobalMenuDocListener::UnregisterForContentChanges(nsIContent *aContent,
241
uMenuChangeObserver *aMenuObject)
243
NS_ENSURE_ARG(aContent);
244
NS_ENSURE_ARG(aMenuObject);
246
nsTArray<uMenuChangeObserver *> *listeners;
247
if (!mContentToObserverTable.Get(aContent, &listeners)) {
248
return NS_ERROR_FAILURE;
251
PRUint32 length = listeners->Length();
252
for (PRUint32 i = 0; i < length; i++) {
253
if (listeners->ElementAt(i) == aMenuObject) {
254
listeners->RemoveElementAt(i);
255
#ifdef DEBUG_chrisccoulson
261
nsresult rv = listeners->Length() < length ? NS_OK : NS_ERROR_FAILURE;
263
if (listeners->Length() == 0) {
264
mContentToObserverTable.Remove(aContent);
271
uGlobalMenuDocListener::RegisterForAllChanges(uMenuChangeObserver *aMenuObject)
273
NS_ENSURE_ARG(aMenuObject);
275
PRUint32 count = mGlobalObservers.Length();
276
for (PRUint32 i = 0; i < count; i ++) {
277
if (mGlobalObservers[i] == aMenuObject) {
278
// Don't add more than once
279
return NS_ERROR_FAILURE;
283
mGlobalObservers.AppendElement(aMenuObject);
288
uGlobalMenuDocListener::UnregisterForAllChanges(uMenuChangeObserver *aMenuObject)
290
NS_ENSURE_ARG(aMenuObject);
292
PRUint32 count = mGlobalObservers.Length();
293
for (PRUint32 i = 0; i < count; i++) {
294
if (mGlobalObservers[i] == aMenuObject) {
295
mGlobalObservers.RemoveElementAt(i);
300
return NS_ERROR_FAILURE;
304
uGlobalMenuDocListener::GetListeners(nsIContent *aContent,
305
nsTArray<uMenuChangeObserver *>& _result)
307
nsTArray<uMenuChangeObserver *> *listeners;
308
if (mContentToObserverTable.Get(aContent, &listeners)) {
309
_result.ReplaceElementsAt(0, _result.Length(), listeners->Elements(),
310
listeners->Length());