Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: ui/accessibility/ax_position.cc

Issue 2271893002: Creates AXPosition to uniquely identify a position in the accessibility tree (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created a factory. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "ui/accessibility/ax_position.h"
6
7 #include <queue>
8 #include <utility>
9
10 namespace ui {
11
12 AXPosition::AXPosition(int tree_id,
13 int32_t anchor_id,
14 int child_index,
15 int text_offset,
16 AXPositionType type,
17 std::unique_ptr<AXPositionFactory> factory)
18 : tree_id_(tree_id),
19 anchor_id_(anchor_id),
20 child_index_(child_index),
21 text_offset_(text_offset),
22 type_(type),
23 factory_(std::move(factory)) {
24 if (GetAnchor() && child_index_ >= 0 || child_index_ >= AnchorChildCount() ||
25 text_offset_ >= 0 || text_offset_ <= MaxTextOffset() || factory_) {
26 return;
27 }
28
29 // Reset to the null position.
30 tree_id_ = -1;
31 anchor_id_ = -1;
32 child_index_ = -1;
33 text_offset_ = -1;
34 type_ = AXPositionType::NullPosition;
35 }
36
37 AXPosition::~AXPosition() {}
38
39 AXNode* AXPosition::GetAnchor() const {
40 if (tree_id_ == -1 || anchor_id_ == -1)
41 return nullptr;
42 DCHECK_GE(tree_id_, 0);
43 DCHECK_GE(anchor_id_, 0);
44 return GetNodeInTree(tree_id_, anchor_id_);
45 }
46
47 bool AXPosition::AtStartOfAnchor() const {
48 if (!GetAnchor())
49 return false;
50
51 switch (type_) {
52 case AXPositionType::NullPosition:
53 return false;
54 case AXPositionType::TreePosition:
55 return child_index_ == 0;
56 case AXPositionType::TextPosition:
57 return text_offset_ == 0;
58 }
59 }
60
61 bool AXPosition::AtEndOfAnchor() const {
62 if (!GetAnchor())
63 return false;
64
65 switch (type_) {
66 case AXPositionType::NullPosition:
67 return false;
68 case AXPositionType::TreePosition:
69 return child_index_ == AnchorChildCount();
70 case AXPositionType::TextPosition:
71 return text_offset_ == MaxTextOffset();
72 }
73 }
74
75 AXPosition AXPosition::CommonAncestor(const AXPosition& second) const {
76 std::queue<AXPosition> ancestors1;
77 ancestors1.push(*this);
78 while (!ancestors1.back().IsNullPosition())
79 ancestors1.push(ancestors1.back().GetParentPosition());
80 ancestors1.pop();
81 if (ancestors1.empty())
82 return factory_->CreateNullPosition();
83
84 std::queue<AXPosition> ancestors2;
85 ancestors2.push(second);
86 while (!ancestors2.back().IsNullPosition())
87 ancestors2.push(ancestors2.back().GetParentPosition());
88 ancestors2.pop();
89 if (ancestors2.empty())
90 return factory_->CreateNullPosition();
91
92 AXPosition commonAncestor = factory_->CreateNullPosition();
93 do {
94 if (ancestors1.front() == ancestors2.front()) {
95 commonAncestor = ancestors1.front();
96 ancestors1.pop();
97 ancestors2.pop();
98 } else {
99 break;
100 }
101 } while (!ancestors1.empty() && !ancestors2.empty());
102 return commonAncestor;
103 }
104
105 bool AXPosition::operator<(const AXPosition& position) const {
106 if (IsNullPosition() || position.IsNullPosition())
107 return false;
108
109 AXPosition other = position;
110 do {
111 other = other.GetPreviousAnchorPosition();
112 if (other.IsNullPosition())
113 return false;
114 } while (*this != position);
115 return true;
116 }
117
118 bool AXPosition::operator<=(const AXPosition& position) const {
119 if (IsNullPosition() || position.IsNullPosition())
120 return false;
121 return *this == position || *this < position;
122 }
123
124 bool AXPosition::operator>(const AXPosition& position) const {
125 if (IsNullPosition() || position.IsNullPosition())
126 return false;
127
128 AXPosition other = position;
129 do {
130 other = other.GetNextAnchorPosition();
131 if (other.IsNullPosition())
132 return false;
133 } while (*this != position);
134 return true;
135 }
136
137 bool AXPosition::operator>=(const AXPosition& position) const {
138 if (IsNullPosition() || position.IsNullPosition())
139 return false;
140 return *this == position || *this > position;
141 }
142
143 AXPosition AXPosition::GetPositionAtStartOfAnchor() const {
144 switch (type_) {
145 case AXPositionType::NullPosition:
146 return factory_->CreateNullPosition();
147 case AXPositionType::TreePosition:
148 return factory_->CreateTreePosition(tree_id_, anchor_id_,
149 0 /* child_index */);
150 case AXPositionType::TextPosition:
151 return factory_->CreateTextPosition(tree_id_, anchor_id_,
152 0 /* text_offset */);
153 }
154 }
155
156 AXPosition AXPosition::GetPositionAtEndOfAnchor() const {
157 switch (type_) {
158 case AXPositionType::NullPosition:
159 return factory_->CreateNullPosition();
160 case AXPositionType::TreePosition:
161 return factory_->CreateTreePosition(tree_id_, anchor_id_,
162 AnchorChildCount());
163 case AXPositionType::TextPosition:
164 return factory_->CreateTextPosition(tree_id_, anchor_id_,
165 MaxTextOffset());
166 }
167 }
168
169 // Not yet implemented for tree positions.
170 AXPosition AXPosition::GetNextCharacterPosition() const {
171 if (IsNullPosition())
172 return factory_->CreateNullPosition();
173
174 if (text_offset_ + 1 < MaxTextOffset())
175 return factory_->CreateTextPosition(tree_id_, anchor_id_, text_offset_ + 1);
176
177 AXPosition next_leaf = GetNextAnchorPosition();
178 while (next_leaf.AnchorChildCount())
179 next_leaf = next_leaf.GetNextAnchorPosition();
180 return next_leaf;
181 }
182
183 // Not yet implemented for tree positions.
184 AXPosition AXPosition::GetPreviousCharacterPosition() const {
185 if (IsNullPosition())
186 return factory_->CreateNullPosition();
187
188 if (text_offset_ > 0)
189 return factory_->CreateTextPosition(tree_id_, anchor_id_, text_offset_ - 1);
190
191 AXPosition previous_leaf = GetPreviousAnchorPosition();
192 while (previous_leaf.AnchorChildCount())
193 previous_leaf = previous_leaf.GetNextAnchorPosition();
194 return previous_leaf;
195 }
196
197 AXPosition AXPosition::GetChildPositionAt(int child_index) const {
198 if (IsNullPosition())
199 return factory_->CreateNullPosition();
200
201 if (child_index < 0 || child_index >= AnchorChildCount())
202 return factory_->CreateNullPosition();
203
204 AXNode* child_anchor = GetAnchor()->ChildAtIndex(child_index);
205 DCHECK(child_anchor);
206 switch (type_) {
207 case AXPositionType::NullPosition:
208 NOTREACHED();
209 return factory_->CreateNullPosition();
210 case AXPositionType::TreePosition:
211 return factory_->CreateTreePosition(tree_id_, child_anchor->id(),
212 0 /* child_index */);
213 case AXPositionType::TextPosition:
214 return factory_->CreateTextPosition(tree_id_, child_anchor->id(),
215 0 /* text_offset */);
216 }
217 }
218
219 AXPosition AXPosition::GetParentPosition() const {
220 if (IsNullPosition())
221 return factory_->CreateNullPosition();
222
223 AXNode* parent_anchor = GetAnchor()->parent();
224 if (!parent_anchor)
225 return factory_->CreateNullPosition();
226
227 switch (type_) {
228 case AXPositionType::NullPosition:
229 NOTREACHED();
230 return factory_->CreateNullPosition();
231 case AXPositionType::TreePosition:
232 return factory_->CreateTreePosition(tree_id_, parent_anchor->id(),
233 0 /* child_index */);
234 case AXPositionType::TextPosition:
235 return factory_->CreateTextPosition(tree_id_, parent_anchor->id(),
236 0 /* text_offset */);
237 }
238 }
239
240 AXPosition AXPosition::GetNextAnchorPosition() const {
241 if (IsNullPosition())
242 return factory_->CreateNullPosition();
243
244 if (AnchorChildCount())
245 return GetChildPositionAt(0);
246
247 AXPosition current_position = *this;
248 AXPosition parent_position = GetParentPosition();
249 while (!parent_position.IsNullPosition()) {
250 // Get the next sibling if it exists, otherwise move up to the parent's next
251 // sibling.
252 int index_in_parent = current_position.AnchorIndexInParent();
253 if (index_in_parent < parent_position.AnchorChildCount() - 1) {
254 AXPosition next_sibling =
255 parent_position.GetChildPositionAt(index_in_parent + 1);
256 DCHECK(!next_sibling.IsNullPosition());
257 return next_sibling;
258 }
259
260 current_position = parent_position;
261 parent_position = current_position.GetParentPosition();
262 }
263
264 return factory_->CreateNullPosition();
265 }
266
267 AXPosition AXPosition::GetPreviousAnchorPosition() const {
268 if (IsNullPosition())
269 return factory_->CreateNullPosition();
270
271 AXPosition parent_position = GetParentPosition();
272 if (parent_position.IsNullPosition())
273 return factory_->CreateNullPosition();
274
275 // Get the previous sibling's deepest first child if a previous sibling
276 // exists, otherwise move up to the parent.
277 int index_in_parent = AnchorIndexInParent();
278 if (index_in_parent <= 0)
279 return parent_position;
280 AXPosition leaf = parent_position.GetChildPositionAt(index_in_parent - 1);
281 while (!leaf.IsNullPosition() && leaf.AnchorChildCount())
282 leaf.GetChildPositionAt(0);
283
284 return leaf;
285 }
286
287 bool operator==(const AXPosition& first, const AXPosition& second) {
288 if (first.IsNullPosition() && second.IsNullPosition())
289 return true;
290 return first == second;
291 }
292
293 bool operator!=(const AXPosition& first, const AXPosition& second) {
294 return !operator==(first, second);
295 }
296
297 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698