diff --git a/editor/base/Makefile.in b/editor/base/Makefile.in index 82d8b7827ac..18338476771 100644 --- a/editor/base/Makefile.in +++ b/editor/base/Makefile.in @@ -32,7 +32,7 @@ IS_COMPONENT = 1 CPPSRCS = \ nsEditor.cpp \ - nsEditorService.cpp \ + nsEditorService.cpp \ nsEditorController.cpp \ nsEditorCommands.cpp \ nsEditorUtils.cpp \ @@ -73,6 +73,7 @@ CPPSRCS = \ EXTRA_DSO_LDOPTS = \ $(MOZ_NECKO_UTIL_LIBS) \ $(MOZ_COMPONENT_LIBS) \ + $(MOZ_TIMER_LIBS) \ -lmozjs \ $(NULL) diff --git a/editor/base/makefile.win b/editor/base/makefile.win index 6c5decc819e..f387c75edaa 100644 --- a/editor/base/makefile.win +++ b/editor/base/makefile.win @@ -136,6 +136,7 @@ LLIBS= \ $(DIST)\lib\js3250.lib \ $(DIST)\lib\gkparser.lib \ $(DIST)\lib\raptorwidget_s.lib \ + $(DIST)\lib\timer_s.lib \ $(LIBNSPR) !if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE) LLIBS=$(LLIBS) $(GLOWDIR)\glowcode.lib diff --git a/editor/base/nsInterfaceState.cpp b/editor/base/nsInterfaceState.cpp index bdaafb803ac..588e7dc2211 100644 --- a/editor/base/nsInterfaceState.cpp +++ b/editor/base/nsInterfaceState.cpp @@ -38,6 +38,7 @@ #include "nsIDOMXULCommandDispatcher.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMWindow.h" +#include "nsITimer.h" #include "nsIEditor.h" #include "nsIHTMLEditor.h" @@ -63,11 +64,14 @@ nsInterfaceState::nsInterfaceState() nsInterfaceState::~nsInterfaceState() { + // cancel any outstanding udpate timer + if (mUpdateTimer) + mUpdateTimer->Cancel(); } NS_IMPL_ADDREF(nsInterfaceState); NS_IMPL_RELEASE(nsInterfaceState); -NS_IMPL_QUERY_INTERFACE3(nsInterfaceState, nsIDOMSelectionListener, nsIDocumentStateListener, nsITransactionListener); +NS_IMPL_QUERY_INTERFACE4(nsInterfaceState, nsIDOMSelectionListener, nsIDocumentStateListener, nsITransactionListener, nsITimerCallback); NS_IMETHODIMP nsInterfaceState::Init(nsIHTMLEditor* aEditor, nsIDOMXULDocument *aChromeDoc) @@ -113,17 +117,13 @@ nsInterfaceState::NotifyDocumentStateChanged(PRBool aNowDirty) NS_IMETHODIMP nsInterfaceState::NotifySelectionChanged() { - // if the selection state has changed, update stuff - PRBool isCollapsed = SelectionIsCollapsed(); - if (isCollapsed != mSelectionCollapsed) - { - CallUpdateCommands(nsAutoString("select")); - mSelectionCollapsed = isCollapsed; - } - - return ForceUpdate(); + return PrimeUpdateTimer(); } +#ifdef XP_MAC +#pragma mark - +#endif + NS_IMETHODIMP nsInterfaceState::WillDo(nsITransactionManager *aManager, nsITransaction *aTransaction, PRBool *aInterrupt) @@ -144,7 +144,7 @@ NS_IMETHODIMP nsInterfaceState::DidDo(nsITransactionManager *aManager, CallUpdateCommands(nsAutoString("undo")); mFirstDoOfFirstUndo = PR_FALSE; } - + return NS_OK; } @@ -217,6 +217,44 @@ NS_IMETHODIMP nsInterfaceState::DidMerge(nsITransactionManager *aManager, return NS_OK; } +#ifdef XP_MAC +#pragma mark - +#endif + + +nsresult nsInterfaceState::PrimeUpdateTimer() +{ + nsresult rv = NS_OK; + + if (mUpdateTimer) + { + // i'd love to be able to just call SetDelay on the existing timer, but + // i think i have to tear it down and make a new one. + mUpdateTimer->Cancel(); + mUpdateTimer = NULL; // free it + } + + rv = NS_NewTimer(getter_AddRefs(mUpdateTimer)); + if (NS_FAILED(rv)) return rv; + + const PRUint32 kUpdateTimerDelay = 150; + return mUpdateTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), kUpdateTimerDelay); +} + + +void nsInterfaceState::TimerCallback() +{ + // if the selection state has changed, update stuff + PRBool isCollapsed = SelectionIsCollapsed(); + if (isCollapsed != mSelectionCollapsed) + { + CallUpdateCommands(nsAutoString("select")); + mSelectionCollapsed = isCollapsed; + } + + (void)ForceUpdate(); +} + nsresult nsInterfaceState::CallUpdateCommands(const nsString& aCommand) { @@ -252,13 +290,16 @@ nsInterfaceState::ForceUpdate() // update bold rv = UpdateTextState("b", "Editor:Bold", "bold", mBoldState); + // update italic rv = UpdateTextState("i", "Editor:Italic", "italic", mItalicState); + // update underline rv = UpdateTextState("u", "Editor:Underline", "underline", mUnderlineState); // update the paragraph format popup rv = UpdateParagraphState("Editor:Paragraph:Format", "format", mParagraphFormat); + // udpate the font face rv = UpdateFontFace("Editor:Font:Face", "font", mFontString); @@ -473,6 +514,24 @@ nsInterfaceState::UnsetNodeAttribute(const char* nodeID, const char* attributeNa } +#ifdef XP_MAC +#pragma mark - +#endif + + +void +nsInterfaceState::Notify(nsITimer *timer) +{ + NS_ASSERTION(timer == mUpdateTimer.get(), "Hey, this ain't my timer!"); + mUpdateTimer = NULL; // release my hold + TimerCallback(); +} + +#ifdef XP_MAC +#pragma mark - +#endif + + nsresult NS_NewInterfaceState(nsIHTMLEditor* aEditor, nsIDOMXULDocument* aChromeDoc, nsIDOMSelectionListener** aInstancePtrResult) { nsInterfaceState* newThang = new nsInterfaceState; diff --git a/editor/base/nsInterfaceState.h b/editor/base/nsInterfaceState.h index dde6b6a40f8..9e1259d3ba8 100644 --- a/editor/base/nsInterfaceState.h +++ b/editor/base/nsInterfaceState.h @@ -29,6 +29,7 @@ #include "nsIDocumentStateListener.h" #include "nsITransactionListener.h" #include "nsIWebShell.h" +#include "nsITimerCallback.h" class nsIHTMLEditor; class nsIDOMXULDocument; @@ -38,7 +39,8 @@ class nsIDOMXULDocument; class nsInterfaceState : public nsIDOMSelectionListener, public nsIDocumentStateListener, - public nsITransactionListener + public nsITransactionListener, + public nsITimerCallback { public: @@ -55,10 +57,12 @@ public: // nsIDOMSelectionListener interface NS_IMETHOD NotifySelectionChanged(); - NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); NS_DECL_NSIDOCUMENTSTATELISTENER + // nsITimerCallback interfaces + NS_IMETHOD_(void) Notify(nsITimer *timer); /** nsITransactionListener interfaces */ @@ -100,6 +104,9 @@ protected: nsresult CallUpdateCommands(const nsString& aCommand); + nsresult PrimeUpdateTimer(); + void TimerCallback(); + // this class should not hold references to the editor or editorShell. Doing // so would result in cirular reference chains. @@ -108,6 +115,8 @@ protected: nsIDOMWindow* mDOMWindow; // nsIDOMWindow used for calling UpdateCommands + nsCOMPtr mUpdateTimer; + // current state PRInt8 mBoldState; PRInt8 mItalicState; diff --git a/editor/composer/src/nsInterfaceState.cpp b/editor/composer/src/nsInterfaceState.cpp index bdaafb803ac..588e7dc2211 100644 --- a/editor/composer/src/nsInterfaceState.cpp +++ b/editor/composer/src/nsInterfaceState.cpp @@ -38,6 +38,7 @@ #include "nsIDOMXULCommandDispatcher.h" #include "nsIScriptGlobalObject.h" #include "nsIDOMWindow.h" +#include "nsITimer.h" #include "nsIEditor.h" #include "nsIHTMLEditor.h" @@ -63,11 +64,14 @@ nsInterfaceState::nsInterfaceState() nsInterfaceState::~nsInterfaceState() { + // cancel any outstanding udpate timer + if (mUpdateTimer) + mUpdateTimer->Cancel(); } NS_IMPL_ADDREF(nsInterfaceState); NS_IMPL_RELEASE(nsInterfaceState); -NS_IMPL_QUERY_INTERFACE3(nsInterfaceState, nsIDOMSelectionListener, nsIDocumentStateListener, nsITransactionListener); +NS_IMPL_QUERY_INTERFACE4(nsInterfaceState, nsIDOMSelectionListener, nsIDocumentStateListener, nsITransactionListener, nsITimerCallback); NS_IMETHODIMP nsInterfaceState::Init(nsIHTMLEditor* aEditor, nsIDOMXULDocument *aChromeDoc) @@ -113,17 +117,13 @@ nsInterfaceState::NotifyDocumentStateChanged(PRBool aNowDirty) NS_IMETHODIMP nsInterfaceState::NotifySelectionChanged() { - // if the selection state has changed, update stuff - PRBool isCollapsed = SelectionIsCollapsed(); - if (isCollapsed != mSelectionCollapsed) - { - CallUpdateCommands(nsAutoString("select")); - mSelectionCollapsed = isCollapsed; - } - - return ForceUpdate(); + return PrimeUpdateTimer(); } +#ifdef XP_MAC +#pragma mark - +#endif + NS_IMETHODIMP nsInterfaceState::WillDo(nsITransactionManager *aManager, nsITransaction *aTransaction, PRBool *aInterrupt) @@ -144,7 +144,7 @@ NS_IMETHODIMP nsInterfaceState::DidDo(nsITransactionManager *aManager, CallUpdateCommands(nsAutoString("undo")); mFirstDoOfFirstUndo = PR_FALSE; } - + return NS_OK; } @@ -217,6 +217,44 @@ NS_IMETHODIMP nsInterfaceState::DidMerge(nsITransactionManager *aManager, return NS_OK; } +#ifdef XP_MAC +#pragma mark - +#endif + + +nsresult nsInterfaceState::PrimeUpdateTimer() +{ + nsresult rv = NS_OK; + + if (mUpdateTimer) + { + // i'd love to be able to just call SetDelay on the existing timer, but + // i think i have to tear it down and make a new one. + mUpdateTimer->Cancel(); + mUpdateTimer = NULL; // free it + } + + rv = NS_NewTimer(getter_AddRefs(mUpdateTimer)); + if (NS_FAILED(rv)) return rv; + + const PRUint32 kUpdateTimerDelay = 150; + return mUpdateTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this), kUpdateTimerDelay); +} + + +void nsInterfaceState::TimerCallback() +{ + // if the selection state has changed, update stuff + PRBool isCollapsed = SelectionIsCollapsed(); + if (isCollapsed != mSelectionCollapsed) + { + CallUpdateCommands(nsAutoString("select")); + mSelectionCollapsed = isCollapsed; + } + + (void)ForceUpdate(); +} + nsresult nsInterfaceState::CallUpdateCommands(const nsString& aCommand) { @@ -252,13 +290,16 @@ nsInterfaceState::ForceUpdate() // update bold rv = UpdateTextState("b", "Editor:Bold", "bold", mBoldState); + // update italic rv = UpdateTextState("i", "Editor:Italic", "italic", mItalicState); + // update underline rv = UpdateTextState("u", "Editor:Underline", "underline", mUnderlineState); // update the paragraph format popup rv = UpdateParagraphState("Editor:Paragraph:Format", "format", mParagraphFormat); + // udpate the font face rv = UpdateFontFace("Editor:Font:Face", "font", mFontString); @@ -473,6 +514,24 @@ nsInterfaceState::UnsetNodeAttribute(const char* nodeID, const char* attributeNa } +#ifdef XP_MAC +#pragma mark - +#endif + + +void +nsInterfaceState::Notify(nsITimer *timer) +{ + NS_ASSERTION(timer == mUpdateTimer.get(), "Hey, this ain't my timer!"); + mUpdateTimer = NULL; // release my hold + TimerCallback(); +} + +#ifdef XP_MAC +#pragma mark - +#endif + + nsresult NS_NewInterfaceState(nsIHTMLEditor* aEditor, nsIDOMXULDocument* aChromeDoc, nsIDOMSelectionListener** aInstancePtrResult) { nsInterfaceState* newThang = new nsInterfaceState; diff --git a/editor/composer/src/nsInterfaceState.h b/editor/composer/src/nsInterfaceState.h index dde6b6a40f8..9e1259d3ba8 100644 --- a/editor/composer/src/nsInterfaceState.h +++ b/editor/composer/src/nsInterfaceState.h @@ -29,6 +29,7 @@ #include "nsIDocumentStateListener.h" #include "nsITransactionListener.h" #include "nsIWebShell.h" +#include "nsITimerCallback.h" class nsIHTMLEditor; class nsIDOMXULDocument; @@ -38,7 +39,8 @@ class nsIDOMXULDocument; class nsInterfaceState : public nsIDOMSelectionListener, public nsIDocumentStateListener, - public nsITransactionListener + public nsITransactionListener, + public nsITimerCallback { public: @@ -55,10 +57,12 @@ public: // nsIDOMSelectionListener interface NS_IMETHOD NotifySelectionChanged(); - NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); + NS_IMETHOD TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset); NS_DECL_NSIDOCUMENTSTATELISTENER + // nsITimerCallback interfaces + NS_IMETHOD_(void) Notify(nsITimer *timer); /** nsITransactionListener interfaces */ @@ -100,6 +104,9 @@ protected: nsresult CallUpdateCommands(const nsString& aCommand); + nsresult PrimeUpdateTimer(); + void TimerCallback(); + // this class should not hold references to the editor or editorShell. Doing // so would result in cirular reference chains. @@ -108,6 +115,8 @@ protected: nsIDOMWindow* mDOMWindow; // nsIDOMWindow used for calling UpdateCommands + nsCOMPtr mUpdateTimer; + // current state PRInt8 mBoldState; PRInt8 mItalicState;