Skip to content

Commit

Permalink
Bug 1632724 - part 2: Move DeleteSelectionWithTransaction() from `T…
Browse files Browse the repository at this point in the history
…extEditor` to `EditorBase` since it's used by `HTMLEditor` too r=m_kato

Depends on D72290

Differential Revision: https://phabricator.services.mozilla.com/D72291
  • Loading branch information
masayuki-nakano committed Apr 24, 2020
1 parent eec92d4 commit 74e4b43
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 131 deletions.
118 changes: 118 additions & 0 deletions editor/libeditor/EditorBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5068,6 +5068,124 @@ nsresult EditorBase::ExtendSelectionForDelete(
}
}

nsresult EditorBase::DeleteSelectionWithTransaction(
nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers) {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);

RefPtr<EditAggregateTransaction> deleteSelectionTransaction;
nsCOMPtr<nsINode> deleteNode;
int32_t deleteCharOffset = 0, deleteCharLength = 0;
if (!SelectionRefPtr()->IsCollapsed() ||
aDirectionAndAmount != nsIEditor::eNone) {
deleteSelectionTransaction = CreateTxnForDeleteSelection(
aDirectionAndAmount, getter_AddRefs(deleteNode), &deleteCharOffset,
&deleteCharLength);
if (!deleteSelectionTransaction) {
NS_WARNING("EditorBase::CreateTxnForDeleteSelection() failed");
return NS_ERROR_FAILURE;
}
}

RefPtr<CharacterData> deleteCharData =
CharacterData::FromNodeOrNull(deleteNode);
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eDeleteSelectedContent, aDirectionAndAmount,
ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored");

if (IsHTMLEditor()) {
if (!deleteNode) {
// XXX We may remove multiple ranges in the following. Therefore,
// this must have a bug since we only add the first range into
// the changed range.
TopLevelEditSubActionDataRef().WillDeleteRange(
*this, EditorBase::GetStartPoint(*SelectionRefPtr()),
EditorBase::GetEndPoint(*SelectionRefPtr()));
} else if (!deleteCharData) {
MOZ_ASSERT(deleteNode->IsContent());
TopLevelEditSubActionDataRef().WillDeleteContent(
*this, *deleteNode->AsContent());
}
}

// Notify nsIEditActionListener::WillDelete[Selection|Text]
if (!mActionListeners.IsEmpty()) {
if (!deleteNode) {
AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) {
DebugOnly<nsresult> rvIgnored =
listener->WillDeleteSelection(SelectionRefPtr());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::WillDeleteSelection() failed, but ignored");
}
} else if (deleteCharData) {
AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) {
DebugOnly<nsresult> rvIgnored =
listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::WillDeleteText() failed, but ignored");
}
}
}

// Delete the specified amount
nsresult rv = DoTransactionInternal(deleteSelectionTransaction);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::DoTransactionInternal() failed");

if (IsHTMLEditor() && deleteCharData) {
MOZ_ASSERT(deleteNode);
TopLevelEditSubActionDataRef().DidDeleteText(*this,
EditorRawDOMPoint(deleteNode));
}

if (mTextServicesDocument && NS_SUCCEEDED(rv) && deleteNode &&
!deleteCharData) {
RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
textServicesDocument->DidDeleteNode(deleteNode);
}

// Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
AutoActionListenerArray listeners(mActionListeners);
if (!deleteNode) {
for (auto& listener : mActionListeners) {
DebugOnly<nsresult> rvIgnored =
listener->DidDeleteSelection(SelectionRefPtr());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteSelection() failed, but ignored");
}
} else if (deleteCharData) {
for (auto& listener : mActionListeners) {
DebugOnly<nsresult> rvIgnored =
listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteText() failed, but ignored");
}
} else {
for (auto& listener : mActionListeners) {
DebugOnly<nsresult> rvIgnored = listener->DidDeleteNode(deleteNode, rv);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteNode() failed, but ignored");
}
}

return rv;
}

nsresult EditorBase::CreateRange(nsINode* aStartContainer, int32_t aStartOffset,
nsINode* aEndContainer, int32_t aEndOffset,
nsRange** aRange) {
Expand Down
12 changes: 12 additions & 0 deletions editor/libeditor/EditorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2548,6 +2548,18 @@ class EditorBase : public nsIEditor,
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
ExtendSelectionForDelete(nsIEditor::EDirection* aDirectionAndAmount);

/**
* DeleteSelectionWithTransaction() removes selected content or content
* around caret with transactions.
*
* @param aDirectionAndAmount How much range should be removed.
* @param aStripWrappers Whether the parent blocks should be removed
* when they become empty.
*/
MOZ_CAN_RUN_SCRIPT virtual nsresult DeleteSelectionWithTransaction(
nsIEditor::EDirection aDirectionAndAmount,
nsIEditor::EStripWrappers aStripWrappers);

private:
nsCOMPtr<nsISelectionController> mSelectionController;
RefPtr<Document> mDocument;
Expand Down
4 changes: 2 additions & 2 deletions editor/libeditor/HTMLEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3050,9 +3050,9 @@ nsresult HTMLEditor::DeleteSelectionWithTransaction(
MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);

nsresult rv =
TextEditor::DeleteSelectionWithTransaction(aAction, aStripWrappers);
EditorBase::DeleteSelectionWithTransaction(aAction, aStripWrappers);
if (NS_FAILED(rv)) {
NS_WARNING("TextEditor::DeleteSelectionWithTransaction() failed");
NS_WARNING("EditorBase::DeleteSelectionWithTransaction() failed");
return rv;
}

Expand Down
4 changes: 2 additions & 2 deletions editor/libeditor/TextEditSubActionHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ EditActionResult TextEditor::HandleDeleteSelectionInternal(
DeleteSelectionWithTransaction(aDirectionAndAmount, aStripWrappers);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rv),
"TextEditor::DeleteSelectionWithTransaction() failed");
"EditorBase::DeleteSelectionWithTransaction() failed");
return EditActionHandled(rv);
}

Expand All @@ -815,7 +815,7 @@ EditActionResult TextEditor::HandleDeleteSelectionInternal(
return EditActionResult(NS_ERROR_EDITOR_DESTROYED);
}
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"TextEditor::DeleteSelectionWithTransaction() failed");
"EditorBase::DeleteSelectionWithTransaction() failed");
return EditActionHandled(rv);
}

Expand Down
116 changes: 0 additions & 116 deletions editor/libeditor/TextEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,122 +424,6 @@ nsresult TextEditor::InsertLineBreakAsAction(nsIPrincipal* aPrincipal) {
return EditorBase::ToGenericNSResult(rv);
}

nsresult TextEditor::DeleteSelectionWithTransaction(
EDirection aDirection, EStripWrappers aStripWrappers) {
MOZ_ASSERT(IsEditActionDataAvailable());

MOZ_ASSERT(aStripWrappers == eStrip || aStripWrappers == eNoStrip);

RefPtr<EditAggregateTransaction> deleteSelectionTransaction;
nsCOMPtr<nsINode> deleteNode;
int32_t deleteCharOffset = 0, deleteCharLength = 0;
if (!SelectionRefPtr()->IsCollapsed() || aDirection != eNone) {
deleteSelectionTransaction =
CreateTxnForDeleteSelection(aDirection, getter_AddRefs(deleteNode),
&deleteCharOffset, &deleteCharLength);
if (!deleteSelectionTransaction) {
NS_WARNING("EditorBase::CreateTxnForDeleteSelection() failed");
return NS_ERROR_FAILURE;
}
}

RefPtr<CharacterData> deleteCharData =
CharacterData::FromNodeOrNull(deleteNode);
IgnoredErrorResult ignoredError;
AutoEditSubActionNotifier startToHandleEditSubAction(
*this, EditSubAction::eDeleteSelectedContent, aDirection, ignoredError);
if (NS_WARN_IF(ignoredError.ErrorCodeIs(NS_ERROR_EDITOR_DESTROYED))) {
return ignoredError.StealNSResult();
}
NS_WARNING_ASSERTION(
!ignoredError.Failed(),
"TextEditor::OnStartToHandleTopLevelEditSubAction() failed, but ignored");

if (AsHTMLEditor()) {
if (!deleteNode) {
// XXX We may remove multiple ranges in the following. Therefore,
// this must have a bug since we only add the first range into
// the changed range.
TopLevelEditSubActionDataRef().WillDeleteRange(
*this, EditorBase::GetStartPoint(*SelectionRefPtr()),
EditorBase::GetEndPoint(*SelectionRefPtr()));
} else if (!deleteCharData) {
MOZ_ASSERT(deleteNode->IsContent());
TopLevelEditSubActionDataRef().WillDeleteContent(
*this, *deleteNode->AsContent());
}
}

// Notify nsIEditActionListener::WillDelete[Selection|Text]
if (!mActionListeners.IsEmpty()) {
if (!deleteNode) {
AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) {
DebugOnly<nsresult> rvIgnored =
listener->WillDeleteSelection(SelectionRefPtr());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::WillDeleteSelection() failed, but ignored");
}
} else if (deleteCharData) {
AutoActionListenerArray listeners(mActionListeners);
for (auto& listener : listeners) {
DebugOnly<nsresult> rvIgnored =
listener->WillDeleteText(deleteCharData, deleteCharOffset, 1);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::WillDeleteText() failed, but ignored");
}
}
}

// Delete the specified amount
nsresult rv = DoTransactionInternal(deleteSelectionTransaction);
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"EditorBase::DoTransactionInternal() failed");

if (AsHTMLEditor() && deleteCharData) {
MOZ_ASSERT(deleteNode);
TopLevelEditSubActionDataRef().DidDeleteText(*this,
EditorRawDOMPoint(deleteNode));
}

if (mTextServicesDocument && NS_SUCCEEDED(rv) && deleteNode &&
!deleteCharData) {
RefPtr<TextServicesDocument> textServicesDocument = mTextServicesDocument;
textServicesDocument->DidDeleteNode(deleteNode);
}

// Notify nsIEditActionListener::DidDelete[Selection|Text|Node]
AutoActionListenerArray listeners(mActionListeners);
if (!deleteNode) {
for (auto& listener : mActionListeners) {
DebugOnly<nsresult> rvIgnored =
listener->DidDeleteSelection(SelectionRefPtr());
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteSelection() failed, but ignored");
}
} else if (deleteCharData) {
for (auto& listener : mActionListeners) {
DebugOnly<nsresult> rvIgnored =
listener->DidDeleteText(deleteCharData, deleteCharOffset, 1, rv);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteText() failed, but ignored");
}
} else {
for (auto& listener : mActionListeners) {
DebugOnly<nsresult> rvIgnored = listener->DidDeleteNode(deleteNode, rv);
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
"nsIEditActionListener::DidDeleteNode() failed, but ignored");
}
}

return rv;
}

already_AddRefed<Element> TextEditor::DeleteSelectionAndCreateElement(
nsAtom& aTag) {
MOZ_ASSERT(IsEditActionDataAvailable());
Expand Down
11 changes: 0 additions & 11 deletions editor/libeditor/TextEditor.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,17 +363,6 @@ class TextEditor : public EditorBase, public nsITimerCallback, public nsINamed {
[[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult
DeleteSelectionByDragAsAction(bool aDispatchInputEvent);

/**
* DeleteSelectionWithTransaction() removes selected content or content
* around caret with transactions.
*
* @param aDirection How much range should be removed.
* @param aStripWrappers Whether the parent blocks should be removed
* when they become empty.
*/
MOZ_CAN_RUN_SCRIPT virtual nsresult DeleteSelectionWithTransaction(
EDirection aAction, EStripWrappers aStripWrappers);

/**
* Replace existed string with aString. Caller must guarantee that there
* is a placeholder transaction which will have the transaction.
Expand Down

0 comments on commit 74e4b43

Please sign in to comment.