 Chromium Code Reviews
 Chromium Code Reviews Issue 2812423002:
  [DMC #1] Refactor DocumentMarkerController on top of new DocumentMarkerListEditor class  (Closed)
    
  
    Issue 2812423002:
  [DMC #1] Refactor DocumentMarkerController on top of new DocumentMarkerListEditor class  (Closed) 
  | 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 ad1da82cbb6413d7efc0093cb387a2629e542d0a..011677bfe54be4ba9cad0ac82c47f3c6afdf519e 100644 | 
| --- a/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp | 
| +++ b/third_party/WebKit/Source/core/editing/markers/DocumentMarkerController.cpp | 
| @@ -209,6 +209,45 @@ static void UpdateMarkerRenderedRect(const Node& node, | 
| range->Dispose(); | 
| } | 
| +// TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | 
| +void DocumentMarkerListEditor::MergeOverlapping( | 
| 
Xiaocheng
2017/04/14 00:48:06
Could you put it at the same place as DMC::MergeOv
 
yosin_UTC9
2017/04/14 01:21:14
Please to follow xiaochengh@'s comment. The purpos
 | 
| + MarkerList* list, | 
| + RenderedDocumentMarker* to_insert) { | 
| + MarkerList::iterator first_overlapping = | 
| + std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); | 
| + size_t index = first_overlapping - list->begin(); | 
| + list->insert(index, to_insert); | 
| + MarkerList::iterator inserted = list->begin() + index; | 
| + first_overlapping = inserted + 1; | 
| + for (MarkerList::iterator i = first_overlapping; | 
| + i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | 
| + (*inserted)->SetStartOffset( | 
| + std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | 
| + (*inserted)->SetEndOffset( | 
| + std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | 
| + list->erase(i - list->begin()); | 
| + } | 
| +} | 
| + | 
| +// TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | 
| +void DocumentMarkerListEditor::AddMarker(MarkerList* list, | 
| + DocumentMarker* marker) { | 
| + RenderedDocumentMarker* rendered_marker = | 
| + RenderedDocumentMarker::Create(*marker); | 
| + if (list->IsEmpty() || list->back()->EndOffset() < marker->StartOffset()) { | 
| + list->push_back(rendered_marker); | 
| + } else { | 
| + if (marker->GetType() != DocumentMarker::kTextMatch && | 
| + marker->GetType() != DocumentMarker::kComposition) { | 
| + MergeOverlapping(list, rendered_marker); | 
| + } else { | 
| + MarkerList::iterator pos = | 
| + std::lower_bound(list->begin(), list->end(), marker, StartsFurther); | 
| + list->insert(pos - list->begin(), rendered_marker); | 
| + } | 
| + } | 
| +} | 
| + | 
| // Markers are stored in order sorted by their start offset. | 
| // Markers of the same type do not overlap each other. | 
| @@ -236,18 +275,7 @@ void DocumentMarkerController::AddMarker(Node* node, | 
| Member<MarkerList>& list = markers->at(marker_list_index); | 
| RenderedDocumentMarker* new_rendered_marker = | 
| 
Xiaocheng
2017/04/14 00:48:06
No need to create RDM here. It's already done in D
 | 
| RenderedDocumentMarker::Create(new_marker); | 
| - if (list->IsEmpty() || list->back()->EndOffset() < new_marker.StartOffset()) { | 
| - list->push_back(new_rendered_marker); | 
| - } else { | 
| - if (new_marker.GetType() != DocumentMarker::kTextMatch && | 
| - new_marker.GetType() != DocumentMarker::kComposition) { | 
| - MergeOverlapping(list.Get(), new_rendered_marker); | 
| - } else { | 
| - MarkerList::iterator pos = std::lower_bound(list->begin(), list->end(), | 
| - &new_marker, StartsFurther); | 
| - list->insert(pos - list->begin(), new_rendered_marker); | 
| - } | 
| - } | 
| + DocumentMarkerListEditor::AddMarker(list, new_rendered_marker); | 
| // repaint the affected node | 
| if (node->GetLayoutObject()) { | 
| @@ -256,23 +284,32 @@ void DocumentMarkerController::AddMarker(Node* node, | 
| } | 
| } | 
| -void DocumentMarkerController::MergeOverlapping( | 
| - MarkerList* list, | 
| - RenderedDocumentMarker* to_insert) { | 
| - MarkerList::iterator first_overlapping = | 
| - std::lower_bound(list->begin(), list->end(), to_insert, DoesNotOverlap); | 
| - size_t index = first_overlapping - list->begin(); | 
| - list->insert(index, to_insert); | 
| - MarkerList::iterator inserted = list->begin() + index; | 
| - first_overlapping = inserted + 1; | 
| - for (MarkerList::iterator i = first_overlapping; | 
| - i != list->end() && (*i)->StartOffset() <= (*inserted)->EndOffset();) { | 
| - (*inserted)->SetStartOffset( | 
| - std::min((*inserted)->StartOffset(), (*i)->StartOffset())); | 
| - (*inserted)->SetEndOffset( | 
| - std::max((*inserted)->EndOffset(), (*i)->EndOffset())); | 
| - list->erase(i - list->begin()); | 
| +// TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | 
| +bool DocumentMarkerListEditor::MoveMarkers(MarkerList* src_list, | 
| + int length, | 
| + MarkerList* dst_list) { | 
| + DCHECK_GT(length, 0); | 
| + bool didMoveMarker = false; | 
| + unsigned end_offset = length - 1; | 
| + | 
| + MarkerList::iterator it; | 
| + for (it = src_list->begin(); it != src_list->end(); ++it) { | 
| + DocumentMarker& marker = **it; | 
| + if (marker.StartOffset() > end_offset) | 
| + break; | 
| + | 
| + // pin the marker to the specified range and apply the shift delta | 
| + if (marker.EndOffset() > end_offset) | 
| + marker.SetEndOffset(end_offset); | 
| + | 
| + DocumentMarkerListEditor::AddMarker(dst_list, &marker); | 
| + didMoveMarker = true; | 
| } | 
| + | 
| + // Remove the range of markers that were moved to dstNode | 
| + src_list->erase(0, it - src_list->begin()); | 
| + | 
| + return didMoveMarker; | 
| } | 
| // Moves markers from src_node to dst_node. Markers are moved if their start | 
| @@ -287,34 +324,30 @@ void DocumentMarkerController::MoveMarkers(Node* src_node, | 
| return; | 
| DCHECK(!markers_.IsEmpty()); | 
| - MarkerLists* markers = markers_.at(src_node); | 
| - if (!markers) | 
| + MarkerLists* src_markers = markers_.at(src_node); | 
| + if (!src_markers) | 
| return; | 
| + Member<MarkerLists>& dst_markers = | 
| 
Xiaocheng
2017/04/14 00:48:06
Could you make the code less hacky?
if (!markers_
 | 
| + markers_.insert(dst_node, nullptr).stored_value->value; | 
| + if (!dst_markers) { | 
| + dst_markers = new MarkerLists; | 
| + dst_markers->Grow(DocumentMarker::kMarkerTypeIndexesCount); | 
| + } | 
| + | 
| bool doc_dirty = false; | 
| - for (Member<MarkerList> list : *markers) { | 
| - if (!list) | 
| + for (size_t marker_list_index = 0; marker_list_index < src_markers->size(); | 
| + marker_list_index++) { | 
| + MarkerList* src_list = src_markers->at(marker_list_index); | 
| + if (!src_list) | 
| continue; | 
| - unsigned end_offset = length - 1; | 
| - MarkerList::iterator it; | 
| - for (it = list->begin(); it != list->end(); ++it) { | 
| - DocumentMarker* marker = it->Get(); | 
| - | 
| - // stop if we are now past the specified range | 
| - if (marker->StartOffset() > end_offset) | 
| - break; | 
| - | 
| - // pin the marker to the specified range | 
| - doc_dirty = true; | 
| - if (marker->EndOffset() > end_offset) | 
| - marker->SetEndOffset(end_offset); | 
| - | 
| - AddMarker(dst_node, *marker); | 
| + if (!dst_markers->at(marker_list_index)) { | 
| + dst_markers->at(marker_list_index) = new MarkerList; | 
| } | 
| - // Remove the range of markers that were moved to dstNode | 
| - list->erase(0, it - list->begin()); | 
| + DocumentMarkerListEditor::MoveMarkers(src_list, length, | 
| 
Xiaocheng
2017/04/14 00:48:06
doc_dirty |= DMLEditor::MoveMarkers(...)
 | 
| + dst_markers->at(marker_list_index)); | 
| } | 
| // repaint the affected node | 
| @@ -324,6 +357,29 @@ void DocumentMarkerController::MoveMarkers(Node* src_node, | 
| } | 
| } | 
| +// TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | 
| +bool DocumentMarkerListEditor::RemoveMarkers(MarkerList* list, | 
| + unsigned start_offset, | 
| + int length) { | 
| + bool doc_dirty = false; | 
| + unsigned end_offset = start_offset + length; | 
| + MarkerList::iterator start_pos = | 
| + std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | 
| + for (MarkerList::iterator i = start_pos; i != list->end();) { | 
| + DocumentMarker marker(*i->Get()); | 
| + | 
| + // markers are returned in order, so stop if we are now past the specified | 
| + // range | 
| + if (marker.StartOffset() >= end_offset) | 
| + break; | 
| + | 
| + list->erase(i - list->begin()); | 
| + doc_dirty = true; | 
| + } | 
| + | 
| + return doc_dirty; | 
| +} | 
| + | 
| void DocumentMarkerController::RemoveMarkers( | 
| Node* node, | 
| unsigned start_offset, | 
| @@ -354,20 +410,10 @@ void DocumentMarkerController::RemoveMarkers( | 
| } | 
| if (!marker_types.Contains((*list->begin())->GetType())) | 
| continue; | 
| - unsigned end_offset = start_offset + length; | 
| - MarkerList::iterator start_pos = | 
| - std::upper_bound(list->begin(), list->end(), start_offset, EndsBefore); | 
| - for (MarkerList::iterator i = start_pos; i != list->end();) { | 
| - DocumentMarker marker(*i->Get()); | 
| - | 
| - // markers are returned in order, so stop if we are now past the specified | 
| - // range | 
| - if (marker.StartOffset() >= end_offset) | 
| - break; | 
| - list->erase(i - list->begin()); | 
| - doc_dirty = true; | 
| - } | 
| + doc_dirty = | 
| 
Xiaocheng
2017/04/14 00:48:06
nit: We can write doc_dirty |= DMLEditor::RemoveMa
 
rlanday
2017/04/14 01:01:16
I don't think so, I think that would be the same a
 
yosin_UTC9
2017/04/14 01:21:14
foo |= bar() always call |bar()| regard less value
 | 
| + DocumentMarkerListEditor::RemoveMarkers(list, start_offset, length) || | 
| + doc_dirty; | 
| if (list->IsEmpty()) { | 
| list.Clear(); | 
| @@ -672,12 +718,10 @@ void DocumentMarkerController::RepaintMarkers( | 
| // inner loop: process each marker in the current node | 
| MarkerLists* markers = i->value.Get(); | 
| - for (size_t marker_list_index = 0; | 
| - marker_list_index < DocumentMarker::kMarkerTypeIndexesCount; | 
| - ++marker_list_index) { | 
| - Member<MarkerList>& list = (*markers)[marker_list_index]; | 
| - if (!list || list->IsEmpty() || | 
| - !marker_types.Contains((*list->begin())->GetType())) | 
| + for (DocumentMarker::MarkerType type : DocumentMarker::AllMarkers()) { | 
| 
Xiaocheng
2017/04/14 00:48:06
Irrelevant change.
Btw, marker type iterators hav
 | 
| + size_t marker_list_index = MarkerTypeToMarkerIndex(type); | 
| + MarkerList* list = (*markers)[marker_list_index]; | 
| + if (!list || list->IsEmpty() || !marker_types.Contains(type)) | 
| continue; | 
| // cause the node to be redrawn | 
| @@ -784,6 +828,34 @@ void DocumentMarkerController::ShowMarkers() const { | 
| } | 
| #endif | 
| +// TODO(rlanday): move DocumentMarkerListEditor into its own .h/.cpp files | 
| +bool DocumentMarkerListEditor::ShiftMarkers(MarkerList* list, | 
| + unsigned offset, | 
| + unsigned old_length, | 
| + unsigned new_length) { | 
| + bool did_shift_marker = false; | 
| + for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | 
| + RenderedDocumentMarker& marker = **it; | 
| + Optional<DocumentMarker::MarkerOffsets> result = | 
| + marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | 
| + if (result == WTF::kNullopt) { | 
| + list->erase(it - list->begin()); | 
| + --it; | 
| + did_shift_marker = true; | 
| + continue; | 
| + } | 
| + | 
| + if (marker.StartOffset() != result.value().start_offset || | 
| + marker.EndOffset() != result.value().end_offset) { | 
| + did_shift_marker = true; | 
| + marker.SetStartOffset(result.value().start_offset); | 
| + marker.SetEndOffset(result.value().end_offset); | 
| + } | 
| + } | 
| + | 
| + return did_shift_marker; | 
| +} | 
| + | 
| // SynchronousMutationObserver | 
| void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node, | 
| unsigned offset, | 
| @@ -802,24 +874,9 @@ void DocumentMarkerController::DidUpdateCharacterData(CharacterData* node, | 
| if (!list) | 
| continue; | 
| - for (MarkerList::iterator it = list->begin(); it != list->end(); ++it) { | 
| 
yosin_UTC9
2017/04/14 01:21:14
Please put |DMListEditor::ShiftMarkers()| here.
 
rlanday
2017/04/14 01:29:37
Sorry, I don't understand what you're asking here,
 | 
| - RenderedDocumentMarker& marker = **it; | 
| - Optional<DocumentMarker::MarkerOffsets> result = | 
| - marker.ComputeOffsetsAfterShift(offset, old_length, new_length); | 
| - if (result == WTF::kNullopt) { | 
| - list->erase(it - list->begin()); | 
| - --it; | 
| - did_shift_marker = true; | 
| - continue; | 
| - } | 
| - | 
| - if (marker.StartOffset() != result.value().start_offset || | 
| - marker.EndOffset() != result.value().end_offset) { | 
| - did_shift_marker = true; | 
| - marker.SetStartOffset(result.value().start_offset); | 
| - marker.SetEndOffset(result.value().end_offset); | 
| - } | 
| - } | 
| + did_shift_marker = DocumentMarkerListEditor::ShiftMarkers( | 
| 
Xiaocheng
2017/04/14 00:48:06
nit: We can write doc_dirty |= DMLEditor::ShiftMar
 | 
| + list, offset, old_length, new_length) || | 
| + did_shift_marker; | 
| } | 
| if (!did_shift_marker) |