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

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

Issue 1409073004: Return EphemeralRange from Editor::findRangeOfString. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Extract text bounds collecting to a function Created 5 years, 1 month 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
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 ASSERT(frame().document()); 1138 ASSERT(frame().document());
1139 ApplyStyleCommand::create(*frame().document(), blockStyle.get(), editing Action)->apply(); 1139 ApplyStyleCommand::create(*frame().document(), blockStyle.get(), editing Action)->apply();
1140 } 1140 }
1141 1141
1142 // Set the remaining style as the typing style. 1142 // Set the remaining style as the typing style.
1143 frame().selection().setTypingStyle(typingStyle); 1143 frame().selection().setTypingStyle(typingStyle);
1144 } 1144 }
1145 1145
1146 bool Editor::findString(const String& target, FindOptions options) 1146 bool Editor::findString(const String& target, FindOptions options)
1147 { 1147 {
1148 VisibleSelection selection = frame().selection().selection(); 1148 const VisibleSelection& selection = frame().selection().selection();
1149 const EphemeralRange& resultRange = findRangeOfString(
1150 target,
1151 EphemeralRange(selection.start(), selection.end()),
1152 static_cast<FindOptions>(options | FindAPICall));
1149 1153
1150 // TODO(yosin) We should make |findRangeOfString()| to return 1154 if (resultRange.isCollapsed())
1151 // |EphemeralRange| rather than|Range| object.
1152 RefPtrWillBeRawPtr<Range> resultRange = findRangeOfString(target, EphemeralR ange(selection.start(), selection.end()), static_cast<FindOptions>(options | Fin dAPICall));
1153
1154 if (!resultRange)
1155 return false; 1155 return false;
1156 1156
1157 frame().selection().setSelection(VisibleSelection(EphemeralRange(resultRange .get()))); 1157 frame().selection().setSelection(VisibleSelection(resultRange));
1158 frame().selection().revealSelection(); 1158 frame().selection().revealSelection();
1159 return true; 1159 return true;
1160 } 1160 }
1161 1161
1162 template <typename Strategy> 1162 template <typename Strategy>
1163 static PassRefPtrWillBeRawPtr<Range> findStringAndScrollToVisibleAlgorithm(Edito r& editor, const String& target, const EphemeralRangeTemplate<Strategy>& previou sMatch, FindOptions options) 1163 static EphemeralRangeTemplate<Strategy> findStringAndScrollToVisibleAlgorithm(Ed itor& editor, const String& target, const EphemeralRangeTemplate<Strategy>& prev iousMatch, FindOptions options)
1164 { 1164 {
1165 RefPtrWillBeRawPtr<Range> nextMatch = editor.findRangeOfString(target, previ ousMatch, options); 1165 const EphemeralRangeTemplate<Strategy>& nextMatch = editor.findRangeOfString (target, previousMatch, options);
1166 if (!nextMatch) 1166 if (nextMatch.isCollapsed())
1167 return nullptr; 1167 return EphemeralRangeTemplate<Strategy>();
1168 1168
1169 nextMatch->firstNode()->layoutObject()->scrollRectToVisible(LayoutRect(nextM atch->boundingBox()), 1169 if (auto* layoutObject = nextMatch.startPosition().nodeAsRangeFirstNode()->l ayoutObject()) {
1170 ScrollAlignment::alignCenterIfNeeded, ScrollAlignment::alignCenterIfNeed ed, UserScroll); 1170 layoutObject->scrollRectToVisible(
1171 LayoutRect(nextMatch.textBoundingBox()),
1172 ScrollAlignment::alignCenterIfNeeded,
1173 ScrollAlignment::alignCenterIfNeeded,
1174 UserScroll);
1175 }
1171 1176
1172 return nextMatch.release(); 1177 return nextMatch;
1173 } 1178 }
1174 1179
1175 PassRefPtrWillBeRawPtr<Range> Editor::findStringAndScrollToVisible(const String& target, Range* range, FindOptions options) 1180 EphemeralRange Editor::findStringAndScrollToVisible(const String& target, const EphemeralRange& range, FindOptions options)
1176 { 1181 {
1177 if (RuntimeEnabledFeatures::selectionForComposedTreeEnabled()) 1182 return findStringAndScrollToVisibleAlgorithm(*this, target, range, options);
1178 return findStringAndScrollToVisibleAlgorithm<EditingInComposedTreeStrate gy>(*this, target, EphemeralRangeInComposedTree(range), options);
1179 return findStringAndScrollToVisibleAlgorithm<EditingStrategy>(*this, target, EphemeralRange(range), options);
1180 } 1183 }
1181 1184
1182 // TODO(yosin) We should return |EphemeralRange| rather than |Range|. We use 1185 EphemeralRangeInComposedTree Editor::findStringAndScrollToVisible(const String& target, const EphemeralRangeInComposedTree& range, FindOptions options)
1183 // |Range| object for checking whether start and end position crossing shadow 1186 {
1184 // boundaries, however we can do it without |Range| object. 1187 ASSERT(RuntimeEnabledFeatures::selectionForComposedTreeEnabled());
1188 return findStringAndScrollToVisibleAlgorithm(*this, target, range, options);
1189 }
1190
1191 // This function checks whether start and end position of the |range|
1192 // crossing shadow boundaries.
1193 // It should be equivalent to !Range::create(ephemeralRange)->collapsed().
1185 template <typename Strategy> 1194 template <typename Strategy>
1186 static PassRefPtrWillBeRawPtr<Range> findStringBetweenPositions(const String& ta rget, const EphemeralRangeTemplate<Strategy>& referenceRange, FindOptions option s) 1195 static bool rangeBoundariesAreValid(const EphemeralRangeTemplate<Strategy>& rang e)
yosin_UTC9 2015/11/04 07:11:06 This function doesn't check shadow boundary crossi
1196 {
1197 const Node* endRootContainer = range.endPosition().computeContainerNode();
yosin_UTC9 2015/11/04 07:11:06 When start is null position, end must be null posi
1198 const Node* startRootContainer = range.startPosition().computeContainerNode( );
1199 if (!startRootContainer || !endRootContainer)
1200 return false;
1201
1202 ASSERT(Strategy::commonAncestor(*startRootContainer, *endRootContainer));
1203 return range.startPosition().compareTo(range.endPosition()) < 0;
1204 }
1205
1206 template <typename Strategy>
1207 static EphemeralRangeTemplate<Strategy> findStringBetweenPositions(const String& target, const EphemeralRangeTemplate<Strategy>& referenceRange, FindOptions opt ions)
1187 { 1208 {
1188 EphemeralRangeTemplate<Strategy> searchRange(referenceRange); 1209 EphemeralRangeTemplate<Strategy> searchRange(referenceRange);
1189 1210
1190 bool forward = !(options & Backwards); 1211 bool forward = !(options & Backwards);
1191 1212
1192 while (true) { 1213 while (true) {
1193 EphemeralRangeTemplate<Strategy> resultRange = findPlainText(searchRange , target, options); 1214 const EphemeralRangeTemplate<Strategy>& resultRange = findPlainText(sear chRange, target, options);
1194 if (resultRange.isCollapsed()) 1215 if (resultRange.isCollapsed())
1195 return nullptr; 1216 return EphemeralRangeTemplate<Strategy>();
1196 1217
1197 RefPtrWillBeRawPtr<Range> rangeObject = Range::create(resultRange.docume nt(), toPositionInDOMTree(resultRange.startPosition()), toPositionInDOMTree(resu ltRange.endPosition())); 1218 if (rangeBoundariesAreValid(resultRange))
yosin_UTC9 2015/11/04 07:11:06 Just return found range even if it is crossing sha
1198 if (!rangeObject->collapsed()) 1219 return resultRange;
1199 return rangeObject.release();
1200 1220
1201 // Found text spans over multiple TreeScopes. Since it's impossible to 1221 // Found text spans over multiple TreeScopes. Since it's impossible to
1202 // return such section as a Range, we skip this match and seek for the 1222 // return such section as a Range, we skip this match and seek for the
1203 // next occurrence. 1223 // next occurrence.
1204 // TODO(yosin) Handle this case. 1224 // TODO(yosin) Handle this case.
1205 if (forward) { 1225 if (forward) {
1206 // TODO(yosin) We should use |PositionMoveType::Character| 1226 // TODO(yosin) We should use |PositionMoveType::Character|
1207 // for |nextPositionOf()|. 1227 // for |nextPositionOf()|.
1208 searchRange = EphemeralRangeTemplate<Strategy>(nextPositionOf(result Range.startPosition(), PositionMoveType::CodePoint), searchRange.endPosition()); 1228 searchRange = EphemeralRangeTemplate<Strategy>(nextPositionOf(result Range.startPosition(), PositionMoveType::CodePoint), searchRange.endPosition());
1209 } else { 1229 } else {
1210 // TODO(yosin) We should use |PositionMoveType::Character| 1230 // TODO(yosin) We should use |PositionMoveType::Character|
1211 // for |previousPositionOf()|. 1231 // for |previousPositionOf()|.
1212 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), previousPositionOf(resultRange.endPosition(), PositionMoveType::CodePoin t)); 1232 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), previousPositionOf(resultRange.endPosition(), PositionMoveType::CodePoin t));
1213 } 1233 }
1214 } 1234 }
1215 1235
1216 ASSERT_NOT_REACHED(); 1236 ASSERT_NOT_REACHED();
1217 return nullptr; 1237 return EphemeralRangeTemplate<Strategy>();
1218 } 1238 }
1219 1239
1220 template <typename Strategy> 1240 template <typename Strategy>
1221 static PassRefPtrWillBeRawPtr<Range> findRangeOfStringAlgorithm(Document& docume nt, const String& target, const EphemeralRangeTemplate<Strategy>& referenceRange , FindOptions options) 1241 static EphemeralRangeTemplate<Strategy> findRangeOfStringAlgorithm(Document& doc ument, const String& target, const EphemeralRangeTemplate<Strategy>& referenceRa nge, FindOptions options)
1222 { 1242 {
1223 if (target.isEmpty()) 1243 if (target.isEmpty())
1224 return nullptr; 1244 return EphemeralRangeTemplate<Strategy>();
1225 1245
1226 // Start from an edge of the reference range. Which edge is used depends on 1246 // Start from an edge of the reference range. Which edge is used depends on
1227 // whether we're searching forward or backward, and whether startInSelection 1247 // whether we're searching forward or backward, and whether startInSelection
1228 // is set. 1248 // is set.
1229 EphemeralRangeTemplate<Strategy> documentRange = EphemeralRangeTemplate<Stra tegy>::rangeOfContents(document); 1249 EphemeralRangeTemplate<Strategy> documentRange = EphemeralRangeTemplate<Stra tegy>::rangeOfContents(document);
1230 EphemeralRangeTemplate<Strategy> searchRange(documentRange); 1250 EphemeralRangeTemplate<Strategy> searchRange(documentRange);
1231 1251
1232 bool forward = !(options & Backwards); 1252 bool forward = !(options & Backwards);
1233 bool startInReferenceRange = false; 1253 bool startInReferenceRange = false;
1234 if (referenceRange.isNotNull()) { 1254 if (referenceRange.isNotNull()) {
1235 startInReferenceRange = options & StartInSelection; 1255 startInReferenceRange = options & StartInSelection;
1236 if (forward && startInReferenceRange) 1256 if (forward && startInReferenceRange)
1237 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.startP osition(), documentRange.endPosition()); 1257 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.startP osition(), documentRange.endPosition());
1238 else if (forward) 1258 else if (forward)
1239 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.endPos ition(), documentRange.endPosition()); 1259 searchRange = EphemeralRangeTemplate<Strategy>(referenceRange.endPos ition(), documentRange.endPosition());
1240 else if (startInReferenceRange) 1260 else if (startInReferenceRange)
1241 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.endPosition()); 1261 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.endPosition());
1242 else 1262 else
1243 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.startPosition()); 1263 searchRange = EphemeralRangeTemplate<Strategy>(documentRange.startPo sition(), referenceRange.startPosition());
1244 } 1264 }
1245 1265
1246 RefPtrWillBeRawPtr<Range> resultRange = findStringBetweenPositions(target, s earchRange, options); 1266 EphemeralRangeTemplate<Strategy> resultRange = findStringBetweenPositions(ta rget, searchRange, options);
1247 1267
1248 // If we started in the reference range and the found range exactly matches 1268 // If we started in the reference range and the found range exactly matches
1249 // the reference range, find again. Build a selection with the found range 1269 // the reference range, find again. Build a selection with the found range
1250 // to remove collapsed whitespace. Compare ranges instead of selection 1270 // to remove collapsed whitespace. Compare ranges instead of selection
1251 // objects to ignore the way that the current selection was made. 1271 // objects to ignore the way that the current selection was made.
1252 if (resultRange && startInReferenceRange && normalizeRange(EphemeralRangeTem plate<Strategy>(resultRange.get())) == referenceRange) { 1272 if (!resultRange.isCollapsed() && startInReferenceRange && normalizeRange(re sultRange) == referenceRange) {
1253 if (forward) 1273 if (forward)
1254 searchRange = EphemeralRangeTemplate<Strategy>(fromPositionInDOMTree <Strategy>(resultRange->endPosition()), searchRange.endPosition()); 1274 searchRange = EphemeralRangeTemplate<Strategy>(resultRange.endPositi on(), searchRange.endPosition());
1255 else 1275 else
1256 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), fromPositionInDOMTree<Strategy>(resultRange->startPosition())); 1276 searchRange = EphemeralRangeTemplate<Strategy>(searchRange.startPosi tion(), resultRange.startPosition());
1257 resultRange = findStringBetweenPositions(target, searchRange, options); 1277 resultRange = findStringBetweenPositions(target, searchRange, options);
1258 } 1278 }
1259 1279
1260 if (!resultRange && options & WrapAround) 1280 if (resultRange.isCollapsed() && options & WrapAround)
1261 return findStringBetweenPositions(target, documentRange, options); 1281 return findStringBetweenPositions(target, documentRange, options);
1262 1282
1263 return resultRange.release(); 1283 return resultRange;
1264 } 1284 }
1265 1285
1266 PassRefPtrWillBeRawPtr<Range> Editor::findRangeOfString(const String& target, co nst EphemeralRange& reference, FindOptions options) 1286 EphemeralRange Editor::findRangeOfString(const String& target, const EphemeralRa nge& reference, FindOptions options)
1267 { 1287 {
1268 return findRangeOfStringAlgorithm<EditingStrategy>(*frame().document(), targ et, reference, options); 1288 return findRangeOfStringAlgorithm<EditingStrategy>(*frame().document(), targ et, reference, options);
1269 } 1289 }
1270 1290
1271 PassRefPtrWillBeRawPtr<Range> Editor::findRangeOfString(const String& target, co nst EphemeralRangeInComposedTree& reference, FindOptions options) 1291 EphemeralRangeInComposedTree Editor::findRangeOfString(const String& target, con st EphemeralRangeInComposedTree& reference, FindOptions options)
1272 { 1292 {
1273 return findRangeOfStringAlgorithm<EditingInComposedTreeStrategy>(*frame().do cument(), target, reference, options); 1293 return findRangeOfStringAlgorithm<EditingInComposedTreeStrategy>(*frame().do cument(), target, reference, options);
1274 } 1294 }
1275 1295
1276 void Editor::setMarkedTextMatchesAreHighlighted(bool flag) 1296 void Editor::setMarkedTextMatchesAreHighlighted(bool flag)
1277 { 1297 {
1278 if (flag == m_areMarkedTextMatchesHighlighted) 1298 if (flag == m_areMarkedTextMatchesHighlighted)
1279 return; 1299 return;
1280 1300
1281 m_areMarkedTextMatchesHighlighted = flag; 1301 m_areMarkedTextMatchesHighlighted = flag;
(...skipping 19 matching lines...) Expand all
1301 } 1321 }
1302 1322
1303 DEFINE_TRACE(Editor) 1323 DEFINE_TRACE(Editor)
1304 { 1324 {
1305 visitor->trace(m_frame); 1325 visitor->trace(m_frame);
1306 visitor->trace(m_lastEditCommand); 1326 visitor->trace(m_lastEditCommand);
1307 visitor->trace(m_mark); 1327 visitor->trace(m_mark);
1308 } 1328 }
1309 1329
1310 } // namespace blink 1330 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698