Bug 1657270 - part 4: Split caret computation part off from AutoEmptyBlockAncestorDeleter::Run() r=m_kato

Differential Revision: https://phabricator.services.mozilla.com/D85998
This commit is contained in:
Masayuki Nakano 2020-08-11 05:04:08 +00:00
parent 087c7979ab
commit 76b257fb0f
2 changed files with 89 additions and 79 deletions

View File

@ -4337,7 +4337,7 @@ nsresult HTMLEditor::InsertBRElementIfHardLineIsEmptyAndEndsWithBlockBoundary(
}
EditorDOMPoint HTMLEditor::GetGoodCaretPointFor(
nsIContent& aContent, nsIEditor::EDirection aDirectionAndAmount) {
nsIContent& aContent, nsIEditor::EDirection aDirectionAndAmount) const {
MOZ_ASSERT(IsEditActionDataAvailable());
MOZ_ASSERT(aDirectionAndAmount == nsIEditor::eNext ||
aDirectionAndAmount == nsIEditor::eNextWord ||
@ -7940,6 +7940,70 @@ Result<RefPtr<Element>, nsresult> HTMLEditor::AutoEmptyBlockAncestorDeleter::
return brElement;
}
Result<EditorDOMPoint, nsresult>
HTMLEditor::AutoEmptyBlockAncestorDeleter::GetNewCaretPoisition(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount) const {
MOZ_ASSERT(mEmptyInclusiveAncestorBlockElement);
MOZ_ASSERT(mEmptyInclusiveAncestorBlockElement->GetParentElement());
MOZ_ASSERT(aHTMLEditor.IsEditActionDataAvailable());
switch (aDirectionAndAmount) {
case nsIEditor::eNext:
case nsIEditor::eNextWord:
case nsIEditor::eToEndOfLine: {
// Collapse Selection to next node of after empty block element
// if there is. Otherwise, to just after the empty block.
EditorDOMPoint afterEmptyBlock(
EditorRawDOMPoint::After(mEmptyInclusiveAncestorBlockElement));
MOZ_ASSERT(afterEmptyBlock.IsSet());
if (nsIContent* nextContentOfEmptyBlock =
aHTMLEditor.GetNextNode(afterEmptyBlock)) {
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
*nextContentOfEmptyBlock, aDirectionAndAmount);
if (!pt.IsSet()) {
NS_WARNING("HTMLEditor::GetGoodCaretPointFor() failed");
return Err(NS_ERROR_FAILURE);
}
return pt;
}
if (NS_WARN_IF(!afterEmptyBlock.IsSet())) {
return Err(NS_ERROR_FAILURE);
}
return afterEmptyBlock;
}
case nsIEditor::ePrevious:
case nsIEditor::ePreviousWord:
case nsIEditor::eToBeginningOfLine: {
// Collapse Selection to previous editable node of the empty block
// if there is. Otherwise, to after the empty block.
EditorRawDOMPoint atEmptyBlock(mEmptyInclusiveAncestorBlockElement);
if (nsIContent* previousContentOfEmptyBlock =
aHTMLEditor.GetPreviousEditableNode(atEmptyBlock)) {
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
*previousContentOfEmptyBlock, aDirectionAndAmount);
if (!pt.IsSet()) {
NS_WARNING("HTMLEditor::GetGoodCaretPointFor() failed");
return Err(NS_ERROR_FAILURE);
}
return pt;
}
EditorDOMPoint afterEmptyBlock(
EditorRawDOMPoint::After(*mEmptyInclusiveAncestorBlockElement));
if (NS_WARN_IF(!afterEmptyBlock.IsSet())) {
return Err(NS_ERROR_FAILURE);
}
return afterEmptyBlock;
}
case nsIEditor::eNone:
return EditorDOMPoint();
default:
MOZ_CRASH(
"AutoEmptyBlockAncestorDeleter doesn't support this action yet");
return EditorDOMPoint();
}
}
EditActionResult HTMLEditor::AutoEmptyBlockAncestorDeleter::Run(
HTMLEditor& aHTMLEditor, nsIEditor::EDirection aDirectionAndAmount) {
MOZ_ASSERT(mEmptyInclusiveAncestorBlockElement);
@ -7966,81 +8030,19 @@ EditActionResult HTMLEditor::AutoEmptyBlockAncestorDeleter::Run(
}
}
} else {
switch (aDirectionAndAmount) {
case nsIEditor::eNext:
case nsIEditor::eNextWord:
case nsIEditor::eToEndOfLine: {
// Collapse Selection to next node of after empty block element
// if there is. Otherwise, to just after the empty block.
EditorRawDOMPoint afterEmptyBlock(mEmptyInclusiveAncestorBlockElement);
bool advancedFromEmptyBlock = afterEmptyBlock.AdvanceOffset();
NS_WARNING_ASSERTION(
advancedFromEmptyBlock,
"Failed to set selection to the after the empty block");
nsCOMPtr<nsIContent> nextContentOfEmptyBlock =
aHTMLEditor.GetNextNode(afterEmptyBlock);
if (nextContentOfEmptyBlock) {
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
*nextContentOfEmptyBlock, aDirectionAndAmount);
NS_WARNING_ASSERTION(
pt.IsSet(),
"HTMLEditor::GetGoodCaretPointFor() failed, but ignored");
nsresult rv = aHTMLEditor.CollapseSelectionTo(pt);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
}
break;
}
if (NS_WARN_IF(!advancedFromEmptyBlock)) {
return EditActionResult(NS_ERROR_FAILURE);
}
nsresult rv = aHTMLEditor.CollapseSelectionTo(afterEmptyBlock);
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
}
break;
Result<EditorDOMPoint, nsresult> result =
GetNewCaretPoisition(aHTMLEditor, aDirectionAndAmount);
if (result.isErr()) {
NS_WARNING(
"AutoEmptyBlockAncestorDeleter::GetNewCaretPoisition() failed");
return EditActionResult(result.inspectErr());
}
if (result.inspect().IsSet()) {
nsresult rv = aHTMLEditor.CollapseSelectionTo(result.inspect());
if (NS_FAILED(rv)) {
NS_WARNING("HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
}
case nsIEditor::ePrevious:
case nsIEditor::ePreviousWord:
case nsIEditor::eToBeginningOfLine: {
// Collapse Selection to previous editable node of the empty block
// if there is. Otherwise, to after the empty block.
EditorRawDOMPoint atEmptyBlock(mEmptyInclusiveAncestorBlockElement);
nsCOMPtr<nsIContent> previousContentOfEmptyBlock =
aHTMLEditor.GetPreviousEditableNode(atEmptyBlock);
if (previousContentOfEmptyBlock) {
EditorDOMPoint pt = aHTMLEditor.GetGoodCaretPointFor(
*previousContentOfEmptyBlock, aDirectionAndAmount);
NS_WARNING_ASSERTION(
pt.IsSet(),
"HTMLEditor::GetGoodCaretPointFor() failed, but ignored");
nsresult rv = aHTMLEditor.CollapseSelectionTo(pt);
if (NS_FAILED(rv)) {
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
}
break;
}
EditorRawDOMPoint afterEmptyBlock(
EditorRawDOMPoint::After(*mEmptyInclusiveAncestorBlockElement));
if (NS_WARN_IF(!afterEmptyBlock.IsSet())) {
return EditActionResult(NS_ERROR_FAILURE);
}
nsresult rv = aHTMLEditor.CollapseSelectionTo(afterEmptyBlock);
if (NS_FAILED(rv)) {
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
"HTMLEditor::CollapseSelectionTo() failed");
return EditActionResult(rv);
}
break;
}
case nsIEditor::eNone:
break;
default:
MOZ_CRASH("CheckForEmptyBlock doesn't support this action yet");
}
}
nsresult rv = aHTMLEditor.DeleteNodeWithTransaction(

View File

@ -2412,7 +2412,7 @@ class HTMLEditor final : public TextEditor,
* Set the direction of handled edit action.
*/
EditorDOMPoint GetGoodCaretPointFor(
nsIContent& aContent, nsIEditor::EDirection aDirectionAndAmount);
nsIContent& aContent, nsIEditor::EDirection aDirectionAndAmount) const;
/**
* RemoveEmptyInclusiveAncestorInlineElements() removes empty inclusive
@ -2678,9 +2678,9 @@ class HTMLEditor final : public TextEditor,
* If found one is a list item element, calls
* `MaybeInsertBRElementBeforeEmptyListItemElement()` before deleting
* the list item element.
* If found empty ancestor is not a list item element, collapse Selection
* to somewhere depending on aDirectionAndAmount. Finally, removes the
* empty block ancestor.
* If found empty ancestor is not a list item element,
* `GetNewCaretPoisition()` will be called to determine new caret position.
* Finally, removes the empty block ancestor.
*
* @param aHTMLEditor The HTMLEditor.
* @param aDirectionAndAmount If found empty ancestor block is a list item
@ -2707,6 +2707,14 @@ class HTMLEditor final : public TextEditor,
[[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<RefPtr<Element>, nsresult>
MaybeInsertBRElementBeforeEmptyListItemElement(HTMLEditor& aHTMLEditor);
/**
* GetNewCaretPoisition() returns new caret position after deleting
* `mEmptyInclusiveAncestorBlockElement`.
*/
[[nodiscard]] Result<EditorDOMPoint, nsresult> GetNewCaretPoisition(
const HTMLEditor& aHTMLEditor,
nsIEditor::EDirection aDirectionAndAmount) const;
RefPtr<Element> mEmptyInclusiveAncestorBlockElement;
};