1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/base/CreateElementTxn.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,156 @@ 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> 1.10 + 1.11 +#include "CreateElementTxn.h" 1.12 +#include "mozilla/dom/Element.h" 1.13 +#include "nsAlgorithm.h" 1.14 +#include "nsDebug.h" 1.15 +#include "nsEditor.h" 1.16 +#include "nsError.h" 1.17 +#include "nsIContent.h" 1.18 +#include "nsIDOMCharacterData.h" 1.19 +#include "nsIEditor.h" 1.20 +#include "nsINode.h" 1.21 +#include "nsISelection.h" 1.22 +#include "nsISupportsUtils.h" 1.23 +#include "nsMemory.h" 1.24 +#include "nsReadableUtils.h" 1.25 +#include "nsStringFwd.h" 1.26 +#include "nsString.h" 1.27 +#include "nsAString.h" 1.28 +#include <algorithm> 1.29 + 1.30 +using namespace mozilla; 1.31 + 1.32 +CreateElementTxn::CreateElementTxn() 1.33 + : EditTxn() 1.34 +{ 1.35 +} 1.36 + 1.37 +NS_IMPL_CYCLE_COLLECTION_INHERITED(CreateElementTxn, EditTxn, 1.38 + mParent, 1.39 + mNewNode, 1.40 + mRefNode) 1.41 + 1.42 +NS_IMPL_ADDREF_INHERITED(CreateElementTxn, EditTxn) 1.43 +NS_IMPL_RELEASE_INHERITED(CreateElementTxn, EditTxn) 1.44 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CreateElementTxn) 1.45 +NS_INTERFACE_MAP_END_INHERITING(EditTxn) 1.46 +NS_IMETHODIMP CreateElementTxn::Init(nsEditor *aEditor, 1.47 + const nsAString &aTag, 1.48 + nsIDOMNode *aParent, 1.49 + uint32_t aOffsetInParent) 1.50 +{ 1.51 + NS_ASSERTION(aEditor&&aParent, "null args"); 1.52 + if (!aEditor || !aParent) { return NS_ERROR_NULL_POINTER; } 1.53 + 1.54 + mEditor = aEditor; 1.55 + mTag = aTag; 1.56 + mParent = do_QueryInterface(aParent); 1.57 + mOffsetInParent = aOffsetInParent; 1.58 + return NS_OK; 1.59 +} 1.60 + 1.61 + 1.62 +NS_IMETHODIMP CreateElementTxn::DoTransaction(void) 1.63 +{ 1.64 + NS_ASSERTION(mEditor && mParent, "bad state"); 1.65 + NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED); 1.66 + 1.67 + nsCOMPtr<dom::Element> newContent; 1.68 + 1.69 + //new call to use instead to get proper HTML element, bug# 39919 1.70 + nsresult result = mEditor->CreateHTMLContent(mTag, getter_AddRefs(newContent)); 1.71 + NS_ENSURE_SUCCESS(result, result); 1.72 + NS_ENSURE_STATE(newContent); 1.73 + 1.74 + mNewNode = newContent->AsDOMNode(); 1.75 + // Try to insert formatting whitespace for the new node: 1.76 + mEditor->MarkNodeDirty(mNewNode); 1.77 + 1.78 + // insert the new node 1.79 + if (CreateElementTxn::eAppend == int32_t(mOffsetInParent)) { 1.80 + nsCOMPtr<nsIDOMNode> resultNode; 1.81 + return mParent->AppendChild(mNewNode, getter_AddRefs(resultNode)); 1.82 + } 1.83 + 1.84 + nsCOMPtr<nsINode> parent = do_QueryInterface(mParent); 1.85 + NS_ENSURE_STATE(parent); 1.86 + 1.87 + mOffsetInParent = XPCOM_MIN(mOffsetInParent, parent->GetChildCount()); 1.88 + 1.89 + // note, it's ok for mRefNode to be null. that means append 1.90 + nsIContent* refNode = parent->GetChildAt(mOffsetInParent); 1.91 + mRefNode = refNode ? refNode->AsDOMNode() : nullptr; 1.92 + 1.93 + nsCOMPtr<nsIDOMNode> resultNode; 1.94 + result = mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode)); 1.95 + NS_ENSURE_SUCCESS(result, result); 1.96 + 1.97 + // only set selection to insertion point if editor gives permission 1.98 + bool bAdjustSelection; 1.99 + mEditor->ShouldTxnSetSelection(&bAdjustSelection); 1.100 + if (!bAdjustSelection) { 1.101 + // do nothing - dom range gravity will adjust selection 1.102 + return NS_OK; 1.103 + } 1.104 + 1.105 + nsCOMPtr<nsISelection> selection; 1.106 + result = mEditor->GetSelection(getter_AddRefs(selection)); 1.107 + NS_ENSURE_SUCCESS(result, result); 1.108 + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); 1.109 + 1.110 + nsCOMPtr<nsIContent> parentContent = do_QueryInterface(mParent); 1.111 + NS_ENSURE_STATE(parentContent); 1.112 + 1.113 + result = selection->CollapseNative(parentContent, 1.114 + parentContent->IndexOf(newContent) + 1); 1.115 + NS_ASSERTION((NS_SUCCEEDED(result)), "selection could not be collapsed after insert."); 1.116 + return result; 1.117 +} 1.118 + 1.119 +NS_IMETHODIMP CreateElementTxn::UndoTransaction(void) 1.120 +{ 1.121 + NS_ASSERTION(mEditor && mParent, "bad state"); 1.122 + NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED); 1.123 + 1.124 + nsCOMPtr<nsIDOMNode> resultNode; 1.125 + return mParent->RemoveChild(mNewNode, getter_AddRefs(resultNode)); 1.126 +} 1.127 + 1.128 +NS_IMETHODIMP CreateElementTxn::RedoTransaction(void) 1.129 +{ 1.130 + NS_ASSERTION(mEditor && mParent, "bad state"); 1.131 + NS_ENSURE_TRUE(mEditor && mParent, NS_ERROR_NOT_INITIALIZED); 1.132 + 1.133 + // first, reset mNewNode so it has no attributes or content 1.134 + nsCOMPtr<nsIDOMCharacterData>nodeAsText = do_QueryInterface(mNewNode); 1.135 + if (nodeAsText) 1.136 + { 1.137 + nodeAsText->SetData(EmptyString()); 1.138 + } 1.139 + 1.140 + // now, reinsert mNewNode 1.141 + nsCOMPtr<nsIDOMNode> resultNode; 1.142 + return mParent->InsertBefore(mNewNode, mRefNode, getter_AddRefs(resultNode)); 1.143 +} 1.144 + 1.145 +NS_IMETHODIMP CreateElementTxn::GetTxnDescription(nsAString& aString) 1.146 +{ 1.147 + aString.AssignLiteral("CreateElementTxn: "); 1.148 + aString += mTag; 1.149 + return NS_OK; 1.150 +} 1.151 + 1.152 +NS_IMETHODIMP CreateElementTxn::GetNewNode(nsIDOMNode **aNewNode) 1.153 +{ 1.154 + NS_ENSURE_TRUE(aNewNode, NS_ERROR_NULL_POINTER); 1.155 + NS_ENSURE_TRUE(mNewNode, NS_ERROR_NOT_INITIALIZED); 1.156 + *aNewNode = mNewNode; 1.157 + NS_ADDREF(*aNewNode); 1.158 + return NS_OK; 1.159 +}