mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 1574852 - part 60: Move HTMLEditRules::MoveNodeSmart()
and HTMLEditRules::MoveContents()
to HTMLEditor
r=m_kato
Making them return next insertion point with `nsresult` makes the callers easier to understand. Therefore, this patch declares `MoveNodeResult` class newly and make them use it. And also we can get rid of the case of setting `*aInOutDestOffset` to -1 because it's a hacky case of `HTMLEditRules::MoveBlock()`. If we keep it, `MoveNodeSmart()` needs to compute new insertion point with different logic. Therefore, this patch makes `HTMLEditRules::MoveBlock()` adjust new insertion point with checking its argument. Differential Revision: https://phabricator.services.mozilla.com/D44199 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
b9e615d3bd
commit
e06533766b
@ -27,6 +27,38 @@ namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::EditActionResult
|
||||
*****************************************************************************/
|
||||
|
||||
EditActionResult& EditActionResult::operator|=(
|
||||
const MoveNodeResult& aMoveNodeResult) {
|
||||
mHandled |= aMoveNodeResult.Handled();
|
||||
// When both result are same, keep the result.
|
||||
if (mRv == aMoveNodeResult.Rv()) {
|
||||
return *this;
|
||||
}
|
||||
// If one of the result is NS_ERROR_EDITOR_DESTROYED, use it since it's
|
||||
// the most important error code for editor.
|
||||
if (EditorDestroyed() || aMoveNodeResult.EditorDestroyed()) {
|
||||
mRv = NS_ERROR_EDITOR_DESTROYED;
|
||||
return *this;
|
||||
}
|
||||
// If aMoveNodeResult hasn't been set explicit nsresult value, keep current
|
||||
// result.
|
||||
if (aMoveNodeResult.Rv() == NS_ERROR_NOT_INITIALIZED) {
|
||||
return *this;
|
||||
}
|
||||
// If one of the results is error, use NS_ERROR_FAILURE.
|
||||
if (Failed() || aMoveNodeResult.Failed()) {
|
||||
mRv = NS_ERROR_FAILURE;
|
||||
return *this;
|
||||
}
|
||||
// Otherwise, use generic success code, NS_OK.
|
||||
mRv = NS_OK;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* some helper classes for iterating the dom tree
|
||||
*****************************************************************************/
|
||||
|
@ -24,6 +24,7 @@ class nsITransferable;
|
||||
class nsRange;
|
||||
|
||||
namespace mozilla {
|
||||
class MoveNodeResult;
|
||||
template <class T>
|
||||
class OwningNonNull;
|
||||
|
||||
@ -89,6 +90,8 @@ class MOZ_STACK_CLASS EditActionResult final {
|
||||
return *this;
|
||||
}
|
||||
|
||||
EditActionResult& operator|=(const MoveNodeResult& aMoveNodeResult);
|
||||
|
||||
private:
|
||||
nsresult mRv;
|
||||
bool mCanceled;
|
||||
@ -175,6 +178,144 @@ class MOZ_STACK_CLASS CreateNodeResultBase final {
|
||||
nsresult mRv;
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* MoveNodeResult is a simple class for MoveSomething() methods.
|
||||
* This holds error code and next insertion point if moving contents succeeded.
|
||||
*/
|
||||
class MOZ_STACK_CLASS MoveNodeResult final {
|
||||
public:
|
||||
bool Succeeded() const { return NS_SUCCEEDED(mRv); }
|
||||
bool Failed() const { return NS_FAILED(mRv); }
|
||||
bool Handled() const { return mHandled; }
|
||||
bool Ignored() const { return !mHandled; }
|
||||
nsresult Rv() const { return mRv; }
|
||||
bool EditorDestroyed() const { return mRv == NS_ERROR_EDITOR_DESTROYED; }
|
||||
const EditorDOMPoint& NextInsertionPointRef() const {
|
||||
return mNextInsertionPoint;
|
||||
}
|
||||
EditorDOMPoint NextInsertionPoint() const { return mNextInsertionPoint; }
|
||||
|
||||
MoveNodeResult() : mRv(NS_ERROR_NOT_INITIALIZED), mHandled(false) {}
|
||||
|
||||
explicit MoveNodeResult(nsresult aRv) : mRv(aRv), mHandled(false) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_FAILED(mRv));
|
||||
}
|
||||
|
||||
MoveNodeResult(const MoveNodeResult& aOther) = delete;
|
||||
MoveNodeResult& operator=(const MoveNodeResult& aOther) = delete;
|
||||
MoveNodeResult(MoveNodeResult&& aOther) = default;
|
||||
MoveNodeResult& operator=(MoveNodeResult&& aOther) = default;
|
||||
|
||||
MoveNodeResult& operator|=(const MoveNodeResult& aOther) {
|
||||
mHandled |= aOther.mHandled;
|
||||
// When both result are same, keep the result but use newer point.
|
||||
if (mRv == aOther.mRv) {
|
||||
mNextInsertionPoint = aOther.mNextInsertionPoint;
|
||||
return *this;
|
||||
}
|
||||
// If one of the result is NS_ERROR_EDITOR_DESTROYED, use it since it's
|
||||
// the most important error code for editor.
|
||||
if (EditorDestroyed() || aOther.EditorDestroyed()) {
|
||||
mRv = NS_ERROR_EDITOR_DESTROYED;
|
||||
mNextInsertionPoint.Clear();
|
||||
return *this;
|
||||
}
|
||||
// If the other one has not been set explicit nsresult, keep current
|
||||
// value.
|
||||
if (aOther.mRv == NS_ERROR_NOT_INITIALIZED) {
|
||||
return *this;
|
||||
}
|
||||
// If this one has not been set explicit nsresult, copy the other one's.
|
||||
if (mRv == NS_ERROR_NOT_INITIALIZED) {
|
||||
mRv = aOther.mRv;
|
||||
mNextInsertionPoint = aOther.mNextInsertionPoint;
|
||||
return *this;
|
||||
}
|
||||
// If one of the results is error, use NS_ERROR_FAILURE.
|
||||
if (Failed() || aOther.Failed()) {
|
||||
mRv = NS_ERROR_FAILURE;
|
||||
mNextInsertionPoint.Clear();
|
||||
return *this;
|
||||
}
|
||||
// Otherwise, use generic success code, NS_OK, and use newer point.
|
||||
mRv = NS_OK;
|
||||
mNextInsertionPoint = aOther.mNextInsertionPoint;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename PT, typename CT>
|
||||
explicit MoveNodeResult(const EditorDOMPointBase<PT, CT>& aNextInsertionPoint,
|
||||
bool aHandled)
|
||||
: mNextInsertionPoint(aNextInsertionPoint),
|
||||
mRv(aNextInsertionPoint.IsSet() ? NS_OK : NS_ERROR_FAILURE),
|
||||
mHandled(aHandled && aNextInsertionPoint.IsSet()) {
|
||||
if (mNextInsertionPoint.IsSet()) {
|
||||
AutoEditorDOMPointChildInvalidator computeOffsetAndForgetChild(
|
||||
mNextInsertionPoint);
|
||||
}
|
||||
}
|
||||
|
||||
MoveNodeResult(nsINode* aParentNode, uint32_t aOffsetOfNextInsertionPoint,
|
||||
bool aHandled) {
|
||||
if (!aParentNode) {
|
||||
mRv = NS_ERROR_FAILURE;
|
||||
mHandled = false;
|
||||
return;
|
||||
}
|
||||
aOffsetOfNextInsertionPoint =
|
||||
std::min(aOffsetOfNextInsertionPoint, aParentNode->Length());
|
||||
mNextInsertionPoint.Set(aParentNode, aOffsetOfNextInsertionPoint);
|
||||
mRv = mNextInsertionPoint.IsSet() ? NS_OK : NS_ERROR_FAILURE;
|
||||
mHandled = aHandled && mNextInsertionPoint.IsSet();
|
||||
}
|
||||
|
||||
EditorDOMPoint mNextInsertionPoint;
|
||||
nsresult mRv;
|
||||
bool mHandled;
|
||||
|
||||
friend MoveNodeResult MoveNodeIgnored(nsINode* aParentNode,
|
||||
uint32_t aOffsetOfNextInsertionPoint);
|
||||
friend MoveNodeResult MoveNodeHandled(nsINode* aParentNode,
|
||||
uint32_t aOffsetOfNextInsertionPoint);
|
||||
template <typename PT, typename CT>
|
||||
friend MoveNodeResult MoveNodeIgnored(
|
||||
const EditorDOMPointBase<PT, CT>& aNextInsertionPoint);
|
||||
template <typename PT, typename CT>
|
||||
friend MoveNodeResult MoveNodeHandled(
|
||||
const EditorDOMPointBase<PT, CT>& aNextInsertionPoint);
|
||||
};
|
||||
|
||||
/***************************************************************************
|
||||
* When a move node handler (or its helper) does nothing,
|
||||
* MoveNodeIgnored should be returned.
|
||||
*/
|
||||
inline MoveNodeResult MoveNodeIgnored(nsINode* aParentNode,
|
||||
uint32_t aOffsetOfNextInsertionPoint) {
|
||||
return MoveNodeResult(aParentNode, aOffsetOfNextInsertionPoint, false);
|
||||
}
|
||||
|
||||
template <typename PT, typename CT>
|
||||
inline MoveNodeResult MoveNodeIgnored(
|
||||
const EditorDOMPointBase<PT, CT>& aNextInsertionPoint) {
|
||||
return MoveNodeResult(aNextInsertionPoint, false);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* When a move node handler (or its helper) handled and not canceled,
|
||||
* MoveNodeHandled should be returned.
|
||||
*/
|
||||
inline MoveNodeResult MoveNodeHandled(nsINode* aParentNode,
|
||||
uint32_t aOffsetOfNextInsertionPoint) {
|
||||
return MoveNodeResult(aParentNode, aOffsetOfNextInsertionPoint, true);
|
||||
}
|
||||
|
||||
template <typename PT, typename CT>
|
||||
inline MoveNodeResult MoveNodeHandled(
|
||||
const EditorDOMPointBase<PT, CT>& aNextInsertionPoint) {
|
||||
return MoveNodeResult(aNextInsertionPoint, true);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
* SplitNodeResult is a simple class for
|
||||
* EditorBase::SplitNodeDeepWithTransaction().
|
||||
|
@ -3593,18 +3593,23 @@ EditActionResult HTMLEditRules::TryToJoinBlocksWithTransaction(
|
||||
HTMLEditorRef().GetInvisibleBRElementAt(leftBlockChild);
|
||||
EditActionResult ret(NS_OK);
|
||||
if (mergeLists) {
|
||||
// XXX Why do we ignore the result of MoveContents()?
|
||||
int32_t offset = leftBlockChild.Offset();
|
||||
EditActionResult retMoveContents =
|
||||
MoveContents(*rightList, *leftList, &offset);
|
||||
if (NS_WARN_IF(retMoveContents.Rv() == NS_ERROR_EDITOR_DESTROYED)) {
|
||||
return ret;
|
||||
// XXX Why do we ignore the error from MoveChildren()?
|
||||
// XXX Why is it guaranteed that `leftBlockChild.GetContainer()` is
|
||||
// `leftList` here? Looks like that above code may run mutation
|
||||
// event listeners.
|
||||
NS_WARNING_ASSERTION(leftList == leftBlockChild.GetContainer(),
|
||||
"This is not guaranteed, but assumed");
|
||||
MoveNodeResult moveNodeResult =
|
||||
MOZ_KnownLive(HTMLEditorRef())
|
||||
.MoveChildren(*rightList,
|
||||
EditorDOMPoint(leftList, leftBlockChild.Offset()));
|
||||
if (NS_WARN_IF(moveNodeResult.EditorDestroyed())) {
|
||||
return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
NS_WARNING_ASSERTION(
|
||||
retMoveContents.Succeeded(),
|
||||
"Failed to move contents from the right list to the left list");
|
||||
if (retMoveContents.Handled()) {
|
||||
ret.MarkAsHandled();
|
||||
NS_WARNING_ASSERTION(moveNodeResult.Succeeded(),
|
||||
"MoveChildren() failed, but ignored");
|
||||
if (moveNodeResult.Succeeded()) {
|
||||
ret |= moveNodeResult;
|
||||
}
|
||||
// leftBlockChild was moved to rightList. So, it's invalid now.
|
||||
leftBlockChild.Clear();
|
||||
@ -3771,32 +3776,56 @@ EditActionResult HTMLEditRules::MoveBlock(Element& aLeftBlock,
|
||||
return EditActionIgnored(rv);
|
||||
}
|
||||
|
||||
uint32_t offset = static_cast<uint32_t>(aLeftOffset);
|
||||
EditActionResult ret(NS_OK);
|
||||
for (uint32_t i = 0; i < arrayOfNodes.Length(); i++) {
|
||||
for (auto& node : arrayOfNodes) {
|
||||
if (aLeftOffset == -1) {
|
||||
// For backward compatibility, we should move contents to end of the
|
||||
// container if this is called with -1 for aLeftOffset.
|
||||
offset = aLeftBlock.Length();
|
||||
}
|
||||
// get the node to act on
|
||||
if (HTMLEditor::NodeIsBlockStatic(arrayOfNodes[i])) {
|
||||
if (HTMLEditor::NodeIsBlockStatic(node)) {
|
||||
// For block nodes, move their contents only, then delete block.
|
||||
ret |= MoveContents(MOZ_KnownLive(*arrayOfNodes[i]->AsElement()),
|
||||
aLeftBlock, &aLeftOffset);
|
||||
if (NS_WARN_IF(ret.Failed())) {
|
||||
return ret;
|
||||
MoveNodeResult moveNodeResult =
|
||||
MOZ_KnownLive(HTMLEditorRef())
|
||||
.MoveChildren(MOZ_KnownLive(*node->AsElement()),
|
||||
EditorDOMPoint(&aLeftBlock, offset));
|
||||
if (NS_WARN_IF(moveNodeResult.Failed())) {
|
||||
return ret.SetResult(moveNodeResult.Rv());
|
||||
}
|
||||
rv = MOZ_KnownLive(HTMLEditorRef())
|
||||
.DeleteNodeWithTransaction(MOZ_KnownLive(*arrayOfNodes[i]));
|
||||
offset = moveNodeResult.NextInsertionPointRef().Offset();
|
||||
ret |= moveNodeResult;
|
||||
|
||||
DebugOnly<nsresult> rvIgnored =
|
||||
MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(*node);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to remove a block node");
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"DeleteNodeWithTransaction() failed, but ignored");
|
||||
ret.MarkAsHandled();
|
||||
if (HTMLEditorRef().HasMutationEventListeners()) {
|
||||
// Mutation event listener may make `offset` value invalid with
|
||||
// removing some previous children while we call
|
||||
// `DeleteNodeWithTransaction()` so that we should adjust it here.
|
||||
offset = std::min(offset, aLeftBlock.Length());
|
||||
}
|
||||
} else {
|
||||
// Otherwise move the content as is, checking against the DTD.
|
||||
ret |= MoveNodeSmart(MOZ_KnownLive(*arrayOfNodes[i]->AsContent()),
|
||||
aLeftBlock, &aLeftOffset);
|
||||
if (NS_WARN_IF(ret.Rv() == NS_ERROR_EDITOR_DESTROYED)) {
|
||||
return ret;
|
||||
MoveNodeResult moveNodeResult =
|
||||
MOZ_KnownLive(HTMLEditorRef())
|
||||
.MoveNodeOrChildren(MOZ_KnownLive(*node->AsContent()),
|
||||
EditorDOMPoint(&aLeftBlock, offset));
|
||||
if (NS_WARN_IF(moveNodeResult.EditorDestroyed())) {
|
||||
return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
NS_WARNING_ASSERTION(moveNodeResult.Succeeded(),
|
||||
"MoveNodeOrChildren() failed, but ignored");
|
||||
if (moveNodeResult.Succeeded()) {
|
||||
offset = moveNodeResult.NextInsertionPointRef().Offset();
|
||||
ret |= moveNodeResult;
|
||||
}
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Failed to move current node to the left block");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3808,80 +3837,75 @@ EditActionResult HTMLEditRules::MoveBlock(Element& aLeftBlock,
|
||||
return ret;
|
||||
}
|
||||
|
||||
EditActionResult HTMLEditRules::MoveNodeSmart(nsIContent& aNode,
|
||||
Element& aDestElement,
|
||||
int32_t* aInOutDestOffset) {
|
||||
MOZ_ASSERT(IsEditorDataAvailable());
|
||||
MOZ_ASSERT(aInOutDestOffset);
|
||||
MoveNodeResult HTMLEditor::MoveNodeOrChildren(
|
||||
nsIContent& aContent, const EditorDOMPoint& aPointToInsert) {
|
||||
MOZ_ASSERT(IsEditActionDataAvailable());
|
||||
MOZ_ASSERT(aPointToInsert.IsSet());
|
||||
|
||||
// Check if this node can go into the destination node
|
||||
if (HTMLEditorRef().CanContain(aDestElement, aNode)) {
|
||||
if (CanContain(*aPointToInsert.GetContainer(), aContent)) {
|
||||
// If it can, move it there.
|
||||
if (*aInOutDestOffset == -1) {
|
||||
nsresult rv = MOZ_KnownLive(HTMLEditorRef())
|
||||
.MoveNodeToEndWithTransaction(aNode, aDestElement);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditActionIgnored(rv);
|
||||
}
|
||||
} else {
|
||||
EditorDOMPoint pointToInsert(&aDestElement, *aInOutDestOffset);
|
||||
nsresult rv = MOZ_KnownLive(HTMLEditorRef())
|
||||
.MoveNodeWithTransaction(aNode, pointToInsert);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return EditActionIgnored(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return EditActionIgnored(rv);
|
||||
}
|
||||
uint32_t offsetAtInserting = aPointToInsert.Offset();
|
||||
nsresult rv = MoveNodeWithTransaction(aContent, aPointToInsert);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return MoveNodeResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (*aInOutDestOffset != -1) {
|
||||
(*aInOutDestOffset)++;
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return MoveNodeResult(rv);
|
||||
}
|
||||
// XXX Should we check if the node is actually moved in this case?
|
||||
return EditActionHandled();
|
||||
// Advance DOM point with offset for keeping backward compatibility.
|
||||
// XXX Where should we insert next content if a mutation event listener
|
||||
// break the relation of offset and moved node?
|
||||
return MoveNodeHandled(aPointToInsert.GetContainer(), ++offsetAtInserting);
|
||||
}
|
||||
|
||||
// If it can't, move its children (if any), and then delete it.
|
||||
EditActionResult ret(NS_OK);
|
||||
if (aNode.IsElement()) {
|
||||
ret = MoveContents(MOZ_KnownLive(*aNode.AsElement()), aDestElement,
|
||||
aInOutDestOffset);
|
||||
if (NS_WARN_IF(ret.Failed())) {
|
||||
return ret;
|
||||
MoveNodeResult result;
|
||||
if (aContent.IsElement()) {
|
||||
result = MoveChildren(MOZ_KnownLive(*aContent.AsElement()), aPointToInsert);
|
||||
if (NS_WARN_IF(result.Failed())) {
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
result = MoveNodeHandled(aPointToInsert);
|
||||
}
|
||||
|
||||
nsresult rv = MOZ_KnownLive(HTMLEditorRef()).DeleteNodeWithTransaction(aNode);
|
||||
if (NS_WARN_IF(!CanHandleEditAction())) {
|
||||
return ret.SetResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
nsresult rv = DeleteNodeWithTransaction(aContent);
|
||||
if (NS_WARN_IF(Destroyed())) {
|
||||
return MoveNodeResult(NS_ERROR_EDITOR_DESTROYED);
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return ret.SetResult(rv);
|
||||
return MoveNodeResult(rv);
|
||||
}
|
||||
return ret.MarkAsHandled();
|
||||
}
|
||||
|
||||
EditActionResult HTMLEditRules::MoveContents(Element& aElement,
|
||||
Element& aDestElement,
|
||||
int32_t* aInOutDestOffset) {
|
||||
MOZ_ASSERT(aInOutDestOffset);
|
||||
|
||||
if (NS_WARN_IF(&aElement == &aDestElement)) {
|
||||
return EditActionIgnored(NS_ERROR_ILLEGAL_VALUE);
|
||||
}
|
||||
|
||||
EditActionResult ret(NS_OK);
|
||||
while (aElement.GetFirstChild()) {
|
||||
ret |= MoveNodeSmart(MOZ_KnownLive(*aElement.GetFirstChild()), aDestElement,
|
||||
aInOutDestOffset);
|
||||
if (NS_WARN_IF(ret.Failed())) {
|
||||
return ret;
|
||||
if (HasMutationEventListeners()) {
|
||||
// Mutation event listener may make `offset` value invalid with
|
||||
// removing some previous children while we call
|
||||
// `DeleteNodeWithTransaction()` so that we should adjust it here.
|
||||
if (!result.NextInsertionPointRef().IsSetAndValid()) {
|
||||
result = MoveNodeHandled(aPointToInsert.GetContainer(),
|
||||
aPointToInsert.GetContainer()->Length());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return result;
|
||||
}
|
||||
|
||||
MoveNodeResult HTMLEditor::MoveChildren(Element& aElement,
|
||||
const EditorDOMPoint& aPointToInsert) {
|
||||
MOZ_ASSERT(aPointToInsert.IsSet());
|
||||
|
||||
if (NS_WARN_IF(&aElement == aPointToInsert.GetContainer())) {
|
||||
return MoveNodeResult(NS_ERROR_INVALID_ARG);
|
||||
}
|
||||
|
||||
MoveNodeResult result = MoveNodeIgnored(aPointToInsert);
|
||||
while (aElement.GetFirstChild()) {
|
||||
result |= MoveNodeOrChildren(MOZ_KnownLive(*aElement.GetFirstChild()),
|
||||
result.NextInsertionPoint());
|
||||
if (NS_WARN_IF(result.Failed())) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nsresult HTMLEditRules::DeleteElementsExceptTableRelatedElements(
|
||||
|
@ -189,34 +189,6 @@ class HTMLEditRules : public TextEditRules {
|
||||
int32_t aLeftOffset,
|
||||
int32_t aRightOffset);
|
||||
|
||||
/**
|
||||
* MoveNodeSmart() moves aNode to (aDestElement, aInOutDestOffset).
|
||||
* DTD containment rules are followed throughout.
|
||||
*
|
||||
* @param aOffset returns the point after inserted content.
|
||||
* @return Sets true to handled if this actually moves
|
||||
* the nodes.
|
||||
* canceled is always false.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
MOZ_MUST_USE EditActionResult MoveNodeSmart(nsIContent& aNode,
|
||||
Element& aDestElement,
|
||||
int32_t* aInOutDestOffset);
|
||||
|
||||
/**
|
||||
* MoveContents() moves the contents of aElement to (aDestElement,
|
||||
* aInOutDestOffset). DTD containment rules are followed throughout.
|
||||
*
|
||||
* @param aInOutDestOffset updated to point after inserted content.
|
||||
* @return Sets true to handled if this actually moves
|
||||
* the nodes.
|
||||
* canceled is always false.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
MOZ_MUST_USE EditActionResult MoveContents(Element& aElement,
|
||||
Element& aDestElement,
|
||||
int32_t* aInOutDestOffset);
|
||||
|
||||
/**
|
||||
* DeleteElementsExceptTableRelatedElements() removes elements except
|
||||
* table related elements (except <table> itself) and their contents
|
||||
|
@ -44,6 +44,7 @@ class AutoSelectionSetterAfterTableEdit;
|
||||
class AutoSetTemporaryAncestorLimiter;
|
||||
class EditActionResult;
|
||||
class EmptyEditableFunctor;
|
||||
class MoveNodeResult;
|
||||
class ResizerSelectionListener;
|
||||
class SplitRangeOffFromNodeResult;
|
||||
enum class EditSubAction : int32_t;
|
||||
@ -1988,6 +1989,31 @@ class HTMLEditor final : public TextEditor,
|
||||
nsIContent& aLeftNode, nsIContent& aRightNode,
|
||||
EditorDOMPoint* aNewFirstChildOfRightNode);
|
||||
|
||||
/**
|
||||
* MoveNodeOrChildren() moves aContent to aPointToInsert. If cannot insert
|
||||
* aContent due to invalid relation, moves only its children recursively
|
||||
* and removes aContent from the DOM tree.
|
||||
*
|
||||
* @param aContent Content which should be moved.
|
||||
* @param aPointToInsert The point to be inserted aContent or its
|
||||
* descendants.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE MoveNodeResult
|
||||
MoveNodeOrChildren(nsIContent& aNode, const EditorDOMPoint& aPointToInsert);
|
||||
|
||||
/**
|
||||
* MoveContents() moves the children of aElement to aPointToInsert. If
|
||||
* cannot insert some children due to invalid relation, calls
|
||||
* MoveNodeOrChildren() to remove the children but keep moving its children.
|
||||
*
|
||||
* @param aElement Container element whose children should be
|
||||
* moved.
|
||||
* @param aPointToInsert The point to be inserted children of aElement
|
||||
* or its descendants.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT MOZ_MUST_USE MoveNodeResult
|
||||
MoveChildren(Element& aElement, const EditorDOMPoint& aPointToInsert);
|
||||
|
||||
protected: // Called by helper classes.
|
||||
virtual void OnStartToHandleTopLevelEditSubAction(
|
||||
EditSubAction aEditSubAction, nsIEditor::EDirection aDirection) override;
|
||||
|
Loading…
Reference in New Issue
Block a user