editor/libeditor/base/CreateElementTxn.cpp

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:46fc04e597aa
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 <stdio.h>
7
8 #include "CreateElementTxn.h"
9 #include "mozilla/dom/Element.h"
10 #include "nsAlgorithm.h"
11 #include "nsDebug.h"
12 #include "nsEditor.h"
13 #include "nsError.h"
14 #include "nsIContent.h"
15 #include "nsIDOMCharacterData.h"
16 #include "nsIEditor.h"
17 #include "nsINode.h"
18 #include "nsISelection.h"
19 #include "nsISupportsUtils.h"
20 #include "nsMemory.h"
21 #include "nsReadableUtils.h"
22 #include "nsStringFwd.h"
23 #include "nsString.h"
24 #include "nsAString.h"
25 #include <algorithm>
26
27 using namespace mozilla;
28
29 CreateElementTxn::CreateElementTxn()
30 : EditTxn()
31 {
32 }
33
34 NS_IMPL_CYCLE_COLLECTION_INHERITED(CreateElementTxn, EditTxn,
35 mParent,
36 mNewNode,
37 mRefNode)
38
39 NS_IMPL_ADDREF_INHERITED(CreateElementTxn, EditTxn)
40 NS_IMPL_RELEASE_INHERITED(CreateElementTxn, EditTxn)
41 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTxn)
42 NS_INTERFACE_MAP_END_INHERITING(EditTxn)
43 NS_IMETHODIMP CreateElementTxn::Init(nsEditor *aEditor,
44 const nsAString &aTag,
45 nsIDOMNode *aParent,
46 uint32_t aOffsetInParent)
47 {
48 NS_ASSERTION(aEditor&&aParent, "null args");
49 if (!aEditor || !aParent) { return NS_ERROR_NULL_POINTER; }
50
51 mEditor = aEditor;
52 mTag = aTag;
53 mParent = do_QueryInterface(aParent);
54 mOffsetInParent = aOffsetInParent;
55 return NS_OK;
56 }
57
58
59 NS_IMETHODIMP CreateElementTxn::DoTransaction(void)
60 {
61 NS_ASSERTION(mEditor && mParent, "bad state");
62 NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
63
64 nsCOMPtr<dom::Element> newContent;
65
66 //new call to use instead to get proper HTML element, bug# 39919
67 nsresult result = mEditor->CreateHTMLContent(mTag, getter_AddRefs(newContent));
68 NS_ENSURE_SUCCESS(result, result);
69 NS_ENSURE_STATE(newContent);
70
71 mNewNode = newContent->AsDOMNode();
72 // Try to insert formatting whitespace for the new node:
73 mEditor->MarkNodeDirty(mNewNode);
74
75 // insert the new node
76 if (CreateElementTxn::eAppend == int32_t(mOffsetInParent)) {
77 nsCOMPtr<nsIDOMNode> resultNode;
78 return mParent->AppendChild(mNewNode, getter_AddRefs(resultNode));
79 }
80
81 nsCOMPtr<nsINode> parent = do_QueryInterface(mParent);
82 NS_ENSURE_STATE(parent);
83
84 mOffsetInParent = XPCOM_MIN(mOffsetInParent, parent->GetChildCount());
85
86 // note, it's ok for mRefNode to be null. that means append
87 nsIContent* refNode = parent->GetChildAt(mOffsetInParent);
88 mRefNode = refNode ? refNode->AsDOMNode() : nullptr;
89
90 nsCOMPtr<nsIDOMNode> resultNode;
91 result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
92 NS_ENSURE_SUCCESS(result, result);
93
94 // only set selection to insertion point if editor gives permission
95 bool bAdjustSelection;
96 mEditor->ShouldTxnSetSelection(&bAdjustSelection);
97 if (!bAdjustSelection) {
98 // do nothing - dom range gravity will adjust selection
99 return NS_OK;
100 }
101
102 nsCOMPtr<nsISelection> selection;
103 result = mEditor->GetSelection(getter_AddRefs(selection));
104 NS_ENSURE_SUCCESS(result, result);
105 NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
106
107 nsCOMPtr<nsIContent> parentContent = do_QueryInterface(mParent);
108 NS_ENSURE_STATE(parentContent);
109
110 result = selection->CollapseNative(parentContent,
111 parentContent->IndexOf(newContent) + 1);
112 NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert.");
113 return result;
114 }
115
116 NS_IMETHODIMP CreateElementTxn::UndoTransaction(void)
117 {
118 NS_ASSERTION(mEditor && mParent, "bad state");
119 NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
120
121 nsCOMPtr<nsIDOMNode> resultNode;
122 return mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode));
123 }
124
125 NS_IMETHODIMP CreateElementTxn::RedoTransaction(void)
126 {
127 NS_ASSERTION(mEditor && mParent, "bad state");
128 NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED);
129
130 // first, reset mNewNode so it has no attributes or content
131 nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(mNewNode);
132 if (nodeAsText)
133 {
134 nodeAsText->SetData(EmptyString());
135 }
136
137 // now, reinsert mNewNode
138 nsCOMPtr<nsIDOMNode> resultNode;
139 return mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode));
140 }
141
142 NS_IMETHODIMP CreateElementTxn::GetTxnDescription(nsAString& aString)
143 {
144 aString.AssignLiteral("CreateElementTxn: ");
145 aString += mTag;
146 return NS_OK;
147 }
148
149 NS_IMETHODIMP CreateElementTxn::GetNewNode(nsIDOMNode **aNewNode)
150 {
151 NS_ENSURE_TRUE(aNewNode, NS_ERROR_NULL_POINTER);
152 NS_ENSURE_TRUE(mNewNode, NS_ERROR_NOT_INITIALIZED);
153 *aNewNode = mNewNode;
154 NS_ADDREF(*aNewNode);
155 return NS_OK;
156 }

mercurial