no bug - Correct some typos in the comments. a=typo-fix
[gecko.git] / accessible / base / TextLeafRange.h
blob23fea2ecfba2872abf352f3e878cdfe66cb3720e
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_a11y_TextLeafRange_h__
8 #define mozilla_a11y_TextLeafRange_h__
10 #include <stdint.h>
12 #include "AccAttributes.h"
13 #include "nsDirection.h"
14 #include "nsIAccessibleText.h"
16 class nsRange;
18 namespace mozilla {
19 namespace dom {
20 class Document;
23 namespace a11y {
24 class Accessible;
25 class LocalAccessible;
27 /**
28 * Represents a point within accessible text.
29 * This is stored as a leaf Accessible and an offset into that Accessible.
30 * For an empty Accessible, the offset will always be 0.
31 * This will eventually replace TextPoint. Unlike TextPoint, this does not
32 * use HyperTextAccessible offsets.
34 class TextLeafPoint final {
35 public:
36 TextLeafPoint(Accessible* aAcc, int32_t aOffset);
38 /**
39 * Constructs an invalid TextPoint (mAcc is null).
40 * A TextLeafPoint in this state will evaluate to false.
41 * mAcc can be set later. Alternatively, this can be used to indicate an error
42 * (e.g. if a requested point couldn't be found).
44 TextLeafPoint() : mAcc(nullptr), mOffset(0) {}
46 /**
47 * Construct a TextLeafPoint representing the caret.
48 * The actual offset used for the caret differs depending on whether the
49 * caret is at the end of a line and the query being made. Thus, mOffset on
50 * the returned TextLeafPoint is not a valid offset.
52 static TextLeafPoint GetCaret(Accessible* aAcc) {
53 return TextLeafPoint(aAcc, nsIAccessibleText::TEXT_OFFSET_CARET);
56 Accessible* mAcc;
57 int32_t mOffset;
59 bool operator==(const TextLeafPoint& aPoint) const {
60 return mAcc == aPoint.mAcc && mOffset == aPoint.mOffset;
63 bool operator!=(const TextLeafPoint& aPoint) const {
64 return !(*this == aPoint);
67 bool operator<(const TextLeafPoint& aPoint) const;
69 bool operator<=(const TextLeafPoint& aPoint) const;
71 /**
72 * A valid TextLeafPoint evaluates to true. An invalid TextLeafPoint
73 * evaluates to false.
75 explicit operator bool() const { return !!mAcc; }
77 bool IsCaret() const {
78 return mOffset == nsIAccessibleText::TEXT_OFFSET_CARET;
81 bool IsCaretAtEndOfLine() const;
83 /**
84 * Get a TextLeafPoint at the actual caret offset.
85 * This should only be called on a TextLeafPoint created with GetCaret.
86 * If aAdjustAtEndOfLine is true, the point will be adjusted if the caret is
87 * at the end of a line so that word and line boundaries can be calculated
88 * correctly.
90 TextLeafPoint ActualizeCaret(bool aAdjustAtEndOfLine = true) const;
92 enum class BoundaryFlags : uint32_t {
93 eDefaultBoundaryFlags = 0,
94 // Return point unchanged if it is at the given boundary type.
95 eIncludeOrigin = 1 << 0,
96 // If current point is in editable, return point within samme editable.
97 eStopInEditable = 1 << 1,
98 // Skip over list items in searches and don't consider them line or
99 // paragraph starts.
100 eIgnoreListItemMarker = 1 << 2,
104 * Find a boundary (word start, line start, etc.) in a specific direction.
105 * If no boundary is found, the start/end of the document is returned
106 * (depending on the direction).
108 TextLeafPoint FindBoundary(
109 AccessibleTextBoundary aBoundaryType, nsDirection aDirection,
110 BoundaryFlags aFlags = BoundaryFlags::eDefaultBoundaryFlags) const;
113 * These two functions find a line start boundary within the same
114 * LocalAccessible as this. That is, they do not cross Accessibles. If no
115 * boundary is found, an invalid TextLeafPoint is returned.
116 * These are used by FindBoundary. Most callers will want FindBoundary
117 * instead.
119 TextLeafPoint FindPrevLineStartSameLocalAcc(bool aIncludeOrigin) const;
120 TextLeafPoint FindNextLineStartSameLocalAcc(bool aIncludeOrigin) const;
123 * These two functions find a word start boundary within the same
124 * Accessible as this. That is, they do not cross Accessibles. If no
125 * boundary is found, an invalid TextLeafPoint is returned.
126 * These are used by FindBoundary. Most callers will want FindBoundary
127 * instead.
129 TextLeafPoint FindPrevWordStartSameAcc(bool aIncludeOrigin) const;
130 TextLeafPoint FindNextWordStartSameAcc(bool aIncludeOrigin) const;
133 * Get the text attributes at this point.
134 * If aIncludeDefaults is true, default attributes on the HyperTextAccessible
135 * will be included.
137 already_AddRefed<AccAttributes> GetTextAttributes(
138 bool aIncludeDefaults = true) const;
141 * Get Get the text attributes at this point in a LocalAccessible.
142 * This is used by GetTextAttributes. Most callers will want GetTextAttributes
143 * instead.
145 already_AddRefed<AccAttributes> GetTextAttributesLocalAcc(
146 bool aIncludeDefaults = true) const;
149 * Get the offsets of all spelling errors in a given LocalAccessible. This
150 * should only be used when pushing the cache. Most callers will want
151 * FindTextAttrsStart instead.
153 static nsTArray<int32_t> GetSpellingErrorOffsets(LocalAccessible* aAcc);
156 * Queue a cache update for a spelling error in a given DOM range.
158 static void UpdateCachedSpellingError(dom::Document* aDocument,
159 const nsRange& aRange);
162 * Find the start of a run of text attributes in a specific direction.
163 * A text attributes run is a span of text where the attributes are the same.
164 * If no boundary is found, the start/end of the container is returned
165 * (depending on the direction).
166 * If aIncludeorigin is true and this is at a boundary, this will be
167 * returned unchanged.
169 TextLeafPoint FindTextAttrsStart(nsDirection aDirection,
170 bool aIncludeOrigin = false) const;
173 * Returns a rect (in dev pixels) describing position and size of
174 * the character at mOffset in mAcc. This rect is screen-relative.
175 * This function only works on remote accessibles, and assumes caching
176 * is enabled.
178 LayoutDeviceIntRect CharBounds();
181 * Returns true if the given point (in screen coords) is contained
182 * in the char bounds of the current TextLeafPoint. Returns false otherwise.
183 * If the current point is an empty container, we use the acc's bounds instead
184 * of char bounds. Because this depends on CharBounds, this function only
185 * works on remote accessibles, and assumes caching is enabled.
187 bool ContainsPoint(int32_t aX, int32_t aY);
189 bool IsLineFeedChar() const { return GetChar() == '\n'; }
191 bool IsSpace() const;
193 bool IsParagraphStart(bool aIgnoreListItemMarker = false) const {
194 return mOffset == 0 &&
195 FindParagraphSameAcc(eDirPrevious, true, aIgnoreListItemMarker);
199 * Translate given TextLeafPoint into a DOM point.
201 MOZ_CAN_RUN_SCRIPT std::pair<nsIContent*, int32_t> ToDOMPoint(
202 bool aIncludeGenerated = true) const;
204 private:
205 bool IsEmptyLastLine() const;
207 bool IsDocEdge(nsDirection aDirection) const;
209 bool IsLeafAfterListItemMarker() const;
211 char16_t GetChar() const;
213 TextLeafPoint FindLineStartSameRemoteAcc(nsDirection aDirection,
214 bool aIncludeOrigin) const;
217 * Helper which just calls the appropriate function based on whether mAcc
218 *is local or remote.
220 TextLeafPoint FindLineStartSameAcc(nsDirection aDirection,
221 bool aIncludeOrigin,
222 bool aIgnoreListItemMarker = false) const;
224 TextLeafPoint FindLineEnd(nsDirection aDirection, BoundaryFlags aFlags) const;
225 TextLeafPoint FindWordEnd(nsDirection aDirection, BoundaryFlags aFlags) const;
227 TextLeafPoint FindParagraphSameAcc(nsDirection aDirection,
228 bool aIncludeOrigin,
229 bool aIgnoreListItemMarker = false) const;
231 bool IsInSpellingError() const;
234 * Find a spelling error boundary in the same Accessible. This function
235 * searches for either start or end points, since either means a change in
236 * text attributes.
238 TextLeafPoint FindSpellingErrorSameAcc(nsDirection aDirection,
239 bool aIncludeOrigin) const;
241 // Return the point immediately succeeding or preceding this leaf depending
242 // on given direction.
243 TextLeafPoint NeighborLeafPoint(nsDirection aDirection, bool aIsEditable,
244 bool aIgnoreListItemMarker) const;
247 * This function assumes mAcc is a LocalAccessible.
248 * It iterates the continuations of mAcc's primary frame until it locates
249 * the continuation containing mOffset (a rendered offset). It then uses
250 * GetScreenRectInAppUnits to compute screen coords for the frame, resizing
251 * such that the resulting rect contains only one character.
253 LayoutDeviceIntRect ComputeBoundsFromFrame() const;
256 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(TextLeafPoint::BoundaryFlags)
259 * Represents a range of accessible text.
260 * This will eventually replace TextRange.
262 class TextLeafRange final {
263 public:
264 TextLeafRange(const TextLeafPoint& aStart, const TextLeafPoint& aEnd)
265 : mStart(aStart), mEnd(aEnd) {}
266 explicit TextLeafRange(const TextLeafPoint& aStart)
267 : mStart(aStart), mEnd(aStart) {}
268 explicit TextLeafRange() {}
271 * A valid TextLeafRange evaluates to true. An invalid TextLeafRange
272 * evaluates to false.
274 explicit operator bool() const { return !!mStart && !!mEnd; }
276 bool operator!=(const TextLeafRange& aOther) const {
277 return mEnd != aOther.mEnd || mStart != aOther.mStart;
280 bool operator==(const TextLeafRange& aOther) const {
281 return mEnd == aOther.mEnd && mStart == aOther.mStart;
284 TextLeafPoint Start() const { return mStart; }
285 void SetStart(const TextLeafPoint& aStart) { mStart = aStart; }
286 TextLeafPoint End() const { return mEnd; }
287 void SetEnd(const TextLeafPoint& aEnd) { mEnd = aEnd; }
289 bool Crop(Accessible* aContainer);
292 * Returns a union rect (in dev pixels) of all character bounds in this range.
293 * This rect is screen-relative and inclusive of mEnd. This function only
294 * works on remote accessibles, and assumes caching is enabled.
296 LayoutDeviceIntRect Bounds() const;
299 * Set range as DOM selection.
300 * aSelectionNum is the selection index to use. If aSelectionNum is
301 * out of bounds for current selection ranges, or is -1, a new selection
302 * range is created.
304 MOZ_CAN_RUN_SCRIPT bool SetSelection(int32_t aSelectionNum) const;
306 MOZ_CAN_RUN_SCRIPT void ScrollIntoView(uint32_t aScrollType) const;
308 private:
309 TextLeafPoint mStart;
310 TextLeafPoint mEnd;
312 public:
314 * A TextLeafRange iterator will iterate through single leaf segments of the
315 * given range.
318 class Iterator {
319 public:
320 Iterator(Iterator&& aOther)
321 : mRange(aOther.mRange),
322 mSegmentStart(aOther.mSegmentStart),
323 mSegmentEnd(aOther.mSegmentEnd) {}
325 static Iterator BeginIterator(const TextLeafRange& aRange);
327 static Iterator EndIterator(const TextLeafRange& aRange);
329 Iterator& operator++();
331 bool operator!=(const Iterator& aOther) const {
332 return mRange != aOther.mRange || mSegmentStart != aOther.mSegmentStart ||
333 mSegmentEnd != aOther.mSegmentEnd;
336 TextLeafRange operator*() {
337 return TextLeafRange(mSegmentStart, mSegmentEnd);
340 private:
341 explicit Iterator(const TextLeafRange& aRange) : mRange(aRange) {}
343 Iterator() = delete;
344 Iterator(const Iterator&) = delete;
345 Iterator& operator=(const Iterator&) = delete;
346 Iterator& operator=(const Iterator&&) = delete;
348 const TextLeafRange& mRange;
349 TextLeafPoint mSegmentStart;
350 TextLeafPoint mSegmentEnd;
353 Iterator begin() const { return Iterator::BeginIterator(*this); }
354 Iterator end() const { return Iterator::EndIterator(*this); }
357 } // namespace a11y
358 } // namespace mozilla
360 #endif