|
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 "DeleteNodeTxn.h" |
|
7 #include "nsDebug.h" |
|
8 #include "nsEditor.h" |
|
9 #include "nsError.h" |
|
10 #include "nsSelectionState.h" // nsRangeUpdater |
|
11 #include "nsAString.h" |
|
12 |
|
13 using namespace mozilla; |
|
14 |
|
15 DeleteNodeTxn::DeleteNodeTxn() |
|
16 : EditTxn(), mNode(), mParent(), mRefNode(), mRangeUpdater(nullptr) |
|
17 { |
|
18 } |
|
19 |
|
20 NS_IMPL_CYCLE_COLLECTION_INHERITED(DeleteNodeTxn, EditTxn, |
|
21 mNode, |
|
22 mParent, |
|
23 mRefNode) |
|
24 |
|
25 NS_IMPL_ADDREF_INHERITED(DeleteNodeTxn, EditTxn) |
|
26 NS_IMPL_RELEASE_INHERITED(DeleteNodeTxn, EditTxn) |
|
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DeleteNodeTxn) |
|
28 NS_INTERFACE_MAP_END_INHERITING(EditTxn) |
|
29 |
|
30 nsresult |
|
31 DeleteNodeTxn::Init(nsEditor* aEditor, nsINode* aNode, |
|
32 nsRangeUpdater* aRangeUpdater) |
|
33 { |
|
34 NS_ENSURE_TRUE(aEditor && aNode, NS_ERROR_NULL_POINTER); |
|
35 mEditor = aEditor; |
|
36 mNode = aNode; |
|
37 mParent = aNode->GetParentNode(); |
|
38 |
|
39 // do nothing if the node has a parent and it's read-only |
|
40 NS_ENSURE_TRUE(!mParent || mEditor->IsModifiableNode(mParent), |
|
41 NS_ERROR_FAILURE); |
|
42 |
|
43 mRangeUpdater = aRangeUpdater; |
|
44 return NS_OK; |
|
45 } |
|
46 |
|
47 |
|
48 NS_IMETHODIMP |
|
49 DeleteNodeTxn::DoTransaction() |
|
50 { |
|
51 NS_ENSURE_TRUE(mNode, NS_ERROR_NOT_INITIALIZED); |
|
52 |
|
53 if (!mParent) { |
|
54 // this is a no-op, there's no parent to delete mNode from |
|
55 return NS_OK; |
|
56 } |
|
57 |
|
58 // remember which child mNode was (by remembering which child was next); |
|
59 // mRefNode can be null |
|
60 mRefNode = mNode->GetNextSibling(); |
|
61 |
|
62 // give range updater a chance. SelAdjDeleteNode() needs to be called |
|
63 // *before* we do the action, unlike some of the other nsRangeStore update |
|
64 // methods. |
|
65 if (mRangeUpdater) { |
|
66 mRangeUpdater->SelAdjDeleteNode(mNode->AsDOMNode()); |
|
67 } |
|
68 |
|
69 ErrorResult error; |
|
70 mParent->RemoveChild(*mNode, error); |
|
71 return error.ErrorCode(); |
|
72 } |
|
73 |
|
74 NS_IMETHODIMP |
|
75 DeleteNodeTxn::UndoTransaction() |
|
76 { |
|
77 if (!mParent) { |
|
78 // this is a legal state, the txn is a no-op |
|
79 return NS_OK; |
|
80 } |
|
81 if (!mNode) { |
|
82 return NS_ERROR_NULL_POINTER; |
|
83 } |
|
84 |
|
85 ErrorResult error; |
|
86 mParent->InsertBefore(*mNode, mRefNode, error); |
|
87 return error.ErrorCode(); |
|
88 } |
|
89 |
|
90 NS_IMETHODIMP |
|
91 DeleteNodeTxn::RedoTransaction() |
|
92 { |
|
93 if (!mParent) { |
|
94 // this is a legal state, the txn is a no-op |
|
95 return NS_OK; |
|
96 } |
|
97 if (!mNode) { |
|
98 return NS_ERROR_NULL_POINTER; |
|
99 } |
|
100 |
|
101 if (mRangeUpdater) { |
|
102 mRangeUpdater->SelAdjDeleteNode(mNode->AsDOMNode()); |
|
103 } |
|
104 |
|
105 ErrorResult error; |
|
106 mParent->RemoveChild(*mNode, error); |
|
107 return error.ErrorCode(); |
|
108 } |
|
109 |
|
110 NS_IMETHODIMP |
|
111 DeleteNodeTxn::GetTxnDescription(nsAString& aString) |
|
112 { |
|
113 aString.AssignLiteral("DeleteNodeTxn"); |
|
114 return NS_OK; |
|
115 } |