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

Side by Side Diff: Source/core/editing/InsertListCommand.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/InsertListCommand.h ('k') | no next file » | 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, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2010 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 using namespace HTMLNames; 44 using namespace HTMLNames;
45 45
46 static Node* enclosingListChild(Node* node, Node* listNode) 46 static Node* enclosingListChild(Node* node, Node* listNode)
47 { 47 {
48 Node* listChild = enclosingListChild(node); 48 Node* listChild = enclosingListChild(node);
49 while (listChild && enclosingList(listChild) != listNode) 49 while (listChild && enclosingList(listChild) != listNode)
50 listChild = enclosingListChild(listChild->parentNode()); 50 listChild = enclosingListChild(listChild->parentNode());
51 return listChild; 51 return listChild;
52 } 52 }
53 53
54 HTMLElement* InsertListCommand::fixOrphanedListChild(Node* node) 54 HTMLUListElement* InsertListCommand::fixOrphanedListChild(Node* node)
55 { 55 {
56 RefPtrWillBeRawPtr<HTMLUListElement> listElement = createUnorderedListElemen t(document()); 56 RefPtrWillBeRawPtr<HTMLUListElement> listElement = createUnorderedListElemen t(document());
57 insertNodeBefore(listElement, node); 57 insertNodeBefore(listElement, node);
58 removeNode(node); 58 removeNode(node);
59 appendNode(node, listElement); 59 appendNode(node, listElement);
60 m_listElement = listElement; 60 m_listElement = listElement;
61 return listElement.get(); 61 return listElement.get();
62 } 62 }
63 63
64 PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists (PassRefPtrWillBeRawPtr<HTMLElement> passedList) 64 PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::mergeWithNeighboringLists (PassRefPtrWillBeRawPtr<HTMLElement> passedList)
(...skipping 20 matching lines...) Expand all
85 85
86 bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection , const HTMLQualifiedName& listTag) 86 bool InsertListCommand::selectionHasListOfType(const VisibleSelection& selection , const HTMLQualifiedName& listTag)
87 { 87 {
88 VisiblePosition start = selection.visibleStart(); 88 VisiblePosition start = selection.visibleStart();
89 89
90 if (!enclosingList(start.deepEquivalent().deprecatedNode())) 90 if (!enclosingList(start.deepEquivalent().deprecatedNode()))
91 return false; 91 return false;
92 92
93 VisiblePosition end = startOfParagraph(selection.visibleEnd()); 93 VisiblePosition end = startOfParagraph(selection.visibleEnd());
94 while (start.isNotNull() && start != end) { 94 while (start.isNotNull() && start != end) {
95 Element* listNode = enclosingList(start.deepEquivalent().deprecatedNode( )); 95 HTMLElement* listElement = enclosingList(start.deepEquivalent().deprecat edNode());
96 if (!listNode || !listNode->hasTagName(listTag)) 96 if (!listElement || !listElement->hasTagName(listTag))
97 return false; 97 return false;
98 start = startOfNextParagraph(start); 98 start = startOfNextParagraph(start);
99 } 99 }
100 100
101 return true; 101 return true;
102 } 102 }
103 103
104 InsertListCommand::InsertListCommand(Document& document, Type type) 104 InsertListCommand::InsertListCommand(Document& document, Type type)
105 : CompositeEditCommand(document), m_type(type) 105 : CompositeEditCommand(document), m_type(type)
106 { 106 {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const HT MLQualifiedName& listTag, Range& currentSelection) 203 void InsertListCommand::doApplyForSingleParagraph(bool forceCreateList, const HT MLQualifiedName& listTag, Range& currentSelection)
204 { 204 {
205 // FIXME: This will produce unexpected results for a selection that starts j ust before a 205 // FIXME: This will produce unexpected results for a selection that starts j ust before a
206 // table and ends inside the first cell, selectionForParagraphIteration shou ld probably 206 // table and ends inside the first cell, selectionForParagraphIteration shou ld probably
207 // be renamed and deployed inside setEndingSelection(). 207 // be renamed and deployed inside setEndingSelection().
208 Node* selectionNode = endingSelection().start().deprecatedNode(); 208 Node* selectionNode = endingSelection().start().deprecatedNode();
209 Node* listChildNode = enclosingListChild(selectionNode); 209 Node* listChildNode = enclosingListChild(selectionNode);
210 bool switchListType = false; 210 bool switchListType = false;
211 if (listChildNode) { 211 if (listChildNode) {
212 // Remove the list chlild. 212 // Remove the list chlild.
213 RefPtrWillBeRawPtr<HTMLElement> listNode = enclosingList(listChildNode); 213 RefPtrWillBeRawPtr<HTMLElement> listElement = enclosingList(listChildNod e);
214 if (!listNode) { 214 if (!listElement) {
215 listNode = fixOrphanedListChild(listChildNode); 215 listElement = fixOrphanedListChild(listChildNode);
216 listNode = mergeWithNeighboringLists(listNode); 216 listElement = mergeWithNeighboringLists(listElement);
217 } 217 }
218 if (!listNode->hasTagName(listTag)) 218 if (!listElement->hasTagName(listTag))
219 // listChildNode will be removed from the list and a list of type m_ type will be created. 219 // listChildNode will be removed from the list and a list of type m_ type will be created.
220 switchListType = true; 220 switchListType = true;
221 221
222 // If the list is of the desired type, and we are not removing the list, then exit early. 222 // If the list is of the desired type, and we are not removing the list, then exit early.
223 if (!switchListType && forceCreateList) 223 if (!switchListType && forceCreateList)
224 return; 224 return;
225 225
226 // If the entire list is selected, then convert the whole list. 226 // If the entire list is selected, then convert the whole list.
227 if (switchListType && isNodeVisiblyContainedWithin(*listNode, currentSel ection)) { 227 if (switchListType && isNodeVisiblyContainedWithin(*listElement, current Selection)) {
228 bool rangeStartIsInList = visiblePositionBeforeNode(*listNode) == Vi siblePosition(currentSelection.startPosition()); 228 bool rangeStartIsInList = visiblePositionBeforeNode(*listElement) == VisiblePosition(currentSelection.startPosition());
229 bool rangeEndIsInList = visiblePositionAfterNode(*listNode) == Visib lePosition(currentSelection.endPosition()); 229 bool rangeEndIsInList = visiblePositionAfterNode(*listElement) == Vi siblePosition(currentSelection.endPosition());
230 230
231 RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document (), listTag); 231 RefPtrWillBeRawPtr<HTMLElement> newList = createHTMLElement(document (), listTag);
232 insertNodeBefore(newList, listNode); 232 insertNodeBefore(newList, listElement);
233 233
234 Node* firstChildInList = enclosingListChild(VisiblePosition(firstPos itionInNode(listNode.get())).deepEquivalent().deprecatedNode(), listNode.get()); 234 Node* firstChildInList = enclosingListChild(VisiblePosition(firstPos itionInNode(listElement.get())).deepEquivalent().deprecatedNode(), listElement.g et());
235 Node* outerBlock = firstChildInList && firstChildInList->isBlockFlow Element() ? firstChildInList : listNode.get(); 235 Element* outerBlock = firstChildInList && firstChildInList->isBlockF lowElement() ? toElement(firstChildInList) : listElement.get();
236 236
237 moveParagraphWithClones(VisiblePosition(firstPositionInNode(listNode .get())), VisiblePosition(lastPositionInNode(listNode.get())), newList.get(), ou terBlock); 237 moveParagraphWithClones(VisiblePosition(firstPositionInNode(listElem ent.get())), VisiblePosition(lastPositionInNode(listElement.get())), newList.get (), outerBlock);
238 238
239 // Manually remove listNode because moveParagraphWithClones sometime s leaves it behind in the document. 239 // Manually remove listNode because moveParagraphWithClones sometime s leaves it behind in the document.
240 // See the bug 33668 and editing/execCommand/insert-list-orphaned-it em-with-nested-lists.html. 240 // See the bug 33668 and editing/execCommand/insert-list-orphaned-it em-with-nested-lists.html.
241 // FIXME: This might be a bug in moveParagraphWithClones or deleteSe lection. 241 // FIXME: This might be a bug in moveParagraphWithClones or deleteSe lection.
242 if (listNode && listNode->inDocument()) 242 if (listElement && listElement->inDocument())
243 removeNode(listNode); 243 removeNode(listElement);
244 244
245 newList = mergeWithNeighboringLists(newList); 245 newList = mergeWithNeighboringLists(newList);
246 246
247 // Restore the start and the end of current selection if they starte d inside listNode 247 // Restore the start and the end of current selection if they starte d inside listNode
248 // because moveParagraphWithClones could have removed them. 248 // because moveParagraphWithClones could have removed them.
249 if (rangeStartIsInList && newList) 249 if (rangeStartIsInList && newList)
250 currentSelection.setStart(newList, 0, IGNORE_EXCEPTION); 250 currentSelection.setStart(newList, 0, IGNORE_EXCEPTION);
251 if (rangeEndIsInList && newList) 251 if (rangeEndIsInList && newList)
252 currentSelection.setEnd(newList, lastOffsetInNode(newList.get()) , IGNORE_EXCEPTION); 252 currentSelection.setEnd(newList, lastOffsetInNode(newList.get()) , IGNORE_EXCEPTION);
253 253
254 setEndingSelection(VisiblePosition(firstPositionInNode(newList.get() ))); 254 setEndingSelection(VisiblePosition(firstPositionInNode(newList.get() )));
255 255
256 return; 256 return;
257 } 257 }
258 258
259 unlistifyParagraph(endingSelection().visibleStart(), listNode.get(), lis tChildNode); 259 unlistifyParagraph(endingSelection().visibleStart(), listElement.get(), listChildNode);
260 } 260 }
261 261
262 if (!listChildNode || switchListType || forceCreateList) 262 if (!listChildNode || switchListType || forceCreateList)
263 m_listElement = listifyParagraph(endingSelection().visibleStart(), listT ag); 263 m_listElement = listifyParagraph(endingSelection().visibleStart(), listT ag);
264 } 264 }
265 265
266 void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart, HTMLElement* listNode, Node* listChildNode) 266 void InsertListCommand::unlistifyParagraph(const VisiblePosition& originalStart, HTMLElement* listElement, Node* listChildNode)
267 { 267 {
268 Node* nextListChild; 268 Node* nextListChild;
269 Node* previousListChild; 269 Node* previousListChild;
270 VisiblePosition start; 270 VisiblePosition start;
271 VisiblePosition end; 271 VisiblePosition end;
272 ASSERT(listChildNode); 272 ASSERT(listChildNode);
273 if (isHTMLLIElement(*listChildNode)) { 273 if (isHTMLLIElement(*listChildNode)) {
274 start = VisiblePosition(firstPositionInNode(listChildNode)); 274 start = VisiblePosition(firstPositionInNode(listChildNode));
275 end = VisiblePosition(lastPositionInNode(listChildNode)); 275 end = VisiblePosition(lastPositionInNode(listChildNode));
276 nextListChild = listChildNode->nextSibling(); 276 nextListChild = listChildNode->nextSibling();
277 previousListChild = listChildNode->previousSibling(); 277 previousListChild = listChildNode->previousSibling();
278 } else { 278 } else {
279 // A paragraph is visually a list item minus a list marker. The paragra ph will be moved. 279 // A paragraph is visually a list item minus a list marker. The paragra ph will be moved.
280 start = startOfParagraph(originalStart, CanSkipOverEditingBoundary); 280 start = startOfParagraph(originalStart, CanSkipOverEditingBoundary);
281 end = endOfParagraph(start, CanSkipOverEditingBoundary); 281 end = endOfParagraph(start, CanSkipOverEditingBoundary);
282 nextListChild = enclosingListChild(end.next().deepEquivalent().deprecate dNode(), listNode); 282 nextListChild = enclosingListChild(end.next().deepEquivalent().deprecate dNode(), listElement);
283 ASSERT(nextListChild != listChildNode); 283 ASSERT(nextListChild != listChildNode);
284 previousListChild = enclosingListChild(start.previous().deepEquivalent() .deprecatedNode(), listNode); 284 previousListChild = enclosingListChild(start.previous().deepEquivalent() .deprecatedNode(), listElement);
285 ASSERT(previousListChild != listChildNode); 285 ASSERT(previousListChild != listChildNode);
286 } 286 }
287 // When removing a list, we must always create a placeholder to act as a poi nt of insertion 287 // When removing a list, we must always create a placeholder to act as a poi nt of insertion
288 // for the list content being removed. 288 // for the list content being removed.
289 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document( )); 289 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document( ));
290 RefPtrWillBeRawPtr<HTMLElement> elementToInsert = placeholder; 290 RefPtrWillBeRawPtr<HTMLElement> elementToInsert = placeholder;
291 // If the content of the list item will be moved into another list, put it i n a list item 291 // If the content of the list item will be moved into another list, put it i n a list item
292 // so that we don't create an orphaned list child. 292 // so that we don't create an orphaned list child.
293 if (enclosingList(listNode)) { 293 if (enclosingList(listElement)) {
294 elementToInsert = createListItemElement(document()); 294 elementToInsert = createListItemElement(document());
295 appendNode(placeholder, elementToInsert); 295 appendNode(placeholder, elementToInsert);
296 } 296 }
297 297
298 if (nextListChild && previousListChild) { 298 if (nextListChild && previousListChild) {
299 // We want to pull listChildNode out of listNode, and place it before ne xtListChild 299 // We want to pull listChildNode out of listNode, and place it before ne xtListChild
300 // and after previousListChild, so we split listNode and insert it betwe en the two lists. 300 // and after previousListChild, so we split listNode and insert it betwe en the two lists.
301 // But to split listNode, we must first split ancestors of listChildNode between it and listNode, 301 // But to split listNode, we must first split ancestors of listChildNode between it and listNode,
302 // if any exist. 302 // if any exist.
303 // FIXME: We appear to split at nextListChild as opposed to listChildNod e so that when we remove 303 // FIXME: We appear to split at nextListChild as opposed to listChildNod e so that when we remove
304 // listChildNode below in moveParagraphs, previousListChild will be remo ved along with it if it is 304 // listChildNode below in moveParagraphs, previousListChild will be remo ved along with it if it is
305 // unrendered. But we ought to remove nextListChild too, if it is unrend ered. 305 // unrendered. But we ought to remove nextListChild too, if it is unrend ered.
306 splitElement(listNode, splitTreeToNode(nextListChild, listNode)); 306 splitElement(listElement, splitTreeToNode(nextListChild, listElement));
307 insertNodeBefore(elementToInsert, listNode); 307 insertNodeBefore(elementToInsert, listElement);
308 } else if (nextListChild || listChildNode->parentNode() != listNode) { 308 } else if (nextListChild || listChildNode->parentNode() != listElement) {
309 // Just because listChildNode has no previousListChild doesn't mean ther e isn't any content 309 // Just because listChildNode has no previousListChild doesn't mean ther e isn't any content
310 // in listNode that comes before listChildNode, as listChildNode could h ave ancestors 310 // in listNode that comes before listChildNode, as listChildNode could h ave ancestors
311 // between it and listNode. So, we split up to listNode before inserting the placeholder 311 // between it and listNode. So, we split up to listNode before inserting the placeholder
312 // where we're about to move listChildNode to. 312 // where we're about to move listChildNode to.
313 if (listChildNode->parentNode() != listNode) 313 if (listChildNode->parentNode() != listElement)
314 splitElement(listNode, splitTreeToNode(listChildNode, listNode).get( )); 314 splitElement(listElement, splitTreeToNode(listChildNode, listElement ).get());
315 insertNodeBefore(elementToInsert, listNode); 315 insertNodeBefore(elementToInsert, listElement);
316 } else { 316 } else {
317 insertNodeAfter(elementToInsert, listNode); 317 insertNodeAfter(elementToInsert, listElement);
318 } 318 }
319 319
320 VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placehol der.get())); 320 VisiblePosition insertionPoint = VisiblePosition(positionBeforeNode(placehol der.get()));
321 moveParagraphs(start, end, insertionPoint, /* preserveSelection */ true, /* preserveStyle */ true, listChildNode); 321 moveParagraphs(start, end, insertionPoint, /* preserveSelection */ true, /* preserveStyle */ true, listChildNode);
322 } 322 }
323 323
324 static Element* adjacentEnclosingList(const VisiblePosition& pos, const VisibleP osition& adjacentPos, const HTMLQualifiedName& listTag) 324 static HTMLElement* adjacentEnclosingList(const VisiblePosition& pos, const Visi blePosition& adjacentPos, const HTMLQualifiedName& listTag)
325 { 325 {
326 Element* listNode = outermostEnclosingList(adjacentPos.deepEquivalent().depr ecatedNode()); 326 HTMLElement* listElement = outermostEnclosingList(adjacentPos.deepEquivalent ().deprecatedNode());
327 327
328 if (!listNode) 328 if (!listElement)
329 return 0; 329 return 0;
330 330
331 Element* previousCell = enclosingTableCell(pos.deepEquivalent()); 331 Element* previousCell = enclosingTableCell(pos.deepEquivalent());
332 Element* currentCell = enclosingTableCell(adjacentPos.deepEquivalent()); 332 Element* currentCell = enclosingTableCell(adjacentPos.deepEquivalent());
333 333
334 if (!listNode->hasTagName(listTag) 334 if (!listElement->hasTagName(listTag)
335 || listNode->contains(pos.deepEquivalent().deprecatedNode()) 335 || listElement->contains(pos.deepEquivalent().deprecatedNode())
336 || previousCell != currentCell 336 || previousCell != currentCell
337 || enclosingList(listNode) != enclosingList(pos.deepEquivalent().depreca tedNode())) 337 || enclosingList(listElement) != enclosingList(pos.deepEquivalent().depr ecatedNode()))
338 return 0; 338 return 0;
339 339
340 return listNode; 340 return listElement;
341 } 341 }
342 342
343 PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::listifyParagraph(const Vi siblePosition& originalStart, const HTMLQualifiedName& listTag) 343 PassRefPtrWillBeRawPtr<HTMLElement> InsertListCommand::listifyParagraph(const Vi siblePosition& originalStart, const HTMLQualifiedName& listTag)
344 { 344 {
345 VisiblePosition start = startOfParagraph(originalStart, CanSkipOverEditingBo undary); 345 VisiblePosition start = startOfParagraph(originalStart, CanSkipOverEditingBo undary);
346 VisiblePosition end = endOfParagraph(start, CanSkipOverEditingBoundary); 346 VisiblePosition end = endOfParagraph(start, CanSkipOverEditingBoundary);
347 347
348 if (start.isNull() || end.isNull()) 348 if (start.isNull() || end.isNull())
349 return nullptr; 349 return nullptr;
350 350
351 // Check for adjoining lists. 351 // Check for adjoining lists.
352 RefPtrWillBeRawPtr<HTMLElement> listItemElement = createListItemElement(docu ment()); 352 RefPtrWillBeRawPtr<HTMLElement> listItemElement = createListItemElement(docu ment());
353 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document( )); 353 RefPtrWillBeRawPtr<HTMLBRElement> placeholder = createBreakElement(document( ));
354 appendNode(placeholder, listItemElement); 354 appendNode(placeholder, listItemElement);
355 355
356 // Place list item into adjoining lists. 356 // Place list item into adjoining lists.
357 Element* previousList = adjacentEnclosingList(start, start.previous(CannotCr ossEditingBoundary), listTag); 357 HTMLElement* previousList = adjacentEnclosingList(start, start.previous(Cann otCrossEditingBoundary), listTag);
358 Element* nextList = adjacentEnclosingList(start, end.next(CannotCrossEditing Boundary), listTag); 358 HTMLElement* nextList = adjacentEnclosingList(start, end.next(CannotCrossEdi tingBoundary), listTag);
359 RefPtrWillBeRawPtr<HTMLElement> listElement = nullptr; 359 RefPtrWillBeRawPtr<HTMLElement> listElement = nullptr;
360 if (previousList) 360 if (previousList)
361 appendNode(listItemElement, previousList); 361 appendNode(listItemElement, previousList);
362 else if (nextList) 362 else if (nextList)
363 insertNodeAt(listItemElement, positionBeforeNode(nextList)); 363 insertNodeAt(listItemElement, positionBeforeNode(nextList));
364 else { 364 else {
365 // Create the list. 365 // Create the list.
366 listElement = createHTMLElement(document(), listTag); 366 listElement = createHTMLElement(document(), listTag);
367 appendNode(listItemElement, listElement); 367 appendNode(listItemElement, listElement);
368 368
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 return listElement; 412 return listElement;
413 } 413 }
414 414
415 void InsertListCommand::trace(Visitor* visitor) 415 void InsertListCommand::trace(Visitor* visitor)
416 { 416 {
417 visitor->trace(m_listElement); 417 visitor->trace(m_listElement);
418 CompositeEditCommand::trace(visitor); 418 CompositeEditCommand::trace(visitor);
419 } 419 }
420 420
421 } 421 }
OLDNEW
« no previous file with comments | « Source/core/editing/InsertListCommand.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698