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

Side by Side Diff: third_party/WebKit/Source/core/editing/SelectionAdjuster.cpp

Issue 2759943004: CANCELLED Merge SelectionAdjuster into VisibleSelection part 2 (Closed)
Patch Set: Rebased Created 3 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
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27 #include "core/editing/SelectionAdjuster.h"
28
29 #include "core/editing/EditingUtilities.h"
30
31 namespace blink {
32
33 // TODO(xiaochengh): Move everything to VisibleSelection.cpp.
34
35 namespace {
36
37 Node* enclosingShadowHost(Node* node) {
38 for (Node* runner = node; runner;
39 runner = FlatTreeTraversal::parent(*runner)) {
40 if (isShadowHost(runner))
41 return runner;
42 }
43 return nullptr;
44 }
45
46 bool isEnclosedBy(const PositionInFlatTree& position, const Node& node) {
47 DCHECK(position.isNotNull());
48 Node* anchorNode = position.anchorNode();
49 if (anchorNode == node)
50 return !position.isAfterAnchor() && !position.isBeforeAnchor();
51
52 return FlatTreeTraversal::isDescendantOf(*anchorNode, node);
53 }
54
55 bool isSelectionBoundary(const Node& node) {
56 return isHTMLTextAreaElement(node) || isHTMLInputElement(node) ||
57 isHTMLSelectElement(node);
58 }
59
60 Node* enclosingShadowHostForStart(const PositionInFlatTree& position) {
61 Node* node = position.nodeAsRangeFirstNode();
62 if (!node)
63 return nullptr;
64 Node* shadowHost = enclosingShadowHost(node);
65 if (!shadowHost)
66 return nullptr;
67 if (!isEnclosedBy(position, *shadowHost))
68 return nullptr;
69 return isSelectionBoundary(*shadowHost) ? shadowHost : nullptr;
70 }
71
72 Node* enclosingShadowHostForEnd(const PositionInFlatTree& position) {
73 Node* node = position.nodeAsRangeLastNode();
74 if (!node)
75 return nullptr;
76 Node* shadowHost = enclosingShadowHost(node);
77 if (!shadowHost)
78 return nullptr;
79 if (!isEnclosedBy(position, *shadowHost))
80 return nullptr;
81 return isSelectionBoundary(*shadowHost) ? shadowHost : nullptr;
82 }
83
84 PositionInFlatTree adjustPositionInFlatTreeForStart(
85 const PositionInFlatTree& position,
86 Node* shadowHost) {
87 if (isEnclosedBy(position, *shadowHost)) {
88 if (position.isBeforeChildren())
89 return PositionInFlatTree::beforeNode(shadowHost);
90 return PositionInFlatTree::afterNode(shadowHost);
91 }
92
93 // We use |firstChild|'s after instead of beforeAllChildren for backward
94 // compatibility. The positions are same but the anchors would be different,
95 // and selection painting uses anchor nodes.
96 if (Node* firstChild = FlatTreeTraversal::firstChild(*shadowHost))
97 return PositionInFlatTree::beforeNode(firstChild);
98 return PositionInFlatTree();
99 }
100
101 Position adjustPositionForEnd(const Position& currentPosition,
102 Node* startContainerNode) {
103 TreeScope& treeScope = startContainerNode->treeScope();
104
105 DCHECK(currentPosition.computeContainerNode()->treeScope() != treeScope);
106
107 if (Node* ancestor = treeScope.ancestorInThisScope(
108 currentPosition.computeContainerNode())) {
109 if (ancestor->contains(startContainerNode))
110 return Position::afterNode(ancestor);
111 return Position::beforeNode(ancestor);
112 }
113
114 if (Node* lastChild = treeScope.rootNode().lastChild())
115 return Position::afterNode(lastChild);
116
117 return Position();
118 }
119
120 PositionInFlatTree adjustPositionInFlatTreeForEnd(
121 const PositionInFlatTree& position,
122 Node* shadowHost) {
123 if (isEnclosedBy(position, *shadowHost)) {
124 if (position.isAfterChildren())
125 return PositionInFlatTree::afterNode(shadowHost);
126 return PositionInFlatTree::beforeNode(shadowHost);
127 }
128
129 // We use |lastChild|'s after instead of afterAllChildren for backward
130 // compatibility. The positions are same but the anchors would be different,
131 // and selection painting uses anchor nodes.
132 if (Node* lastChild = FlatTreeTraversal::lastChild(*shadowHost))
133 return PositionInFlatTree::afterNode(lastChild);
134 return PositionInFlatTree();
135 }
136
137 Position adjustPositionForStart(const Position& currentPosition,
138 Node* endContainerNode) {
139 TreeScope& treeScope = endContainerNode->treeScope();
140
141 DCHECK(currentPosition.computeContainerNode()->treeScope() != treeScope);
142
143 if (Node* ancestor = treeScope.ancestorInThisScope(
144 currentPosition.computeContainerNode())) {
145 if (ancestor->contains(endContainerNode))
146 return Position::beforeNode(ancestor);
147 return Position::afterNode(ancestor);
148 }
149
150 if (Node* firstChild = treeScope.rootNode().firstChild())
151 return Position::beforeNode(firstChild);
152
153 return Position();
154 }
155
156 } // namespace
157
158 std::pair<AdjustDirection, Position> adjustmentToAvoidCrossingShadowBoundaries(
159 const VisibleSelection& selection) {
160 // Note: |m_selectionType| isn't computed yet.
161 DCHECK(selection.base().isNotNull());
162 DCHECK(selection.extent().isNotNull());
163 DCHECK(selection.start().isNotNull());
164 DCHECK(selection.end().isNotNull());
165
166 // TODO(hajimehoshi): Checking treeScope is wrong when a node is
167 // distributed, but we leave it as it is for backward compatibility.
168 if (selection.start().anchorNode()->treeScope() ==
169 selection.end().anchorNode()->treeScope())
170 return std::make_pair(AdjustDirection::kAdjustNone, Position());
171
172 if (selection.isBaseFirst()) {
173 const Position& newEnd = adjustPositionForEnd(
174 selection.end(), selection.start().computeContainerNode());
175 return std::make_pair(AdjustDirection::kAdjustEnd, newEnd);
176 }
177
178 const Position& newStart = adjustPositionForStart(
179 selection.start(), selection.end().computeContainerNode());
180 return std::make_pair(AdjustDirection::kAdjustStart, newStart);
181 }
182
183 // This function is called twice. The first is called when |m_start| and |m_end|
184 // or |m_extent| are same, and the second when |m_start| and |m_end| are changed
185 // after downstream/upstream.
186 std::pair<AdjustDirection, PositionInFlatTree>
187 adjustmentToAvoidCrossingShadowBoundaries(
188 const VisibleSelectionInFlatTree& selection) {
189 Node* const shadowHostStart = enclosingShadowHostForStart(selection.start());
190 Node* const shadowHostEnd = enclosingShadowHostForEnd(selection.end());
191 if (shadowHostStart == shadowHostEnd)
192 return std::make_pair(AdjustDirection::kAdjustNone, PositionInFlatTree());
193
194 if (selection.isBaseFirst()) {
195 Node* const shadowHost = shadowHostStart ? shadowHostStart : shadowHostEnd;
196 const PositionInFlatTree& newEnd =
197 adjustPositionInFlatTreeForEnd(selection.end(), shadowHost);
198 return std::make_pair(AdjustDirection::kAdjustEnd, newEnd);
199 }
200 Node* const shadowHost = shadowHostEnd ? shadowHostEnd : shadowHostStart;
201 const PositionInFlatTree& newStart =
202 adjustPositionInFlatTreeForStart(selection.start(), shadowHost);
203 return std::make_pair(AdjustDirection::kAdjustStart, newStart);
204 }
205
206 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/SelectionAdjuster.h ('k') | third_party/WebKit/Source/core/editing/SelectionEditor.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698