Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(548)

Side by Side Diff: Source/core/editing/CompositeEditCommand.cpp

Issue 196683003: Use new is*Element() helper functions more in editing code (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 applyCommandToComposite(ApplyStyleCommand::create(element, true)); 270 applyCommandToComposite(ApplyStyleCommand::create(element, true));
271 } 271 }
272 272
273 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem ent, bool pasteBlockqutoeIntoUnquotedArea) 273 void CompositeEditCommand::insertParagraphSeparator(bool useDefaultParagraphElem ent, bool pasteBlockqutoeIntoUnquotedArea)
274 { 274 {
275 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea)); 275 applyCommandToComposite(InsertParagraphSeparatorCommand::create(document(), useDefaultParagraphElement, pasteBlockqutoeIntoUnquotedArea));
276 } 276 }
277 277
278 bool CompositeEditCommand::isRemovableBlock(const Node* node) 278 bool CompositeEditCommand::isRemovableBlock(const Node* node)
279 { 279 {
280 if (!node->hasTagName(divTag)) 280 ASSERT(node);
281 if (!isHTMLDivElement(*node))
281 return false; 282 return false;
282 283
283 Node* parentNode = node->parentNode(); 284 Node* parentNode = node->parentNode();
284 if (parentNode && parentNode->firstChild() != parentNode->lastChild()) 285 if (parentNode && parentNode->firstChild() != parentNode->lastChild())
285 return false; 286 return false;
286 287
287 if (!toElement(node)->hasAttributes()) 288 if (!toElement(node)->hasAttributes())
288 return true; 289 return true;
289 290
290 return false; 291 return false;
291 } 292 }
292 293
293 void CompositeEditCommand::insertNodeBefore(PassRefPtr<Node> insertChild, PassRe fPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAl waysEditable) 294 void CompositeEditCommand::insertNodeBefore(PassRefPtr<Node> insertChild, PassRe fPtr<Node> refChild, ShouldAssumeContentIsAlwaysEditable shouldAssumeContentIsAl waysEditable)
294 { 295 {
295 ASSERT(!refChild->hasTagName(bodyTag)); 296 ASSERT(!isHTMLBodyElement(*refChild));
296 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil d, shouldAssumeContentIsAlwaysEditable)); 297 applyCommandToComposite(InsertNodeBeforeCommand::create(insertChild, refChil d, shouldAssumeContentIsAlwaysEditable));
297 } 298 }
298 299
299 void CompositeEditCommand::insertNodeAfter(PassRefPtr<Node> insertChild, PassRef Ptr<Node> refChild) 300 void CompositeEditCommand::insertNodeAfter(PassRefPtr<Node> insertChild, PassRef Ptr<Node> refChild)
300 { 301 {
301 ASSERT(insertChild); 302 ASSERT(insertChild);
302 ASSERT(refChild); 303 ASSERT(refChild);
303 ASSERT(!refChild->hasTagName(bodyTag)); 304 ASSERT(!isHTMLBodyElement(*refChild));
304 ContainerNode* parent = refChild->parentNode(); 305 ContainerNode* parent = refChild->parentNode();
305 ASSERT(parent); 306 ASSERT(parent);
306 ASSERT(!parent->isShadowRoot()); 307 ASSERT(!parent->isShadowRoot());
307 if (parent->lastChild() == refChild) 308 if (parent->lastChild() == refChild)
308 appendNode(insertChild, parent); 309 appendNode(insertChild, parent);
309 else { 310 else {
310 ASSERT(refChild->nextSibling()); 311 ASSERT(refChild->nextSibling());
311 insertNodeBefore(insertChild, refChild->nextSibling()); 312 insertNodeBefore(insertChild, refChild->nextSibling());
312 } 313 }
313 } 314 }
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
677 VisiblePosition previousVisiblePos(visiblePos.previous()); 678 VisiblePosition previousVisiblePos(visiblePos.previous());
678 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(previousVisiblePos) ; 679 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(previousVisiblePos) ;
679 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(visiblePos); 680 replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNeeded(visiblePos);
680 } 681 }
681 682
682 void CompositeEditCommand::replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNee ded(const VisiblePosition& visiblePosition) 683 void CompositeEditCommand::replaceCollapsibleWhitespaceWithNonBreakingSpaceIfNee ded(const VisiblePosition& visiblePosition)
683 { 684 {
684 if (!isCollapsibleWhitespace(visiblePosition.characterAfter())) 685 if (!isCollapsibleWhitespace(visiblePosition.characterAfter()))
685 return; 686 return;
686 Position pos = visiblePosition.deepEquivalent().downstream(); 687 Position pos = visiblePosition.deepEquivalent().downstream();
687 if (!pos.containerNode() || !pos.containerNode()->isTextNode() || pos.contai nerNode()->hasTagName(brTag)) 688 if (!pos.containerNode() || !pos.containerNode()->isTextNode())
688 return; 689 return;
689 replaceTextInNodePreservingMarkers(pos.containerText(), pos.offsetInContaine rNode(), 1, nonBreakingSpaceString()); 690 replaceTextInNodePreservingMarkers(pos.containerText(), pos.offsetInContaine rNode(), 1, nonBreakingSpaceString());
690 } 691 }
691 692
692 void CompositeEditCommand::rebalanceWhitespace() 693 void CompositeEditCommand::rebalanceWhitespace()
693 { 694 {
694 VisibleSelection selection = endingSelection(); 695 VisibleSelection selection = endingSelection();
695 if (selection.isNone()) 696 if (selection.isNone())
696 return; 697 return;
697 698
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 858
858 return nullptr; 859 return nullptr;
859 } 860 }
860 861
861 // Assumes that the position is at a placeholder and does the removal without mu ch checking. 862 // Assumes that the position is at a placeholder and does the removal without mu ch checking.
862 void CompositeEditCommand::removePlaceholderAt(const Position& p) 863 void CompositeEditCommand::removePlaceholderAt(const Position& p)
863 { 864 {
864 ASSERT(lineBreakExistsAtPosition(p)); 865 ASSERT(lineBreakExistsAtPosition(p));
865 866
866 // We are certain that the position is at a line break, but it may be a br o r a preserved newline. 867 // We are certain that the position is at a line break, but it may be a br o r a preserved newline.
867 if (p.anchorNode()->hasTagName(brTag)) { 868 if (isHTMLBRElement(*p.anchorNode())) {
868 removeNode(p.anchorNode()); 869 removeNode(p.anchorNode());
869 return; 870 return;
870 } 871 }
871 872
872 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1); 873 deleteTextFromNode(toText(p.anchorNode()), p.offsetInContainerNode(), 1);
873 } 874 }
874 875
875 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position) 876 PassRefPtr<Node> CompositeEditCommand::insertNewDefaultParagraphElementAt(const Position& position)
876 { 877 {
877 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document()) ; 878 RefPtr<Element> paragraphElement = createDefaultParagraphElement(document()) ;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock (upstreamEnd.deprecatedNode()))); 927 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock (upstreamEnd.deprecatedNode())));
927 return nullptr; 928 return nullptr;
928 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { 929 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) {
929 // At the end of the editable region. We can bail here as well. 930 // At the end of the editable region. We can bail here as well.
930 return nullptr; 931 return nullptr;
931 } 932 }
932 } 933 }
933 934
934 RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); 935 RefPtr<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
935 936
936 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa gName(brTag); 937 bool endWasBr = isHTMLBRElement(*visibleParagraphEnd.deepEquivalent().deprec atedNode());
937 938
938 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f irstPositionInNode(newBlock.get()))); 939 moveParagraphs(visibleParagraphStart, visibleParagraphEnd, VisiblePosition(f irstPositionInNode(newBlock.get())));
939 940
940 if (newBlock->lastChild() && newBlock->lastChild()->hasTagName(brTag) && !en dWasBr) 941 if (newBlock->lastChild() && isHTMLBRElement(*newBlock->lastChild()) && !end WasBr)
941 removeNode(newBlock->lastChild()); 942 removeNode(newBlock->lastChild());
942 943
943 return newBlock.release(); 944 return newBlock.release();
944 } 945 }
945 946
946 void CompositeEditCommand::pushAnchorElementDown(Node* anchorNode) 947 void CompositeEditCommand::pushAnchorElementDown(Node* anchorNode)
947 { 948 {
948 if (!anchorNode) 949 if (!anchorNode)
949 return; 950 return;
950 951
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 if (caretAfterDelete != destination && isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) { 1042 if (caretAfterDelete != destination && isStartOfParagraph(caretAfterDelete) && isEndOfParagraph(caretAfterDelete)) {
1042 // Note: We want the rightmost candidate. 1043 // Note: We want the rightmost candidate.
1043 Position position = caretAfterDelete.deepEquivalent().downstream(); 1044 Position position = caretAfterDelete.deepEquivalent().downstream();
1044 Node* node = position.deprecatedNode(); 1045 Node* node = position.deprecatedNode();
1045 1046
1046 // Bail if we'd remove an ancestor of our destination. 1047 // Bail if we'd remove an ancestor of our destination.
1047 if (destinationNode && destinationNode->isDescendantOf(node)) 1048 if (destinationNode && destinationNode->isDescendantOf(node))
1048 return; 1049 return;
1049 1050
1050 // Normally deletion will leave a br as a placeholder. 1051 // Normally deletion will leave a br as a placeholder.
1051 if (node->hasTagName(brTag)) { 1052 if (isHTMLBRElement(*node)) {
1052 removeNodeAndPruneAncestors(node, destinationNode); 1053 removeNodeAndPruneAncestors(node, destinationNode);
1053 1054
1054 // If the selection to move was empty and in an empty block that 1055 // If the selection to move was empty and in an empty block that
1055 // doesn't require a placeholder to prop itself open (like a bordere d 1056 // doesn't require a placeholder to prop itself open (like a bordere d
1056 // div or an li), remove it during the move (the list removal code 1057 // div or an li), remove it during the move (the list removal code
1057 // expects this behavior). 1058 // expects this behavior).
1058 } else if (isBlock(node)) { 1059 } else if (isBlock(node)) {
1059 // If caret position after deletion and destination position coincid es, 1060 // If caret position after deletion and destination position coincid es,
1060 // node should not be removed. 1061 // node should not be removed.
1061 if (!position.rendersInDifferentPosition(destination.deepEquivalent( ))) { 1062 if (!position.rendersInDifferentPosition(destination.deepEquivalent( ))) {
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
1257 RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl eStart()); 1258 RefPtr<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl eStart());
1258 if (!emptyListItem) 1259 if (!emptyListItem)
1259 return false; 1260 return false;
1260 1261
1261 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start()) ; 1262 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start()) ;
1262 style->mergeTypingStyle(&document()); 1263 style->mergeTypingStyle(&document());
1263 1264
1264 RefPtr<ContainerNode> listNode = emptyListItem->parentNode(); 1265 RefPtr<ContainerNode> listNode = emptyListItem->parentNode();
1265 // FIXME: Can't we do something better when the immediate parent wasn't a li st node? 1266 // FIXME: Can't we do something better when the immediate parent wasn't a li st node?
1266 if (!listNode 1267 if (!listNode
1267 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) 1268 || (!isHTMLUListElement(*listNode) && !isHTMLOListElement(*listNode))
1268 || !listNode->rendererIsEditable() 1269 || !listNode->rendererIsEditable()
1269 || listNode == emptyListItem->rootEditableElement()) 1270 || listNode == emptyListItem->rootEditableElement())
1270 return false; 1271 return false;
1271 1272
1272 RefPtr<Element> newBlock = nullptr; 1273 RefPtr<Element> newBlock = nullptr;
1273 if (ContainerNode* blockEnclosingList = listNode->parentNode()) { 1274 if (ContainerNode* blockEnclosingList = listNode->parentNode()) {
1274 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth er list item 1275 if (isHTMLLIElement(*blockEnclosingList)) { // listNode is inside anothe r list item
1275 if (visiblePositionAfterNode(*blockEnclosingList) == visiblePosition AfterNode(*listNode)) { 1276 if (visiblePositionAfterNode(*blockEnclosingList) == visiblePosition AfterNode(*listNode)) {
1276 // If listNode appears at the end of the outer list item, then m ove listNode outside of this list item 1277 // If listNode appears at the end of the outer list item, then m ove listNode outside of this list item
1277 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section 1278 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section
1278 // If listNode does NOT appear at the end, then we should consid er it as a regular paragraph. 1279 // If listNode does NOT appear at the end, then we should consid er it as a regular paragraph.
1279 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b ecome <ul><li> <div><br></div> hello</li></ul> at the end 1280 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b ecome <ul><li> <div><br></div> hello</li></ul> at the end
1280 splitElement(toElement(blockEnclosingList), listNode); 1281 splitElement(toElement(blockEnclosingList), listNode);
1281 removeNodePreservingChildren(listNode->parentNode()); 1282 removeNodePreservingChildren(listNode->parentNode());
1282 newBlock = createListItemElement(document()); 1283 newBlock = createListItemElement(document());
1283 } 1284 }
1284 // If listNode does NOT appear at the end of the outer list item, th en behave as if in a regular paragraph. 1285 // If listNode does NOT appear at the end of the outer list item, th en behave as if in a regular paragraph.
1285 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList-> hasTagName(ulTag)) { 1286 } else if (isHTMLOListElement(*blockEnclosingList) || isHTMLUListElement (*blockEnclosingList)) {
1286 newBlock = createListItemElement(document()); 1287 newBlock = createListItemElement(document());
1287 } 1288 }
1288 } 1289 }
1289 if (!newBlock) 1290 if (!newBlock)
1290 newBlock = createDefaultParagraphElement(document()); 1291 newBlock = createDefaultParagraphElement(document());
1291 1292
1292 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTrav ersal::previousSibling(*emptyListItem): emptyListItem->previousSibling(); 1293 RefPtr<Node> previousListNode = emptyListItem->isElementNode() ? ElementTrav ersal::previousSibling(*emptyListItem): emptyListItem->previousSibling();
1293 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversa l::nextSibling(*emptyListItem): emptyListItem->nextSibling(); 1294 RefPtr<Node> nextListNode = emptyListItem->isElementNode() ? ElementTraversa l::nextSibling(*emptyListItem): emptyListItem->nextSibling();
1294 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) { 1295 if (isListItem(nextListNode.get()) || isListElement(nextListNode.get())) {
1295 // If emptyListItem follows another list item or nested list, split the list node. 1296 // If emptyListItem follows another list item or nested list, split the list node.
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1348 if (!isStartOfParagraph(atBR)) 1349 if (!isStartOfParagraph(atBR))
1349 insertNodeBefore(createBreakElement(document()), br); 1350 insertNodeBefore(createBreakElement(document()), br);
1350 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()) ); 1351 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()) );
1351 1352
1352 // If this is an empty paragraph there must be a line break here. 1353 // If this is an empty paragraph there must be a line break here.
1353 if (!lineBreakExistsAtVisiblePosition(caret)) 1354 if (!lineBreakExistsAtVisiblePosition(caret))
1354 return false; 1355 return false;
1355 1356
1356 Position caretPos(caret.deepEquivalent().downstream()); 1357 Position caretPos(caret.deepEquivalent().downstream());
1357 // A line break is either a br or a preserved newline. 1358 // A line break is either a br or a preserved newline.
1358 ASSERT(caretPos.deprecatedNode()->hasTagName(brTag) || (caretPos.deprecatedN ode()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveN ewline())); 1359 ASSERT(isHTMLBRElement(caretPos.deprecatedNode()) || (caretPos.deprecatedNod e()->isTextNode() && caretPos.deprecatedNode()->renderer()->style()->preserveNew line()));
1359 1360
1360 if (caretPos.deprecatedNode()->hasTagName(brTag)) 1361 if (isHTMLBRElement(*caretPos.deprecatedNode()))
1361 removeNodeAndPruneAncestors(caretPos.deprecatedNode()); 1362 removeNodeAndPruneAncestors(caretPos.deprecatedNode());
1362 else if (caretPos.deprecatedNode()->isTextNode()) { 1363 else if (caretPos.deprecatedNode()->isTextNode()) {
1363 ASSERT(caretPos.deprecatedEditingOffset() == 0); 1364 ASSERT(caretPos.deprecatedEditingOffset() == 0);
1364 Text* textNode = toText(caretPos.deprecatedNode()); 1365 Text* textNode = toText(caretPos.deprecatedNode());
1365 ContainerNode* parentNode = textNode->parentNode(); 1366 ContainerNode* parentNode = textNode->parentNode();
1366 // The preserved newline must be the first thing in the node, since othe rwise the previous 1367 // The preserved newline must be the first thing in the node, since othe rwise the previous
1367 // paragraph would be quoted, and we verified that it wasn't above. 1368 // paragraph would be quoted, and we verified that it wasn't above.
1368 deleteTextFromNode(textNode, 0, 1); 1369 deleteTextFromNode(textNode, 0, 1);
1369 prune(parentNode); 1370 prune(parentNode);
1370 } 1371 }
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1459 return node.release(); 1460 return node.release();
1460 } 1461 }
1461 1462
1462 PassRefPtr<Element> createBlockPlaceholderElement(Document& document) 1463 PassRefPtr<Element> createBlockPlaceholderElement(Document& document)
1463 { 1464 {
1464 RefPtr<Element> breakNode = document.createElement(brTag, false); 1465 RefPtr<Element> breakNode = document.createElement(brTag, false);
1465 return breakNode.release(); 1466 return breakNode.release();
1466 } 1467 }
1467 1468
1468 } // namespace WebCore 1469 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/editing/BreakBlockquoteCommand.cpp ('k') | Source/core/editing/DeleteSelectionCommand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698