From 5ca13143ec9fc30487e3070fd11310bc9c09efaa Mon Sep 17 00:00:00 2001 From: "buster%netscape.com" Date: Wed, 6 Jan 1999 20:29:11 +0000 Subject: [PATCH] support for ChangeAttributeTxn git-svn-id: svn://10.0.0.236/trunk@17252 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/base/editor.cpp | 185 ++++++++++++++++++++++- mozilla/editor/base/editor.h | 53 +++++++ mozilla/editor/base/editorInterfaces.cpp | 127 +++++++++++++--- mozilla/editor/base/editorInterfaces.h | 1 + mozilla/editor/core/editor.cpp | 185 ++++++++++++++++++++++- mozilla/editor/core/editor.h | 53 +++++++ mozilla/editor/core/editorInterfaces.cpp | 127 +++++++++++++--- mozilla/editor/core/editorInterfaces.h | 1 + 8 files changed, 686 insertions(+), 46 deletions(-) diff --git a/mozilla/editor/base/editor.cpp b/mozilla/editor/base/editor.cpp index b67d1cb9391..e646ef1cb36 100644 --- a/mozilla/editor/base/editor.cpp +++ b/mozilla/editor/base/editor.cpp @@ -22,11 +22,15 @@ #include "nsIDOMEventReceiver.h" #include "nsIDOMText.h" #include "nsIDOMElement.h" +#include "nsIDOMAttr.h" #include "nsIDocument.h" #include "nsRepository.h" +#include "nsIServiceManager.h" #include "nsEditFactory.h" #include "nsEditorCID.h" - +#include "nsTransactionManagerCID.h" +#include "nsITransactionManager.h" +#include "nsIAtom.h" static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID); @@ -41,6 +45,20 @@ static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID); static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID); +static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID); +static NS_DEFINE_CID(kCTransactionManagerFactoryCID, NS_TRANSACTION_MANAGER_FACTORY_CID); + + +#ifdef XP_PC +#define TRANSACTION_MANAGER_DLL "txmgr.dll" +#else +#ifdef XP_MAC +#define TRANSACTION_MANAGER_DLL "TRANSACTION_MANAGER_DLL" +#else // XP_UNIX +#define TRANSACTION_MANAGER_DLL "libtxmgr.so" +#endif +#endif + //monitor for the editor @@ -98,26 +116,29 @@ NSRegisterSelf(const char *path) PR_TRUE, PR_TRUE); //this will register the factory with the xpcom dll. } - - extern "C" NS_EXPORT nsresult NSUnregisterSelf(const char *path) { return nsRepository::UnregisterFactory(kIEditFactoryIID, path);//this will unregister the factory with the xpcom dll. } - - //END EXPORTS //class implementations are in order they are declared in editor.h - +static PRBool needsInit=PR_TRUE; nsEditor::nsEditor() { //initialize member variables here NS_INIT_REFCNT(); + if (PR_TRUE==needsInit) + { + needsInit=PR_FALSE; + nsRepository::RegisterFactory(kCTransactionManagerFactoryCID, + TRANSACTION_MANAGER_DLL, PR_FALSE, PR_FALSE); + } + mTxnMgr = nsnull; } @@ -210,6 +231,8 @@ nsEditor::Init(nsIDOMDocument *aDomInterface) erP->AddEventListener(mKeyListenerP, kIDOMKeyListenerIID); //erP->AddEventListener(mMouseListenerP, kIDOMMouseListenerIID); + /* fire up the transaction manager */ + /* now to handle selection */ @@ -229,6 +252,29 @@ nsEditor::Init(nsIDOMDocument *aDomInterface) return t_result; } */ + + nsISupports *isup = 0; + nsresult result; + + result = nsServiceManager::GetService(kCTransactionManagerFactoryCID, + kITransactionManagerIID, &isup); + + if (NS_FAILED(result) || !isup) { + printf("ERROR: Failed to get TransactionManager nsISupports interface.\n"); + return NS_ERROR_OUT_OF_MEMORY; + } + + result = isup->QueryInterface(kITransactionManagerIID, (void **)&mTxnMgr); + + if (NS_FAILED(result)) { + printf("ERROR: Failed to get TransactionManager interface. (%d)\n", result); + return result; + } + + if (!mTxnMgr) { + printf("ERROR: QueryInterface() returned NULL pointer.\n"); + return NS_ERROR_NULL_POINTER; + } return NS_OK; } @@ -258,6 +304,40 @@ nsEditor::GetProperties(PROPERTIES **) } +nsresult +nsEditor::SetAttribute(nsIDOMElement *aElement, const nsString& aAttribute, const nsString& aValue) +{ + return aElement->SetDOMAttribute(aAttribute, aValue); +} + +nsresult +nsEditor::GetAttributeValue(nsIDOMElement *aElement, + const nsString& aAttribute, + nsString& aResultValue, + PRBool& aResultIsSet) +{ + aResultIsSet=PR_FALSE; + nsresult result=NS_OK; + if (nsnull!=aElement) + { + nsIDOMAttr* attNode=nsnull; + result = aElement->GetAttributeNode(aAttribute, &attNode); + if ((NS_SUCCEEDED(result)) && (nsnull!=attNode)) + { + attNode->GetSpecified(&aResultIsSet); + attNode->GetValue(aResultValue); + } + } + return result; +} + +nsresult +nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute) +{ + return aElement->RemoveAttribute(aAttribute); +} + + nsresult nsEditor::Commit(PRBool aCtrlKey) @@ -337,6 +417,59 @@ nsEditor::GetCurrentNode(nsIDOMNode ** aNode) return NS_ERROR_FAILURE; } +nsresult +nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult) +{ + nsresult result=NS_OK; + + if (!aResult) + return NS_ERROR_NULL_POINTER; + + /* If no node set, get root node */ + nsCOMPtr node; + nsCOMPtr element; + + if (nsnull==aStartNode) + { + mDomInterfaceP->GetDocumentElement(getter_AddRefs(element)); + result = element->QueryInterface(kIDOMNodeIID,getter_AddRefs(node)); + if (NS_FAILED(result)) + return result; + if (!node) + return NS_ERROR_NULL_POINTER; + } + else + node=aStartNode; + + *aResult = nsnull; + nsCOMPtr childNode; + result = node->GetFirstChild(getter_AddRefs(childNode)); + while (childNode) + { + result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element)); + nsString tag; + if (NS_SUCCEEDED(result) && (element)) + { + element->GetTagName(tag); + if (PR_TRUE==aTag.Equals(tag)) + { + return (childNode->QueryInterface(kIDOMNodeIID,(void **) aResult)); // does the addref + } + else + { + nsresult result = GetFirstNodeOfType(childNode, aTag, aResult); + if (nsnull!=*aResult) + return result; + } + } + nsCOMPtr xNode; + childNode->GetNextSibling(getter_AddRefs(xNode)); + childNode=xNode; + } + + return NS_ERROR_FAILURE; +} + nsresult @@ -387,6 +520,46 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode) return NS_OK; } +nsresult +nsEditor::ExecuteTransaction(nsITransaction *aTxn) +{ + nsresult result = NS_OK; + if (nsnull!=aTxn) + { + if (nsnull!=mTxnMgr) + { + result = mTxnMgr->Do(aTxn); + } + else + { + result = aTxn->Do(); + } + } + return result; +} + +nsresult +nsEditor::Undo() +{ + nsresult result = NS_OK; + if (nsnull!=mTxnMgr) + { + result = mTxnMgr->Undo(); + } + return result; +} + +nsresult +nsEditor::Redo() +{ + nsresult result = NS_OK; + if (nsnull!=mTxnMgr) + { + result = mTxnMgr->Redo(); + } + return result; +} + //END nsEditor Private methods diff --git a/mozilla/editor/base/editor.h b/mozilla/editor/base/editor.h index e1f599ef891..1ebec7a593d 100644 --- a/mozilla/editor/base/editor.h +++ b/mozilla/editor/base/editor.h @@ -23,6 +23,7 @@ #include "nsIDOMEventListener.h" #include "nsCOMPtr.h" #include "editorInterfaces.h" +#include "nsITransactionManager.h" //#include "nsISelection.h" @@ -42,6 +43,9 @@ private: nsCOMPtr mKeyListenerP; nsCOMPtr mMouseListenerP; // nsCOMPtr mSelectionP; + //nsCOMPtr mTxnMgrP; + nsITransactionManager * mTxnMgr; + public: /** The default constructor. This should suffice. the setting of the interfaces is done * after the construction of the editor class. @@ -66,10 +70,23 @@ public: virtual nsresult GetProperties(PROPERTIES **); + virtual nsresult SetAttribute(nsIDOMElement * aElement, + const nsString& aAttribute, + const nsString& aValue); + + virtual nsresult GetAttributeValue(nsIDOMElement * aElement, + const nsString& aAttribute, + nsString& aResultValue, + PRBool& aResultIsSet); + + virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute); + virtual nsresult InsertString(nsString *aString); virtual nsresult Commit(PRBool aCtrlKey); + + /*END nsIEditor interfaces*/ /*BEGIN nsEditor interfaces*/ @@ -112,6 +129,42 @@ public: */ nsresult GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode); + /** GetFirstNodeOfType ADDREFFS and will get the next available node from the passed + * in aStartNode parameter of type aTag. + * It can also return NS_ERROR_FAILURE if no such nodes are available + * @param nsIDOMNode *aStartNode is the node to start looking from + * @param nsIAtom *aTag is the type of node we are searching for + * @param nsIDOMNode **aResult is the node we found, or nsnull if there is none + */ + nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult); + + /** ExecuteTransaction fires a transaction. It is provided here so + * clients need no knowledge of whether the editor has a transaction manager or not. + * If a transaction manager is present, it is used. + * Otherwise, the transaction is just executed directly. + * + * @param aTxn the transaction to execute + */ + nsresult ExecuteTransaction(nsITransaction *aTxn); + + /** Undo reverses the effects of the last ExecuteTransaction operation + * It is provided here so clients need no knowledge of whether the editor has a transaction manager or not. + * If a transaction manager is present, it is told to undo and the result of + * that undo is returned. + * Otherwise, the Undo request is ignored. + * + */ + nsresult Undo(); + + /** Redo reverses the effects of the last Undo operation + * It is provided here so clients need no knowledge of whether the editor has a transaction manager or not. + * If a transaction manager is present, it is told to redo and the result of + * that redo is returned. + * Otherwise, the Redo request is ignored. + * + */ + nsresult Redo(); + /*END private methods of nsEditor*/ }; diff --git a/mozilla/editor/base/editorInterfaces.cpp b/mozilla/editor/base/editorInterfaces.cpp index ff35b161e66..49a29cea8b6 100644 --- a/mozilla/editor/base/editorInterfaces.cpp +++ b/mozilla/editor/base/editorInterfaces.cpp @@ -18,7 +18,11 @@ #include "editorInterfaces.h" #include "nsString.h" #include "editor.h" +#include "ChangeAttributeTxn.h" #include "nsIDOMDocument.h" +#include "nsIDOMElement.h" + +static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); /* * nsEditorKeyListener implementation @@ -113,25 +117,30 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) NS_SUCCEEDED(aKeyEvent->GetShiftKey(&isShift)) && NS_SUCCEEDED(aKeyEvent->GetCtrlKey(&ctrlKey)) ) { - switch(keyCode) { - case nsIDOMEvent::VK_BACK: - break; - case nsIDOMEvent::VK_RETURN: - // Need to implement creation of either

or
nodes. - mEditor->Commit(ctrlKey); - break; - default: - // XXX Replace with x-platform NS-virtkeycode transform. - if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) { - nsString* key = new nsString(); - *key += character; - if (!isShift) { - key->ToLowerCase(); + PRBool keyProcessed; + ProcessShortCutKeys(aKeyEvent, keyProcessed); + if (PR_FALSE==keyProcessed) + { + switch(keyCode) { + case nsIDOMEvent::VK_BACK: + break; + case nsIDOMEvent::VK_RETURN: + // Need to implement creation of either

or
nodes. + mEditor->Commit(ctrlKey); + break; + default: + // XXX Replace with x-platform NS-virtkeycode transform. + if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) { + nsString* key = new nsString(); + *key += character; + if (!isShift) { + key->ToLowerCase(); + } + mEditor->InsertString(key); + delete key; } - mEditor->InsertString(key); - delete key; + break; } - break; } } @@ -154,6 +163,90 @@ nsEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) return NS_OK; } +nsresult +nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed) +{ + aProcessed=PR_FALSE; + PRUint32 keyCode; + PRBool isShift; + PRBool ctrlKey; + + if (NS_SUCCEEDED(aKeyEvent->GetKeyCode(&keyCode)) && + NS_SUCCEEDED(aKeyEvent->GetShiftKey(&isShift)) && + NS_SUCCEEDED(aKeyEvent->GetCtrlKey(&ctrlKey)) + ) + { + // XXX: please please please get these mappings from an external source! + switch (keyCode) + { + // hard-coded undo + case nsIDOMEvent::VK_Z: + if (PR_TRUE==ctrlKey) + { + if (nsnull!=mEditor) + mEditor->Undo(); + } + aProcessed=PR_TRUE; + break; + + // hard-coded redo + case nsIDOMEvent::VK_Y: + if (PR_TRUE==ctrlKey) + { + if (nsnull!=mEditor) + mEditor->Redo(); + } + aProcessed=PR_TRUE; + break; + + case nsIDOMEvent::VK_TAB: + { + //XXX: should be from a factory + //XXX: should manage the refcount of txn + nsString attribute("width"); + nsString value("400"); + + nsString tableTag("TABLE"); + nsCOMPtr currentNode; + nsCOMPtr element; + if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode)))) + { + if (NS_SUCCEEDED(currentNode->QueryInterface(kIDOMElementIID, getter_AddRefs(element)))) + { + ChangeAttributeTxn *txn = new ChangeAttributeTxn(mEditor, element, attribute, value); + mEditor->ExecuteTransaction(txn); + } + } + } + aProcessed=PR_TRUE; + break; + + case nsIDOMEvent::VK_SPACE: + { + //XXX: should be from a factory + //XXX: should manage the refcount of txn + nsString attribute("height"); + nsString value("200"); + + nsString tableTag("TABLE"); + nsCOMPtr currentNode; + nsCOMPtr element; + if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode)))) + { + if (NS_SUCCEEDED(currentNode->QueryInterface(kIDOMElementIID, getter_AddRefs(element)))) + { + ChangeAttributeTxn *txn = new ChangeAttributeTxn(mEditor, element, attribute, value); + mEditor->ExecuteTransaction(txn); + } + } + } + aProcessed=PR_TRUE; + break; + } + } + return NS_OK; +} + /* diff --git a/mozilla/editor/base/editorInterfaces.h b/mozilla/editor/base/editorInterfaces.h index dfb7a3a3926..a09fcf9800d 100644 --- a/mozilla/editor/base/editorInterfaces.h +++ b/mozilla/editor/base/editorInterfaces.h @@ -65,6 +65,7 @@ public: /*END interfaces from nsIDOMKeyListener*/ private: virtual nsresult GetCharFromKeyCode(PRUint32 aKeyCode, PRBool aIsShift, char *aChar); + virtual nsresult ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed); }; diff --git a/mozilla/editor/core/editor.cpp b/mozilla/editor/core/editor.cpp index b67d1cb9391..e646ef1cb36 100644 --- a/mozilla/editor/core/editor.cpp +++ b/mozilla/editor/core/editor.cpp @@ -22,11 +22,15 @@ #include "nsIDOMEventReceiver.h" #include "nsIDOMText.h" #include "nsIDOMElement.h" +#include "nsIDOMAttr.h" #include "nsIDocument.h" #include "nsRepository.h" +#include "nsIServiceManager.h" #include "nsEditFactory.h" #include "nsEditorCID.h" - +#include "nsTransactionManagerCID.h" +#include "nsITransactionManager.h" +#include "nsIAtom.h" static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID); @@ -41,6 +45,20 @@ static NS_DEFINE_IID(kIEditFactoryIID, NS_IEDITORFACTORY_IID); static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kEditorCID, NS_EDITOR_CID); +static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID); +static NS_DEFINE_CID(kCTransactionManagerFactoryCID, NS_TRANSACTION_MANAGER_FACTORY_CID); + + +#ifdef XP_PC +#define TRANSACTION_MANAGER_DLL "txmgr.dll" +#else +#ifdef XP_MAC +#define TRANSACTION_MANAGER_DLL "TRANSACTION_MANAGER_DLL" +#else // XP_UNIX +#define TRANSACTION_MANAGER_DLL "libtxmgr.so" +#endif +#endif + //monitor for the editor @@ -98,26 +116,29 @@ NSRegisterSelf(const char *path) PR_TRUE, PR_TRUE); //this will register the factory with the xpcom dll. } - - extern "C" NS_EXPORT nsresult NSUnregisterSelf(const char *path) { return nsRepository::UnregisterFactory(kIEditFactoryIID, path);//this will unregister the factory with the xpcom dll. } - - //END EXPORTS //class implementations are in order they are declared in editor.h - +static PRBool needsInit=PR_TRUE; nsEditor::nsEditor() { //initialize member variables here NS_INIT_REFCNT(); + if (PR_TRUE==needsInit) + { + needsInit=PR_FALSE; + nsRepository::RegisterFactory(kCTransactionManagerFactoryCID, + TRANSACTION_MANAGER_DLL, PR_FALSE, PR_FALSE); + } + mTxnMgr = nsnull; } @@ -210,6 +231,8 @@ nsEditor::Init(nsIDOMDocument *aDomInterface) erP->AddEventListener(mKeyListenerP, kIDOMKeyListenerIID); //erP->AddEventListener(mMouseListenerP, kIDOMMouseListenerIID); + /* fire up the transaction manager */ + /* now to handle selection */ @@ -229,6 +252,29 @@ nsEditor::Init(nsIDOMDocument *aDomInterface) return t_result; } */ + + nsISupports *isup = 0; + nsresult result; + + result = nsServiceManager::GetService(kCTransactionManagerFactoryCID, + kITransactionManagerIID, &isup); + + if (NS_FAILED(result) || !isup) { + printf("ERROR: Failed to get TransactionManager nsISupports interface.\n"); + return NS_ERROR_OUT_OF_MEMORY; + } + + result = isup->QueryInterface(kITransactionManagerIID, (void **)&mTxnMgr); + + if (NS_FAILED(result)) { + printf("ERROR: Failed to get TransactionManager interface. (%d)\n", result); + return result; + } + + if (!mTxnMgr) { + printf("ERROR: QueryInterface() returned NULL pointer.\n"); + return NS_ERROR_NULL_POINTER; + } return NS_OK; } @@ -258,6 +304,40 @@ nsEditor::GetProperties(PROPERTIES **) } +nsresult +nsEditor::SetAttribute(nsIDOMElement *aElement, const nsString& aAttribute, const nsString& aValue) +{ + return aElement->SetDOMAttribute(aAttribute, aValue); +} + +nsresult +nsEditor::GetAttributeValue(nsIDOMElement *aElement, + const nsString& aAttribute, + nsString& aResultValue, + PRBool& aResultIsSet) +{ + aResultIsSet=PR_FALSE; + nsresult result=NS_OK; + if (nsnull!=aElement) + { + nsIDOMAttr* attNode=nsnull; + result = aElement->GetAttributeNode(aAttribute, &attNode); + if ((NS_SUCCEEDED(result)) && (nsnull!=attNode)) + { + attNode->GetSpecified(&aResultIsSet); + attNode->GetValue(aResultValue); + } + } + return result; +} + +nsresult +nsEditor::RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute) +{ + return aElement->RemoveAttribute(aAttribute); +} + + nsresult nsEditor::Commit(PRBool aCtrlKey) @@ -337,6 +417,59 @@ nsEditor::GetCurrentNode(nsIDOMNode ** aNode) return NS_ERROR_FAILURE; } +nsresult +nsEditor::GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult) +{ + nsresult result=NS_OK; + + if (!aResult) + return NS_ERROR_NULL_POINTER; + + /* If no node set, get root node */ + nsCOMPtr node; + nsCOMPtr element; + + if (nsnull==aStartNode) + { + mDomInterfaceP->GetDocumentElement(getter_AddRefs(element)); + result = element->QueryInterface(kIDOMNodeIID,getter_AddRefs(node)); + if (NS_FAILED(result)) + return result; + if (!node) + return NS_ERROR_NULL_POINTER; + } + else + node=aStartNode; + + *aResult = nsnull; + nsCOMPtr childNode; + result = node->GetFirstChild(getter_AddRefs(childNode)); + while (childNode) + { + result = childNode->QueryInterface(kIDOMNodeIID,getter_AddRefs(element)); + nsString tag; + if (NS_SUCCEEDED(result) && (element)) + { + element->GetTagName(tag); + if (PR_TRUE==aTag.Equals(tag)) + { + return (childNode->QueryInterface(kIDOMNodeIID,(void **) aResult)); // does the addref + } + else + { + nsresult result = GetFirstNodeOfType(childNode, aTag, aResult); + if (nsnull!=*aResult) + return result; + } + } + nsCOMPtr xNode; + childNode->GetNextSibling(getter_AddRefs(xNode)); + childNode=xNode; + } + + return NS_ERROR_FAILURE; +} + nsresult @@ -387,6 +520,46 @@ nsEditor::GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode) return NS_OK; } +nsresult +nsEditor::ExecuteTransaction(nsITransaction *aTxn) +{ + nsresult result = NS_OK; + if (nsnull!=aTxn) + { + if (nsnull!=mTxnMgr) + { + result = mTxnMgr->Do(aTxn); + } + else + { + result = aTxn->Do(); + } + } + return result; +} + +nsresult +nsEditor::Undo() +{ + nsresult result = NS_OK; + if (nsnull!=mTxnMgr) + { + result = mTxnMgr->Undo(); + } + return result; +} + +nsresult +nsEditor::Redo() +{ + nsresult result = NS_OK; + if (nsnull!=mTxnMgr) + { + result = mTxnMgr->Redo(); + } + return result; +} + //END nsEditor Private methods diff --git a/mozilla/editor/core/editor.h b/mozilla/editor/core/editor.h index e1f599ef891..1ebec7a593d 100644 --- a/mozilla/editor/core/editor.h +++ b/mozilla/editor/core/editor.h @@ -23,6 +23,7 @@ #include "nsIDOMEventListener.h" #include "nsCOMPtr.h" #include "editorInterfaces.h" +#include "nsITransactionManager.h" //#include "nsISelection.h" @@ -42,6 +43,9 @@ private: nsCOMPtr mKeyListenerP; nsCOMPtr mMouseListenerP; // nsCOMPtr mSelectionP; + //nsCOMPtr mTxnMgrP; + nsITransactionManager * mTxnMgr; + public: /** The default constructor. This should suffice. the setting of the interfaces is done * after the construction of the editor class. @@ -66,10 +70,23 @@ public: virtual nsresult GetProperties(PROPERTIES **); + virtual nsresult SetAttribute(nsIDOMElement * aElement, + const nsString& aAttribute, + const nsString& aValue); + + virtual nsresult GetAttributeValue(nsIDOMElement * aElement, + const nsString& aAttribute, + nsString& aResultValue, + PRBool& aResultIsSet); + + virtual nsresult RemoveAttribute(nsIDOMElement *aElement, const nsString& aAttribute); + virtual nsresult InsertString(nsString *aString); virtual nsresult Commit(PRBool aCtrlKey); + + /*END nsIEditor interfaces*/ /*BEGIN nsEditor interfaces*/ @@ -112,6 +129,42 @@ public: */ nsresult GetFirstTextNode(nsIDOMNode *aNode, nsIDOMNode **aRetNode); + /** GetFirstNodeOfType ADDREFFS and will get the next available node from the passed + * in aStartNode parameter of type aTag. + * It can also return NS_ERROR_FAILURE if no such nodes are available + * @param nsIDOMNode *aStartNode is the node to start looking from + * @param nsIAtom *aTag is the type of node we are searching for + * @param nsIDOMNode **aResult is the node we found, or nsnull if there is none + */ + nsresult GetFirstNodeOfType(nsIDOMNode *aStartNode, const nsString &aTag, nsIDOMNode **aResult); + + /** ExecuteTransaction fires a transaction. It is provided here so + * clients need no knowledge of whether the editor has a transaction manager or not. + * If a transaction manager is present, it is used. + * Otherwise, the transaction is just executed directly. + * + * @param aTxn the transaction to execute + */ + nsresult ExecuteTransaction(nsITransaction *aTxn); + + /** Undo reverses the effects of the last ExecuteTransaction operation + * It is provided here so clients need no knowledge of whether the editor has a transaction manager or not. + * If a transaction manager is present, it is told to undo and the result of + * that undo is returned. + * Otherwise, the Undo request is ignored. + * + */ + nsresult Undo(); + + /** Redo reverses the effects of the last Undo operation + * It is provided here so clients need no knowledge of whether the editor has a transaction manager or not. + * If a transaction manager is present, it is told to redo and the result of + * that redo is returned. + * Otherwise, the Redo request is ignored. + * + */ + nsresult Redo(); + /*END private methods of nsEditor*/ }; diff --git a/mozilla/editor/core/editorInterfaces.cpp b/mozilla/editor/core/editorInterfaces.cpp index ff35b161e66..49a29cea8b6 100644 --- a/mozilla/editor/core/editorInterfaces.cpp +++ b/mozilla/editor/core/editorInterfaces.cpp @@ -18,7 +18,11 @@ #include "editorInterfaces.h" #include "nsString.h" #include "editor.h" +#include "ChangeAttributeTxn.h" #include "nsIDOMDocument.h" +#include "nsIDOMElement.h" + +static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); /* * nsEditorKeyListener implementation @@ -113,25 +117,30 @@ nsEditorKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) NS_SUCCEEDED(aKeyEvent->GetShiftKey(&isShift)) && NS_SUCCEEDED(aKeyEvent->GetCtrlKey(&ctrlKey)) ) { - switch(keyCode) { - case nsIDOMEvent::VK_BACK: - break; - case nsIDOMEvent::VK_RETURN: - // Need to implement creation of either

or
nodes. - mEditor->Commit(ctrlKey); - break; - default: - // XXX Replace with x-platform NS-virtkeycode transform. - if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) { - nsString* key = new nsString(); - *key += character; - if (!isShift) { - key->ToLowerCase(); + PRBool keyProcessed; + ProcessShortCutKeys(aKeyEvent, keyProcessed); + if (PR_FALSE==keyProcessed) + { + switch(keyCode) { + case nsIDOMEvent::VK_BACK: + break; + case nsIDOMEvent::VK_RETURN: + // Need to implement creation of either

or
nodes. + mEditor->Commit(ctrlKey); + break; + default: + // XXX Replace with x-platform NS-virtkeycode transform. + if (NS_OK == GetCharFromKeyCode(keyCode, isShift, & character)) { + nsString* key = new nsString(); + *key += character; + if (!isShift) { + key->ToLowerCase(); + } + mEditor->InsertString(key); + delete key; } - mEditor->InsertString(key); - delete key; + break; } - break; } } @@ -154,6 +163,90 @@ nsEditorKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) return NS_OK; } +nsresult +nsEditorKeyListener::ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed) +{ + aProcessed=PR_FALSE; + PRUint32 keyCode; + PRBool isShift; + PRBool ctrlKey; + + if (NS_SUCCEEDED(aKeyEvent->GetKeyCode(&keyCode)) && + NS_SUCCEEDED(aKeyEvent->GetShiftKey(&isShift)) && + NS_SUCCEEDED(aKeyEvent->GetCtrlKey(&ctrlKey)) + ) + { + // XXX: please please please get these mappings from an external source! + switch (keyCode) + { + // hard-coded undo + case nsIDOMEvent::VK_Z: + if (PR_TRUE==ctrlKey) + { + if (nsnull!=mEditor) + mEditor->Undo(); + } + aProcessed=PR_TRUE; + break; + + // hard-coded redo + case nsIDOMEvent::VK_Y: + if (PR_TRUE==ctrlKey) + { + if (nsnull!=mEditor) + mEditor->Redo(); + } + aProcessed=PR_TRUE; + break; + + case nsIDOMEvent::VK_TAB: + { + //XXX: should be from a factory + //XXX: should manage the refcount of txn + nsString attribute("width"); + nsString value("400"); + + nsString tableTag("TABLE"); + nsCOMPtr currentNode; + nsCOMPtr element; + if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode)))) + { + if (NS_SUCCEEDED(currentNode->QueryInterface(kIDOMElementIID, getter_AddRefs(element)))) + { + ChangeAttributeTxn *txn = new ChangeAttributeTxn(mEditor, element, attribute, value); + mEditor->ExecuteTransaction(txn); + } + } + } + aProcessed=PR_TRUE; + break; + + case nsIDOMEvent::VK_SPACE: + { + //XXX: should be from a factory + //XXX: should manage the refcount of txn + nsString attribute("height"); + nsString value("200"); + + nsString tableTag("TABLE"); + nsCOMPtr currentNode; + nsCOMPtr element; + if (NS_SUCCEEDED(mEditor->GetFirstNodeOfType(nsnull, tableTag, getter_AddRefs(currentNode)))) + { + if (NS_SUCCEEDED(currentNode->QueryInterface(kIDOMElementIID, getter_AddRefs(element)))) + { + ChangeAttributeTxn *txn = new ChangeAttributeTxn(mEditor, element, attribute, value); + mEditor->ExecuteTransaction(txn); + } + } + } + aProcessed=PR_TRUE; + break; + } + } + return NS_OK; +} + /* diff --git a/mozilla/editor/core/editorInterfaces.h b/mozilla/editor/core/editorInterfaces.h index dfb7a3a3926..a09fcf9800d 100644 --- a/mozilla/editor/core/editorInterfaces.h +++ b/mozilla/editor/core/editorInterfaces.h @@ -65,6 +65,7 @@ public: /*END interfaces from nsIDOMKeyListener*/ private: virtual nsresult GetCharFromKeyCode(PRUint32 aKeyCode, PRBool aIsShift, char *aChar); + virtual nsresult ProcessShortCutKeys(nsIDOMEvent* aKeyEvent, PRBool& aProcessed); };