summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/editing/markers/document_marker_controller.h
blob: 4f50d427fccb3191a2989d3b9db41f020f8cbafb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
 *           (C) 2001 Dirk Mueller (mueller@kde.org)
 *           (C) 2006 Alexey Proskuryakov (ap@webkit.org)
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights
 * reserved.
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (C) Research In Motion Limited 2010. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_DOCUMENT_MARKER_CONTROLLER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_DOCUMENT_MARKER_CONTROLLER_H_

#include <utility>

#include "base/dcheck_is_on.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/synchronous_mutation_observer.h"
#include "third_party/blink/renderer/core/editing/forward.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
#include "third_party/blink/renderer/core/editing/markers/composition_marker.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker.h"
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker.h"
#include "third_party/blink/renderer/core/editing/markers/text_match_marker.h"
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

namespace blink {

class DocumentMarkerList;
class Highlight;
class SuggestionMarkerProperties;

class CORE_EXPORT DocumentMarkerController final
    : public GarbageCollected<DocumentMarkerController>,
      public SynchronousMutationObserver {
 public:
  explicit DocumentMarkerController(Document&);
  DocumentMarkerController(const DocumentMarkerController&) = delete;
  DocumentMarkerController& operator=(const DocumentMarkerController&) = delete;

  void Clear();
  void AddSpellingMarker(const EphemeralRange&,
                         const String& description = g_empty_string);
  void AddGrammarMarker(const EphemeralRange&,
                        const String& description = g_empty_string);
  void AddTextMatchMarker(const EphemeralRange&, TextMatchMarker::MatchStatus);
  void AddCompositionMarker(const EphemeralRange&,
                            Color underline_color,
                            ui::mojom::ImeTextSpanThickness,
                            ui::mojom::ImeTextSpanUnderlineStyle,
                            Color text_color,
                            Color background_color);
  void AddActiveSuggestionMarker(const EphemeralRange&,
                                 Color underline_color,
                                 ui::mojom::ImeTextSpanThickness,
                                 ui::mojom::ImeTextSpanUnderlineStyle,
                                 Color text_color,
                                 Color background_color);
  void AddSuggestionMarker(const EphemeralRange&,
                           const SuggestionMarkerProperties&);
  void AddTextFragmentMarker(const EphemeralRange&);
  void AddHighlightMarker(const EphemeralRange&,
                          const String& highlight_name,
                          const Member<Highlight> highlight);

  void MoveMarkers(const Text& src_node, int length, const Text& dst_node);

  void PrepareForDestruction();
  void RemoveMarkersInRange(const EphemeralRange&, DocumentMarker::MarkerTypes);
  void RemoveMarkersOfTypes(DocumentMarker::MarkerTypes);
  void RemoveMarkersForNode(
      const Text&,
      DocumentMarker::MarkerTypes = DocumentMarker::MarkerTypes::All());
  void RemoveSpellingMarkersUnderWords(const Vector<String>& words);
  void RemoveSuggestionMarkerByTag(const Text&, int32_t marker_tag);
  void RemoveSuggestionMarkerByType(
      const EphemeralRangeInFlatTree& range,
      const SuggestionMarker::SuggestionType& type);
  void RemoveSuggestionMarkerByType(
      const SuggestionMarker::SuggestionType& type);
  // Removes suggestion marker with |RemoveOnFinishComposing::kRemove|.
  void RemoveSuggestionMarkerInRangeOnFinish(const EphemeralRangeInFlatTree&);
  void RepaintMarkers(
      DocumentMarker::MarkerTypes = DocumentMarker::MarkerTypes::All());
  // Returns true if markers within a range are found.
  bool SetTextMatchMarkersActive(const EphemeralRange&, bool);
  // Returns true if markers within a range defined by a text node,
  // |start_offset| and |end_offset| are found.
  bool SetTextMatchMarkersActive(const Text&,
                                 unsigned start_offset,
                                 unsigned end_offset,
                                 bool);

  // TODO(rlanday): can these methods for retrieving markers be consolidated
  // without hurting efficiency?

  // If the given position is either at the boundary or inside a word, expands
  // the position to the surrounding word and then looks for a marker having the
  // specified type. If the position is neither at the boundary or inside a
  // word, expands the position to cover the space between the end of the
  // previous and the start of the next words. If such a marker exists, this
  // method will return one of them (no guarantees are provided as to which
  // one). Otherwise, this method will return null.
  DocumentMarker* FirstMarkerAroundPosition(const PositionInFlatTree&,
                                            DocumentMarker::MarkerTypes);
  // Looks for a marker in the specified EphemeralRange of the specified type
  // whose interior has non-empty overlap with the bounds of the range.
  // If the range is collapsed, it uses FirstMarkerAroundPosition to expand the
  // range to the surrounding word.
  // If such a marker exists, this method will return one of them (no guarantees
  // are provided as to which one). Otherwise, this method will return null.
  DocumentMarker* FirstMarkerIntersectingEphemeralRange(
      const EphemeralRange&,
      DocumentMarker::MarkerTypes);
  // Looks for a marker in the specified node of the specified type whose
  // interior has non-empty overlap with the range [start_offset, end_offset].
  // If the range is collapsed, this looks for a marker containing the offset of
  // the collapsed range in its interior.
  // If such a marker exists, this method will return one of them (no guarantees
  // are provided as to which one). Otherwise, this method will return null.
  DocumentMarker* FirstMarkerIntersectingOffsetRange(
      const Text&,
      unsigned start_offset,
      unsigned end_offset,
      DocumentMarker::MarkerTypes);
  // If the given position is either at the boundary or inside a word, expands
  // the position to the surrounding word and then looks for all markers having
  // the specified type. If the position is neither at the boundary or inside a
  // word, expands the position to cover the space between the end of the
  // previous and the start of the next words. If such markers exist, this
  // method will return all of them in their corresponding node. Otherwise,
  // this method will return an empty list.
  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
  MarkersAroundPosition(const PositionInFlatTree& position,
                        DocumentMarker::MarkerTypes types);
  // Return all markers of the specified types whose interiors have non-empty
  // overlap with the specified range. Note that the range can be collapsed, in
  // in which case markers containing the position in their interiors are
  // returned.
  HeapVector<std::pair<Member<const Text>, Member<DocumentMarker>>>
  MarkersIntersectingRange(const EphemeralRangeInFlatTree&,
                           DocumentMarker::MarkerTypes);
  DocumentMarkerVector MarkersFor(
      const Text&,
      DocumentMarker::MarkerTypes = DocumentMarker::MarkerTypes::All()) const;
  DocumentMarkerVector Markers() const;
  DocumentMarkerVector ComputeMarkersToPaint(const Text&) const;

  bool PossiblyHasTextMatchMarkers() const;
  Vector<IntRect> LayoutRectsForTextMatchMarkers();
  void InvalidateRectsForAllTextMatchMarkers();
  void InvalidateRectsForTextMatchMarkersInNode(const Text&);

  void Trace(Visitor*) const override;

#if DCHECK_IS_ON()
  void ShowMarkers() const;
#endif

  // SynchronousMutationObserver
  // For performance, observer is only registered when
  // |possibly_existing_marker_types_| is non-zero.
  void DidUpdateCharacterData(CharacterData*,
                              unsigned offset,
                              unsigned old_length,
                              unsigned new_length) final;

 private:
  void AddMarkerInternal(
      const EphemeralRange&,
      std::function<DocumentMarker*(int, int)> create_marker_from_offsets,
      const TextIteratorBehavior& iterator_behavior = {});
  void AddMarkerToNode(const Text&, DocumentMarker*);

  using MarkerLists = HeapVector<Member<DocumentMarkerList>,
                                 DocumentMarker::kMarkerTypeIndexesCount>;
  using MarkerMap = HeapHashMap<WeakMember<const Text>, Member<MarkerLists>>;
  static Member<DocumentMarkerList>& ListForType(MarkerLists*,
                                                 DocumentMarker::MarkerType);
  bool PossiblyHasMarkers(DocumentMarker::MarkerTypes) const;
  bool PossiblyHasMarkers(DocumentMarker::MarkerType) const;
  void RemoveMarkersFromList(MarkerMap::iterator, DocumentMarker::MarkerTypes);
  void RemoveMarkers(TextIterator&, DocumentMarker::MarkerTypes);
  void RemoveMarkersInternal(const Text&,
                             unsigned start_offset,
                             int length,
                             DocumentMarker::MarkerTypes);

  // Called after weak processing of |markers_| is done.
  void DidProcessMarkerMap(const LivenessBroker&);

  MarkerMap markers_;
  // Provide a quick way to determine whether a particular marker type is absent
  // without going through the map.
  DocumentMarker::MarkerTypes possibly_existing_marker_types_;
  const Member<Document> document_;
};

}  // namespace blink

#if DCHECK_IS_ON()
void showDocumentMarkers(const blink::DocumentMarkerController*);
#endif

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_MARKERS_DOCUMENT_MARKER_CONTROLLER_H_