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

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

Issue 421793002: Use tighter typing in editing: IndentOutdentCommand / InsertListCommand (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase Created 6 years, 4 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
« no previous file with comments | « Source/core/editing/CompositeEditCommand.cpp ('k') | Source/core/editing/InsertListCommand.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 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 22 matching lines...) Expand all
33 #include "core/editing/VisibleUnits.h" 33 #include "core/editing/VisibleUnits.h"
34 #include "core/editing/htmlediting.h" 34 #include "core/editing/htmlediting.h"
35 #include "core/html/HTMLBRElement.h" 35 #include "core/html/HTMLBRElement.h"
36 #include "core/html/HTMLElement.h" 36 #include "core/html/HTMLElement.h"
37 #include "core/rendering/RenderObject.h" 37 #include "core/rendering/RenderObject.h"
38 38
39 namespace blink { 39 namespace blink {
40 40
41 using namespace HTMLNames; 41 using namespace HTMLNames;
42 42
43 static bool isListOrIndentBlockquote(const Node* node) 43 static bool isHTMLListOrBlockquoteElement(const Node* node)
44 { 44 {
45 return node && (isHTMLUListElement(*node) || isHTMLOListElement(*node) || no de->hasTagName(blockquoteTag)); 45 if (!node || !node->isHTMLElement())
46 return false;
47 const HTMLElement& element = toHTMLElement(*node);
48 return isHTMLUListElement(element) || isHTMLOListElement(element) || element .hasTagName(blockquoteTag);
46 } 49 }
47 50
48 IndentOutdentCommand::IndentOutdentCommand(Document& document, EIndentType typeO fAction) 51 IndentOutdentCommand::IndentOutdentCommand(Document& document, EIndentType typeO fAction)
49 : ApplyBlockElementCommand(document, blockquoteTag, "margin: 0 0 0 40px; bor der: none; padding: 0px;") 52 : ApplyBlockElementCommand(document, blockquoteTag, "margin: 0 0 0 40px; bor der: none; padding: 0px;")
50 , m_typeOfAction(typeOfAction) 53 , m_typeOfAction(typeOfAction)
51 { 54 {
52 } 55 }
53 56
54 bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const P osition& end) 57 bool IndentOutdentCommand::tryIndentingAsListItem(const Position& start, const P osition& end)
55 { 58 {
56 // If our selection is not inside a list, bail out. 59 // If our selection is not inside a list, bail out.
57 RefPtrWillBeRawPtr<Node> lastNodeInSelectedParagraph = start.deprecatedNode( ); 60 RefPtrWillBeRawPtr<Node> lastNodeInSelectedParagraph = start.deprecatedNode( );
58 RefPtrWillBeRawPtr<Element> listNode = enclosingList(lastNodeInSelectedParag raph.get()); 61 RefPtrWillBeRawPtr<HTMLElement> listElement = enclosingList(lastNodeInSelect edParagraph.get());
59 if (!listNode) 62 if (!listElement)
60 return false; 63 return false;
61 64
62 // Find the block that we want to indent. If it's not a list item (e.g., a div inside a list item), we bail out. 65 // Find the block that we want to indent. If it's not a list item (e.g., a div inside a list item), we bail out.
63 RefPtrWillBeRawPtr<Element> selectedListItem = enclosingBlock(lastNodeInSele ctedParagraph.get()); 66 RefPtrWillBeRawPtr<Element> selectedListItem = enclosingBlock(lastNodeInSele ctedParagraph.get());
64 67
65 // FIXME: we need to deal with the case where there is no li (malformed HTML ) 68 // FIXME: we need to deal with the case where there is no li (malformed HTML )
66 if (!selectedListItem || !isHTMLLIElement(*selectedListItem)) 69 if (!isHTMLLIElement(selectedListItem))
67 return false; 70 return false;
68 71
69 // FIXME: previousElementSibling does not ignore non-rendered content like < span></span>. Should we? 72 // FIXME: previousElementSibling does not ignore non-rendered content like < span></span>. Should we?
70 RefPtrWillBeRawPtr<Element> previousList = ElementTraversal::previousSibling (*selectedListItem); 73 RefPtrWillBeRawPtr<Element> previousList = ElementTraversal::previousSibling (*selectedListItem);
71 RefPtrWillBeRawPtr<Element> nextList = ElementTraversal::nextSibling(*select edListItem); 74 RefPtrWillBeRawPtr<Element> nextList = ElementTraversal::nextSibling(*select edListItem);
72 75
73 // We should calculate visible range in list item because inserting new 76 // We should calculate visible range in list item because inserting new
74 // list element will change visibility of list item, e.g. :first-child 77 // list element will change visibility of list item, e.g. :first-child
75 // CSS selector. 78 // CSS selector.
76 RefPtrWillBeRawPtr<Element> newList = document().createElement(listNode->tag QName(), false); 79 RefPtrWillBeRawPtr<HTMLElement> newList = toHTMLElement(document().createEle ment(listElement->tagQName(), false).get());
77 insertNodeBefore(newList, selectedListItem.get()); 80 insertNodeBefore(newList, selectedListItem.get());
78 81
79 // We should clone all the children of the list item for indenting purposes. However, in case the current 82 // We should clone all the children of the list item for indenting purposes. However, in case the current
80 // selection does not encompass all its children, we need to explicitally ha ndle the same. The original 83 // selection does not encompass all its children, we need to explicitally ha ndle the same. The original
81 // list item too would require proper deletion in that case. 84 // list item too would require proper deletion in that case.
82 if (end.anchorNode() == selectedListItem.get() || end.anchorNode()->isDescen dantOf(selectedListItem->lastChild())) { 85 if (end.anchorNode() == selectedListItem.get() || end.anchorNode()->isDescen dantOf(selectedListItem->lastChild())) {
83 moveParagraphWithClones(VisiblePosition(start), VisiblePosition(end), ne wList.get(), selectedListItem.get()); 86 moveParagraphWithClones(VisiblePosition(start), VisiblePosition(end), ne wList.get(), selectedListItem.get());
84 } else { 87 } else {
85 moveParagraphWithClones(VisiblePosition(start), VisiblePosition(position AfterNode(selectedListItem->lastChild())), newList.get(), selectedListItem.get() ); 88 moveParagraphWithClones(VisiblePosition(start), VisiblePosition(position AfterNode(selectedListItem->lastChild())), newList.get(), selectedListItem.get() );
86 removeNode(selectedListItem.get()); 89 removeNode(selectedListItem.get());
87 } 90 }
88 91
89 if (canMergeLists(previousList.get(), newList.get())) 92 if (canMergeLists(previousList.get(), newList.get()))
90 mergeIdenticalElements(previousList.get(), newList.get()); 93 mergeIdenticalElements(previousList.get(), newList.get());
91 if (canMergeLists(newList.get(), nextList.get())) 94 if (canMergeLists(newList.get(), nextList.get()))
92 mergeIdenticalElements(newList.get(), nextList.get()); 95 mergeIdenticalElements(newList.get(), nextList.get());
93 96
94 return true; 97 return true;
95 } 98 }
96 99
97 void IndentOutdentCommand::indentIntoBlockquote(const Position& start, const Pos ition& end, RefPtrWillBeRawPtr<HTMLElement>& targetBlockquote) 100 void IndentOutdentCommand::indentIntoBlockquote(const Position& start, const Pos ition& end, RefPtrWillBeRawPtr<HTMLElement>& targetBlockquote)
98 { 101 {
99 Node* enclosingCell = enclosingNodeOfType(start, &isTableCell); 102 Element* enclosingCell = toElement(enclosingNodeOfType(start, &isTableCell)) ;
100 Node* nodeToSplitTo; 103 Element* elementToSplitTo;
101 if (enclosingCell) 104 if (enclosingCell)
102 nodeToSplitTo = enclosingCell; 105 elementToSplitTo = enclosingCell;
103 else if (enclosingList(start.containerNode())) 106 else if (enclosingList(start.containerNode()))
104 nodeToSplitTo = enclosingBlock(start.containerNode()); 107 elementToSplitTo = enclosingBlock(start.containerNode());
105 else 108 else
106 nodeToSplitTo = editableRootForPosition(start); 109 elementToSplitTo = editableRootForPosition(start);
107 110
108 if (!nodeToSplitTo) 111 if (!elementToSplitTo)
109 return; 112 return;
110 113
111 RefPtrWillBeRawPtr<Node> outerBlock = (start.containerNode() == nodeToSplitT o) ? start.containerNode() : splitTreeToNode(start.containerNode(), nodeToSplitT o).get(); 114 RefPtrWillBeRawPtr<Node> outerBlock = (start.containerNode() == elementToSpl itTo) ? start.containerNode() : splitTreeToNode(start.containerNode(), elementTo SplitTo).get();
112 115
113 VisiblePosition startOfContents(start); 116 VisiblePosition startOfContents(start);
114 if (!targetBlockquote) { 117 if (!targetBlockquote) {
115 // Create a new blockquote and insert it as a child of the root editable element. We accomplish 118 // Create a new blockquote and insert it as a child of the root editable element. We accomplish
116 // this by splitting all parents of the current paragraph up to that poi nt. 119 // this by splitting all parents of the current paragraph up to that poi nt.
117 targetBlockquote = createBlockElement(); 120 targetBlockquote = createBlockElement();
118 if (outerBlock == start.containerNode()) 121 if (outerBlock == start.containerNode())
119 insertNodeAt(targetBlockquote, start); 122 insertNodeAt(targetBlockquote, start);
120 else 123 else
121 insertNodeBefore(targetBlockquote, outerBlock); 124 insertNodeBefore(targetBlockquote, outerBlock);
122 startOfContents = VisiblePosition(positionInParentAfterNode(*targetBlock quote)); 125 startOfContents = VisiblePosition(positionInParentAfterNode(*targetBlock quote));
123 } 126 }
124 127
125 VisiblePosition endOfContents(end); 128 VisiblePosition endOfContents(end);
126 if (startOfContents.isNull() || endOfContents.isNull()) 129 if (startOfContents.isNull() || endOfContents.isNull())
127 return; 130 return;
128 moveParagraphWithClones(startOfContents, endOfContents, targetBlockquote.get (), outerBlock.get()); 131 moveParagraphWithClones(startOfContents, endOfContents, targetBlockquote.get (), outerBlock.get());
129 } 132 }
130 133
131 void IndentOutdentCommand::outdentParagraph() 134 void IndentOutdentCommand::outdentParagraph()
132 { 135 {
133 VisiblePosition visibleStartOfParagraph = startOfParagraph(endingSelection() .visibleStart()); 136 VisiblePosition visibleStartOfParagraph = startOfParagraph(endingSelection() .visibleStart());
134 VisiblePosition visibleEndOfParagraph = endOfParagraph(visibleStartOfParagra ph); 137 VisiblePosition visibleEndOfParagraph = endOfParagraph(visibleStartOfParagra ph);
135 138
136 Node* enclosingNode = enclosingNodeOfType(visibleStartOfParagraph.deepEquiva lent(), &isListOrIndentBlockquote); 139 HTMLElement* enclosingElement = toHTMLElement(enclosingNodeOfType(visibleSta rtOfParagraph.deepEquivalent(), &isHTMLListOrBlockquoteElement));
137 if (!enclosingNode || !enclosingNode->parentNode()->hasEditableStyle()) // W e can't outdent if there is no place to go! 140 if (!enclosingElement || !enclosingElement->parentNode()->hasEditableStyle() ) // We can't outdent if there is no place to go!
138 return; 141 return;
139 142
140 // Use InsertListCommand to remove the selection from the list 143 // Use InsertListCommand to remove the selection from the list
141 if (isHTMLOListElement(*enclosingNode)) { 144 if (isHTMLOListElement(*enclosingElement)) {
142 applyCommandToComposite(InsertListCommand::create(document(), InsertList Command::OrderedList)); 145 applyCommandToComposite(InsertListCommand::create(document(), InsertList Command::OrderedList));
143 return; 146 return;
144 } 147 }
145 if (isHTMLUListElement(*enclosingNode)) { 148 if (isHTMLUListElement(*enclosingElement)) {
146 applyCommandToComposite(InsertListCommand::create(document(), InsertList Command::UnorderedList)); 149 applyCommandToComposite(InsertListCommand::create(document(), InsertList Command::UnorderedList));
147 return; 150 return;
148 } 151 }
149 152
150 // The selection is inside a blockquote i.e. enclosingNode is a blockquote 153 // The selection is inside a blockquote i.e. enclosingNode is a blockquote
151 VisiblePosition positionInEnclosingBlock = VisiblePosition(firstPositionInNo de(enclosingNode)); 154 VisiblePosition positionInEnclosingBlock = VisiblePosition(firstPositionInNo de(enclosingElement));
152 // If the blockquote is inline, the start of the enclosing block coincides w ith 155 // If the blockquote is inline, the start of the enclosing block coincides w ith
153 // positionInEnclosingBlock. 156 // positionInEnclosingBlock.
154 VisiblePosition startOfEnclosingBlock = (enclosingNode->renderer() && enclos ingNode->renderer()->isInline()) ? positionInEnclosingBlock : startOfBlock(posit ionInEnclosingBlock); 157 VisiblePosition startOfEnclosingBlock = (enclosingElement->renderer() && enc losingElement->renderer()->isInline()) ? positionInEnclosingBlock : startOfBlock (positionInEnclosingBlock);
155 VisiblePosition lastPositionInEnclosingBlock = VisiblePosition(lastPositionI nNode(enclosingNode)); 158 VisiblePosition lastPositionInEnclosingBlock = VisiblePosition(lastPositionI nNode(enclosingElement));
156 VisiblePosition endOfEnclosingBlock = endOfBlock(lastPositionInEnclosingBloc k); 159 VisiblePosition endOfEnclosingBlock = endOfBlock(lastPositionInEnclosingBloc k);
157 if (visibleStartOfParagraph == startOfEnclosingBlock && 160 if (visibleStartOfParagraph == startOfEnclosingBlock &&
158 visibleEndOfParagraph == endOfEnclosingBlock) { 161 visibleEndOfParagraph == endOfEnclosingBlock) {
159 // The blockquote doesn't contain anything outside the paragraph, so it can be totally removed. 162 // The blockquote doesn't contain anything outside the paragraph, so it can be totally removed.
160 Node* splitPoint = enclosingNode->nextSibling(); 163 Node* splitPoint = enclosingElement->nextSibling();
161 removeNodePreservingChildren(enclosingNode); 164 removeNodePreservingChildren(enclosingElement);
162 // outdentRegion() assumes it is operating on the first paragraph of an enclosing blockquote, but if there are multiply nested blockquotes and we've 165 // outdentRegion() assumes it is operating on the first paragraph of an enclosing blockquote, but if there are multiply nested blockquotes and we've
163 // just removed one, then this assumption isn't true. By splitting the n ext containing blockquote after this node, we keep this assumption true 166 // just removed one, then this assumption isn't true. By splitting the n ext containing blockquote after this node, we keep this assumption true
164 if (splitPoint) { 167 if (splitPoint) {
165 if (ContainerNode* splitPointParent = splitPoint->parentNode()) { 168 if (Element* splitPointParent = splitPoint->parentElement()) {
166 if (splitPointParent->hasTagName(blockquoteTag) 169 if (splitPointParent->hasTagName(blockquoteTag)
167 && !splitPoint->hasTagName(blockquoteTag) 170 && !splitPoint->hasTagName(blockquoteTag)
168 && splitPointParent->parentNode()->hasEditableStyle()) // We can't outdent if there is no place to go! 171 && splitPointParent->parentNode()->hasEditableStyle()) // We can't outdent if there is no place to go!
169 splitElement(toElement(splitPointParent), splitPoint); 172 splitElement(splitPointParent, splitPoint);
170 } 173 }
171 } 174 }
172 175
173 document().updateLayoutIgnorePendingStylesheets(); 176 document().updateLayoutIgnorePendingStylesheets();
174 visibleStartOfParagraph = VisiblePosition(visibleStartOfParagraph.deepEq uivalent()); 177 visibleStartOfParagraph = VisiblePosition(visibleStartOfParagraph.deepEq uivalent());
175 visibleEndOfParagraph = VisiblePosition(visibleEndOfParagraph.deepEquiva lent()); 178 visibleEndOfParagraph = VisiblePosition(visibleEndOfParagraph.deepEquiva lent());
176 if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleSt artOfParagraph)) 179 if (visibleStartOfParagraph.isNotNull() && !isStartOfParagraph(visibleSt artOfParagraph))
177 insertNodeAt(createBreakElement(document()), visibleStartOfParagraph .deepEquivalent()); 180 insertNodeAt(createBreakElement(document()), visibleStartOfParagraph .deepEquivalent());
178 if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfP aragraph)) 181 if (visibleEndOfParagraph.isNotNull() && !isEndOfParagraph(visibleEndOfP aragraph))
179 insertNodeAt(createBreakElement(document()), visibleEndOfParagraph.d eepEquivalent()); 182 insertNodeAt(createBreakElement(document()), visibleEndOfParagraph.d eepEquivalent());
180 183
181 return; 184 return;
182 } 185 }
183 RefPtrWillBeRawPtr<Node> splitBlockquoteNode = enclosingNode; 186 RefPtrWillBeRawPtr<Node> splitBlockquoteNode = enclosingElement;
184 if (Node* enclosingBlockFlow = enclosingBlock(visibleStartOfParagraph.deepEq uivalent().deprecatedNode())) { 187 if (Element* enclosingBlockFlow = enclosingBlock(visibleStartOfParagraph.dee pEquivalent().deprecatedNode())) {
185 if (enclosingBlockFlow != enclosingNode) { 188 if (enclosingBlockFlow != enclosingElement) {
186 splitBlockquoteNode = splitTreeToNode(enclosingBlockFlow, enclosingN ode, true); 189 splitBlockquoteNode = splitTreeToNode(enclosingBlockFlow, enclosingE lement, true);
187 } else { 190 } else {
188 // We split the blockquote at where we start outdenting. 191 // We split the blockquote at where we start outdenting.
189 Node* highestInlineNode = highestEnclosingNodeOfType(visibleStartOfP aragraph.deepEquivalent(), isInline, CannotCrossEditingBoundary, enclosingBlockF low); 192 Node* highestInlineNode = highestEnclosingNodeOfType(visibleStartOfP aragraph.deepEquivalent(), isInline, CannotCrossEditingBoundary, enclosingBlockF low);
190 splitElement(toElement(enclosingNode), (highestInlineNode) ? highest InlineNode : visibleStartOfParagraph.deepEquivalent().deprecatedNode()); 193 splitElement(enclosingElement, highestInlineNode ? highestInlineNode : visibleStartOfParagraph.deepEquivalent().deprecatedNode());
191 } 194 }
192 } 195 }
193 VisiblePosition startOfParagraphToMove(startOfParagraph(visibleStartOfParagr aph)); 196 VisiblePosition startOfParagraphToMove(startOfParagraph(visibleStartOfParagr aph));
194 VisiblePosition endOfParagraphToMove(endOfParagraph(visibleEndOfParagraph)); 197 VisiblePosition endOfParagraphToMove(endOfParagraph(visibleEndOfParagraph));
195 if (startOfParagraphToMove.isNull() || endOfParagraphToMove.isNull()) 198 if (startOfParagraphToMove.isNull() || endOfParagraphToMove.isNull())
196 return; 199 return;
197 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document( )); 200 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document( ));
198 insertNodeBefore(placeholder, splitBlockquoteNode); 201 insertNodeBefore(placeholder, splitBlockquoteNode);
199 moveParagraph(startOfParagraphToMove, endOfParagraphToMove, VisiblePosition( positionBeforeNode(placeholder.get())), true); 202 moveParagraph(startOfParagraphToMove, endOfParagraphToMove, VisiblePosition( positionBeforeNode(placeholder.get())), true);
200 } 203 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 249
247 void IndentOutdentCommand::formatRange(const Position& start, const Position& en d, const Position&, RefPtrWillBeRawPtr<HTMLElement>& blockquoteForNextIndent) 250 void IndentOutdentCommand::formatRange(const Position& start, const Position& en d, const Position&, RefPtrWillBeRawPtr<HTMLElement>& blockquoteForNextIndent)
248 { 251 {
249 if (tryIndentingAsListItem(start, end)) 252 if (tryIndentingAsListItem(start, end))
250 blockquoteForNextIndent = nullptr; 253 blockquoteForNextIndent = nullptr;
251 else 254 else
252 indentIntoBlockquote(start, end, blockquoteForNextIndent); 255 indentIntoBlockquote(start, end, blockquoteForNextIndent);
253 } 256 }
254 257
255 } 258 }
OLDNEW
« no previous file with comments | « Source/core/editing/CompositeEditCommand.cpp ('k') | Source/core/editing/InsertListCommand.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698