TextRange.h (5720B)
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/. */ 6 7 #ifndef mozilla_a11y_TextRange_h__ 8 #define mozilla_a11y_TextRange_h__ 9 10 #include <utility> 11 12 #include "nsTArray.h" 13 14 class nsRange; 15 16 namespace mozilla { 17 namespace dom { 18 class Selection; 19 } // namespace dom 20 namespace a11y { 21 22 class Accessible; 23 class LocalAccessible; 24 25 /** 26 * A text point (HyperText + offset), represents a boundary of text range. 27 * In new code, This should only be used when you explicitly need to deal with 28 * HyperText containers and offsets, including embedded objects; e.g. for 29 * IAccessible2 and ATK. Otherwise, use TextLeafPoint instead. 30 */ 31 struct TextPoint final { 32 TextPoint(Accessible* aContainer, int32_t aOffset) 33 : mContainer(aContainer), mOffset(aOffset) {} 34 TextPoint(const TextPoint& aPoint) 35 : mContainer(aPoint.mContainer), mOffset(aPoint.mOffset) {} 36 37 Accessible* mContainer; 38 int32_t mOffset; 39 40 bool operator==(const TextPoint& aPoint) const { 41 return mContainer == aPoint.mContainer && mOffset == aPoint.mOffset; 42 } 43 bool operator<(const TextPoint& aPoint) const; 44 45 /** 46 * Return 0 if the two points are equal, -1 if this is before aOther, 1 if 47 * this is after aOther. 48 */ 49 int Compare(const TextPoint& aOther) const { 50 if (*this == aOther) { 51 return 0; 52 } 53 if (*this < aOther) { 54 return -1; 55 } 56 return 1; 57 } 58 }; 59 60 /** 61 * Represents a HyperText range within the text control or document. 62 * In new code, This should only be used when you explicitly need to deal with 63 * HyperText containers and offsets, including embedded objects; e.g. for 64 * IAccessible2 and ATK. Otherwise, use TextLeafRange instead. 65 */ 66 class TextRange final { 67 public: 68 TextRange(Accessible* aRoot, Accessible* aStartContainer, 69 int32_t aStartOffset, Accessible* aEndContainer, 70 int32_t aEndOffset); 71 TextRange() : mStartOffset{0}, mEndOffset{0} {} 72 TextRange(TextRange&& aRange) 73 : mRoot(std::move(aRange.mRoot)), 74 mStartContainer(std::move(aRange.mStartContainer)), 75 mEndContainer(std::move(aRange.mEndContainer)), 76 mStartOffset(aRange.mStartOffset), 77 mEndOffset(aRange.mEndOffset) {} 78 79 TextRange& operator=(TextRange&& aRange) { 80 mRoot = std::move(aRange.mRoot); 81 mStartContainer = std::move(aRange.mStartContainer); 82 mEndContainer = std::move(aRange.mEndContainer); 83 mStartOffset = aRange.mStartOffset; 84 mEndOffset = aRange.mEndOffset; 85 return *this; 86 } 87 88 Accessible* Root() { return mRoot; } 89 Accessible* StartContainer() const { return mStartContainer; } 90 int32_t StartOffset() const { return mStartOffset; } 91 Accessible* EndContainer() const { return mEndContainer; } 92 int32_t EndOffset() const { return mEndOffset; } 93 94 bool operator==(const TextRange& aRange) const { 95 return mStartContainer == aRange.mStartContainer && 96 mStartOffset == aRange.mStartOffset && 97 mEndContainer == aRange.mEndContainer && 98 mEndOffset == aRange.mEndOffset; 99 } 100 101 TextPoint StartPoint() const { 102 return TextPoint(mStartContainer, mStartOffset); 103 } 104 TextPoint EndPoint() const { return TextPoint(mEndContainer, mEndOffset); } 105 106 /** 107 * Return a container containing both start and end points. 108 */ 109 Accessible* Container() const; 110 111 /** 112 * Crops the range if it overlaps the given accessible element boundaries, 113 * returns true if the range was cropped successfully. 114 */ 115 bool Crop(Accessible* aContainer); 116 117 /** 118 * Convert stored hypertext offsets into DOM offsets and assign it to DOM 119 * range. 120 * 121 * Note that if start and/or end accessible offsets are in generated content 122 * such as ::before or 123 * ::after, the result range excludes the generated content. See also 124 * ClosestNotGeneratedDOMPoint() for more information. 125 * 126 * @param aRange [in, out] the range whose bounds to set 127 * @param aReversed [out] whether the start/end offsets were reversed. 128 * @return true if conversion was successful 129 */ 130 bool AssignDOMRange(nsRange* aRange, bool* aReversed = nullptr) const; 131 132 /** 133 * Return true if this TextRange object represents an actual range of text. 134 */ 135 bool IsValid() const { return mRoot; } 136 137 void SetStartPoint(Accessible* aContainer, int32_t aOffset) { 138 mStartContainer = aContainer; 139 mStartOffset = aOffset; 140 } 141 void SetEndPoint(Accessible* aContainer, int32_t aOffset) { 142 mStartContainer = aContainer; 143 mStartOffset = aOffset; 144 } 145 146 static void TextRangesFromSelection(dom::Selection* aSelection, 147 nsTArray<TextRange>* aRanges); 148 149 private: 150 TextRange(const TextRange& aRange) = delete; 151 TextRange& operator=(const TextRange& aRange) = delete; 152 153 friend class HyperTextAccessible; 154 friend class xpcAccessibleTextRange; 155 156 void Set(Accessible* aRoot, Accessible* aStartContainer, int32_t aStartOffset, 157 Accessible* aEndContainer, int32_t aEndOffset); 158 159 /** 160 * A helper method returning a common parent for two given accessible 161 * elements. 162 */ 163 Accessible* CommonParent(Accessible* aAcc1, Accessible* aAcc2, 164 nsTArray<Accessible*>* aParents1, uint32_t* aPos1, 165 nsTArray<Accessible*>* aParents2, 166 uint32_t* aPos2) const; 167 168 Accessible* mRoot; 169 Accessible* mStartContainer; 170 Accessible* mEndContainer; 171 int32_t mStartOffset; 172 int32_t mEndOffset; 173 }; 174 175 } // namespace a11y 176 } // namespace mozilla 177 178 #endif