Fix command updating for GFX text widgets. for bug 18395. r=pinkerton

git-svn-id: svn://10.0.0.236/trunk@61009 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
sfraser%netscape.com
2000-02-16 01:41:59 +00:00
parent 1044a92ddb
commit 32d1e793b2
2 changed files with 263 additions and 72 deletions

View File

@@ -43,8 +43,10 @@
#include "nsIFrameManager.h"
#include "nsIDOMHTMLInputElement.h"
#include "nsIDOMHTMLTextAreaElement.h"
#include "nsIDOMWindow.h"
#include "nsIScrollbar.h"
#include "nsIScrollableFrame.h"
#include "nsIScriptGlobalObject.h"
#include "nsCSSRendering.h"
#include "nsIDeviceContext.h"
@@ -68,6 +70,7 @@
#include "nsIEditorIMESupport.h"
#include "nsIDocumentEncoder.h"
#include "nsIEditorMailSupport.h"
#include "nsITransactionManager.h"
#include "nsEditorCID.h"
#include "nsIDOMNode.h"
#include "nsIDOMElement.h"
@@ -330,6 +333,8 @@ nsGfxTextControlFrame::nsGfxTextControlFrame()
mFrameConstructor(nsnull),
mDisplayFrame(nsnull),
mDidSetFocus(PR_FALSE),
mGotSelectionState(PR_FALSE),
mSelectionWasCollapsed(PR_FALSE),
mPassThroughMouseEvents(eUninitialized)
{
#ifdef DEBUG
@@ -404,16 +409,25 @@ nsGfxTextControlFrame::~nsGfxTextControlFrame()
if (mEditor)
{
// remove selection listener
nsCOMPtr<nsIDOMSelection>selection;
nsCOMPtr<nsIDOMSelection> selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_SUCCEEDED(result) && selection)
{
nsCOMPtr<nsIDOMSelectionListener>selListener;
selListener = do_QueryInterface(mEventListener);
if (selListener) {
nsCOMPtr<nsIDOMSelectionListener> selListener = do_QueryInterface(mEventListener);
if (selListener)
selection->RemoveSelectionListener(selListener);
}
}
// remove the txnListener
nsCOMPtr<nsITransactionManager> txnMgr;
result = mEditor->GetTransactionManager(getter_AddRefs(txnMgr));
if (NS_SUCCEEDED(result) && txnMgr)
{
nsCOMPtr<nsITransactionListener> txnListener = do_QueryInterface(mEventListener);
if (txnListener)
txnMgr->RemoveListener(txnListener);
}
// remove all other listeners from embedded document
nsCOMPtr<nsIDOMDocument>domDoc;
result = mEditor->GetDocument(getter_AddRefs(domDoc));
@@ -616,8 +630,7 @@ NS_METHOD nsGfxTextControlFrame::HandleEvent(nsIPresContext* aPresContext,
break;
case NS_FORM_SELECTED:
nsAutoString commandString("selection-changed");
return UpdateTextControlCommands(commandString);
return UpdateTextControlCommands(nsAutoString("select"));
break;
}
return NS_OK;
@@ -2744,18 +2757,32 @@ nsGfxTextControlFrame::InstallEventListeners()
if (NS_FAILED(result)) { return result; }
// add the selection listener
nsCOMPtr<nsIDOMSelection>selection;
if (mEditor && mEventListener)
{
nsCOMPtr<nsIDOMSelection>selection;
result = mEditor->GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) { return result; }
if (!selection) { return NS_ERROR_NULL_POINTER; }
nsCOMPtr<nsIDOMSelectionListener> selectionListener = do_QueryInterface(mEventListener);
if (!selectionListener) { return NS_ERROR_NO_INTERFACE; }
selection->AddSelectionListener(selectionListener);
result = selection->AddSelectionListener(selectionListener);
if (NS_FAILED(result)) { return result; }
}
// add the transation listener
if (mEditor && mEventListener)
{
nsCOMPtr<nsITransactionManager> txMgr;
result = mEditor->GetTransactionManager(getter_AddRefs(txMgr));
if (NS_FAILED(result)) return result;
if (!txMgr) { return NS_ERROR_NULL_POINTER; }
nsCOMPtr<nsITransactionListener> txnListener = do_QueryInterface(mEventListener);
if (!txnListener) { return NS_ERROR_NO_INTERFACE; }
result = txMgr->AddListener(txnListener);
if (NS_FAILED(result)) { return result; }
}
return result;
}
@@ -3073,51 +3100,62 @@ nsGfxTextControlFrame::InternalContentChanged()
// Dispatch the change event
nsEventStatus status = nsEventStatus_eIgnore;
nsGUIEvent event;
event.eventStructType = NS_GUI_EVENT;
event.widget = nsnull;
event.message = NS_FORM_INPUT;
event.flags = NS_EVENT_FLAG_INIT;
nsGUIEvent theEvent;
theEvent.eventStructType = NS_GUI_EVENT;
theEvent.widget = nsnull;
theEvent.message = NS_FORM_INPUT;
theEvent.flags = NS_EVENT_FLAG_INIT;
// Have the content handle the event, propogating it according to normal DOM rules.
nsresult result = mContent->HandleDOMEvent(mFramePresContext, &event, nsnull, NS_EVENT_FLAG_INIT, &status);
// update commands via controllers interface, if present
nsAutoString commandString("furby");
result = UpdateTextControlCommands(commandString);
return result;
return mContent->HandleDOMEvent(mFramePresContext, &theEvent, nsnull, NS_EVENT_FLAG_INIT, &status);
}
nsresult nsGfxTextControlFrame::UpdateTextControlCommands(const nsString& aCommand)
{
nsresult result;
nsresult rv = NS_OK;
nsCOMPtr<nsIControllers> controllers;
nsCOMPtr<nsIDOMNSHTMLInputElement> textInputDOMElement = do_QueryInterface(mContent);
if (textInputDOMElement) {
result = textInputDOMElement->GetControllers(getter_AddRefs(controllers));
}
else
{
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textAreaDOMElement = do_QueryInterface(mContent);
if (textAreaDOMElement) {
result = textAreaDOMElement->GetControllers(getter_AddRefs(controllers));
}
}
if (NS_FAILED(result)) { return result; }
if (controllers)
{
nsCOMPtr<nsIDOMXULCommandDispatcher> commandDispatcher;
result = controllers->GetCommandDispatcher(getter_AddRefs(commandDispatcher));
if (NS_FAILED(result)) { return result; }
if (commandDispatcher)
if (mEditor)
{
if (aCommand == nsAutoString("select")) // optimize select updates
{
result = commandDispatcher->UpdateCommands(aCommand);
nsCOMPtr<nsIDOMSelection> domSelection;
rv = mEditor->GetSelection(getter_AddRefs(domSelection));
if (NS_FAILED(rv)) return rv;
if (!domSelection) return NS_ERROR_UNEXPECTED;
PRBool selectionCollapsed;
domSelection->GetIsCollapsed(&selectionCollapsed);
if (mGotSelectionState && mSelectionWasCollapsed == selectionCollapsed)
{
return NS_OK; // no update necessary
}
else
{
mGotSelectionState = PR_TRUE;
mSelectionWasCollapsed = selectionCollapsed;
}
}
}
return result;
nsCOMPtr<nsIContent> content;
rv = GetContent(getter_AddRefs(content));
if (NS_FAILED(rv)) return rv;
if (!content) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDocument> doc;
rv = content->GetDocument(*getter_AddRefs(doc));
if (NS_FAILED(rv)) return rv;
if (!doc) return NS_ERROR_FAILURE;
nsCOMPtr<nsIScriptGlobalObject> scriptGlobalObject;
rv = doc->GetScriptGlobalObject(getter_AddRefs(scriptGlobalObject));
if (NS_FAILED(rv)) return rv;
if (!scriptGlobalObject) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMWindow> domWindow = do_QueryInterface(scriptGlobalObject);
if (!domWindow) return NS_ERROR_FAILURE;
return domWindow->UpdateCommands(aCommand);
}
@@ -3321,6 +3359,10 @@ EnderFrameLoadingInfo::EnderFrameLoadingInfo(const nsSize& aSize)
NS_IMPL_ISUPPORTS(EnderFrameLoadingInfo,kISupportsIID);
#ifdef XP_MAC
#pragma mark -
#endif
/*******************************************************************************
* nsEnderDocumentObserver
******************************************************************************/
@@ -3494,6 +3536,9 @@ NS_IMETHODIMP nsEnderDocumentObserver::DocumentWillBeDestroyed(nsIDocument *aDoc
return NS_OK;
}
#ifdef XP_MAC
#pragma mark -
#endif
/*******************************************************************************
@@ -3516,14 +3561,11 @@ NS_IMPL_RELEASE(nsEnderEventListener)
nsEnderEventListener::nsEnderEventListener()
: mView(nsnull)
, mSkipFocusDispatch(PR_FALSE) // needed for when mouse down set focus on native widgets
, mFirstDoOfFirstUndo(PR_TRUE)
{
NS_INIT_REFCNT();
mView = nsnull;
// needed for when mouse down set focus on native widgets
mSkipFocusDispatch = PR_FALSE;
// other fields are objects that initialize themselves
}
nsEnderEventListener::~nsEnderEventListener()
@@ -3585,6 +3627,11 @@ nsEnderEventListener::QueryInterface(REFNSIID aIID, void** aInstancePtr)
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsITransactionListener))) {
*aInstancePtr = (void*)(nsITransactionListener*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIEnderEventListener))) {
*aInstancePtr = (void*)(nsIEnderEventListener*)this;
NS_ADDREF_THIS();
@@ -4235,7 +4282,118 @@ nsEnderEventListener::TableCellNotification(nsIDOMNode* aNode, PRInt32 aOffset)
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::WillDo(nsITransactionManager *aManager,
nsITransaction *aTransaction, PRBool *aInterrupt)
{
*aInterrupt = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::DidDo(nsITransactionManager *aManager,
nsITransaction *aTransaction, nsresult aDoResult)
{
// we only need to update if the undo count is now 1
nsGfxTextControlFrame *gfxFrame = mFrame.Reference();
PRBool mustUpdate = PR_FALSE;
if (gfxFrame)
{
PRInt32 undoCount;
aManager->GetNumberOfUndoItems(&undoCount);
if (undoCount == 1)
{
if (mFirstDoOfFirstUndo)
gfxFrame->UpdateTextControlCommands(nsAutoString("undo"));
mFirstDoOfFirstUndo = PR_FALSE;
}
}
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::WillUndo(nsITransactionManager *aManager,
nsITransaction *aTransaction, PRBool *aInterrupt)
{
*aInterrupt = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::DidUndo(nsITransactionManager *aManager,
nsITransaction *aTransaction, nsresult aUndoResult)
{
nsGfxTextControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame)
{
PRInt32 undoCount;
aManager->GetNumberOfUndoItems(&undoCount);
if (undoCount == 0)
mFirstDoOfFirstUndo = PR_TRUE; // reset the state for the next do
gfxFrame->UpdateTextControlCommands(nsAutoString("undo"));
}
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::WillRedo(nsITransactionManager *aManager,
nsITransaction *aTransaction, PRBool *aInterrupt)
{
*aInterrupt = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::DidRedo(nsITransactionManager *aManager,
nsITransaction *aTransaction, nsresult aRedoResult)
{
nsGfxTextControlFrame *gfxFrame = mFrame.Reference();
if (gfxFrame)
{
gfxFrame->UpdateTextControlCommands(nsAutoString("undo"));
}
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::WillBeginBatch(nsITransactionManager *aManager, PRBool *aInterrupt)
{
*aInterrupt = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::DidBeginBatch(nsITransactionManager *aManager, nsresult aResult)
{
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::WillEndBatch(nsITransactionManager *aManager, PRBool *aInterrupt)
{
*aInterrupt = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::DidEndBatch(nsITransactionManager *aManager, nsresult aResult)
{
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::WillMerge(nsITransactionManager *aManager,
nsITransaction *aTopTransaction, nsITransaction *aTransactionToMerge, PRBool *aInterrupt)
{
*aInterrupt = PR_FALSE;
return NS_OK;
}
NS_IMETHODIMP nsEnderEventListener::DidMerge(nsITransactionManager *aManager,
nsITransaction *aTopTransaction, nsITransaction *aTransactionToMerge,
PRBool aDidMerge, nsresult aMergeResult)
{
return NS_OK;
}
#ifdef XP_MAC
#pragma mark -
#endif
/*******************************************************************************
* nsEnderFocusListenerForDisplayContent
@@ -4306,6 +4464,9 @@ nsEnderFocusListenerForDisplayContent::SetFrame(nsGfxTextControlFrame *aFrame)
return NS_OK;
}
#ifdef XP_MAC
#pragma mark -
#endif
/*******************************************************************************
* EnderTempObserver
@@ -4421,8 +4582,9 @@ EnderTempObserver::SetFrame(nsGfxTextControlFrame *aFrame)
}
#ifdef XP_MAC
#pragma mark -
#endif
/*******************************************************************************
* nsEnderListenerForContent