OLD | NEW |
---|---|
1 /* | 1 /* |
2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) | 3 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no) |
4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) | 4 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no) |
5 * (C) 2001 Peter Kelly (pmk@post.com) | 5 * (C) 2001 Peter Kelly (pmk@post.com) |
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All |
7 * rights reserved. | 7 * rights reserved. |
8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 8 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
9 * | 9 * |
10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
(...skipping 18 matching lines...) Expand all Loading... | |
29 #include "core/dom/ClientRect.h" | 29 #include "core/dom/ClientRect.h" |
30 #include "core/dom/ClientRectList.h" | 30 #include "core/dom/ClientRectList.h" |
31 #include "core/dom/DocumentFragment.h" | 31 #include "core/dom/DocumentFragment.h" |
32 #include "core/dom/ExceptionCode.h" | 32 #include "core/dom/ExceptionCode.h" |
33 #include "core/dom/Node.h" | 33 #include "core/dom/Node.h" |
34 #include "core/dom/NodeTraversal.h" | 34 #include "core/dom/NodeTraversal.h" |
35 #include "core/dom/NodeWithIndex.h" | 35 #include "core/dom/NodeWithIndex.h" |
36 #include "core/dom/ProcessingInstruction.h" | 36 #include "core/dom/ProcessingInstruction.h" |
37 #include "core/dom/Text.h" | 37 #include "core/dom/Text.h" |
38 #include "core/editing/EditingUtilities.h" | 38 #include "core/editing/EditingUtilities.h" |
39 #include "core/editing/EphemeralRange.h" | |
40 #include "core/editing/FrameSelection.h" | |
39 #include "core/editing/VisiblePosition.h" | 41 #include "core/editing/VisiblePosition.h" |
40 #include "core/editing/VisibleUnits.h" | 42 #include "core/editing/VisibleUnits.h" |
41 #include "core/editing/iterators/TextIterator.h" | 43 #include "core/editing/iterators/TextIterator.h" |
42 #include "core/editing/serializers/Serialization.h" | 44 #include "core/editing/serializers/Serialization.h" |
43 #include "core/events/ScopedEventQueue.h" | 45 #include "core/events/ScopedEventQueue.h" |
44 #include "core/html/HTMLBodyElement.h" | 46 #include "core/html/HTMLBodyElement.h" |
45 #include "core/html/HTMLElement.h" | 47 #include "core/html/HTMLElement.h" |
46 #include "core/layout/LayoutObject.h" | 48 #include "core/layout/LayoutObject.h" |
47 #include "core/layout/LayoutText.h" | 49 #include "core/layout/LayoutText.h" |
48 #include "core/svg/SVGSVGElement.h" | 50 #include "core/svg/SVGSVGElement.h" |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 setDocument(refNode->document()); | 177 setDocument(refNode->document()); |
176 didMoveDocument = true; | 178 didMoveDocument = true; |
177 } | 179 } |
178 | 180 |
179 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); | 181 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); |
180 if (exceptionState.hadException()) | 182 if (exceptionState.hadException()) |
181 return; | 183 return; |
182 | 184 |
183 m_start.set(refNode, offset, childNode); | 185 m_start.set(refNode, offset, childNode); |
184 | 186 |
185 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 187 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
yosin_UTC9
2017/02/10 10:26:27
nit: Can we use early-return style?
if (didMoveDo
tkent
2017/02/13 04:04:13
Good point. I'll investigate Firefox/Edge behavio
tkent
2017/02/13 05:45:29
Both of Firefox and Edge keep Selection.getRangeAt
tkent
2017/02/13 07:31:40
We discussed offline, and agreed that we should un
| |
186 collapse(true); | 188 collapse(true); |
189 else | |
190 updateSelectionIfAddedToSelection(); | |
187 } | 191 } |
188 | 192 |
189 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { | 193 void Range::setEnd(Node* refNode, int offset, ExceptionState& exceptionState) { |
190 if (!refNode) { | 194 if (!refNode) { |
191 // FIXME: Generated bindings code never calls with null, and neither should | 195 // FIXME: Generated bindings code never calls with null, and neither should |
192 // other callers! | 196 // other callers! |
193 exceptionState.throwTypeError("The node provided is null."); | 197 exceptionState.throwTypeError("The node provided is null."); |
194 return; | 198 return; |
195 } | 199 } |
196 | 200 |
197 bool didMoveDocument = false; | 201 bool didMoveDocument = false; |
198 if (refNode->document() != m_ownerDocument) { | 202 if (refNode->document() != m_ownerDocument) { |
199 setDocument(refNode->document()); | 203 setDocument(refNode->document()); |
200 didMoveDocument = true; | 204 didMoveDocument = true; |
201 } | 205 } |
202 | 206 |
203 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); | 207 Node* childNode = checkNodeWOffset(refNode, offset, exceptionState); |
204 if (exceptionState.hadException()) | 208 if (exceptionState.hadException()) |
205 return; | 209 return; |
206 | 210 |
207 m_end.set(refNode, offset, childNode); | 211 m_end.set(refNode, offset, childNode); |
208 | 212 |
209 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) | 213 if (didMoveDocument || checkForDifferentRootContainer(m_start, m_end)) |
yosin_UTC9
2017/02/10 10:26:27
Similar to L187 in Range::setStart()
tkent
2017/02/13 07:31:40
Done.
| |
210 collapse(false); | 214 collapse(false); |
215 else | |
216 updateSelectionIfAddedToSelection(); | |
211 } | 217 } |
212 | 218 |
213 void Range::setStart(const Position& start, ExceptionState& exceptionState) { | 219 void Range::setStart(const Position& start, ExceptionState& exceptionState) { |
214 Position parentAnchored = start.parentAnchoredEquivalent(); | 220 Position parentAnchored = start.parentAnchoredEquivalent(); |
215 setStart(parentAnchored.computeContainerNode(), | 221 setStart(parentAnchored.computeContainerNode(), |
216 parentAnchored.offsetInContainerNode(), exceptionState); | 222 parentAnchored.offsetInContainerNode(), exceptionState); |
217 } | 223 } |
218 | 224 |
219 void Range::setEnd(const Position& end, ExceptionState& exceptionState) { | 225 void Range::setEnd(const Position& end, ExceptionState& exceptionState) { |
220 Position parentAnchored = end.parentAnchoredEquivalent(); | 226 Position parentAnchored = end.parentAnchoredEquivalent(); |
221 setEnd(parentAnchored.computeContainerNode(), | 227 setEnd(parentAnchored.computeContainerNode(), |
222 parentAnchored.offsetInContainerNode(), exceptionState); | 228 parentAnchored.offsetInContainerNode(), exceptionState); |
223 } | 229 } |
224 | 230 |
225 void Range::collapse(bool toStart) { | 231 void Range::collapse(bool toStart) { |
226 if (toStart) | 232 if (toStart) |
227 m_end = m_start; | 233 m_end = m_start; |
228 else | 234 else |
229 m_start = m_end; | 235 m_start = m_end; |
236 updateSelectionIfAddedToSelection(); | |
230 } | 237 } |
231 | 238 |
232 bool Range::isNodeFullyContained(Node& node) const { | 239 bool Range::isNodeFullyContained(Node& node) const { |
233 ContainerNode* parentNode = node.parentNode(); | 240 ContainerNode* parentNode = node.parentNode(); |
234 int nodeIndex = node.nodeIndex(); | 241 int nodeIndex = node.nodeIndex(); |
235 return isPointInRange( | 242 return isPointInRange( |
236 parentNode, nodeIndex, | 243 parentNode, nodeIndex, |
237 IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this | 244 IGNORE_EXCEPTION_FOR_TESTING) // starts in the middle of this |
238 // range, or on the boundary points. | 245 // range, or on the boundary points. |
239 && isPointInRange( | 246 && isPointInRange( |
(...skipping 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1211 "The node provided is of type '" + refNode->nodeName() + "'."); | 1218 "The node provided is of type '" + refNode->nodeName() + "'."); |
1212 return; | 1219 return; |
1213 } | 1220 } |
1214 } | 1221 } |
1215 | 1222 |
1216 if (m_ownerDocument != refNode->document()) | 1223 if (m_ownerDocument != refNode->document()) |
1217 setDocument(refNode->document()); | 1224 setDocument(refNode->document()); |
1218 | 1225 |
1219 m_start.setToStartOfNode(*refNode); | 1226 m_start.setToStartOfNode(*refNode); |
1220 m_end.setToEndOfNode(*refNode); | 1227 m_end.setToEndOfNode(*refNode); |
1228 updateSelectionIfAddedToSelection(); | |
1221 } | 1229 } |
1222 | 1230 |
1223 bool Range::selectNodeContents(Node* refNode, Position& start, Position& end) { | 1231 bool Range::selectNodeContents(Node* refNode, Position& start, Position& end) { |
1224 if (!refNode) { | 1232 if (!refNode) { |
1225 return false; | 1233 return false; |
1226 } | 1234 } |
1227 | 1235 |
1228 for (Node* n = refNode; n; n = n->parentNode()) { | 1236 for (Node* n = refNode; n; n = n->parentNode()) { |
1229 switch (n->getNodeType()) { | 1237 switch (n->getNodeType()) { |
1230 case Node::kAttributeNode: | 1238 case Node::kAttributeNode: |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1693 for (const FloatQuad& quad : quads) | 1701 for (const FloatQuad& quad : quads) |
1694 result.unite(quad.boundingBox()); // Skips empty rects. | 1702 result.unite(quad.boundingBox()); // Skips empty rects. |
1695 | 1703 |
1696 // If all rects are empty, return the first rect. | 1704 // If all rects are empty, return the first rect. |
1697 if (result.isEmpty() && !quads.isEmpty()) | 1705 if (result.isEmpty() && !quads.isEmpty()) |
1698 return quads.front().boundingBox(); | 1706 return quads.front().boundingBox(); |
1699 | 1707 |
1700 return result; | 1708 return result; |
1701 } | 1709 } |
1702 | 1710 |
1711 void Range::updateSelectionIfAddedToSelection() { | |
1712 if (!ownerDocument().frame()) | |
1713 return; | |
1714 FrameSelection& selection = ownerDocument().frame()->selection(); | |
1715 if (this != selection.documentCachedRange()) | |
1716 return; | |
1717 selection.setSelectedRange(EphemeralRange(this), VP_DEFAULT_AFFINITY); | |
1718 selection.cacheRangeOfDocument(this); | |
1719 } | |
1720 | |
1703 DEFINE_TRACE(Range) { | 1721 DEFINE_TRACE(Range) { |
1704 visitor->trace(m_ownerDocument); | 1722 visitor->trace(m_ownerDocument); |
1705 visitor->trace(m_start); | 1723 visitor->trace(m_start); |
1706 visitor->trace(m_end); | 1724 visitor->trace(m_end); |
1707 } | 1725 } |
1708 | 1726 |
1709 } // namespace blink | 1727 } // namespace blink |
1710 | 1728 |
1711 #ifndef NDEBUG | 1729 #ifndef NDEBUG |
1712 | 1730 |
1713 void showTree(const blink::Range* range) { | 1731 void showTree(const blink::Range* range) { |
1714 if (range && range->boundaryPointsValid()) { | 1732 if (range && range->boundaryPointsValid()) { |
1715 LOG(INFO) << "\n" | 1733 LOG(INFO) << "\n" |
1716 << range->startContainer() | 1734 << range->startContainer() |
1717 ->toMarkedTreeString(range->startContainer(), "S", | 1735 ->toMarkedTreeString(range->startContainer(), "S", |
1718 range->endContainer(), "E") | 1736 range->endContainer(), "E") |
1719 .utf8() | 1737 .utf8() |
1720 .data() | 1738 .data() |
1721 << "start offset: " << range->startOffset() | 1739 << "start offset: " << range->startOffset() |
1722 << ", end offset: " << range->endOffset(); | 1740 << ", end offset: " << range->endOffset(); |
1723 } else { | 1741 } else { |
1724 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " | 1742 LOG(INFO) << "Cannot show tree if range is null, or if boundary points are " |
1725 "invalid."; | 1743 "invalid."; |
1726 } | 1744 } |
1727 } | 1745 } |
1728 | 1746 |
1729 #endif | 1747 #endif |
OLD | NEW |