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

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

Issue 434393003: Use tighter typing in editing: VisiblePosition & VisibleSelection (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: 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/htmlediting.h ('k') | Source/core/rendering/RenderBox.cpp » ('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) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2007 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty le updateStyle) 154 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty le updateStyle)
155 { 155 {
156 Node* node = p.parentAnchoredEquivalent().anchorNode(); 156 Node* node = p.parentAnchoredEquivalent().anchorNode();
157 if (!node) 157 if (!node)
158 return false; 158 return false;
159 if (updateStyle == UpdateStyle) 159 if (updateStyle == UpdateStyle)
160 node->document().updateLayoutIgnorePendingStylesheets(); 160 node->document().updateLayoutIgnorePendingStylesheets();
161 else 161 else
162 ASSERT(updateStyle == DoNotUpdateStyle); 162 ASSERT(updateStyle == DoNotUpdateStyle);
163 163
164 if (isRenderedTableElement(node)) 164 if (isRenderedHTMLTableElement(node))
165 node = node->parentNode(); 165 node = node->parentNode();
166 166
167 return node->hasEditableStyle(editableType); 167 return node->hasEditableStyle(editableType);
168 } 168 }
169 169
170 bool isAtUnsplittableElement(const Position& pos) 170 bool isAtUnsplittableElement(const Position& pos)
171 { 171 {
172 Node* node = pos.deprecatedNode(); 172 Node* node = pos.deprecatedNode();
173 return (node == editableRootForPosition(pos) || node == enclosingNodeOfType( pos, &isTableCell)); 173 return (node == editableRootForPosition(pos) || node == enclosingNodeOfType( pos, &isTableCell));
174 } 174 }
175 175
176 176
177 bool isRichlyEditablePosition(const Position& p, EditableType editableType) 177 bool isRichlyEditablePosition(const Position& p, EditableType editableType)
178 { 178 {
179 Node* node = p.deprecatedNode(); 179 Node* node = p.deprecatedNode();
180 if (!node) 180 if (!node)
181 return false; 181 return false;
182 182
183 if (isRenderedTableElement(node)) 183 if (isRenderedHTMLTableElement(node))
184 node = node->parentNode(); 184 node = node->parentNode();
185 185
186 return node->rendererIsRichlyEditable(editableType); 186 return node->rendererIsRichlyEditable(editableType);
187 } 187 }
188 188
189 Element* editableRootForPosition(const Position& p, EditableType editableType) 189 Element* editableRootForPosition(const Position& p, EditableType editableType)
190 { 190 {
191 Node* node = p.containerNode(); 191 Node* node = p.containerNode();
192 if (!node) 192 if (!node)
193 return 0; 193 return 0;
194 194
195 if (isRenderedTableElement(node)) 195 if (isRenderedHTMLTableElement(node))
196 node = node->parentNode(); 196 node = node->parentNode();
197 197
198 return node->rootEditableElement(editableType); 198 return node->rootEditableElement(editableType);
199 } 199 }
200 200
201 // Finds the enclosing element until which the tree can be split. 201 // Finds the enclosing element until which the tree can be split.
202 // When a user hits ENTER, he/she won't expect this element to be split into two . 202 // When a user hits ENTER, he/she won't expect this element to be split into two .
203 // You may pass it as the second argument of splitTreeToNode. 203 // You may pass it as the second argument of splitTreeToNode.
204 Element* unsplittableElementForPosition(const Position& p) 204 Element* unsplittableElementForPosition(const Position& p)
205 { 205 {
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 } 450 }
451 451
452 static HTMLElement* firstInSpecialElement(const Position& pos) 452 static HTMLElement* firstInSpecialElement(const Position& pos)
453 { 453 {
454 Element* rootEditableElement = pos.containerNode()->rootEditableElement(); 454 Element* rootEditableElement = pos.containerNode()->rootEditableElement();
455 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd itableElement; n = n->parentNode()) { 455 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd itableElement; n = n->parentNode()) {
456 if (isSpecialHTMLElement(n)) { 456 if (isSpecialHTMLElement(n)) {
457 HTMLElement* specialElement = toHTMLElement(n); 457 HTMLElement* specialElement = toHTMLElement(n);
458 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); 458 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
459 VisiblePosition firstInElement = VisiblePosition(firstPositionInOrBe foreNode(specialElement), DOWNSTREAM); 459 VisiblePosition firstInElement = VisiblePosition(firstPositionInOrBe foreNode(specialElement), DOWNSTREAM);
460 if (isRenderedTable(specialElement) && vPos == firstInElement.next() ) 460 if (isRenderedTableElement(specialElement) && vPos == firstInElement .next())
461 return specialElement; 461 return specialElement;
462 if (vPos == firstInElement) 462 if (vPos == firstInElement)
463 return specialElement; 463 return specialElement;
464 } 464 }
465 } 465 }
466 return 0; 466 return 0;
467 } 467 }
468 468
469 static HTMLElement* lastInSpecialElement(const Position& pos) 469 static HTMLElement* lastInSpecialElement(const Position& pos)
470 { 470 {
471 Element* rootEditableElement = pos.containerNode()->rootEditableElement(); 471 Element* rootEditableElement = pos.containerNode()->rootEditableElement();
472 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd itableElement; n = n->parentNode()) { 472 for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEd itableElement; n = n->parentNode()) {
473 if (isSpecialHTMLElement(n)) { 473 if (isSpecialHTMLElement(n)) {
474 HTMLElement* specialElement = toHTMLElement(n); 474 HTMLElement* specialElement = toHTMLElement(n);
475 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM); 475 VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
476 VisiblePosition lastInElement = VisiblePosition(lastPositionInOrAfte rNode(specialElement), DOWNSTREAM); 476 VisiblePosition lastInElement = VisiblePosition(lastPositionInOrAfte rNode(specialElement), DOWNSTREAM);
477 if (isRenderedTable(specialElement) && vPos == lastInElement.previou s()) 477 if (isRenderedTableElement(specialElement) && vPos == lastInElement. previous())
478 return specialElement; 478 return specialElement;
479 if (vPos == lastInElement) 479 if (vPos == lastInElement)
480 return specialElement; 480 return specialElement;
481 } 481 }
482 } 482 }
483 return 0; 483 return 0;
484 } 484 }
485 485
486 Position positionBeforeContainingSpecialElement(const Position& pos, HTMLElement ** containingSpecialElement) 486 Position positionBeforeContainingSpecialElement(const Position& pos, HTMLElement ** containingSpecialElement)
487 { 487 {
(...skipping 14 matching lines...) Expand all
502 if (!n) 502 if (!n)
503 return pos; 503 return pos;
504 Position result = positionInParentAfterNode(*n); 504 Position result = positionInParentAfterNode(*n);
505 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos .deprecatedNode()->rootEditableElement()) 505 if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos .deprecatedNode()->rootEditableElement())
506 return pos; 506 return pos;
507 if (containingSpecialElement) 507 if (containingSpecialElement)
508 *containingSpecialElement = n; 508 *containingSpecialElement = n;
509 return result; 509 return result;
510 } 510 }
511 511
512 Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition) 512 Element* isFirstPositionAfterTable(const VisiblePosition& visiblePosition)
513 { 513 {
514 Position upstream(visiblePosition.deepEquivalent().upstream()); 514 Position upstream(visiblePosition.deepEquivalent().upstream());
515 if (isRenderedTable(upstream.deprecatedNode()) && upstream.atLastEditingPosi tionForNode()) 515 if (isRenderedTableElement(upstream.deprecatedNode()) && upstream.atLastEdit ingPositionForNode())
516 return upstream.deprecatedNode(); 516 return toElement(upstream.deprecatedNode());
517 517
518 return 0; 518 return 0;
519 } 519 }
520 520
521 Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition) 521 Element* isLastPositionBeforeTable(const VisiblePosition& visiblePosition)
522 { 522 {
523 Position downstream(visiblePosition.deepEquivalent().downstream()); 523 Position downstream(visiblePosition.deepEquivalent().downstream());
524 if (isRenderedTable(downstream.deprecatedNode()) && downstream.atFirstEditin gPositionForNode()) 524 if (isRenderedTableElement(downstream.deprecatedNode()) && downstream.atFirs tEditingPositionForNode())
525 return downstream.deprecatedNode(); 525 return toElement(downstream.deprecatedNode());
526 526
527 return 0; 527 return 0;
528 } 528 }
529 529
530 // Returns the visible position at the beginning of a node 530 // Returns the visible position at the beginning of a node
531 VisiblePosition visiblePositionBeforeNode(Node& node) 531 VisiblePosition visiblePositionBeforeNode(Node& node)
532 { 532 {
533 if (node.hasChildren()) 533 if (node.hasChildren())
534 return VisiblePosition(firstPositionInOrBeforeNode(&node), DOWNSTREAM); 534 return VisiblePosition(firstPositionInOrBeforeNode(&node), DOWNSTREAM);
535 ASSERT(node.parentNode()); 535 ASSERT(node.parentNode());
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
743 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList- >isHTMLElement()) 743 if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList- >isHTMLElement())
744 return false; 744 return false;
745 745
746 return firstList->hasTagName(secondList->tagQName()) // make sure the list t ypes match (ol vs. ul) 746 return firstList->hasTagName(secondList->tagQName()) // make sure the list t ypes match (ol vs. ul)
747 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l ists are editable 747 && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both l ists are editable
748 && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries 748 && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries
749 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent BeforeNode(*secondList)); 749 && isVisiblyAdjacent(positionInParentAfterNode(*firstList), positionInParent BeforeNode(*secondList));
750 // Make sure there is no visible content between this li and the previous li st 750 // Make sure there is no visible content between this li and the previous li st
751 } 751 }
752 752
753 bool isRenderedHTMLTableElement(const Node* node)
754 {
755 return isHTMLTableElement(*node) && node->renderer();
756 }
757
753 bool isRenderedTableElement(const Node* node) 758 bool isRenderedTableElement(const Node* node)
754 { 759 {
755 return isHTMLTableElement(*node) && node->renderer();
756 }
757
758 bool isRenderedTable(const Node* node)
759 {
760 if (!node || !node->isElementNode()) 760 if (!node || !node->isElementNode())
761 return false; 761 return false;
762 762
763 RenderObject* renderer = node->renderer(); 763 RenderObject* renderer = node->renderer();
764 return (renderer && renderer->isTable()); 764 return (renderer && renderer->isTable());
765 } 765 }
766 766
767 bool isTableCell(const Node* node) 767 bool isTableCell(const Node* node)
768 { 768 {
769 ASSERT(node); 769 ASSERT(node);
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1074 VisibleSelection selectionForParagraphIteration(const VisibleSelection& original ) 1074 VisibleSelection selectionForParagraphIteration(const VisibleSelection& original )
1075 { 1075 {
1076 VisibleSelection newSelection(original); 1076 VisibleSelection newSelection(original);
1077 VisiblePosition startOfSelection(newSelection.visibleStart()); 1077 VisiblePosition startOfSelection(newSelection.visibleStart());
1078 VisiblePosition endOfSelection(newSelection.visibleEnd()); 1078 VisiblePosition endOfSelection(newSelection.visibleEnd());
1079 1079
1080 // If the end of the selection to modify is just after a table, and 1080 // If the end of the selection to modify is just after a table, and
1081 // if the start of the selection is inside that table, then the last paragra ph 1081 // if the start of the selection is inside that table, then the last paragra ph
1082 // that we'll want modify is the last one inside the table, not the table it self 1082 // that we'll want modify is the last one inside the table, not the table it self
1083 // (a table is itself a paragraph). 1083 // (a table is itself a paragraph).
1084 if (Node* table = isFirstPositionAfterTable(endOfSelection)) 1084 if (Element* table = isFirstPositionAfterTable(endOfSelection))
1085 if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(t able)) 1085 if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(t able))
1086 newSelection = VisibleSelection(startOfSelection, endOfSelection.pre vious(CannotCrossEditingBoundary)); 1086 newSelection = VisibleSelection(startOfSelection, endOfSelection.pre vious(CannotCrossEditingBoundary));
1087 1087
1088 // If the start of the selection to modify is just before a table, 1088 // If the start of the selection to modify is just before a table,
1089 // and if the end of the selection is inside that table, then the first para graph 1089 // and if the end of the selection is inside that table, then the first para graph
1090 // we'll want to modify is the first one inside the table, not the paragraph 1090 // we'll want to modify is the first one inside the table, not the paragraph
1091 // containing the table itself. 1091 // containing the table itself.
1092 if (Node* table = isLastPositionBeforeTable(startOfSelection)) 1092 if (Element* table = isLastPositionBeforeTable(startOfSelection))
1093 if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(tab le)) 1093 if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(tab le))
1094 newSelection = VisibleSelection(startOfSelection.next(CannotCrossEdi tingBoundary), endOfSelection); 1094 newSelection = VisibleSelection(startOfSelection.next(CannotCrossEdi tingBoundary), endOfSelection);
1095 1095
1096 return newSelection; 1096 return newSelection;
1097 } 1097 }
1098 1098
1099 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators to convert between 1099 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators to convert between
1100 // VisiblePositions and indices. But TextIterator iteration using TextIteratorEm itsCharactersBetweenAllVisiblePositions 1100 // VisiblePositions and indices. But TextIterator iteration using TextIteratorEm itsCharactersBetweenAllVisiblePositions
1101 // does not exactly match VisiblePosition iteration, so using them to preserve a selection during an editing 1101 // does not exactly match VisiblePosition iteration, so using them to preserve a selection during an editing
1102 // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllV isiblePositions mode needs to be fixed, 1102 // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllV isiblePositions mode needs to be fixed,
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 // if the selection starts just before a paragraph break, skip over it 1224 // if the selection starts just before a paragraph break, skip over it
1225 if (isEndOfParagraph(visiblePosition)) 1225 if (isEndOfParagraph(visiblePosition))
1226 return visiblePosition.next().deepEquivalent().downstream(); 1226 return visiblePosition.next().deepEquivalent().downstream();
1227 1227
1228 // otherwise, make sure to be at the start of the first selected node, 1228 // otherwise, make sure to be at the start of the first selected node,
1229 // instead of possibly at the end of the last node before the selection 1229 // instead of possibly at the end of the last node before the selection
1230 return visiblePosition.deepEquivalent().downstream(); 1230 return visiblePosition.deepEquivalent().downstream();
1231 } 1231 }
1232 1232
1233 } // namespace blink 1233 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/editing/htmlediting.h ('k') | Source/core/rendering/RenderBox.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698