mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 15:25:52 +00:00
365f79c262
EditorUtils::IsDescendantOf() current takes a pointer to offset or a pointer to child content if the caller needs to know the child of the most ancestor node. However, some callers should get a child as EditorDOMPoint or EditorRawDOMPoint. Then, they can be used for some editor methods which need to take child node for performance optimization. This patch makes EditorUtils::IsDescendantOf() as only two overloads. One takes pointer to EditorRawDOMPoint as optional out argument. The other takes pointer to EditorDOMPoint as an out param. Additionally, this creates new constructor of AutoTrackDOMPoint for making it can treat EditorDOMPoint directly. MozReview-Commit-ID: IsAGTUvKI19 --HG-- extra : rebase_source : 97469a21b974c6a1dd515ab472bbc4a88c1899c8
244 lines
6.6 KiB
C++
244 lines
6.6 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "mozilla/EditorUtils.h"
|
|
|
|
#include "mozilla/EditorDOMPoint.h"
|
|
#include "mozilla/OwningNonNull.h"
|
|
#include "mozilla/dom/Selection.h"
|
|
#include "nsComponentManagerUtils.h"
|
|
#include "nsError.h"
|
|
#include "nsIClipboardDragDropHookList.h"
|
|
// hooks
|
|
#include "nsIClipboardDragDropHooks.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIContentIterator.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIDocShell.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsINode.h"
|
|
#include "nsISimpleEnumerator.h"
|
|
|
|
class nsISupports;
|
|
class nsRange;
|
|
|
|
namespace mozilla {
|
|
|
|
using namespace dom;
|
|
|
|
/******************************************************************************
|
|
* AutoSelectionRestorer
|
|
*****************************************************************************/
|
|
|
|
AutoSelectionRestorer::AutoSelectionRestorer(
|
|
Selection* aSelection,
|
|
EditorBase* aEditorBase
|
|
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
|
: mEditorBase(nullptr)
|
|
{
|
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
|
if (NS_WARN_IF(!aSelection) || NS_WARN_IF(!aEditorBase)) {
|
|
return;
|
|
}
|
|
if (aEditorBase->ArePreservingSelection()) {
|
|
// We already have initialized mSavedSel, so this must be nested call.
|
|
return;
|
|
}
|
|
mSelection = aSelection;
|
|
mEditorBase = aEditorBase;
|
|
mEditorBase->PreserveSelectionAcrossActions(mSelection);
|
|
}
|
|
|
|
AutoSelectionRestorer::~AutoSelectionRestorer()
|
|
{
|
|
NS_ASSERTION(!mSelection || mEditorBase,
|
|
"mEditorBase should be non-null when mSelection is");
|
|
// mSelection will be null if this was nested call.
|
|
if (mSelection && mEditorBase->ArePreservingSelection()) {
|
|
mEditorBase->RestorePreservedSelection(mSelection);
|
|
}
|
|
}
|
|
|
|
void
|
|
AutoSelectionRestorer::Abort()
|
|
{
|
|
NS_ASSERTION(!mSelection || mEditorBase,
|
|
"mEditorBase should be non-null when mSelection is");
|
|
if (mSelection) {
|
|
mEditorBase->StopPreservingSelection();
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
* some helper classes for iterating the dom tree
|
|
*****************************************************************************/
|
|
|
|
DOMIterator::DOMIterator(nsINode& aNode MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
|
{
|
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
|
mIter = NS_NewContentIterator();
|
|
DebugOnly<nsresult> rv = mIter->Init(&aNode);
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
|
}
|
|
|
|
nsresult
|
|
DOMIterator::Init(nsRange& aRange)
|
|
{
|
|
mIter = NS_NewContentIterator();
|
|
return mIter->Init(&aRange);
|
|
}
|
|
|
|
DOMIterator::DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
|
{
|
|
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
|
}
|
|
|
|
DOMIterator::~DOMIterator()
|
|
{
|
|
}
|
|
|
|
void
|
|
DOMIterator::AppendList(const BoolDomIterFunctor& functor,
|
|
nsTArray<OwningNonNull<nsINode>>& arrayOfNodes) const
|
|
{
|
|
// Iterate through dom and build list
|
|
for (; !mIter->IsDone(); mIter->Next()) {
|
|
nsCOMPtr<nsINode> node = mIter->GetCurrentNode();
|
|
|
|
if (functor(node)) {
|
|
arrayOfNodes.AppendElement(*node);
|
|
}
|
|
}
|
|
}
|
|
|
|
DOMSubtreeIterator::DOMSubtreeIterator(
|
|
MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
|
: DOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT)
|
|
{
|
|
}
|
|
|
|
nsresult
|
|
DOMSubtreeIterator::Init(nsRange& aRange)
|
|
{
|
|
mIter = NS_NewContentSubtreeIterator();
|
|
return mIter->Init(&aRange);
|
|
}
|
|
|
|
DOMSubtreeIterator::~DOMSubtreeIterator()
|
|
{
|
|
}
|
|
|
|
/******************************************************************************
|
|
* some general purpose editor utils
|
|
*****************************************************************************/
|
|
|
|
bool
|
|
EditorUtils::IsDescendantOf(const nsINode& aNode,
|
|
const nsINode& aParent,
|
|
EditorRawDOMPoint* aOutPoint /* = nullptr */)
|
|
{
|
|
if (aOutPoint) {
|
|
aOutPoint->Clear();
|
|
}
|
|
|
|
if (&aNode == &aParent) {
|
|
return false;
|
|
}
|
|
|
|
for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
|
|
if (node->GetParentNode() == &aParent) {
|
|
if (aOutPoint) {
|
|
MOZ_ASSERT(node->IsContent());
|
|
aOutPoint->Set(node->AsContent());
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
EditorUtils::IsDescendantOf(const nsINode& aNode,
|
|
const nsINode& aParent,
|
|
EditorDOMPoint* aOutPoint)
|
|
{
|
|
MOZ_ASSERT(aOutPoint);
|
|
aOutPoint->Clear();
|
|
if (&aNode == &aParent) {
|
|
return false;
|
|
}
|
|
|
|
for (const nsINode* node = &aNode; node; node = node->GetParentNode()) {
|
|
if (node->GetParentNode() == &aParent) {
|
|
MOZ_ASSERT(node->IsContent());
|
|
aOutPoint->Set(node->AsContent());
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
EditorUtils::IsLeafNode(nsIDOMNode* aNode)
|
|
{
|
|
bool hasChildren = false;
|
|
if (aNode)
|
|
aNode->HasChildNodes(&hasChildren);
|
|
return !hasChildren;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* utility methods for drag/drop/copy/paste hooks
|
|
*****************************************************************************/
|
|
|
|
nsresult
|
|
EditorHookUtils::GetHookEnumeratorFromDocument(nsIDOMDocument* aDoc,
|
|
nsISimpleEnumerator** aResult)
|
|
{
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDoc);
|
|
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
|
|
|
nsCOMPtr<nsIDocShell> docShell = doc->GetDocShell();
|
|
nsCOMPtr<nsIClipboardDragDropHookList> hookObj = do_GetInterface(docShell);
|
|
NS_ENSURE_TRUE(hookObj, NS_ERROR_FAILURE);
|
|
|
|
return hookObj->GetHookEnumerator(aResult);
|
|
}
|
|
|
|
bool
|
|
EditorHookUtils::DoInsertionHook(nsIDOMDocument* aDoc,
|
|
nsIDOMEvent* aDropEvent,
|
|
nsITransferable *aTrans)
|
|
{
|
|
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
|
GetHookEnumeratorFromDocument(aDoc, getter_AddRefs(enumerator));
|
|
NS_ENSURE_TRUE(enumerator, true);
|
|
|
|
bool hasMoreHooks = false;
|
|
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreHooks)) &&
|
|
hasMoreHooks) {
|
|
nsCOMPtr<nsISupports> isupp;
|
|
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(isupp)))) {
|
|
break;
|
|
}
|
|
|
|
nsCOMPtr<nsIClipboardDragDropHooks> override = do_QueryInterface(isupp);
|
|
if (override) {
|
|
bool doInsert = true;
|
|
DebugOnly<nsresult> hookResult =
|
|
override->OnPasteOrDrop(aDropEvent, aTrans, &doInsert);
|
|
NS_ASSERTION(NS_SUCCEEDED(hookResult), "hook failure in OnPasteOrDrop");
|
|
NS_ENSURE_TRUE(doInsert, false);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace mozilla
|