caught up to new ScrollIntoView changes.
most transactions now properly set selection after modifying content, for Do, Undo, Redo. lots of cleanup and minor bug fixes. git-svn-id: svn://10.0.0.236/trunk@21466 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -17,21 +17,25 @@
|
||||
*/
|
||||
|
||||
#include "CreateElementTxn.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
CreateElementTxn::CreateElementTxn()
|
||||
: EditTxn()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
||||
nsresult CreateElementTxn::Init(nsIEditor *aEditor,
|
||||
const nsString& aTag,
|
||||
nsIDOMNode *aParent,
|
||||
PRUint32 aOffsetInParent)
|
||||
{
|
||||
if ((nsnull!=aDoc) && (nsnull!=aParent))
|
||||
NS_ASSERTION(aEditor&&aParent, "null args");
|
||||
if (aEditor && aParent)
|
||||
{
|
||||
mDoc = do_QueryInterface(aDoc);
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
mTag = aTag;
|
||||
mParent = do_QueryInterface(aParent);
|
||||
mOffsetInParent = aOffsetInParent;
|
||||
@@ -57,28 +61,50 @@ CreateElementTxn::~CreateElementTxn()
|
||||
|
||||
nsresult CreateElementTxn::Do(void)
|
||||
{
|
||||
// create a new node
|
||||
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||
|
||||
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||
NS_ASSERTION(mEditor, "bad state -- null editor");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (mEditor)
|
||||
{
|
||||
// insert the new node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||
// create a new node
|
||||
nsCOMPtr<nsIDOMDocument>doc;
|
||||
result = mEditor->GetDocument(getter_AddRefs(doc));
|
||||
if ((NS_SUCCEEDED(result)) && (doc))
|
||||
{
|
||||
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
result = doc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||
{
|
||||
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||
// insert the new node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||
{
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||
{
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +116,19 @@ nsresult CreateElementTxn::Undo(void)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mRefNode, mParent, offset);
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -97,6 +136,19 @@ nsresult CreateElementTxn::Redo(void)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsresult selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define CreateElementTxn_h__
|
||||
|
||||
#include "EditTxn.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@@ -40,13 +40,13 @@ public:
|
||||
enum { eAppend=-1 };
|
||||
|
||||
/** Initialize the transaction.
|
||||
* @param aDoc the document containing aParent
|
||||
* @param aEditor the provider of basic editing functionality
|
||||
* @param aTag the tag (P, HR, TABLE, etc.) for the new element
|
||||
* @param aParent the node into which the new element will be inserted
|
||||
* @param aOffsetInParent the location in aParent to insert the new element
|
||||
* if eAppend, the new element is appended as the last child
|
||||
*/
|
||||
virtual nsresult Init(nsIDOMDocument *aDoc,
|
||||
virtual nsresult Init(nsIEditor *aEditor,
|
||||
const nsString& aTag,
|
||||
nsIDOMNode *aParent,
|
||||
PRUint32 aOffsetInParent);
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
protected:
|
||||
|
||||
/** the document into which the new node will be inserted */
|
||||
nsCOMPtr<nsIDOMDocument> mDoc;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
/** the tag (mapping to object type) for the new element */
|
||||
nsString mTag;
|
||||
|
||||
@@ -231,7 +231,12 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||
if (nsnull!=txn)
|
||||
{
|
||||
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
|
||||
PRInt32 numToDel;
|
||||
if (aStartOffset==aEndOffset)
|
||||
numToDel = 1;
|
||||
else
|
||||
numToDel = aEndOffset-aStartOffset;
|
||||
txn->Init(mEditor, textNode, aStartOffset, numToDel);
|
||||
AppendChild(txn);
|
||||
}
|
||||
}
|
||||
@@ -293,7 +298,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||
if (nsnull!=txn)
|
||||
{
|
||||
txn->Init(textNode, start, numToDelete);
|
||||
txn->Init(mEditor, textNode, start, numToDelete);
|
||||
AppendChild(txn);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "DeleteTextTxn.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
|
||||
|
||||
DeleteTextTxn::DeleteTextTxn()
|
||||
@@ -25,10 +26,13 @@ DeleteTextTxn::DeleteTextTxn()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||
nsresult DeleteTextTxn::Init(nsIEditor *aEditor,
|
||||
nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aNumCharsToDelete)
|
||||
{
|
||||
NS_ASSERTION(aEditor&&aElement, "bad arg");
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mOffset = aOffset;
|
||||
mNumCharsToDelete = aNumCharsToDelete;
|
||||
@@ -38,15 +42,49 @@ nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||
|
||||
nsresult DeleteTextTxn::Do(void)
|
||||
{
|
||||
// get the text that we're about to delete
|
||||
nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
|
||||
return (mElement->DeleteData(mOffset, mNumCharsToDelete));
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (mEditor && mElement)
|
||||
{
|
||||
// get the text that we're about to delete
|
||||
result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
|
||||
result = mElement->DeleteData(mOffset, mNumCharsToDelete);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
selectionResult = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//XXX: we may want to store the selection state and restore it properly
|
||||
// was it an insertion point or an extended selection?
|
||||
nsresult DeleteTextTxn::Undo(void)
|
||||
{
|
||||
return (mElement->InsertData(mOffset, mDeletedText));
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (mEditor && mElement)
|
||||
{
|
||||
result = mElement->InsertData(mOffset, mDeletedText);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
selectionResult = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define DeleteTextTxn_h__
|
||||
|
||||
#include "EditTxn.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
@@ -36,11 +37,13 @@ class DeleteTextTxn : public EditTxn
|
||||
public:
|
||||
|
||||
/** initialize the transaction.
|
||||
* @param aEditor the provider of basic editing operations
|
||||
* @param aElement the content node to remove text from
|
||||
* @param aOffset the location in aElement to begin the deletion
|
||||
* @param aNumCharsToDelete the number of characters to delete. Not the number of bytes!
|
||||
*/
|
||||
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||
virtual nsresult Init(nsIEditor *aEditor,
|
||||
nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aNumCharsToDelete);
|
||||
|
||||
@@ -62,7 +65,10 @@ public:
|
||||
virtual nsresult GetRedoString(nsString **aString);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/** the provider of basic editing operations */
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
/** the text element to operate upon */
|
||||
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||
|
||||
|
||||
@@ -113,8 +113,12 @@ nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction
|
||||
if (nsnull!=mChildren)
|
||||
{
|
||||
PRInt32 count = mChildren->Count();
|
||||
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
|
||||
result = txn->Merge(aDidMerge, aTransaction);
|
||||
NS_ASSERTION(count>0, "bad count");
|
||||
if (0<count)
|
||||
{
|
||||
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
|
||||
result = txn->Merge(aDidMerge, aTransaction);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
|
||||
@@ -56,16 +56,18 @@ nsresult InsertTextTxn::Do(void)
|
||||
{
|
||||
// advance caret: This requires the presentation shell to get the selection.
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult res = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
selection->StartBatchChanges();
|
||||
res = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
res = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
|
||||
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
NS_ASSERTION(selection,"Could not get selection in InsertTextTxn::Do\n");
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
result = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(PR_FALSE,"Could not get selection in InsertTextTxn::Do\n");
|
||||
selection->EndBatchChanges();
|
||||
return res;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult InsertTextTxn::Undo(void)
|
||||
@@ -77,8 +79,11 @@ nsresult InsertTextTxn::Undo(void)
|
||||
{ // set the selection to the insertion point where the string was removed
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -711,7 +711,7 @@ nsresult nsEditor::CreateTxnForCreateElement(const nsString& aTag,
|
||||
{
|
||||
result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)aTxn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = (*aTxn)->Init(mDoc, aTag, aParent, aPosition);
|
||||
result = (*aTxn)->Init(this, aTag, aParent, aPosition);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -866,7 +866,7 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement,
|
||||
{
|
||||
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)aTxn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = (*aTxn)->Init(aElement, aOffset, aLength);
|
||||
result = (*aTxn)->Init(this, aElement, aOffset, aLength);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1486,6 +1486,40 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
{
|
||||
NS_ASSERTION((aChild && aParent), "bad args");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aChild && aParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
PRInt32 i=0;
|
||||
for ( ; NS_SUCCEEDED(result); i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (childNode.get()==aChild)
|
||||
{
|
||||
aOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!childNode)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
else if (!childNodes)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ public:
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst)=0;
|
||||
|
||||
static nsresult GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "nsTextEditor.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
#include "nsEditorEventListeners.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
@@ -167,9 +168,6 @@ nsresult nsTextEditor::InsertText(const nsString& aStringToInsert)
|
||||
if (mEditor)
|
||||
{
|
||||
result = mEditor->InsertText(aStringToInsert);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mEditor->ScrollIntoView(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -207,7 +205,7 @@ nsresult nsTextEditor::InsertBreak(PRBool aCtrlKey)
|
||||
result = node->GetParentNode(getter_AddRefs(parentNode));
|
||||
result = mEditor->SplitNode(node, offset);
|
||||
// now get the node's offset in it's parent, and insert the new BR there
|
||||
result = GetChildOffset(node, parentNode, offset);
|
||||
result = nsIEditorSupport::GetChildOffset(node, parentNode, offset);
|
||||
nsAutoString tag("BR");
|
||||
result = mEditor->CreateNode(tag, parentNode, offset);
|
||||
selection->Collapse(parentNode, offset);
|
||||
@@ -232,12 +230,8 @@ nsresult nsTextEditor::EnableUndo(PRBool aEnable)
|
||||
nsresult nsTextEditor::Undo(PRUint32 aCount)
|
||||
{
|
||||
nsresult result=NS_ERROR_NOT_INITIALIZED;
|
||||
if (mEditor)
|
||||
{
|
||||
if (mEditor) {
|
||||
result = mEditor->Undo(aCount);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mEditor->ScrollIntoView(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -258,9 +252,6 @@ nsresult nsTextEditor::Redo(PRUint32 aCount)
|
||||
if (mEditor)
|
||||
{
|
||||
result = mEditor->Redo(aCount);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
mEditor->ScrollIntoView(PR_TRUE);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -440,37 +431,3 @@ nsTextEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
}
|
||||
|
||||
|
||||
// utility methods
|
||||
|
||||
nsresult nsTextEditor::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
{
|
||||
NS_ASSERTION((aChild && aParent), "bad args");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aChild && aParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
PRInt32 i=0;
|
||||
for ( ; NS_SUCCEEDED(result); i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (childNode.get()==aChild)
|
||||
{
|
||||
aOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!childNode)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
else if (!childNodes)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -77,10 +77,6 @@ public:
|
||||
virtual nsresult OutputText(nsIOutputStream *aOutputStream);
|
||||
virtual nsresult OutputHTML(nsIOutputStream *aOutputStream);
|
||||
|
||||
// Utility methods
|
||||
protected:
|
||||
virtual nsresult GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset);
|
||||
|
||||
// Data members
|
||||
protected:
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
@@ -17,21 +17,25 @@
|
||||
*/
|
||||
|
||||
#include "CreateElementTxn.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
#include "nsIEditorSupport.h"
|
||||
|
||||
CreateElementTxn::CreateElementTxn()
|
||||
: EditTxn()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult CreateElementTxn::Init(nsIDOMDocument *aDoc,
|
||||
nsresult CreateElementTxn::Init(nsIEditor *aEditor,
|
||||
const nsString& aTag,
|
||||
nsIDOMNode *aParent,
|
||||
PRUint32 aOffsetInParent)
|
||||
{
|
||||
if ((nsnull!=aDoc) && (nsnull!=aParent))
|
||||
NS_ASSERTION(aEditor&&aParent, "null args");
|
||||
if (aEditor && aParent)
|
||||
{
|
||||
mDoc = do_QueryInterface(aDoc);
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
mTag = aTag;
|
||||
mParent = do_QueryInterface(aParent);
|
||||
mOffsetInParent = aOffsetInParent;
|
||||
@@ -57,28 +61,50 @@ CreateElementTxn::~CreateElementTxn()
|
||||
|
||||
nsresult CreateElementTxn::Do(void)
|
||||
{
|
||||
// create a new node
|
||||
nsresult result = mDoc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||
|
||||
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||
NS_ASSERTION(mEditor, "bad state -- null editor");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (mEditor)
|
||||
{
|
||||
// insert the new node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||
// create a new node
|
||||
nsCOMPtr<nsIDOMDocument>doc;
|
||||
result = mEditor->GetDocument(getter_AddRefs(doc));
|
||||
if ((NS_SUCCEEDED(result)) && (doc))
|
||||
{
|
||||
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
result = doc->CreateElement(mTag, getter_AddRefs(mNewNode));
|
||||
NS_ASSERTION(((NS_SUCCEEDED(result)) && (mNewNode)), "could not create element.");
|
||||
if ((NS_SUCCEEDED(result)) && (mNewNode))
|
||||
{
|
||||
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||
// insert the new node
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
if (CreateElementTxn::eAppend==mOffsetInParent)
|
||||
{
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
result = mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = mParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
result = childNodes->Item(mOffsetInParent, getter_AddRefs(mRefNode));
|
||||
if ((NS_SUCCEEDED(result)) && (mRefNode))
|
||||
{
|
||||
result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,6 +116,19 @@ nsresult CreateElementTxn::Undo(void)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mRefNode, mParent, offset);
|
||||
selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -97,6 +136,19 @@ nsresult CreateElementTxn::Redo(void)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> resultNode;
|
||||
nsresult result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
PRInt32 offset=0;
|
||||
nsIEditorSupport::GetChildOffset(mNewNode, mParent, offset);
|
||||
nsresult selectionResult = selection->Collapse(mParent, offset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#define CreateElementTxn_h__
|
||||
|
||||
#include "EditTxn.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@@ -40,13 +40,13 @@ public:
|
||||
enum { eAppend=-1 };
|
||||
|
||||
/** Initialize the transaction.
|
||||
* @param aDoc the document containing aParent
|
||||
* @param aEditor the provider of basic editing functionality
|
||||
* @param aTag the tag (P, HR, TABLE, etc.) for the new element
|
||||
* @param aParent the node into which the new element will be inserted
|
||||
* @param aOffsetInParent the location in aParent to insert the new element
|
||||
* if eAppend, the new element is appended as the last child
|
||||
*/
|
||||
virtual nsresult Init(nsIDOMDocument *aDoc,
|
||||
virtual nsresult Init(nsIEditor *aEditor,
|
||||
const nsString& aTag,
|
||||
nsIDOMNode *aParent,
|
||||
PRUint32 aOffsetInParent);
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
protected:
|
||||
|
||||
/** the document into which the new node will be inserted */
|
||||
nsCOMPtr<nsIDOMDocument> mDoc;
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
/** the tag (mapping to object type) for the new element */
|
||||
nsString mTag;
|
||||
|
||||
@@ -231,7 +231,12 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteBetween(nsIDOMNode *aStartParent,
|
||||
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||
if (nsnull!=txn)
|
||||
{
|
||||
txn->Init(textNode, aStartOffset, (aEndOffset-aStartOffset)+1);
|
||||
PRInt32 numToDel;
|
||||
if (aStartOffset==aEndOffset)
|
||||
numToDel = 1;
|
||||
else
|
||||
numToDel = aEndOffset-aStartOffset;
|
||||
txn->Init(mEditor, textNode, aStartOffset, numToDel);
|
||||
AppendChild(txn);
|
||||
}
|
||||
}
|
||||
@@ -293,7 +298,7 @@ nsresult DeleteRangeTxn::CreateTxnsToDeleteContent(nsIDOMNode *aParent,
|
||||
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)&txn);
|
||||
if (nsnull!=txn)
|
||||
{
|
||||
txn->Init(textNode, start, numToDelete);
|
||||
txn->Init(mEditor, textNode, start, numToDelete);
|
||||
AppendChild(txn);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "DeleteTextTxn.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsIDOMSelection.h"
|
||||
|
||||
|
||||
DeleteTextTxn::DeleteTextTxn()
|
||||
@@ -25,10 +26,13 @@ DeleteTextTxn::DeleteTextTxn()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||
nsresult DeleteTextTxn::Init(nsIEditor *aEditor,
|
||||
nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aNumCharsToDelete)
|
||||
{
|
||||
NS_ASSERTION(aEditor&&aElement, "bad arg");
|
||||
mEditor = do_QueryInterface(aEditor);
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mOffset = aOffset;
|
||||
mNumCharsToDelete = aNumCharsToDelete;
|
||||
@@ -38,15 +42,49 @@ nsresult DeleteTextTxn::Init(nsIDOMCharacterData *aElement,
|
||||
|
||||
nsresult DeleteTextTxn::Do(void)
|
||||
{
|
||||
// get the text that we're about to delete
|
||||
nsresult result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
|
||||
return (mElement->DeleteData(mOffset, mNumCharsToDelete));
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (mEditor && mElement)
|
||||
{
|
||||
// get the text that we're about to delete
|
||||
result = mElement->SubstringData(mOffset, mNumCharsToDelete, mDeletedText);
|
||||
NS_ASSERTION(NS_SUCCEEDED(result), "could not get text to delete.");
|
||||
result = mElement->DeleteData(mOffset, mNumCharsToDelete);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
selectionResult = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//XXX: we may want to store the selection state and restore it properly
|
||||
// was it an insertion point or an extended selection?
|
||||
nsresult DeleteTextTxn::Undo(void)
|
||||
{
|
||||
return (mElement->InsertData(mOffset, mDeletedText));
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (mEditor && mElement)
|
||||
{
|
||||
result = mElement->InsertData(mOffset, mDeletedText);
|
||||
if (NS_SUCCEEDED(result))
|
||||
{
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult selectionResult = mEditor->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(selectionResult) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
selectionResult = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(selectionResult)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult DeleteTextTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction)
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define DeleteTextTxn_h__
|
||||
|
||||
#include "EditTxn.h"
|
||||
#include "nsIEditor.h"
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
@@ -36,11 +37,13 @@ class DeleteTextTxn : public EditTxn
|
||||
public:
|
||||
|
||||
/** initialize the transaction.
|
||||
* @param aEditor the provider of basic editing operations
|
||||
* @param aElement the content node to remove text from
|
||||
* @param aOffset the location in aElement to begin the deletion
|
||||
* @param aNumCharsToDelete the number of characters to delete. Not the number of bytes!
|
||||
*/
|
||||
virtual nsresult Init(nsIDOMCharacterData *aElement,
|
||||
virtual nsresult Init(nsIEditor *aEditor,
|
||||
nsIDOMCharacterData *aElement,
|
||||
PRUint32 aOffset,
|
||||
PRUint32 aNumCharsToDelete);
|
||||
|
||||
@@ -62,7 +65,10 @@ public:
|
||||
virtual nsresult GetRedoString(nsString **aString);
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
/** the provider of basic editing operations */
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
/** the text element to operate upon */
|
||||
nsCOMPtr<nsIDOMCharacterData> mElement;
|
||||
|
||||
|
||||
@@ -113,8 +113,12 @@ nsresult EditAggregateTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransaction
|
||||
if (nsnull!=mChildren)
|
||||
{
|
||||
PRInt32 count = mChildren->Count();
|
||||
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
|
||||
result = txn->Merge(aDidMerge, aTransaction);
|
||||
NS_ASSERTION(count>0, "bad count");
|
||||
if (0<count)
|
||||
{
|
||||
EditTxn *txn = (EditTxn*)(mChildren->ElementAt(count-1));
|
||||
result = txn->Merge(aDidMerge, aTransaction);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
|
||||
@@ -56,16 +56,18 @@ nsresult InsertTextTxn::Do(void)
|
||||
{
|
||||
// advance caret: This requires the presentation shell to get the selection.
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
nsresult res = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
selection->StartBatchChanges();
|
||||
res = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_SUCCEEDED(res)) {
|
||||
res = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
|
||||
nsresult result = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
NS_ASSERTION(selection,"Could not get selection in InsertTextTxn::Do\n");
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
result = mElement->InsertData(mOffset, mStringToInsert);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = selection->Collapse(mElement, mOffset+mStringToInsert.Length());
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
|
||||
}
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
else
|
||||
NS_ASSERTION(PR_FALSE,"Could not get selection in InsertTextTxn::Do\n");
|
||||
selection->EndBatchChanges();
|
||||
return res;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult InsertTextTxn::Undo(void)
|
||||
@@ -77,8 +79,11 @@ nsresult InsertTextTxn::Undo(void)
|
||||
{ // set the selection to the insertion point where the string was removed
|
||||
nsCOMPtr<nsIDOMSelection> selection;
|
||||
result = mPresShell->GetSelection(getter_AddRefs(selection));
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (NS_SUCCEEDED(result) && selection) {
|
||||
selection->StartBatchChanges();
|
||||
result = selection->Collapse(mElement, mOffset);
|
||||
NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after undo of insert.");
|
||||
selection->EndBatchChanges();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -711,7 +711,7 @@ nsresult nsEditor::CreateTxnForCreateElement(const nsString& aTag,
|
||||
{
|
||||
result = TransactionFactory::GetNewTransaction(kCreateElementTxnIID, (EditTxn **)aTxn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = (*aTxn)->Init(mDoc, aTag, aParent, aPosition);
|
||||
result = (*aTxn)->Init(this, aTag, aParent, aPosition);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -866,7 +866,7 @@ nsresult nsEditor::CreateTxnForDeleteText(nsIDOMCharacterData *aElement,
|
||||
{
|
||||
result = TransactionFactory::GetNewTransaction(kDeleteTextTxnIID, (EditTxn **)aTxn);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = (*aTxn)->Init(aElement, aOffset, aLength);
|
||||
result = (*aTxn)->Init(this, aElement, aOffset, aLength);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@@ -1486,6 +1486,40 @@ nsEditor::JoinNodesImpl(nsIDOMNode * aNodeToKeep,
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult nsIEditorSupport::GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset)
|
||||
{
|
||||
NS_ASSERTION((aChild && aParent), "bad args");
|
||||
nsresult result = NS_ERROR_NULL_POINTER;
|
||||
if (aChild && aParent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
result = aParent->GetChildNodes(getter_AddRefs(childNodes));
|
||||
if ((NS_SUCCEEDED(result)) && (childNodes))
|
||||
{
|
||||
PRInt32 i=0;
|
||||
for ( ; NS_SUCCEEDED(result); i++)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
result = childNodes->Item(i, getter_AddRefs(childNode));
|
||||
if ((NS_SUCCEEDED(result)) && (childNode))
|
||||
{
|
||||
if (childNode.get()==aChild)
|
||||
{
|
||||
aOffset = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!childNode)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
}
|
||||
else if (!childNodes)
|
||||
result = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//END nsEditor Private methods
|
||||
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ public:
|
||||
nsIDOMNode *aNodeToJoin,
|
||||
nsIDOMNode *aParent,
|
||||
PRBool aNodeToKeepIsFirst)=0;
|
||||
|
||||
static nsresult GetChildOffset(nsIDOMNode *aChild, nsIDOMNode *aParent, PRInt32 &aOffset);
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user