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

Unified Diff: third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp

Issue 2650113004: [WIP] Add support for Android SuggestionSpans when editing text (Closed)
Patch Set: Created 3 years, 11 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
diff --git a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
index 2a23e42732c35eea6bfa9e9388161fd933e740c6..a3bb48474967a6c8585d2371925405563c9d4c98 100644
--- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
+++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp
@@ -71,6 +71,10 @@ DocumentMarker::MarkerTypeIndex MarkerTypeToMarkerIndex(
return DocumentMarker::InvisibleSpellcheckMarkerIndex;
case DocumentMarker::Composition:
return DocumentMarker::CompositionMarkerIndex;
+ case DocumentMarker::Suggestion:
+ return DocumentMarker::SuggestionMarkerIndex;
+ case DocumentMarker::SuggestionBackgroundHighlight:
+ return DocumentMarker::SuggestionBackgroundHighlightMarkerIndex;
}
NOTREACHED();
@@ -85,11 +89,14 @@ inline bool DocumentMarkerController::possiblyHasMarkers(
}
DocumentMarkerController::DocumentMarkerController(const Document& document)
- : m_possiblyExistingMarkerTypes(0), m_document(&document) {}
+ : m_possiblyExistingMarkerTypes(0),
+ m_document(&document),
+ m_nextSuggestionMarkerID(0) {}
void DocumentMarkerController::clear() {
m_markers.clear();
m_possiblyExistingMarkerTypes = 0;
+ m_nextSuggestionMarkerID = 0;
}
void DocumentMarkerController::addMarker(const Position& start,
@@ -124,19 +131,40 @@ void DocumentMarkerController::addTextMatchMarker(const EphemeralRange& range,
// throttling algorithm. crbug.com/6819.
}
-void DocumentMarkerController::addCompositionMarker(const Position& start,
- const Position& end,
- Color underlineColor,
- bool thick,
- Color backgroundColor) {
+void DocumentMarkerController::addCompositionMarker(
+ const Position& start,
+ const Position& end,
+ Color underlineColor,
+ bool thick,
+ Color backgroundColor,
+ const std::vector<std::string>& suggestions) {
DCHECK(!m_document->needsLayoutTreeUpdate());
-
for (TextIterator markedText(start, end); !markedText.atEnd();
- markedText.advance())
+ markedText.advance()) {
addMarker(markedText.currentContainer(),
DocumentMarker(markedText.startOffsetInCurrentContainer(),
markedText.endOffsetInCurrentContainer(),
+ underlineColor, thick, backgroundColor,
+ suggestions, m_nextSuggestionMarkerID++));
+ }
+}
+
+void DocumentMarkerController::addSuggestionBackgroundHighlightMarker(
+ const Position& start,
+ const Position& end,
+ Color underlineColor,
+ bool thick,
+ Color backgroundColor) {
+ DCHECK(!m_document->needsLayoutTreeUpdate());
+
+ for (TextIterator markedText(start, end); !markedText.atEnd();
+ markedText.advance()) {
+ addMarker(markedText.currentContainer(),
+ DocumentMarker(DocumentMarker::SuggestionBackgroundHighlight,
+ markedText.startOffsetInCurrentContainer(),
+ markedText.endOffsetInCurrentContainer(),
underlineColor, thick, backgroundColor));
+ }
}
void DocumentMarkerController::prepareForDestruction() {
@@ -159,6 +187,7 @@ void DocumentMarkerController::removeMarkers(
endOffset - startOffset, markerTypes,
shouldRemovePartiallyOverlappingMarker);
}
+ showMarkers();
}
void DocumentMarkerController::removeMarkers(
@@ -171,6 +200,7 @@ void DocumentMarkerController::removeMarkers(
TextIterator markedText(range.startPosition(), range.endPosition());
DocumentMarkerController::removeMarkers(
markedText, markerTypes, shouldRemovePartiallyOverlappingMarker);
+ showMarkers();
}
static bool startsFurther(const Member<RenderedDocumentMarker>& lhv,
@@ -178,11 +208,6 @@ static bool startsFurther(const Member<RenderedDocumentMarker>& lhv,
return lhv->startOffset() < rhv->startOffset();
}
-static bool startsAfter(const Member<RenderedDocumentMarker>& marker,
- size_t startOffset) {
- return marker->startOffset() < startOffset;
-}
-
static bool endsBefore(size_t startOffset,
const Member<RenderedDocumentMarker>& rhv) {
return startOffset < rhv->endOffset();
@@ -255,7 +280,8 @@ void DocumentMarkerController::addMarker(Node* node,
list->push_back(newRenderedMarker);
} else {
if (newMarker.type() != DocumentMarker::TextMatch &&
- newMarker.type() != DocumentMarker::Composition) {
+ newMarker.type() != DocumentMarker::Composition &&
+ newMarker.type() != DocumentMarker::Suggestion) {
mergeOverlapping(list.get(), newRenderedMarker);
} else {
MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(),
@@ -354,6 +380,7 @@ void DocumentMarkerController::removeMarkers(
if (!possiblyHasMarkers(markerTypes))
return;
+
DCHECK(!(m_markers.isEmpty()));
MarkerLists* markers = m_markers.get(node);
@@ -430,6 +457,8 @@ void DocumentMarkerController::removeMarkers(
// repaint the affected node
if (docDirty && node->layoutObject())
node->layoutObject()->setShouldDoFullPaintInvalidation();
+
+ showMarkers();
}
DocumentMarkerVector DocumentMarkerController::markersFor(
@@ -482,22 +511,38 @@ DocumentMarkerVector DocumentMarkerController::markersInRange(
DocumentMarkerVector foundMarkers;
Node* startContainer = range.startPosition().computeContainerNode();
- DCHECK(startContainer);
+ if (!startContainer)
+ return DocumentMarkerVector();
+
unsigned startOffset = static_cast<unsigned>(
range.startPosition().computeOffsetInContainerNode());
+
Node* endContainer = range.endPosition().computeContainerNode();
- DCHECK(endContainer);
+ if (!endContainer)
+ return DocumentMarkerVector();
+
unsigned endOffset =
static_cast<unsigned>(range.endPosition().computeOffsetInContainerNode());
+ // For zero-length ranges, include spans whose endpoints touch the range
aelias_OOO_until_Jul13 2017/01/25 03:34:27 That's not very principled. I'd prefer you introd
rlanday 2017/01/25 18:48:10 That's a good idea; I got the idea to do it the wa
+ // location
+ bool isZeroLengthRange =
+ (startContainer == endContainer) && (startOffset == endOffset);
+
for (Node& node : range.nodes()) {
for (DocumentMarker* marker : markersFor(&node)) {
if (!markerTypes.contains(marker->type()))
continue;
- if (node == startContainer && marker->endOffset() <= startOffset)
- continue;
- if (node == endContainer && marker->startOffset() >= endOffset)
- continue;
+ if (node == startContainer) {
+ if (marker->endOffset() < startOffset ||
+ (marker->endOffset() == startOffset && !isZeroLengthRange))
+ continue;
+ }
+ if (node == endContainer) {
+ if (marker->startOffset() > endOffset ||
+ (marker->startOffset() == endOffset && !isZeroLengthRange))
+ continue;
+ }
foundMarkers.push_back(marker);
}
}
@@ -600,6 +645,8 @@ void DocumentMarkerController::removeMarkers(
MarkerMap::iterator iterator = m_markers.find(node);
if (iterator != m_markers.end())
removeMarkersFromList(iterator, markerTypes);
+
+ showMarkers();
}
void DocumentMarkerController::removeMarkers(
@@ -628,6 +675,8 @@ void DocumentMarkerController::removeMarkers(
invalidatePaintForTickmarks(node);
}
}
+
+ showMarkers();
}
void DocumentMarkerController::removeMarkers(
@@ -646,6 +695,27 @@ void DocumentMarkerController::removeMarkers(
}
m_possiblyExistingMarkerTypes.remove(markerTypes);
+
+ showMarkers();
+}
+
+void DocumentMarkerController::removeSuggestionMarkersByID(
+ const Vector<int>& idsToRemove) {
+ for (auto& nodeMarkers : m_markers) {
+ MarkerLists& markers = *nodeMarkers.value;
+ Member<MarkerList>& suggestionMarkerList =
+ markers[DocumentMarker::SuggestionMarkerIndex];
+ if (!suggestionMarkerList)
+ continue;
+ bool removedMarkers = false;
+ for (size_t j = suggestionMarkerList->size(); j > 0; --j) {
+ if (idsToRemove.contains(
+ suggestionMarkerList->at(j - 1)->suggestionMarkerID())) {
+ suggestionMarkerList->remove(j - 1);
+ removedMarkers = true;
+ }
+ }
+ }
}
void DocumentMarkerController::removeMarkersFromList(
@@ -695,6 +765,8 @@ void DocumentMarkerController::removeMarkersFromList(
if (m_markers.isEmpty())
m_possiblyExistingMarkerTypes = 0;
}
+
+ showMarkers();
}
void DocumentMarkerController::repaintMarkers(
@@ -728,8 +800,13 @@ void DocumentMarkerController::repaintMarkers(
}
void DocumentMarkerController::shiftMarkers(Node* node,
- unsigned startOffset,
- int delta) {
+ int startOffset,
+ int prevLength,
+ int newLength) {
+ DCHECK_GE(startOffset, 0);
+ DCHECK_GE(prevLength, 0);
+ DCHECK_GE(newLength, 0);
+
if (!possiblyHasMarkers(DocumentMarker::AllMarkers()))
return;
DCHECK(!m_markers.isEmpty());
@@ -745,15 +822,34 @@ void DocumentMarkerController::shiftMarkers(Node* node,
Member<MarkerList>& list = (*markers)[markerListIndex];
if (!list)
continue;
- MarkerList::iterator startPos =
- std::lower_bound(list->begin(), list->end(), startOffset, startsAfter);
- for (MarkerList::iterator marker = startPos; marker != list->end();
+
+ // algorithm from https://dom.spec.whatwg.org/#concept-cd-replace
+ for (MarkerList::iterator marker = list->begin(); marker != list->end();
++marker) {
-#if DCHECK_IS_ON()
- int startOffset = (*marker)->startOffset();
- DCHECK_GE(startOffset + delta, 0);
-#endif
- (*marker)->shiftOffsets(delta);
+ if ((*marker)->startOffset() > (unsigned)startOffset) {
+ if ((*marker)->startOffset() <= (unsigned)(startOffset + prevLength)) {
+ // Marker start was in the replaced text. Move to beginning of new
+ // text
+ (*marker)->setStartOffset(startOffset);
+ } else {
+ // Marker start was after the replaced text. Shift by length
+ // difference
+ unsigned oldStartOffset = (*marker)->startOffset();
+ (*marker)->setStartOffset(oldStartOffset + newLength - prevLength);
+ }
+ }
+
+ if ((*marker)->endOffset() > (unsigned)startOffset) {
+ if ((*marker)->endOffset() <= (unsigned)(startOffset + prevLength)) {
+ // Marker end was in the replaced text. Move to beginning of new text
+ (*marker)->setEndOffset(startOffset);
+ } else {
+ // Marker end was after the replaced text. Shift by length difference
+ unsigned oldEndOffset = (*marker)->endOffset();
+ (*marker)->setEndOffset(oldEndOffset + newLength - prevLength);
+ }
+ }
+
didShiftMarker = true;
}
}

Powered by Google App Engine
This is Rietveld 408576698