Bug 1154701 part 9 - Clean up nsHTMLEditor::RelativeFontChange; r=ehsan

This commit is contained in:
Aryeh Gregor 2015-04-24 14:27:36 +03:00
parent 34c6f87a69
commit 1b16335f84
2 changed files with 69 additions and 93 deletions

View File

@ -634,7 +634,8 @@ protected:
nsresult InsertBasicBlock(const nsAString & aBlockType); nsresult InsertBasicBlock(const nsAString & aBlockType);
/* increase/decrease the font size of selection */ /* increase/decrease the font size of selection */
nsresult RelativeFontChange( int32_t aSizeChange); enum class FontSize { incr, decr };
nsresult RelativeFontChange(FontSize aDir);
/* helper routines for font size changing */ /* helper routines for font size changing */
nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange, nsresult RelativeFontChangeOnTextNode( int32_t aSizeChange,

View File

@ -10,7 +10,6 @@
#include "nsAString.h" #include "nsAString.h"
#include "nsAttrName.h" #include "nsAttrName.h"
#include "nsAutoPtr.h" #include "nsAutoPtr.h"
#include "nsCOMArray.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsCaseTreatment.h" #include "nsCaseTreatment.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
@ -1392,150 +1391,126 @@ nsHTMLEditor::RemoveInlinePropertyImpl(nsIAtom* aProperty,
NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize() NS_IMETHODIMP nsHTMLEditor::IncreaseFontSize()
{ {
return RelativeFontChange(1); return RelativeFontChange(FontSize::incr);
} }
NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize() NS_IMETHODIMP nsHTMLEditor::DecreaseFontSize()
{ {
return RelativeFontChange(-1); return RelativeFontChange(FontSize::decr);
} }
nsresult nsresult
nsHTMLEditor::RelativeFontChange( int32_t aSizeChange) nsHTMLEditor::RelativeFontChange(FontSize aDir)
{ {
// Can only change font size by + or - 1
if ( !( (aSizeChange==1) || (aSizeChange==-1) ) )
return NS_ERROR_ILLEGAL_VALUE;
ForceCompositionEnd(); ForceCompositionEnd();
// Get the selection // Get the selection
nsRefPtr<Selection> selection = GetSelection(); nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE); NS_ENSURE_TRUE(selection, NS_ERROR_FAILURE);
// Is the selection collapsed? // If selection is collapsed, set typing state
// if it's collapsed set typing state
if (selection->Collapsed()) { if (selection->Collapsed()) {
nsCOMPtr<nsIAtom> atom; nsIAtom& atom = aDir == FontSize::incr ? *nsGkAtoms::big :
if (aSizeChange == 1) { *nsGkAtoms::small;
atom = nsGkAtoms::big;
} else {
atom = nsGkAtoms::small;
}
// Let's see in what kind of element the selection is // Let's see in what kind of element the selection is
int32_t offset; NS_ENSURE_TRUE(selection->RangeCount() &&
nsCOMPtr<nsINode> selectedNode; selection->GetRangeAt(0)->GetStartParent(), NS_OK);
GetStartNodeAndOffset(selection, getter_AddRefs(selectedNode), &offset); OwningNonNull<nsINode> selectedNode =
if (selectedNode && IsTextNode(selectedNode)) { *selection->GetRangeAt(0)->GetStartParent();
selectedNode = selectedNode->GetParentNode(); if (IsTextNode(selectedNode)) {
NS_ENSURE_TRUE(selectedNode->GetParentNode(), NS_OK);
selectedNode = *selectedNode->GetParentNode();
} }
NS_ENSURE_TRUE(selectedNode, NS_OK); if (!CanContainTag(selectedNode, atom)) {
if (!CanContainTag(*selectedNode, *atom)) {
return NS_OK; return NS_OK;
} }
// manipulating text attributes on a collapsed selection only sets state for the next text insertion // Manipulating text attributes on a collapsed selection only sets state
mTypeInState->SetProp(atom, EmptyString(), EmptyString()); // for the next text insertion
mTypeInState->SetProp(&atom, EmptyString(), EmptyString());
return NS_OK; return NS_OK;
} }
// wrap with txn batching, rules sniffing, and selection preservation code // Wrap with txn batching, rules sniffing, and selection preservation code
nsAutoEditBatch batchIt(this); nsAutoEditBatch batchIt(this);
nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty, nsIEditor::eNext); nsAutoRules beginRulesSniffing(this, EditAction::setTextProperty,
nsIEditor::eNext);
nsAutoSelectionReset selectionResetter(selection, this); nsAutoSelectionReset selectionResetter(selection, this);
nsAutoTxnsConserveSelection dontSpazMySelection(this); nsAutoTxnsConserveSelection dontSpazMySelection(this);
// loop thru the ranges in the selection // Loop through the ranges in the selection
uint32_t rangeCount = selection->RangeCount(); uint32_t rangeCount = selection->RangeCount();
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) { for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx); nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
// adjust range to include any ancestors who's children are entirely selected // Adjust range to include any ancestors with entirely selected children
nsresult res = PromoteInlineRange(range); nsresult res = PromoteInlineRange(range);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
// check for easy case: both range endpoints in same text node
nsCOMPtr<nsIDOMNode> startNode, endNode;
res = range->GetStartContainer(getter_AddRefs(startNode));
NS_ENSURE_SUCCESS(res, res);
res = range->GetEndContainer(getter_AddRefs(endNode));
NS_ENSURE_SUCCESS(res, res);
if ((startNode == endNode) && IsTextNode(startNode))
{
int32_t startOffset, endOffset;
range->GetStartOffset(&startOffset);
range->GetEndOffset(&endOffset);
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode);
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, endOffset);
NS_ENSURE_SUCCESS(res, res);
}
else
{
// not the easy case. range not contained in single text node.
// there are up to three phases here. There are all the nodes
// reported by the subtree iterator to be processed. And there
// are potentially a starting textnode and an ending textnode
// which are only partially contained by the range.
// lets handle the nodes reported by the iterator. These nodes
// are entirely contained in the selection range. We build up
// a list of them (since doing operations on the document during
// iteration would perturb the iterator).
nsCOMPtr<nsIContentIterator> iter = // Check for easy case: both range endpoints in same text node
do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); nsCOMPtr<nsINode> startNode = range->GetStartParent();
nsCOMPtr<nsINode> endNode = range->GetEndParent();
if (startNode == endNode && IsTextNode(startNode)) {
res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1,
static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()),
range->StartOffset(), range->EndOffset());
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); } else {
// Not the easy case. Range not contained in single text node. There
// are up to three phases here. There are all the nodes reported by the
// subtree iterator to be processed. And there are potentially a
// starting textnode and an ending textnode which are only partially
// contained by the range.
// iterate range and build up array // Let's handle the nodes reported by the iterator. These nodes are
// entirely contained in the selection range. We build up a list of them
// (since doing operations on the document during iteration would perturb
// the iterator).
OwningNonNull<nsIContentIterator> iter = NS_NewContentSubtreeIterator();
// Iterate range and build up array
res = iter->Init(range); res = iter->Init(range);
if (NS_SUCCEEDED(res)) { if (NS_SUCCEEDED(res)) {
nsCOMArray<nsIContent> arrayOfNodes; nsTArray<OwningNonNull<nsIContent>> arrayOfNodes;
while (!iter->IsDone()) { for (; !iter->IsDone(); iter->Next()) {
NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE); NS_ENSURE_TRUE(iter->GetCurrentNode()->IsContent(), NS_ERROR_FAILURE);
nsCOMPtr<nsIContent> node = iter->GetCurrentNode()->AsContent(); OwningNonNull<nsIContent> node = *iter->GetCurrentNode()->AsContent();
if (IsEditable(node)) { if (IsEditable(node)) {
arrayOfNodes.AppendObject(node); arrayOfNodes.AppendElement(node);
} }
iter->Next();
} }
// now that we have the list, do the font size change on each node // Now that we have the list, do the font size change on each node
int32_t listCount = arrayOfNodes.Count(); for (auto& node : arrayOfNodes) {
for (int32_t j = 0; j < listCount; ++j) { res = RelativeFontChangeOnNode(aDir == FontSize::incr ? +1 : -1,
nsIContent* node = arrayOfNodes[j]; node);
res = RelativeFontChangeOnNode(aSizeChange, node);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
arrayOfNodes.Clear();
} }
// now check the start and end parents of the range to see if they need to // Now check the start and end parents of the range to see if they need
// be separately handled (they do if they are text nodes, due to how the // to be separately handled (they do if they are text nodes, due to how
// subtree iterator works - it will not have reported them). // the subtree iterator works - it will not have reported them).
if (IsTextNode(startNode) && IsEditable(startNode)) if (IsTextNode(startNode) && IsEditable(startNode)) {
{ res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1,
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(startNode); static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()),
int32_t startOffset; range->StartOffset(), startNode->Length());
uint32_t textLen;
range->GetStartOffset(&startOffset);
nodeAsText->GetLength(&textLen);
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, startOffset, textLen);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
if (IsTextNode(endNode) && IsEditable(endNode)) if (IsTextNode(endNode) && IsEditable(endNode)) {
{
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode); nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(endNode);
int32_t endOffset; int32_t endOffset;
range->GetEndOffset(&endOffset); range->GetEndOffset(&endOffset);
res = RelativeFontChangeOnTextNode(aSizeChange, nodeAsText, 0, endOffset); res = RelativeFontChangeOnTextNode(aDir == FontSize::incr ? +1 : -1,
static_cast<nsIDOMCharacterData*>(startNode->AsDOMNode()),
0, range->EndOffset());
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
} }
} }
} }
return NS_OK; return NS_OK;
} }
nsresult nsresult