Bug 1154701 part 13 - Clean up nsHTMLEditor::SetCSSBackgroundColor; r=ehsan

This commit is contained in:
Aryeh Gregor 2015-04-22 14:27:18 +03:00
parent be20af1451
commit bfb3f9c688

View File

@ -4503,196 +4503,156 @@ nsHTMLEditor::SetIsCSSEnabled(bool aIsCSSPrefChecked)
nsresult nsresult
nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor) nsHTMLEditor::SetCSSBackgroundColor(const nsAString& aColor)
{ {
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; } NS_ENSURE_TRUE(mRules, NS_ERROR_NOT_INITIALIZED);
ForceCompositionEnd(); ForceCompositionEnd();
// Protect the edit rules object from dying // Protect the edit rules object from dying
nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules);
nsRefPtr<Selection> selection = GetSelection(); nsRefPtr<Selection> selection = GetSelection();
NS_ENSURE_STATE(selection);
bool isCollapsed = selection->Collapsed(); bool isCollapsed = selection->Collapsed();
nsAutoEditBatch batchIt(this); nsAutoEditBatch batchIt(this);
nsAutoRules beginRulesSniffing(this, EditAction::insertElement, nsIEditor::eNext); nsAutoRules beginRulesSniffing(this, EditAction::insertElement,
nsIEditor::eNext);
nsAutoSelectionReset selectionResetter(selection, this); nsAutoSelectionReset selectionResetter(selection, this);
nsAutoTxnsConserveSelection dontSpazMySelection(this); nsAutoTxnsConserveSelection dontSpazMySelection(this);
bool cancel, handled; bool cancel, handled;
nsTextRulesInfo ruleInfo(EditAction::setTextProperty); nsTextRulesInfo ruleInfo(EditAction::setTextProperty);
nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
NS_ENSURE_SUCCESS(res, res); NS_ENSURE_SUCCESS(res, res);
if (!cancel && !handled) if (!cancel && !handled) {
{ // Loop through the ranges in the selection
// loop thru the ranges in the selection NS_NAMED_LITERAL_STRING(bgcolor, "bgcolor");
nsAutoString bgcolor; bgcolor.AssignLiteral("bgcolor"); for (uint32_t i = 0; i < selection->RangeCount(); i++) {
uint32_t rangeCount = selection->RangeCount(); nsRefPtr<nsRange> range = selection->GetRangeAt(i);
for (uint32_t rangeIdx = 0; rangeIdx < rangeCount; ++rangeIdx) {
nsCOMPtr<nsIDOMNode> cachedBlockParent = nullptr;
nsRefPtr<nsRange> range = selection->GetRangeAt(rangeIdx);
NS_ENSURE_TRUE(range, NS_ERROR_FAILURE); NS_ENSURE_TRUE(range, NS_ERROR_FAILURE);
// check for easy case: both range endpoints in same text node nsCOMPtr<Element> cachedBlockParent;
nsCOMPtr<nsIDOMNode> startNode, endNode;
int32_t startOffset, endOffset; // Check for easy case: both range endpoints in same text node
res = range->GetStartContainer(getter_AddRefs(startNode)); nsCOMPtr<nsINode> startNode = range->GetStartParent();
NS_ENSURE_SUCCESS(res, res); int32_t startOffset = range->StartOffset();
res = range->GetEndContainer(getter_AddRefs(endNode)); nsCOMPtr<nsINode> endNode = range->GetEndParent();
NS_ENSURE_SUCCESS(res, res); int32_t endOffset = range->EndOffset();
res = range->GetStartOffset(&startOffset); if (startNode == endNode && IsTextNode(startNode)) {
NS_ENSURE_SUCCESS(res, res); // Let's find the block container of the text node
res = range->GetEndOffset(&endOffset); nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
NS_ENSURE_SUCCESS(res, res); // And apply the background color to that block container
if ((startNode == endNode) && IsTextNode(startNode))
{
// let's find the block container of the text node
nsCOMPtr<nsIDOMNode> blockParent;
blockParent = GetBlockNodeParent(startNode);
// and apply the background color to that block container
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor, false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false);
NS_ENSURE_SUCCESS(res, res);
} }
} } else if (startNode == endNode &&
else if ((startNode == endNode) && nsTextEditUtils::IsBody(startNode) && isCollapsed) startNode->IsHTMLElement(nsGkAtoms::body) && isCollapsed) {
{ // No block in the document, let's apply the background to the body
// we have no block in the document, let's apply the background to the body mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(startNode->AsElement(),
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(startNode); nullptr, &bgcolor, &aColor,
int32_t count; false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); } else if (startNode == endNode && (endOffset - startOffset == 1 ||
NS_ENSURE_SUCCESS(res, res); (!startOffset && !endOffset))) {
} // A unique node is selected, let's also apply the background color to
else if ((startNode == endNode) && (((endOffset-startOffset) == 1) || (!startOffset && !endOffset))) // the containing block, possibly the node itself
{ nsCOMPtr<nsIContent> selectedNode = startNode->GetChildAt(startOffset);
// a unique node is selected, let's also apply the background color nsCOMPtr<Element> blockParent;
// to the containing block, possibly the node itself if (NodeIsBlockStatic(selectedNode)) {
nsCOMPtr<nsIDOMNode> selectedNode = GetChildAt(startNode, startOffset); blockParent = selectedNode->AsElement();
bool isBlock =false; } else {
res = NodeIsBlockStatic(selectedNode, &isBlock);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> blockParent = selectedNode;
if (!isBlock) {
blockParent = GetBlockNodeParent(selectedNode); blockParent = GetBlockNodeParent(selectedNode);
} }
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor, false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false);
NS_ENSURE_SUCCESS(res, res);
} }
} } else {
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
// not the easy case. range not contained in single text node. // the subtree iterator to be processed. And there are potentially a
// there are up to three phases here. There are all the nodes // starting textnode and an ending textnode which are only partially
// reported by the subtree iterator to be processed. And there // contained by the range.
// 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 = // Let's handle the nodes reported by the iterator. These nodes are
do_CreateInstance("@mozilla.org/content/subtree-content-iterator;1", &res); // entirely contained in the selection range. We build up a list of
NS_ENSURE_SUCCESS(res, res); // them (since doing operations on the document during iteration would
NS_ENSURE_TRUE(iter, NS_ERROR_FAILURE); // perturb the iterator).
nsCOMArray<nsIDOMNode> arrayOfNodes; OwningNonNull<nsIContentIterator> iter =
nsCOMPtr<nsIDOMNode> node; NS_NewContentSubtreeIterator();
// iterate range and build up array nsTArray<OwningNonNull<nsINode>> arrayOfNodes;
nsCOMPtr<nsINode> node;
// Iterate range and build up array
res = iter->Init(range); res = iter->Init(range);
// init returns an error if no nodes in range. // Init returns an error if no nodes in range. This can easily happen
// this can easily happen with the subtree // with the subtree iterator if the selection doesn't contain any
// iterator if the selection doesn't contain // *whole* nodes.
// any *whole* nodes. if (NS_SUCCEEDED(res)) {
if (NS_SUCCEEDED(res)) for (; !iter->IsDone(); iter->Next()) {
{
while (!iter->IsDone())
{
node = do_QueryInterface(iter->GetCurrentNode()); node = do_QueryInterface(iter->GetCurrentNode());
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE); NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
if (IsEditable(node)) if (IsEditable(node)) {
{ arrayOfNodes.AppendElement(*node);
arrayOfNodes.AppendObject(node);
} }
iter->Next();
} }
} }
// first check the start parent of the range to see if it needs to // First check the start parent of the range to see if it needs to be
// be separately handled (it does if it's a text node, due to how the // separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it). // subtree iterator works - it will not have reported it).
if (IsTextNode(startNode) && IsEditable(startNode)) if (IsTextNode(startNode) && IsEditable(startNode)) {
{ nsCOMPtr<Element> blockParent = GetBlockNodeParent(startNode);
nsCOMPtr<nsIDOMNode> blockParent;
blockParent = GetBlockNodeParent(startNode);
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor,
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); false);
NS_ENSURE_SUCCESS(res, res);
} }
} }
// then loop through the list, set the property on each node // Then loop through the list, set the property on each node
int32_t listCount = arrayOfNodes.Count(); for (auto& node : arrayOfNodes) {
int32_t j; nsCOMPtr<Element> blockParent;
for (j = 0; j < listCount; j++) if (NodeIsBlockStatic(node)) {
{ blockParent = node->AsElement();
node = arrayOfNodes[j]; } else {
// do we have a block here ?
bool isBlock =false;
res = NodeIsBlockStatic(node, &isBlock);
NS_ENSURE_SUCCESS(res, res);
nsCOMPtr<nsIDOMNode> blockParent = node;
if (!isBlock) {
// no we don't, let's find the block ancestor
blockParent = GetBlockNodeParent(node); blockParent = GetBlockNodeParent(node);
} }
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor,
// and set the property on it false);
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false);
NS_ENSURE_SUCCESS(res, res);
} }
} }
arrayOfNodes.Clear(); arrayOfNodes.Clear();
// last check the end parent of the range to see if it needs to // Last, check the end parent of the range to see if it needs to be
// be separately handled (it does if it's a text node, due to how the // separately handled (it does if it's a text node, due to how the
// subtree iterator works - it will not have reported it). // subtree iterator works - it will not have reported it).
if (IsTextNode(endNode) && IsEditable(endNode)) if (IsTextNode(endNode) && IsEditable(endNode)) {
{ nsCOMPtr<Element> blockParent = GetBlockNodeParent(endNode);
nsCOMPtr<nsIDOMNode> blockParent;
blockParent = GetBlockNodeParent(endNode);
if (blockParent && cachedBlockParent != blockParent) { if (blockParent && cachedBlockParent != blockParent) {
cachedBlockParent = blockParent; cachedBlockParent = blockParent;
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(blockParent); mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(blockParent, nullptr,
int32_t count; &bgcolor, &aColor,
res = mHTMLCSSUtils->SetCSSEquivalentToHTMLStyle(element, nullptr, &bgcolor, &aColor, &count, false); false);
NS_ENSURE_SUCCESS(res, res);
} }
} }
} }
} }
} }
if (!cancel) if (!cancel) {
{ // Post-process
// post-process
res = mRules->DidDoAction(selection, &ruleInfo, res); res = mRules->DidDoAction(selection, &ruleInfo, res);
NS_ENSURE_SUCCESS(res, res);
} }
return res; return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP