editor/libeditor/base/CreateElementTxn.cpp

changeset 0
6474c204b198
     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 +}

mercurial