From 411cfc84dae48f80ed26bfd8cdcc38ed9b1983e5 Mon Sep 17 00:00:00 2001 From: "cmanske%netscape.com" Date: Wed, 27 Nov 2002 00:35:09 +0000 Subject: [PATCH] Added command to notify when document url changes. b=181091, r=akkana, sr=sfraser --- editor/composer/src/nsComposerCommands.cpp | 31 +++++++-- editor/composer/src/nsComposerController.cpp | 1 + editor/composer/src/nsEditingSession.cpp | 71 +++++++++++++++----- editor/idl/nsIHTMLEditor.idl | 13 +++- editor/libeditor/html/nsHTMLEditor.cpp | 38 +++++++++++ editor/libeditor/html/nsHTMLEditor.h | 2 + editor/ui/composer/content/editor.js | 12 +++- 7 files changed, 145 insertions(+), 23 deletions(-) diff --git a/editor/composer/src/nsComposerCommands.cpp b/editor/composer/src/nsComposerCommands.cpp index 9f2222b27c73..6df0caaf8a92 100644 --- a/editor/composer/src/nsComposerCommands.cpp +++ b/editor/composer/src/nsComposerCommands.cpp @@ -47,6 +47,8 @@ #include "nsIDOMElement.h" #include "nsIDOMWindowInternal.h" #include "nsIDOMDocument.h" +#include "nsIDocument.h" +#include "nsIURI.h" #include "nsIClipboard.h" @@ -58,6 +60,7 @@ #include "nsICommandParams.h" #include "nsComponentManagerUtils.h" #include "nsCRT.h" + //prototype nsresult GetListState(nsIEditor *aEditor, PRBool *aMixed, PRUnichar **tagStr); nsresult RemoveOneProperty(nsIHTMLEditor *aEditor,const nsString& aProp, @@ -1747,9 +1750,10 @@ nsSetDocumentStateCommand::GetCommandStateParams(const char *aCommandName, /** * Commands just for state notification - * As of 11/11/02, possible commands are: + * As of 11/21/02, possible commands are: * "obs_documentCreated" * "obs_documentWillBeDestroyed" + * "obs_documentLocationChanged" * Note that you can use the same command class, nsDocumentStateCommand * for these or future observer commands. * We check the input command param for different behavior @@ -1817,13 +1821,13 @@ nsDocumentStateCommand::GetCommandStateParams(const char *aCommandName, nsICommandParams *aParams, nsISupports *refCon) { + NS_ENSURE_ARG_POINTER(aParams); NS_ENSURE_ARG_POINTER(aCommandName); nsCOMPtr editingSession = do_QueryInterface(refCon); - + nsresult rv; if (!nsCRT::strcmp(aCommandName, "obs_documentCreated")) { - NS_ENSURE_ARG_POINTER(aParams); PRUint32 editorStatus = nsIEditingSession::eEditorErrorUnknown; if (editingSession) @@ -1833,7 +1837,7 @@ nsDocumentStateCommand::GetCommandStateParams(const char *aCommandName, // Embedder gets error status if this fails // If called before startup is finished, // status = eEditorCreationInProgress - nsresult rv = editingSession->GetEditorStatus(&editorStatus); + rv = editingSession->GetEditorStatus(&editorStatus); NS_ENSURE_SUCCESS(rv, rv); } else @@ -1849,6 +1853,25 @@ nsDocumentStateCommand::GetCommandStateParams(const char *aCommandName, aParams->SetLongValue(STATE_DATA, editorStatus); return NS_OK; } + else if (!nsCRT::strcmp(aCommandName, "obs_documentLocationChanged")) + { + nsCOMPtr editor = do_QueryInterface(refCon); + if (editor) + { + nsCOMPtr domDoc; + editor->GetDocument(getter_AddRefs(domDoc)); + nsCOMPtr doc = do_QueryInterface(domDoc); + if (!doc) return NS_ERROR_FAILURE; + + nsCOMPtr uri; + rv = doc->GetDocumentURL(getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + if (!uri) return NS_ERROR_FAILURE; + + return aParams->SetISupportsValue(STATE_DATA, (nsISupports*)uri); + } + return NS_OK; + } return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/editor/composer/src/nsComposerController.cpp b/editor/composer/src/nsComposerController.cpp index f76dce5ad588..de9311239aba 100644 --- a/editor/composer/src/nsComposerController.cpp +++ b/editor/composer/src/nsComposerController.cpp @@ -97,6 +97,7 @@ nsComposerController::RegisterEditorDocStateCommands( // observer commands for document state NS_REGISTER_ONE_COMMAND(nsDocumentStateCommand, "obs_documentCreated") NS_REGISTER_ONE_COMMAND(nsDocumentStateCommand, "obs_documentWillBeDestroyed") + NS_REGISTER_ONE_COMMAND(nsDocumentStateCommand, "obs_documentLocationChanged") // commands that may get or change state NS_REGISTER_ONE_COMMAND(nsSetDocumentStateCommand, "cmd_setDocumentModified") diff --git a/editor/composer/src/nsEditingSession.cpp b/editor/composer/src/nsEditingSession.cpp index a83ae9e807d6..86e76a8f340c 100644 --- a/editor/composer/src/nsEditingSession.cpp +++ b/editor/composer/src/nsEditingSession.cpp @@ -41,7 +41,9 @@ #include "nsIDOMWindow.h" #include "nsIDOMWindowInternal.h" +#include "nsIDocument.h" #include "nsIDOMDocument.h" +#include "nsIURI.h" #include "nsIScriptGlobalObject.h" #include "nsISelectionPrivate.h" #include "nsITransactionManager.h" @@ -55,6 +57,8 @@ #include "nsIControllers.h" #include "nsIController.h" #include "nsIControllerContext.h" +#include "nsICommandManager.h" +#include "nsPICommandUpdater.h" #include "nsIPresShell.h" @@ -74,7 +78,6 @@ #include "nsEditorParserObserver.h" #if DEBUG -#include "nsIURI.h" //#define NOISY_DOC_LOADING 1 #endif @@ -571,7 +574,8 @@ nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress, { nsXPIDLCString spec; uri->GetSpec(spec); - printf(" **** STATE_START: CHANNEL URI=%s, flags=%x\n",spec.get(), aStateFlags); + printf(" **** STATE_START: CHANNEL URI=%s, + flags=%x\n",spec.get(), aStateFlags); } } else @@ -636,7 +640,8 @@ nsEditingSession::OnStateChange(nsIWebProgress *aWebProgress, { nsXPIDLCString spec; uri->GetSpec(spec); - printf(" **** STATE_STOP: CHANNEL URI=%s, flags=%x\n",spec.get(), aStateFlags); + printf(" **** STATE_STOP: CHANNEL URI=%s, + flags=%x\n",spec.get(), aStateFlags); } } else @@ -699,10 +704,34 @@ nsEditingSession::OnProgressChange(nsIWebProgress *aWebProgress, ----------------------------------------------------------------------------*/ NS_IMETHODIMP nsEditingSession::OnLocationChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, nsIURI *location) + nsIRequest *aRequest, nsIURI *aURI) { - NS_NOTREACHED("notification excluded in AddProgressListener(...)"); - return NS_OK; + nsCOMPtr domWindow; + nsresult rv = aWebProgress->GetDOMWindow(getter_AddRefs(domWindow)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr domDoc; + rv = domWindow->GetDocument(getter_AddRefs(domDoc)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr doc = do_QueryInterface(domDoc); + if (!doc) return NS_ERROR_FAILURE; + + rv = doc->SetDocumentURL(aURI); + if (NS_FAILED(rv)) return rv; + + // Notify the location-changed observer that + // the document URL has changed + nsCOMPtr docShell; + rv = GetDocShellFromWindow(domWindow, getter_AddRefs(docShell)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr commandManager = do_GetInterface(docShell); + nsCOMPtr commandUpdater = + do_QueryInterface(commandManager); + if (!commandUpdater) return NS_ERROR_FAILURE; + + return commandUpdater->CommandStatusChanged("obs_documentLocationChanged"); } /*--------------------------------------------------------------------------- @@ -812,7 +841,8 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress, #ifdef NOISY_DOC_LOADING printf("Editing shell EndDocumentLoad\n"); #endif - // We want to call the base class EndDocumentLoad, but avoid some of the stuff + // We want to call the base class EndDocumentLoad, + // but avoid some of the stuff // that nsWebShell does (need to refactor). // OK, time to make an editor on this document @@ -853,9 +883,10 @@ nsEditingSession::EndDocumentLoad(nsIWebProgress *aWebProgress, if (NS_FAILED(rv)) return rv; mEditorStatus = eEditorCreationInProgress; - mLoadBlankDocTimer->InitWithFuncCallback(nsEditingSession::TimerCallback, - (void*)docShell, - 10, nsITimer::TYPE_ONE_SHOT); + mLoadBlankDocTimer->InitWithFuncCallback( + nsEditingSession::TimerCallback, + (void*)docShell, + 10, nsITimer::TYPE_ONE_SHOT); } } } @@ -977,7 +1008,10 @@ nsEditingSession::PrepareForEditing() nsCOMPtr webProgress = do_GetInterface(docShell); if (!webProgress) return NS_ERROR_FAILURE; - return webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_ALL); + return webProgress->AddProgressListener(this, + (nsIWebProgress::NOTIFY_STATE_NETWORK | + nsIWebProgress::NOTIFY_STATE_DOCUMENT | + nsIWebProgress::NOTIFY_LOCATION)); } /*--------------------------------------------------------------------------- @@ -988,10 +1022,11 @@ nsEditingSession::PrepareForEditing() get and return the controller ID, and set the refCon ----------------------------------------------------------------------------*/ nsresult -nsEditingSession::SetupEditorCommandController(const char *aControllerClassName, - nsIDOMWindow *aWindow, - nsISupports *aRefCon, - PRUint32 *aControllerId) +nsEditingSession::SetupEditorCommandController( + const char *aControllerClassName, + nsIDOMWindow *aWindow, + nsISupports *aRefCon, + PRUint32 *aControllerId) { NS_ENSURE_ARG_POINTER(aControllerClassName); NS_ENSURE_ARG_POINTER(aWindow); @@ -999,7 +1034,8 @@ nsEditingSession::SetupEditorCommandController(const char *aControllerClassName, NS_ENSURE_ARG_POINTER(aControllerId); nsresult rv; - nsCOMPtr domWindowInt = do_QueryInterface(aWindow, &rv); + nsCOMPtr domWindowInt = + do_QueryInterface(aWindow, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr controllers; @@ -1043,7 +1079,8 @@ nsEditingSession::SetEditorOnControllers(nsIDOMWindow *aWindow, nsresult rv; // set the editor on the controller - nsCOMPtr domWindowInt = do_QueryInterface(aWindow, &rv); + nsCOMPtr domWindowInt = + do_QueryInterface(aWindow, &rv); if (NS_FAILED(rv)) return rv; nsCOMPtr controllers; diff --git a/editor/idl/nsIHTMLEditor.idl b/editor/idl/nsIHTMLEditor.idl index 941da88e0072..24ef49429562 100644 --- a/editor/idl/nsIHTMLEditor.idl +++ b/editor/idl/nsIHTMLEditor.idl @@ -239,10 +239,21 @@ interface nsIHTMLEditor : nsISupports void insertElementAtSelection(in nsIDOMElement aElement, in boolean aDeleteSelection); - /** Set the documents title. + /** + * Set the documents title. */ void setDocumentTitle(in AString aTitle); + /** + * Set the BaseURL for the document to the current URL + * but only if the page doesn't have a tag + * This should be done after the document URL has changed, + * such as after saving a file + * This is used as base for relativizing link and image urls + */ + void updateBaseURL(); + + /* ------------ Selection manipulation -------------- */ /* Should these be moved to nsISelection? */ diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 2e9f965479f6..1f20b207b062 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -1238,6 +1238,44 @@ PRBool nsHTMLEditor::IsModifiable() #pragma mark - #endif +NS_IMETHODIMP +nsHTMLEditor::UpdateBaseURL() +{ + nsCOMPtr domDoc; + GetDocument(getter_AddRefs(domDoc)); + if (!domDoc) return NS_ERROR_FAILURE; + + // Look for an HTML tag + nsCOMPtr nodeList; + nsresult rv = domDoc->GetElementsByTagName(NS_LITERAL_STRING("base"), getter_AddRefs(nodeList)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr baseNode; + if (nodeList) + { + PRUint32 count; + nodeList->GetLength(&count); + if (count >= 1) + { + rv = nodeList->Item(0, getter_AddRefs(baseNode)); + NS_ENSURE_SUCCESS(rv, rv); + } + } + // If no base tag, then set baseURL to the document's URL + // This is very important, else relative URLs for links and images are wrong + if (!baseNode) + { + nsCOMPtr doc = do_QueryInterface(domDoc); + if (!doc) return NS_ERROR_FAILURE; + nsCOMPtr uri; + rv = doc->GetDocumentURL(getter_AddRefs(uri)); + NS_ENSURE_SUCCESS(rv, rv); + + return doc->SetBaseURL(uri); + } + return NS_OK; +} + NS_IMETHODIMP nsHTMLEditor::HandleKeyPress(nsIDOMKeyEvent* aKeyEvent) { PRUint32 keyCode, character; diff --git a/editor/libeditor/html/nsHTMLEditor.h b/editor/libeditor/html/nsHTMLEditor.h index 876a81c70518..cb9c0001f1ff 100644 --- a/editor/libeditor/html/nsHTMLEditor.h +++ b/editor/libeditor/html/nsHTMLEditor.h @@ -124,6 +124,8 @@ public: NS_IMETHODIMP BeginningOfDocument(); /* ------------ nsIHTMLEditor methods -------------- */ + NS_IMETHOD UpdateBaseURL(); + NS_IMETHOD CopyLastEditableChildStyles(nsIDOMNode *aPreviousBlock, nsIDOMNode *aNewBlock, nsIDOMNode **aOutBrNode); diff --git a/editor/ui/composer/content/editor.js b/editor/ui/composer/content/editor.js index 590d33eae402..e60180e7a9dd 100644 --- a/editor/ui/composer/content/editor.js +++ b/editor/ui/composer/content/editor.js @@ -389,6 +389,15 @@ var gEditorDocumentObserver = dump("obs_documentWillBeDestroyed notification\n"); break; + case "obs_documentLocationChanged": + // Ignore this when editor doesn't exist, + // which happens once when page load starts + if (editor) + try { + editor.updateBaseURL(); + } catch(e) { dump (e); } + break; + case "cmd_bold": // Update all style items window.updateCommands("style"); @@ -483,6 +492,7 @@ function EditorSharedStartup() commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentCreated"); commandManager.addCommandObserver(gEditorDocumentObserver, "cmd_setDocumentModified"); commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentWillBeDestroyed"); + commandManager.addCommandObserver(gEditorDocumentObserver, "obs_documentLocationChanged"); // Until nsIControllerCommandGroup-based code is implemented, // we will observe just the bold command to trigger update of @@ -564,6 +574,7 @@ function EditorShutdown() var commandManager = GetCurrentCommandManager(); commandManager.removeCommandObserver(gEditorDocumentObserver, "obs_documentCreated"); commandManager.removeCommandObserver(gEditorDocumentObserver, "obs_documentWillBeDestroyed"); + commandManager.removeCommandObserver(gEditorDocumentObserver, "obs_documentLocationChanged"); } catch (e) { dump (e); } } @@ -3199,4 +3210,3 @@ function FillInHTMLTooltip(tooltip) } return false; } -