1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/base/JoinElementTxn.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,122 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include <stdio.h> // for printf 1.10 + 1.11 +#include "JoinElementTxn.h" 1.12 +#include "nsAString.h" 1.13 +#include "nsDebug.h" // for NS_ASSERTION, etc 1.14 +#include "nsEditor.h" // for nsEditor 1.15 +#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc 1.16 +#include "nsIDOMCharacterData.h" // for nsIDOMCharacterData 1.17 +#include "nsIEditor.h" // for nsEditor::IsModifiableNode 1.18 +#include "nsINode.h" // for nsINode 1.19 +#include "nsISupportsImpl.h" // for EditTxn::QueryInterface, etc 1.20 + 1.21 +JoinElementTxn::JoinElementTxn() 1.22 + : EditTxn() 1.23 +{ 1.24 +} 1.25 + 1.26 +NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinElementTxn, EditTxn, 1.27 + mLeftNode, 1.28 + mRightNode, 1.29 + mParent) 1.30 + 1.31 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinElementTxn) 1.32 +NS_INTERFACE_MAP_END_INHERITING(EditTxn) 1.33 + 1.34 +NS_IMETHODIMP JoinElementTxn::Init(nsEditor *aEditor, 1.35 + nsIDOMNode *aLeftNode, 1.36 + nsIDOMNode *aRightNode) 1.37 +{ 1.38 + NS_PRECONDITION((aEditor && aLeftNode && aRightNode), "null arg"); 1.39 + if (!aEditor || !aLeftNode || !aRightNode) { return NS_ERROR_NULL_POINTER; } 1.40 + mEditor = aEditor; 1.41 + mLeftNode = do_QueryInterface(aLeftNode); 1.42 + nsCOMPtr<nsIDOMNode>leftParent; 1.43 + nsresult result = mLeftNode->GetParentNode(getter_AddRefs(leftParent)); 1.44 + NS_ENSURE_SUCCESS(result, result); 1.45 + if (!mEditor->IsModifiableNode(leftParent)) { 1.46 + return NS_ERROR_FAILURE; 1.47 + } 1.48 + mRightNode = do_QueryInterface(aRightNode); 1.49 + mOffset = 0; 1.50 + return NS_OK; 1.51 +} 1.52 + 1.53 +// After DoTransaction() and RedoTransaction(), the left node is removed from the content tree and right node remains. 1.54 +NS_IMETHODIMP JoinElementTxn::DoTransaction(void) 1.55 +{ 1.56 + NS_PRECONDITION((mEditor && mLeftNode && mRightNode), "null arg"); 1.57 + if (!mEditor || !mLeftNode || !mRightNode) { return NS_ERROR_NOT_INITIALIZED; } 1.58 + 1.59 + // get the parent node 1.60 + nsCOMPtr<nsIDOMNode> leftParent; 1.61 + mLeftNode->GetParentNode(getter_AddRefs(leftParent)); 1.62 + NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER); 1.63 + 1.64 + // verify that mLeftNode and mRightNode have the same parent 1.65 + nsCOMPtr<nsIDOMNode> rightParent; 1.66 + mRightNode->GetParentNode(getter_AddRefs(rightParent)); 1.67 + NS_ENSURE_TRUE(rightParent, NS_ERROR_NULL_POINTER); 1.68 + 1.69 + if (leftParent != rightParent) { 1.70 + NS_ASSERTION(false, "2 nodes do not have same parent"); 1.71 + return NS_ERROR_INVALID_ARG; 1.72 + } 1.73 + 1.74 + // set this instance mParent. 1.75 + // Other methods will see a non-null mParent and know all is well 1.76 + mParent = leftParent; 1.77 + nsCOMPtr<nsINode> leftNode = do_QueryInterface(mLeftNode); 1.78 + nsCOMPtr<nsINode> rightNode = do_QueryInterface(mRightNode); 1.79 + nsCOMPtr<nsINode> parent = do_QueryInterface(mParent); 1.80 + NS_ENSURE_TRUE(leftNode && rightNode && parent, NS_ERROR_FAILURE); 1.81 + mOffset = leftNode->Length(); 1.82 + 1.83 + return mEditor->JoinNodesImpl(rightNode, leftNode, parent); 1.84 +} 1.85 + 1.86 +//XXX: what if instead of split, we just deleted the unneeded children of mRight 1.87 +// and re-inserted mLeft? 1.88 +NS_IMETHODIMP JoinElementTxn::UndoTransaction(void) 1.89 +{ 1.90 + NS_ASSERTION(mRightNode && mLeftNode && mParent, "bad state"); 1.91 + if (!mRightNode || !mLeftNode || !mParent) { return NS_ERROR_NOT_INITIALIZED; } 1.92 + nsresult result; 1.93 + nsCOMPtr<nsIDOMNode>resultNode; 1.94 + // first, massage the existing node so it is in its post-split state 1.95 + nsCOMPtr<nsIDOMCharacterData>rightNodeAsText = do_QueryInterface(mRightNode); 1.96 + if (rightNodeAsText) 1.97 + { 1.98 + result = rightNodeAsText->DeleteData(0, mOffset); 1.99 + } 1.100 + else 1.101 + { 1.102 + nsCOMPtr<nsIDOMNode>child; 1.103 + result = mRightNode->GetFirstChild(getter_AddRefs(child)); 1.104 + nsCOMPtr<nsIDOMNode>nextSibling; 1.105 + uint32_t i; 1.106 + for (i=0; i<mOffset; i++) 1.107 + { 1.108 + if (NS_FAILED(result)) {return result;} 1.109 + if (!child) {return NS_ERROR_NULL_POINTER;} 1.110 + child->GetNextSibling(getter_AddRefs(nextSibling)); 1.111 + result = mLeftNode->AppendChild(child, getter_AddRefs(resultNode)); 1.112 + child = do_QueryInterface(nextSibling); 1.113 + } 1.114 + } 1.115 + // second, re-insert the left node into the tree 1.116 + result = mParent->InsertBefore(mLeftNode, mRightNode, getter_AddRefs(resultNode)); 1.117 + return result; 1.118 + 1.119 +} 1.120 + 1.121 +NS_IMETHODIMP JoinElementTxn::GetTxnDescription(nsAString& aString) 1.122 +{ 1.123 + aString.AssignLiteral("JoinElementTxn"); 1.124 + return NS_OK; 1.125 +}