OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "core/editing/markers/EditingMarkerList.h" | |
6 | |
7 #include <algorithm> | |
8 #include "core/editing/markers/DocumentMarkerController.h" | |
9 | |
10 namespace blink { | |
11 | |
12 namespace { | |
13 | |
14 bool compareByStart(const Member<DocumentMarker>& lhv, | |
15 const Member<DocumentMarker>& rhv) { | |
16 return lhv->startOffset() < rhv->startOffset(); | |
17 } | |
18 | |
19 } // namespace | |
20 | |
21 EditingMarkerList::EditingMarkerList( | |
22 DocumentMarkerController* documentMarkerController) | |
23 : DocumentMarkerList(documentMarkerController), m_markersAreSorted(true) {} | |
24 | |
25 bool EditingMarkerList::isEditingMarkerList() const { | |
26 return true; | |
27 } | |
28 | |
29 void EditingMarkerList::clear() { | |
30 m_markers.clear(); | |
31 m_markersAreSorted = true; | |
32 } | |
33 | |
34 void EditingMarkerList::removeMarkers( | |
35 unsigned startOffset, | |
36 int length, | |
37 bool shouldRemovePartiallyOverlappingMarkers, | |
38 bool* didRemoveMarker) { | |
39 unsigned endOffset = startOffset + length; | |
40 size_t markerIndex = 0; | |
41 if (m_markersAreSorted) { | |
42 markerIndex = | |
43 getPosOfFirstMarkerNotEndingBefore(startOffset) - m_markers.begin(); | |
44 } | |
45 | |
46 for (; markerIndex < m_markers.size();) { | |
47 DocumentMarker& marker = *m_markers.at(markerIndex); | |
48 if (!m_markersAreSorted) { | |
49 if (marker.endOffset() <= startOffset) { | |
50 ++markerIndex; | |
51 continue; | |
52 } | |
53 } | |
54 | |
55 if (marker.startOffset() >= endOffset) { | |
56 if (m_markersAreSorted) | |
57 break; | |
58 ++markerIndex; | |
59 continue; | |
60 } | |
61 | |
62 // pitch the old marker | |
63 m_markers.remove(markerIndex); | |
Xiaocheng
2017/03/24 03:57:47
The handling of each marker in the removal range i
rlanday
2017/03/24 17:45:49
Yeah, I think we can add a helper method that just
| |
64 *didRemoveMarker = true; | |
65 | |
66 if (shouldRemovePartiallyOverlappingMarkers) { | |
67 // Stop here. Don't add resulting slices back. | |
68 continue; | |
69 } | |
70 | |
71 // add either of the resulting slices that are left after removing target | |
72 if (startOffset > marker.startOffset()) { | |
Xiaocheng
2017/03/24 03:57:47
The case |startOffset > marker.startOffset() && en
rlanday
2017/03/24 17:45:48
I'm pretty sure this case is handled (it goes thro
| |
73 DocumentMarker* newLeft = new DocumentMarker(marker); | |
74 newLeft->setEndOffset(startOffset); | |
75 if (m_markersAreSorted) { | |
76 m_markers.insert(markerIndex, *newLeft); | |
77 // Move to the marker after the inserted one. | |
78 ++markerIndex; | |
79 } else { | |
80 // For the unsorted case, we just stick the new marker at the end of the | |
81 // list. The loop will eventually run on it but that's not a problem | |
82 // since it's known to be outside the range being removed. | |
83 m_markers.push_back(*newLeft); | |
84 } | |
85 } | |
86 if (marker.endOffset() > endOffset) { | |
87 DocumentMarker* newRight = new DocumentMarker(marker); | |
88 newRight->setStartOffset(endOffset); | |
89 if (m_markersAreSorted) { | |
90 m_markers.insert(markerIndex, *newRight); | |
91 // Move to the marker after the inserted one. | |
92 ++markerIndex; | |
93 } else { | |
94 m_markers.push_back(*newRight); | |
95 } | |
96 } | |
97 } | |
98 } | |
99 | |
100 bool EditingMarkerList::shiftMarkers(unsigned offset, | |
Xiaocheng
2017/03/24 03:57:47
This function is completely the same as TextMatchM
rlanday
2017/03/24 17:45:48
Oh...I think at one point, I thought I could optim
| |
101 unsigned oldLength, | |
102 unsigned newLength) { | |
103 bool didShift = false; | |
104 for (auto it = m_markers.begin(); it != m_markers.end(); ++it) { | |
105 DocumentMarker& marker = **it; | |
106 | |
107 DocumentMarker::ShiftMarkerResult result = | |
108 marker.getShiftedMarkerPosition(offset, oldLength, newLength); | |
109 if (result.shouldRemoveMarker) { | |
110 m_markers.remove(it - m_markers.begin()); | |
111 --it; | |
112 | |
113 didShift = true; | |
114 } else if (result.newStartOffset != marker.startOffset() || | |
115 result.newEndOffset != marker.endOffset()) { | |
116 marker.setStartOffset(result.newStartOffset); | |
117 marker.setEndOffset(result.newEndOffset); | |
118 | |
119 didShift = true; | |
120 } | |
121 } | |
122 | |
123 return didShift; | |
124 } | |
125 | |
126 void EditingMarkerList::insert(DocumentMarker* marker) { | |
127 DCHECK(marker->type() == allowedMarkerType()); | |
128 if (m_markersAreSorted && !m_markers.isEmpty() && | |
129 m_markers.back()->endOffset() > marker->startOffset()) | |
130 m_markersAreSorted = false; | |
131 m_markers.push_back(marker); | |
132 } | |
133 | |
134 void EditingMarkerList::sortMarkerList() { | |
135 if (m_markersAreSorted) | |
136 return; | |
137 | |
138 std::sort(m_markers.begin(), m_markers.end(), compareByStart); | |
139 | |
140 m_markersAreSorted = true; | |
141 } | |
142 | |
143 DEFINE_TRACE(EditingMarkerList) { | |
144 visitor->trace(m_markers); | |
145 DocumentMarkerList::trace(visitor); | |
146 } | |
147 | |
148 } // namespace blink | |
OLD | NEW |