Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "JoinNodeTransaction.h"
7 :
8 : #include "mozilla/EditorBase.h" // for EditorBase
9 : #include "nsAString.h"
10 : #include "nsDebug.h" // for NS_ASSERTION, etc.
11 : #include "nsError.h" // for NS_ERROR_NULL_POINTER, etc.
12 : #include "nsIContent.h" // for nsIContent
13 : #include "nsIDOMCharacterData.h" // for nsIDOMCharacterData
14 : #include "nsIEditor.h" // for EditorBase::IsModifiableNode
15 : #include "nsISupportsImpl.h" // for QueryInterface, etc.
16 :
17 : namespace mozilla {
18 :
19 : using namespace dom;
20 :
21 0 : JoinNodeTransaction::JoinNodeTransaction(EditorBase& aEditorBase,
22 : nsINode& aLeftNode,
23 0 : nsINode& aRightNode)
24 : : mEditorBase(&aEditorBase)
25 : , mLeftNode(&aLeftNode)
26 : , mRightNode(&aRightNode)
27 0 : , mOffset(0)
28 : {
29 0 : }
30 :
31 0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(JoinNodeTransaction, EditTransactionBase,
32 : mEditorBase,
33 : mLeftNode,
34 : mRightNode,
35 : mParent)
36 :
37 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(JoinNodeTransaction)
38 0 : NS_INTERFACE_MAP_END_INHERITING(EditTransactionBase)
39 :
40 : bool
41 0 : JoinNodeTransaction::CanDoIt() const
42 : {
43 0 : if (NS_WARN_IF(!mLeftNode) ||
44 0 : NS_WARN_IF(!mRightNode) ||
45 0 : NS_WARN_IF(!mEditorBase) ||
46 0 : !mLeftNode->GetParentNode()) {
47 0 : return false;
48 : }
49 0 : return mEditorBase->IsModifiableNode(mLeftNode->GetParentNode());
50 : }
51 :
52 : // After DoTransaction() and RedoTransaction(), the left node is removed from
53 : // the content tree and right node remains.
54 : NS_IMETHODIMP
55 0 : JoinNodeTransaction::DoTransaction()
56 : {
57 0 : if (NS_WARN_IF(!mEditorBase) ||
58 0 : NS_WARN_IF(!mLeftNode) ||
59 0 : NS_WARN_IF(!mRightNode)) {
60 0 : return NS_ERROR_NOT_INITIALIZED;
61 : }
62 :
63 : // Get the parent node
64 0 : nsCOMPtr<nsINode> leftParent = mLeftNode->GetParentNode();
65 0 : NS_ENSURE_TRUE(leftParent, NS_ERROR_NULL_POINTER);
66 :
67 : // Verify that mLeftNode and mRightNode have the same parent
68 0 : if (leftParent != mRightNode->GetParentNode()) {
69 0 : NS_ASSERTION(false, "Nodes do not have same parent");
70 0 : return NS_ERROR_INVALID_ARG;
71 : }
72 :
73 : // Set this instance's mParent. Other methods will see a non-null mParent
74 : // and know all is well
75 0 : mParent = leftParent;
76 0 : mOffset = mLeftNode->Length();
77 :
78 0 : return mEditorBase->JoinNodesImpl(mRightNode, mLeftNode, mParent);
79 : }
80 :
81 : //XXX: What if instead of split, we just deleted the unneeded children of
82 : // mRight and re-inserted mLeft?
83 : NS_IMETHODIMP
84 0 : JoinNodeTransaction::UndoTransaction()
85 : {
86 0 : if (NS_WARN_IF(!mParent) ||
87 0 : NS_WARN_IF(!mLeftNode) ||
88 0 : NS_WARN_IF(!mRightNode)) {
89 0 : return NS_ERROR_NOT_INITIALIZED;
90 : }
91 :
92 : // First, massage the existing node so it is in its post-split state
93 0 : ErrorResult rv;
94 0 : if (mRightNode->GetAsText()) {
95 0 : rv = mRightNode->GetAsText()->DeleteData(0, mOffset);
96 : } else {
97 0 : nsCOMPtr<nsIContent> child = mRightNode->GetFirstChild();
98 0 : for (uint32_t i = 0; i < mOffset; i++) {
99 0 : if (rv.Failed()) {
100 0 : return rv.StealNSResult();
101 : }
102 0 : if (!child) {
103 0 : return NS_ERROR_NULL_POINTER;
104 : }
105 0 : nsCOMPtr<nsIContent> nextSibling = child->GetNextSibling();
106 0 : mLeftNode->AppendChild(*child, rv);
107 0 : child = nextSibling;
108 : }
109 : }
110 : // Second, re-insert the left node into the tree
111 0 : nsCOMPtr<nsINode> refNode = mRightNode;
112 0 : mParent->InsertBefore(*mLeftNode, refNode, rv);
113 0 : return rv.StealNSResult();
114 : }
115 :
116 : NS_IMETHODIMP
117 0 : JoinNodeTransaction::GetTxnDescription(nsAString& aString)
118 : {
119 0 : aString.AssignLiteral("JoinNodeTransaction");
120 0 : return NS_OK;
121 : }
122 :
123 : } // namespace mozilla
|