diff --git a/mozilla/editor/base/nsEditor.cpp b/mozilla/editor/base/nsEditor.cpp index 5b70090103b..4c11d85bf66 100644 --- a/mozilla/editor/base/nsEditor.cpp +++ b/mozilla/editor/base/nsEditor.cpp @@ -54,6 +54,7 @@ #include "nsICaret.h" #include "nsIStyleContext.h" #include "nsIEditActionListener.h" +#include "nsIEditorObserver.h" #include "nsIKBStateControl.h" #include "nsIWidget.h" #include "nsIScrollbar.h" @@ -780,6 +781,7 @@ nsEditor::nsEditor() , mIMETextOffset(0) , mIMEBufferLength(0) , mActionListeners(nsnull) +, mEditorObservers(nsnull) , mDocDirtyState(-1) , mDocWeak(nsnull) { @@ -794,6 +796,9 @@ nsEditor::~nsEditor() // not sure if this needs to be called earlier. NotifyDocumentListeners(eDocumentToBeDestroyed); + delete mEditorObservers; // no need to release observers; we didn't addref them + mEditorObservers = 0; + if (mActionListeners) { PRInt32 i; @@ -1107,7 +1112,7 @@ nsEditor::Undo(PRUint32 aCount) } EndUpdateViewBatch(); - + NotifyEditorObservers(); return result; } @@ -1153,7 +1158,7 @@ nsEditor::Redo(PRUint32 aCount) } EndUpdateViewBatch(); - + NotifyEditorObservers(); return result; } @@ -1257,6 +1262,8 @@ nsEditor::EndPlaceHolderTransaction() // since that is the only known case where the placeholdertxn would disappear on us. // For now just removing the assert. } + // notify editor observers of action unless it is uncommitted IME + if (!mInIMEMode) NotifyEditorObservers(); } } mPlaceHolderBatch--; @@ -2035,6 +2042,73 @@ nsEditor::MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset) return res; } +#ifdef XP_MAC +#pragma mark - +#pragma mark editor observer maintainance +#pragma mark - +#endif + +NS_IMETHODIMP +nsEditor::AddEditorObserver(nsIEditorObserver *aObserver) +{ + // we don't keep ownership of the observers. They must + // remove themselves as observers before they are destroyed. + + if (!aObserver) + return NS_ERROR_NULL_POINTER; + + if (!mEditorObservers) + { + mEditorObservers = new nsVoidArray(); + + if (!mEditorObservers) + return NS_ERROR_OUT_OF_MEMORY; + } + + // Make sure the listener isn't already on the list + if (mEditorObservers->IndexOf(aObserver) == -1) + { + if (!mEditorObservers->AppendElement((void *)aObserver)) + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsEditor::RemoveEditorObserver(nsIEditorObserver *aObserver) +{ + if (!aObserver || !mEditorObservers) + return NS_ERROR_FAILURE; + + if (!mEditorObservers->RemoveElement((void *)aObserver)) + return NS_ERROR_FAILURE; + + if (mEditorObservers->Count() < 1) + { + delete mEditorObservers; + mEditorObservers = 0; + } + + return NS_OK; +} + +void nsEditor::NotifyEditorObservers(void) +{ + if (mEditorObservers) + { + PRInt32 i; + nsIEditorObserver *observer; + for (i = 0; i < mEditorObservers->Count(); i++) + { + observer = (nsIEditorObserver*)mEditorObservers->ElementAt(i); + if (observer) + observer->EditAction(); + } + } +} + #ifdef XP_MAC #pragma mark - #pragma mark action listener maintainance @@ -2055,10 +2129,14 @@ nsEditor::AddEditActionListener(nsIEditActionListener *aListener) return NS_ERROR_OUT_OF_MEMORY; } - if (!mActionListeners->AppendElement((void *)aListener)) - return NS_ERROR_FAILURE; - - NS_ADDREF(aListener); + // Make sure the listener isn't already on the list + if (mActionListeners->IndexOf(aListener) == -1) + { + if (!mActionListeners->AppendElement((void *)aListener)) + return NS_ERROR_FAILURE; + else + NS_ADDREF(aListener); + } return NS_OK; } @@ -2085,6 +2163,13 @@ nsEditor::RemoveEditActionListener(nsIEditActionListener *aListener) } +#ifdef XP_MAC +#pragma mark - +#pragma mark docstate listener maintainance +#pragma mark - +#endif + + NS_IMETHODIMP nsEditor::AddDocumentStateListener(nsIDocumentStateListener *aListener) { @@ -2261,6 +2346,9 @@ nsEditor::EndComposition(void) mIMEBufferLength = 0; mInIMEMode = PR_FALSE; + // notify editor observers of action + NotifyEditorObservers(); + return result; } @@ -2342,14 +2430,6 @@ nsEditor::ForceCompositionEnd() return NS_OK; } -NS_IMETHODIMP -nsEditor::Composing(PRBool *aInIMEMode) -{ - if (!aInIMEMode) return NS_ERROR_NULL_POINTER; - *aInIMEMode = mInIMEMode; - return NS_OK; -} - #ifdef XP_MAC #pragma mark - #pragma mark public nsEditor methods diff --git a/mozilla/editor/base/nsEditor.h b/mozilla/editor/base/nsEditor.h index a78df373706..35626fac2a7 100644 --- a/mozilla/editor/base/nsEditor.h +++ b/mozilla/editor/base/nsEditor.h @@ -282,6 +282,10 @@ public: PRUint32 aFlags); /* Listeners */ + NS_IMETHOD AddEditorObserver(nsIEditorObserver *aObserver); + NS_IMETHOD RemoveEditorObserver(nsIEditorObserver *aObserver); + void NotifyEditorObservers(void); + NS_IMETHOD AddEditActionListener(nsIEditActionListener *aListener); NS_IMETHOD RemoveEditActionListener(nsIEditActionListener *aListener); @@ -300,7 +304,6 @@ public: NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply); NS_IMETHOD EndComposition(void); NS_IMETHOD ForceCompositionEnd(void); - NS_IMETHOD Composing(PRBool *aInIMEMode); public: @@ -760,8 +763,9 @@ protected: PRUint32 mIMETextOffset; // offset in text node where IME comp string begins PRUint32 mIMEBufferLength; // current length of IME comp string - nsVoidArray* mActionListeners; - nsCOMPtr mDocStateListeners; + nsVoidArray* mActionListeners; // listens to all low level actions on the doc + nsVoidArray* mEditorObservers; // just notify once per high level change + nsCOMPtr mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc) PRInt8 mDocDirtyState; // -1 = not initialized nsWeakPtr mDocWeak; // weak reference to the nsIDOMDocument diff --git a/mozilla/editor/libeditor/base/nsEditor.cpp b/mozilla/editor/libeditor/base/nsEditor.cpp index 5b70090103b..4c11d85bf66 100644 --- a/mozilla/editor/libeditor/base/nsEditor.cpp +++ b/mozilla/editor/libeditor/base/nsEditor.cpp @@ -54,6 +54,7 @@ #include "nsICaret.h" #include "nsIStyleContext.h" #include "nsIEditActionListener.h" +#include "nsIEditorObserver.h" #include "nsIKBStateControl.h" #include "nsIWidget.h" #include "nsIScrollbar.h" @@ -780,6 +781,7 @@ nsEditor::nsEditor() , mIMETextOffset(0) , mIMEBufferLength(0) , mActionListeners(nsnull) +, mEditorObservers(nsnull) , mDocDirtyState(-1) , mDocWeak(nsnull) { @@ -794,6 +796,9 @@ nsEditor::~nsEditor() // not sure if this needs to be called earlier. NotifyDocumentListeners(eDocumentToBeDestroyed); + delete mEditorObservers; // no need to release observers; we didn't addref them + mEditorObservers = 0; + if (mActionListeners) { PRInt32 i; @@ -1107,7 +1112,7 @@ nsEditor::Undo(PRUint32 aCount) } EndUpdateViewBatch(); - + NotifyEditorObservers(); return result; } @@ -1153,7 +1158,7 @@ nsEditor::Redo(PRUint32 aCount) } EndUpdateViewBatch(); - + NotifyEditorObservers(); return result; } @@ -1257,6 +1262,8 @@ nsEditor::EndPlaceHolderTransaction() // since that is the only known case where the placeholdertxn would disappear on us. // For now just removing the assert. } + // notify editor observers of action unless it is uncommitted IME + if (!mInIMEMode) NotifyEditorObservers(); } } mPlaceHolderBatch--; @@ -2035,6 +2042,73 @@ nsEditor::MoveNode(nsIDOMNode *aNode, nsIDOMNode *aParent, PRInt32 aOffset) return res; } +#ifdef XP_MAC +#pragma mark - +#pragma mark editor observer maintainance +#pragma mark - +#endif + +NS_IMETHODIMP +nsEditor::AddEditorObserver(nsIEditorObserver *aObserver) +{ + // we don't keep ownership of the observers. They must + // remove themselves as observers before they are destroyed. + + if (!aObserver) + return NS_ERROR_NULL_POINTER; + + if (!mEditorObservers) + { + mEditorObservers = new nsVoidArray(); + + if (!mEditorObservers) + return NS_ERROR_OUT_OF_MEMORY; + } + + // Make sure the listener isn't already on the list + if (mEditorObservers->IndexOf(aObserver) == -1) + { + if (!mEditorObservers->AppendElement((void *)aObserver)) + return NS_ERROR_FAILURE; + } + + return NS_OK; +} + + +NS_IMETHODIMP +nsEditor::RemoveEditorObserver(nsIEditorObserver *aObserver) +{ + if (!aObserver || !mEditorObservers) + return NS_ERROR_FAILURE; + + if (!mEditorObservers->RemoveElement((void *)aObserver)) + return NS_ERROR_FAILURE; + + if (mEditorObservers->Count() < 1) + { + delete mEditorObservers; + mEditorObservers = 0; + } + + return NS_OK; +} + +void nsEditor::NotifyEditorObservers(void) +{ + if (mEditorObservers) + { + PRInt32 i; + nsIEditorObserver *observer; + for (i = 0; i < mEditorObservers->Count(); i++) + { + observer = (nsIEditorObserver*)mEditorObservers->ElementAt(i); + if (observer) + observer->EditAction(); + } + } +} + #ifdef XP_MAC #pragma mark - #pragma mark action listener maintainance @@ -2055,10 +2129,14 @@ nsEditor::AddEditActionListener(nsIEditActionListener *aListener) return NS_ERROR_OUT_OF_MEMORY; } - if (!mActionListeners->AppendElement((void *)aListener)) - return NS_ERROR_FAILURE; - - NS_ADDREF(aListener); + // Make sure the listener isn't already on the list + if (mActionListeners->IndexOf(aListener) == -1) + { + if (!mActionListeners->AppendElement((void *)aListener)) + return NS_ERROR_FAILURE; + else + NS_ADDREF(aListener); + } return NS_OK; } @@ -2085,6 +2163,13 @@ nsEditor::RemoveEditActionListener(nsIEditActionListener *aListener) } +#ifdef XP_MAC +#pragma mark - +#pragma mark docstate listener maintainance +#pragma mark - +#endif + + NS_IMETHODIMP nsEditor::AddDocumentStateListener(nsIDocumentStateListener *aListener) { @@ -2261,6 +2346,9 @@ nsEditor::EndComposition(void) mIMEBufferLength = 0; mInIMEMode = PR_FALSE; + // notify editor observers of action + NotifyEditorObservers(); + return result; } @@ -2342,14 +2430,6 @@ nsEditor::ForceCompositionEnd() return NS_OK; } -NS_IMETHODIMP -nsEditor::Composing(PRBool *aInIMEMode) -{ - if (!aInIMEMode) return NS_ERROR_NULL_POINTER; - *aInIMEMode = mInIMEMode; - return NS_OK; -} - #ifdef XP_MAC #pragma mark - #pragma mark public nsEditor methods diff --git a/mozilla/editor/libeditor/base/nsEditor.h b/mozilla/editor/libeditor/base/nsEditor.h index a78df373706..35626fac2a7 100644 --- a/mozilla/editor/libeditor/base/nsEditor.h +++ b/mozilla/editor/libeditor/base/nsEditor.h @@ -282,6 +282,10 @@ public: PRUint32 aFlags); /* Listeners */ + NS_IMETHOD AddEditorObserver(nsIEditorObserver *aObserver); + NS_IMETHOD RemoveEditorObserver(nsIEditorObserver *aObserver); + void NotifyEditorObservers(void); + NS_IMETHOD AddEditActionListener(nsIEditActionListener *aListener); NS_IMETHOD RemoveEditActionListener(nsIEditActionListener *aListener); @@ -300,7 +304,6 @@ public: NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIPrivateTextRangeList* aTextRangeList,nsTextEventReply* aReply); NS_IMETHOD EndComposition(void); NS_IMETHOD ForceCompositionEnd(void); - NS_IMETHOD Composing(PRBool *aInIMEMode); public: @@ -760,8 +763,9 @@ protected: PRUint32 mIMETextOffset; // offset in text node where IME comp string begins PRUint32 mIMEBufferLength; // current length of IME comp string - nsVoidArray* mActionListeners; - nsCOMPtr mDocStateListeners; + nsVoidArray* mActionListeners; // listens to all low level actions on the doc + nsVoidArray* mEditorObservers; // just notify once per high level change + nsCOMPtr mDocStateListeners;// listen to overall doc state (dirty or not, just created, etc) PRInt8 mDocDirtyState; // -1 = not initialized nsWeakPtr mDocWeak; // weak reference to the nsIDOMDocument diff --git a/mozilla/editor/public/nsIEditor.h b/mozilla/editor/public/nsIEditor.h index f1601421eb4..4b1d0b5eca7 100644 --- a/mozilla/editor/public/nsIEditor.h +++ b/mozilla/editor/public/nsIEditor.h @@ -43,6 +43,7 @@ class nsITransaction; class nsITransactionManager; class nsIOutputStream; class nsIEditActionListener; +class nsIEditorObserver; class nsIDocumentStateListener; class nsFileSpec; class nsISelectionController; @@ -429,6 +430,12 @@ public: /* ------------ Various listeners methods -------------- */ + /** add an EditorObserver to the editors list of observers. */ + NS_IMETHOD AddEditorObserver(nsIEditorObserver *aObserver)=0; + + /** Remove an EditorObserver from the editor's list of observers. */ + NS_IMETHOD RemoveEditorObserver(nsIEditorObserver *aObserver)=0; + /** add an EditActionListener to the editors list of listeners. */ NS_IMETHOD AddEditActionListener(nsIEditActionListener *aListener)=0;