From 9f6733aa0f57852157012d8214ddf02748ea1523 Mon Sep 17 00:00:00 2001 From: "sfraser%netscape.com" Date: Tue, 3 Aug 1999 00:57:57 +0000 Subject: [PATCH] Support for pre-registering nsIDocumentStateListeners before the editor is created. --- editor/base/nsEditorShell.cpp | 139 +++++++++++++++++++++++++- editor/base/nsEditorShell.h | 9 +- editor/composer/src/nsEditorShell.cpp | 139 +++++++++++++++++++++++++- editor/composer/src/nsEditorShell.h | 9 +- 4 files changed, 286 insertions(+), 10 deletions(-) diff --git a/editor/base/nsEditorShell.cpp b/editor/base/nsEditorShell.cpp index cde2d7b7dec6..34184f1e8042 100644 --- a/editor/base/nsEditorShell.cpp +++ b/editor/base/nsEditorShell.cpp @@ -676,8 +676,107 @@ nsEditorShell::LoadUrl(const PRUnichar *url) return mContentAreaWebShell->LoadURL(url); } + NS_IMETHODIMP -nsEditorShell::PrepareDocumentForEditing() +nsEditorShell::RegisterDocumentStateListener(nsIDocumentStateListener *docListener) +{ + nsresult rv = NS_OK; + + if (!docListener) + return NS_ERROR_NULL_POINTER; + + // if we have an editor already, just pass this baby through. + if (mEditor) + { + nsCOMPtr editor = do_QueryInterface(mEditor, &rv); + if (NS_FAILED(rv)) + return rv; + + return editor->AddDocumentStateListener(docListener); + } + + // otherwise, keep it until we create an editor. + if (!mDocStateListeners) + { + rv = NS_NewISupportsArray(getter_AddRefs(mDocStateListeners)); + if (NS_FAILED(rv)) return rv; + } + nsCOMPtr iSupports = do_QueryInterface(docListener, &rv); + if (NS_FAILED(rv)) return rv; + + // note that this return value is really a PRBool, so be sure to use + // NS_SUCCEEDED or NS_FAILED to check it. + return mDocStateListeners->AppendElement(iSupports); +} + +NS_IMETHODIMP +nsEditorShell::UnregisterDocumentStateListener(nsIDocumentStateListener *docListener) +{ + if (!docListener) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + // if we have an editor already, just pass this baby through. + if (mEditor) + { + nsCOMPtr editor = do_QueryInterface(mEditor, &rv); + if (NS_FAILED(rv)) + return rv; + + return editor->RemoveDocumentStateListener(docListener); + } + + // otherwise, see if it exists in our list + if (!mDocStateListeners) + return (nsresult)PR_FALSE; // yeah, this sucks, but I'm emulating the behaviour of + // nsISupportsArray::RemoveElement() + + nsCOMPtr iSupports = do_QueryInterface(docListener, &rv); + if (NS_FAILED(rv)) return rv; + + // note that this return value is really a PRBool, so be sure to use + // NS_SUCCEEDED or NS_FAILED to check it. + return mDocStateListeners->RemoveElement(iSupports); +} + +// called after making an editor. Transfer the nsIDOcumentStateListeners +// that we have been stashing in mDocStateListeners to the editor. +NS_IMETHODIMP +nsEditorShell::TransferDocumentStateListeners() +{ + if (!mDocStateListeners) + return NS_OK; + + if (!mEditor) + return NS_ERROR_NOT_INITIALIZED; // called too early. + + nsresult rv; + nsCOMPtr editor = do_QueryInterface(mEditor, &rv); + if (NS_FAILED(rv)) return rv; + + PRUint32 numListeners; + while (NS_SUCCEEDED(mDocStateListeners->Count(&numListeners)) && numListeners > 0) + { + nsCOMPtr iSupports = getter_AddRefs(mDocStateListeners->ElementAt(0)); + nsCOMPtr docStateListener = do_QueryInterface(iSupports); + if (docStateListener) + { + // this checks for duplicates + rv = editor->AddDocumentStateListener(docStateListener); + } + + mDocStateListeners->RemoveElementAt(0); + } + + // free the array + mDocStateListeners = 0; + return NS_OK; +} + + +NS_IMETHODIMP +nsEditorShell::PrepareDocumentForEditing(nsIURI *aUrl) { if (!mContentAreaWebShell) return NS_ERROR_NOT_INITIALIZED; @@ -692,11 +791,16 @@ nsEditorShell::PrepareDocumentForEditing() // and tell them that they are doing bad things NS_WARNING("Multiple loads of the editor's document detected."); + // Note that if you registered doc state listeners before the second + // URL load, they don't get transferred to the new editor. } nsresult rv = DoEditorMode(mContentAreaWebShell); - if (NS_FAILED(rv)) - return rv; + if (NS_FAILED(rv)) return rv; + + // transfer the doc state listeners to the editor + rv = TransferDocumentStateListeners(); + if (NS_FAILED(rv)) return rv; // make the UI state maintainer mStateMaintainer = new nsInterfaceState; @@ -719,6 +823,29 @@ nsEditorShell::PrepareDocumentForEditing() rv = editor->AddDocumentStateListener(mStateMaintainer); if (NS_FAILED(rv)) return rv; +#if 0 + // get the URL of the page we are editing + // does not work currently, because file URL has /usr/local/bin crap in it. + char* pageURLString = nsnull; + if (aUrl) + { + aUrl->GetSpec(&pageURLString); + + nsFileURL pageURL(pageURLString); + nsFileSpec pageSpec(pageURL); + + nsCOMPtr domDoc; + editor->GetDocument(getter_AddRefs(domDoc)); + + if (domDoc) + { + nsCOMPtr diskDoc = do_QueryInterface(domDoc); + if (diskDoc) + diskDoc->InitDiskDocument(&pageSpec); + } + } +#endif + // Force initial focus to the content window -- HOW? // mWebShellWin->SetFocus(); return NS_OK; @@ -2598,7 +2725,11 @@ nsEditorShell::OnEndDocumentLoad(nsIDocumentLoader* loader, nsIChannel* channel, nsIDocumentLoaderObserver * aObserver) #endif // NECKO { - return PrepareDocumentForEditing(); +#ifdef NECKO + nsCOMPtr aUrl; + channel->GetURI(getter_AddRefs(aUrl)); +#endif + return PrepareDocumentForEditing(aUrl); } NS_IMETHODIMP diff --git a/editor/base/nsEditorShell.h b/editor/base/nsEditorShell.h index 7c6d1a3891f3..f8a545ee2e56 100644 --- a/editor/base/nsEditorShell.h +++ b/editor/base/nsEditorShell.h @@ -99,6 +99,8 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD SetContentWindow(nsIDOMWindow *win); NS_IMETHOD SetWebShellWindow(nsIDOMWindow *win); NS_IMETHOD LoadUrl(const PRUnichar *url); + NS_IMETHOD RegisterDocumentStateListener(nsIDocumentStateListener *docListener); + NS_IMETHOD UnregisterDocumentStateListener(nsIDocumentStateListener *docListener); /* void NewWindow (); */ NS_IMETHOD NewWindow(); @@ -284,10 +286,11 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD DoEditorMode(nsIWebShell *aWebShell); NS_IMETHOD ExecuteScript(nsIScriptContext * aContext, const nsString& aScript); NS_IMETHOD InstantiateEditor(nsIDOMDocument *aDoc, nsIPresShell *aPresShell); + NS_IMETHOD TransferDocumentStateListeners(); NS_IMETHOD RemoveOneProperty(const nsString& aProp, const nsString& aAttr); void SetButtonImage(nsIDOMNode * aParentNode, PRInt32 aBtnNum, const nsString &aResName); NS_IMETHOD CreateWindowWithURL(const char* urlStr); - NS_IMETHOD PrepareDocumentForEditing(); + NS_IMETHOD PrepareDocumentForEditing(nsIURI *aUrl); NS_IMETHOD DoFind(PRBool aFindNext); // this returns an AddReffed nsIScriptContext. You must relase it. @@ -312,6 +315,10 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD DeleteSuggestedWordList(); nsStringArray mDictionaryList; PRInt32 mDictionaryIndex; + + // this is a holding pen for doc state listeners. They will be registered with + // the editor when that gets created. + nsCOMPtr mDocStateListeners; // contents are nsISupports }; #endif // nsEditorAppCore_h___ diff --git a/editor/composer/src/nsEditorShell.cpp b/editor/composer/src/nsEditorShell.cpp index cde2d7b7dec6..34184f1e8042 100644 --- a/editor/composer/src/nsEditorShell.cpp +++ b/editor/composer/src/nsEditorShell.cpp @@ -676,8 +676,107 @@ nsEditorShell::LoadUrl(const PRUnichar *url) return mContentAreaWebShell->LoadURL(url); } + NS_IMETHODIMP -nsEditorShell::PrepareDocumentForEditing() +nsEditorShell::RegisterDocumentStateListener(nsIDocumentStateListener *docListener) +{ + nsresult rv = NS_OK; + + if (!docListener) + return NS_ERROR_NULL_POINTER; + + // if we have an editor already, just pass this baby through. + if (mEditor) + { + nsCOMPtr editor = do_QueryInterface(mEditor, &rv); + if (NS_FAILED(rv)) + return rv; + + return editor->AddDocumentStateListener(docListener); + } + + // otherwise, keep it until we create an editor. + if (!mDocStateListeners) + { + rv = NS_NewISupportsArray(getter_AddRefs(mDocStateListeners)); + if (NS_FAILED(rv)) return rv; + } + nsCOMPtr iSupports = do_QueryInterface(docListener, &rv); + if (NS_FAILED(rv)) return rv; + + // note that this return value is really a PRBool, so be sure to use + // NS_SUCCEEDED or NS_FAILED to check it. + return mDocStateListeners->AppendElement(iSupports); +} + +NS_IMETHODIMP +nsEditorShell::UnregisterDocumentStateListener(nsIDocumentStateListener *docListener) +{ + if (!docListener) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + // if we have an editor already, just pass this baby through. + if (mEditor) + { + nsCOMPtr editor = do_QueryInterface(mEditor, &rv); + if (NS_FAILED(rv)) + return rv; + + return editor->RemoveDocumentStateListener(docListener); + } + + // otherwise, see if it exists in our list + if (!mDocStateListeners) + return (nsresult)PR_FALSE; // yeah, this sucks, but I'm emulating the behaviour of + // nsISupportsArray::RemoveElement() + + nsCOMPtr iSupports = do_QueryInterface(docListener, &rv); + if (NS_FAILED(rv)) return rv; + + // note that this return value is really a PRBool, so be sure to use + // NS_SUCCEEDED or NS_FAILED to check it. + return mDocStateListeners->RemoveElement(iSupports); +} + +// called after making an editor. Transfer the nsIDOcumentStateListeners +// that we have been stashing in mDocStateListeners to the editor. +NS_IMETHODIMP +nsEditorShell::TransferDocumentStateListeners() +{ + if (!mDocStateListeners) + return NS_OK; + + if (!mEditor) + return NS_ERROR_NOT_INITIALIZED; // called too early. + + nsresult rv; + nsCOMPtr editor = do_QueryInterface(mEditor, &rv); + if (NS_FAILED(rv)) return rv; + + PRUint32 numListeners; + while (NS_SUCCEEDED(mDocStateListeners->Count(&numListeners)) && numListeners > 0) + { + nsCOMPtr iSupports = getter_AddRefs(mDocStateListeners->ElementAt(0)); + nsCOMPtr docStateListener = do_QueryInterface(iSupports); + if (docStateListener) + { + // this checks for duplicates + rv = editor->AddDocumentStateListener(docStateListener); + } + + mDocStateListeners->RemoveElementAt(0); + } + + // free the array + mDocStateListeners = 0; + return NS_OK; +} + + +NS_IMETHODIMP +nsEditorShell::PrepareDocumentForEditing(nsIURI *aUrl) { if (!mContentAreaWebShell) return NS_ERROR_NOT_INITIALIZED; @@ -692,11 +791,16 @@ nsEditorShell::PrepareDocumentForEditing() // and tell them that they are doing bad things NS_WARNING("Multiple loads of the editor's document detected."); + // Note that if you registered doc state listeners before the second + // URL load, they don't get transferred to the new editor. } nsresult rv = DoEditorMode(mContentAreaWebShell); - if (NS_FAILED(rv)) - return rv; + if (NS_FAILED(rv)) return rv; + + // transfer the doc state listeners to the editor + rv = TransferDocumentStateListeners(); + if (NS_FAILED(rv)) return rv; // make the UI state maintainer mStateMaintainer = new nsInterfaceState; @@ -719,6 +823,29 @@ nsEditorShell::PrepareDocumentForEditing() rv = editor->AddDocumentStateListener(mStateMaintainer); if (NS_FAILED(rv)) return rv; +#if 0 + // get the URL of the page we are editing + // does not work currently, because file URL has /usr/local/bin crap in it. + char* pageURLString = nsnull; + if (aUrl) + { + aUrl->GetSpec(&pageURLString); + + nsFileURL pageURL(pageURLString); + nsFileSpec pageSpec(pageURL); + + nsCOMPtr domDoc; + editor->GetDocument(getter_AddRefs(domDoc)); + + if (domDoc) + { + nsCOMPtr diskDoc = do_QueryInterface(domDoc); + if (diskDoc) + diskDoc->InitDiskDocument(&pageSpec); + } + } +#endif + // Force initial focus to the content window -- HOW? // mWebShellWin->SetFocus(); return NS_OK; @@ -2598,7 +2725,11 @@ nsEditorShell::OnEndDocumentLoad(nsIDocumentLoader* loader, nsIChannel* channel, nsIDocumentLoaderObserver * aObserver) #endif // NECKO { - return PrepareDocumentForEditing(); +#ifdef NECKO + nsCOMPtr aUrl; + channel->GetURI(getter_AddRefs(aUrl)); +#endif + return PrepareDocumentForEditing(aUrl); } NS_IMETHODIMP diff --git a/editor/composer/src/nsEditorShell.h b/editor/composer/src/nsEditorShell.h index 7c6d1a3891f3..f8a545ee2e56 100644 --- a/editor/composer/src/nsEditorShell.h +++ b/editor/composer/src/nsEditorShell.h @@ -99,6 +99,8 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD SetContentWindow(nsIDOMWindow *win); NS_IMETHOD SetWebShellWindow(nsIDOMWindow *win); NS_IMETHOD LoadUrl(const PRUnichar *url); + NS_IMETHOD RegisterDocumentStateListener(nsIDocumentStateListener *docListener); + NS_IMETHOD UnregisterDocumentStateListener(nsIDocumentStateListener *docListener); /* void NewWindow (); */ NS_IMETHOD NewWindow(); @@ -284,10 +286,11 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD DoEditorMode(nsIWebShell *aWebShell); NS_IMETHOD ExecuteScript(nsIScriptContext * aContext, const nsString& aScript); NS_IMETHOD InstantiateEditor(nsIDOMDocument *aDoc, nsIPresShell *aPresShell); + NS_IMETHOD TransferDocumentStateListeners(); NS_IMETHOD RemoveOneProperty(const nsString& aProp, const nsString& aAttr); void SetButtonImage(nsIDOMNode * aParentNode, PRInt32 aBtnNum, const nsString &aResName); NS_IMETHOD CreateWindowWithURL(const char* urlStr); - NS_IMETHOD PrepareDocumentForEditing(); + NS_IMETHOD PrepareDocumentForEditing(nsIURI *aUrl); NS_IMETHOD DoFind(PRBool aFindNext); // this returns an AddReffed nsIScriptContext. You must relase it. @@ -312,6 +315,10 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD DeleteSuggestedWordList(); nsStringArray mDictionaryList; PRInt32 mDictionaryIndex; + + // this is a holding pen for doc state listeners. They will be registered with + // the editor when that gets created. + nsCOMPtr mDocStateListeners; // contents are nsISupports }; #endif // nsEditorAppCore_h___