|
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 #include "XULTreeAccessible.h" |
|
8 |
|
9 #include "Accessible-inl.h" |
|
10 #include "DocAccessible-inl.h" |
|
11 #include "nsAccCache.h" |
|
12 #include "nsAccUtils.h" |
|
13 #include "nsCoreUtils.h" |
|
14 #include "nsEventShell.h" |
|
15 #include "DocAccessible.h" |
|
16 #include "Relation.h" |
|
17 #include "Role.h" |
|
18 #include "States.h" |
|
19 |
|
20 #include "nsComponentManagerUtils.h" |
|
21 #include "nsIAccessibleRelation.h" |
|
22 #include "nsIAutoCompleteInput.h" |
|
23 #include "nsIAutoCompletePopup.h" |
|
24 #include "nsIBoxObject.h" |
|
25 #include "nsIDOMXULElement.h" |
|
26 #include "nsIDOMXULMenuListElement.h" |
|
27 #include "nsIDOMXULMultSelectCntrlEl.h" |
|
28 #include "nsIDOMXULTreeElement.h" |
|
29 #include "nsITreeSelection.h" |
|
30 #include "nsIMutableArray.h" |
|
31 #include "nsTreeBodyFrame.h" |
|
32 #include "nsTreeColumns.h" |
|
33 #include "nsTreeUtils.h" |
|
34 |
|
35 using namespace mozilla::a11y; |
|
36 |
|
37 //////////////////////////////////////////////////////////////////////////////// |
|
38 // XULTreeAccessible |
|
39 //////////////////////////////////////////////////////////////////////////////// |
|
40 |
|
41 XULTreeAccessible:: |
|
42 XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc, |
|
43 nsTreeBodyFrame* aTreeFrame) : |
|
44 AccessibleWrap(aContent, aDoc), |
|
45 mAccessibleCache(kDefaultTreeCacheSize) |
|
46 { |
|
47 mType = eXULTreeType; |
|
48 mGenericTypes |= eSelect; |
|
49 |
|
50 nsCOMPtr<nsITreeView> view = aTreeFrame->GetExistingView(); |
|
51 mTreeView = view; |
|
52 |
|
53 mTree = nsCoreUtils::GetTreeBoxObject(aContent); |
|
54 NS_ASSERTION(mTree, "Can't get mTree!\n"); |
|
55 |
|
56 nsIContent* parentContent = mContent->GetParent(); |
|
57 if (parentContent) { |
|
58 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = |
|
59 do_QueryInterface(parentContent); |
|
60 if (autoCompletePopupElm) |
|
61 mGenericTypes |= eAutoCompletePopup; |
|
62 } |
|
63 } |
|
64 |
|
65 //////////////////////////////////////////////////////////////////////////////// |
|
66 // XULTreeAccessible: nsISupports and cycle collection implementation |
|
67 |
|
68 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeAccessible, Accessible, |
|
69 mTree, mAccessibleCache) |
|
70 |
|
71 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeAccessible) |
|
72 NS_INTERFACE_MAP_END_INHERITING(Accessible) |
|
73 |
|
74 NS_IMPL_ADDREF_INHERITED(XULTreeAccessible, Accessible) |
|
75 NS_IMPL_RELEASE_INHERITED(XULTreeAccessible, Accessible) |
|
76 |
|
77 //////////////////////////////////////////////////////////////////////////////// |
|
78 // XULTreeAccessible: Accessible implementation |
|
79 |
|
80 uint64_t |
|
81 XULTreeAccessible::NativeState() |
|
82 { |
|
83 // Get focus status from base class. |
|
84 uint64_t state = Accessible::NativeState(); |
|
85 |
|
86 // readonly state |
|
87 state |= states::READONLY; |
|
88 |
|
89 // multiselectable state. |
|
90 if (!mTreeView) |
|
91 return state; |
|
92 |
|
93 nsCOMPtr<nsITreeSelection> selection; |
|
94 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
95 NS_ENSURE_TRUE(selection, state); |
|
96 |
|
97 bool isSingle = false; |
|
98 nsresult rv = selection->GetSingle(&isSingle); |
|
99 NS_ENSURE_SUCCESS(rv, state); |
|
100 |
|
101 if (!isSingle) |
|
102 state |= states::MULTISELECTABLE; |
|
103 |
|
104 return state; |
|
105 } |
|
106 |
|
107 void |
|
108 XULTreeAccessible::Value(nsString& aValue) |
|
109 { |
|
110 aValue.Truncate(); |
|
111 if (!mTreeView) |
|
112 return; |
|
113 |
|
114 // Return the value is the first selected child. |
|
115 nsCOMPtr<nsITreeSelection> selection; |
|
116 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
117 if (!selection) |
|
118 return; |
|
119 |
|
120 int32_t currentIndex; |
|
121 nsCOMPtr<nsIDOMElement> selectItem; |
|
122 selection->GetCurrentIndex(¤tIndex); |
|
123 if (currentIndex >= 0) { |
|
124 nsCOMPtr<nsITreeColumn> keyCol; |
|
125 |
|
126 nsCOMPtr<nsITreeColumns> cols; |
|
127 mTree->GetColumns(getter_AddRefs(cols)); |
|
128 if (cols) |
|
129 cols->GetKeyColumn(getter_AddRefs(keyCol)); |
|
130 |
|
131 mTreeView->GetCellText(currentIndex, keyCol, aValue); |
|
132 } |
|
133 |
|
134 } |
|
135 |
|
136 //////////////////////////////////////////////////////////////////////////////// |
|
137 // XULTreeAccessible: Accessible implementation |
|
138 |
|
139 void |
|
140 XULTreeAccessible::Shutdown() |
|
141 { |
|
142 // XXX: we don't remove accessible from document cache if shutdown wasn't |
|
143 // initiated by document destroying. Note, we can't remove accessible from |
|
144 // document cache here while document is going to be shutdown. Note, this is |
|
145 // not unique place where we have similar problem. |
|
146 ClearCache(mAccessibleCache); |
|
147 |
|
148 mTree = nullptr; |
|
149 mTreeView = nullptr; |
|
150 |
|
151 AccessibleWrap::Shutdown(); |
|
152 } |
|
153 |
|
154 role |
|
155 XULTreeAccessible::NativeRole() |
|
156 { |
|
157 // No primary column means we're in a list. In fact, history and mail turn off |
|
158 // the primary flag when switching to a flat view. |
|
159 |
|
160 nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren); |
|
161 NS_ASSERTION(child, "tree without treechildren!"); |
|
162 nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame()); |
|
163 NS_ASSERTION(treeFrame, "xul tree accessible for tree without a frame!"); |
|
164 if (!treeFrame) |
|
165 return roles::LIST; |
|
166 |
|
167 nsRefPtr<nsTreeColumns> cols = treeFrame->Columns(); |
|
168 nsCOMPtr<nsITreeColumn> primaryCol; |
|
169 cols->GetPrimaryColumn(getter_AddRefs(primaryCol)); |
|
170 |
|
171 return primaryCol ? roles::OUTLINE : roles::LIST; |
|
172 } |
|
173 |
|
174 //////////////////////////////////////////////////////////////////////////////// |
|
175 // XULTreeAccessible: Accessible implementation (DON'T put methods here) |
|
176 |
|
177 Accessible* |
|
178 XULTreeAccessible::ChildAtPoint(int32_t aX, int32_t aY, |
|
179 EWhichChildAtPoint aWhichChild) |
|
180 { |
|
181 nsIFrame *frame = GetFrame(); |
|
182 if (!frame) |
|
183 return nullptr; |
|
184 |
|
185 nsPresContext *presContext = frame->PresContext(); |
|
186 nsIPresShell* presShell = presContext->PresShell(); |
|
187 |
|
188 nsIFrame *rootFrame = presShell->GetRootFrame(); |
|
189 NS_ENSURE_TRUE(rootFrame, nullptr); |
|
190 |
|
191 nsIntRect rootRect = rootFrame->GetScreenRect(); |
|
192 |
|
193 int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x; |
|
194 int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y; |
|
195 |
|
196 int32_t row = -1; |
|
197 nsCOMPtr<nsITreeColumn> column; |
|
198 nsAutoCString childEltUnused; |
|
199 mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column), |
|
200 childEltUnused); |
|
201 |
|
202 // If we failed to find tree cell for the given point then it might be |
|
203 // tree columns. |
|
204 if (row == -1 || !column) |
|
205 return AccessibleWrap::ChildAtPoint(aX, aY, aWhichChild); |
|
206 |
|
207 Accessible* child = GetTreeItemAccessible(row); |
|
208 if (aWhichChild == eDeepestChild && child) { |
|
209 // Look for accessible cell for the found item accessible. |
|
210 nsRefPtr<XULTreeItemAccessibleBase> treeitem = do_QueryObject(child); |
|
211 |
|
212 Accessible* cell = treeitem->GetCellAccessible(column); |
|
213 if (cell) |
|
214 child = cell; |
|
215 } |
|
216 |
|
217 return child; |
|
218 } |
|
219 |
|
220 //////////////////////////////////////////////////////////////////////////////// |
|
221 // XULTreeAccessible: SelectAccessible |
|
222 |
|
223 Accessible* |
|
224 XULTreeAccessible::CurrentItem() |
|
225 { |
|
226 if (!mTreeView) |
|
227 return nullptr; |
|
228 |
|
229 nsCOMPtr<nsITreeSelection> selection; |
|
230 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
231 if (selection) { |
|
232 int32_t currentIndex = -1; |
|
233 selection->GetCurrentIndex(¤tIndex); |
|
234 if (currentIndex >= 0) |
|
235 return GetTreeItemAccessible(currentIndex); |
|
236 } |
|
237 |
|
238 return nullptr; |
|
239 } |
|
240 |
|
241 void |
|
242 XULTreeAccessible::SetCurrentItem(Accessible* aItem) |
|
243 { |
|
244 NS_ERROR("XULTreeAccessible::SetCurrentItem not implemented"); |
|
245 } |
|
246 |
|
247 already_AddRefed<nsIArray> |
|
248 XULTreeAccessible::SelectedItems() |
|
249 { |
|
250 if (!mTreeView) |
|
251 return nullptr; |
|
252 |
|
253 nsCOMPtr<nsITreeSelection> selection; |
|
254 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
255 if (!selection) |
|
256 return nullptr; |
|
257 |
|
258 nsCOMPtr<nsIMutableArray> selectedItems = |
|
259 do_CreateInstance(NS_ARRAY_CONTRACTID); |
|
260 if (!selectedItems) |
|
261 return nullptr; |
|
262 |
|
263 int32_t rangeCount = 0; |
|
264 selection->GetRangeCount(&rangeCount); |
|
265 for (int32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) { |
|
266 int32_t firstIdx = 0, lastIdx = -1; |
|
267 selection->GetRangeAt(rangeIdx, &firstIdx, &lastIdx); |
|
268 for (int32_t rowIdx = firstIdx; rowIdx <= lastIdx; rowIdx++) { |
|
269 nsIAccessible* item = GetTreeItemAccessible(rowIdx); |
|
270 if (item) |
|
271 selectedItems->AppendElement(item, false); |
|
272 } |
|
273 } |
|
274 |
|
275 return selectedItems.forget(); |
|
276 } |
|
277 |
|
278 uint32_t |
|
279 XULTreeAccessible::SelectedItemCount() |
|
280 { |
|
281 if (!mTreeView) |
|
282 return 0; |
|
283 |
|
284 nsCOMPtr<nsITreeSelection> selection; |
|
285 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
286 if (selection) { |
|
287 int32_t count = 0; |
|
288 selection->GetCount(&count); |
|
289 return count; |
|
290 } |
|
291 |
|
292 return 0; |
|
293 } |
|
294 |
|
295 bool |
|
296 XULTreeAccessible::AddItemToSelection(uint32_t aIndex) |
|
297 { |
|
298 if (!mTreeView) |
|
299 return false; |
|
300 |
|
301 nsCOMPtr<nsITreeSelection> selection; |
|
302 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
303 if (selection) { |
|
304 bool isSelected = false; |
|
305 selection->IsSelected(aIndex, &isSelected); |
|
306 if (!isSelected) |
|
307 selection->ToggleSelect(aIndex); |
|
308 |
|
309 return true; |
|
310 } |
|
311 return false; |
|
312 } |
|
313 |
|
314 bool |
|
315 XULTreeAccessible::RemoveItemFromSelection(uint32_t aIndex) |
|
316 { |
|
317 if (!mTreeView) |
|
318 return false; |
|
319 |
|
320 nsCOMPtr<nsITreeSelection> selection; |
|
321 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
322 if (selection) { |
|
323 bool isSelected = false; |
|
324 selection->IsSelected(aIndex, &isSelected); |
|
325 if (isSelected) |
|
326 selection->ToggleSelect(aIndex); |
|
327 |
|
328 return true; |
|
329 } |
|
330 return false; |
|
331 } |
|
332 |
|
333 bool |
|
334 XULTreeAccessible::IsItemSelected(uint32_t aIndex) |
|
335 { |
|
336 if (!mTreeView) |
|
337 return false; |
|
338 |
|
339 nsCOMPtr<nsITreeSelection> selection; |
|
340 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
341 if (selection) { |
|
342 bool isSelected = false; |
|
343 selection->IsSelected(aIndex, &isSelected); |
|
344 return isSelected; |
|
345 } |
|
346 return false; |
|
347 } |
|
348 |
|
349 bool |
|
350 XULTreeAccessible::UnselectAll() |
|
351 { |
|
352 if (!mTreeView) |
|
353 return false; |
|
354 |
|
355 nsCOMPtr<nsITreeSelection> selection; |
|
356 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
357 if (!selection) |
|
358 return false; |
|
359 |
|
360 selection->ClearSelection(); |
|
361 return true; |
|
362 } |
|
363 |
|
364 Accessible* |
|
365 XULTreeAccessible::GetSelectedItem(uint32_t aIndex) |
|
366 { |
|
367 if (!mTreeView) |
|
368 return nullptr; |
|
369 |
|
370 nsCOMPtr<nsITreeSelection> selection; |
|
371 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
372 if (!selection) |
|
373 return nullptr; |
|
374 |
|
375 uint32_t selCount = 0; |
|
376 int32_t rangeCount = 0; |
|
377 selection->GetRangeCount(&rangeCount); |
|
378 for (int32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) { |
|
379 int32_t firstIdx = 0, lastIdx = -1; |
|
380 selection->GetRangeAt(rangeIdx, &firstIdx, &lastIdx); |
|
381 for (int32_t rowIdx = firstIdx; rowIdx <= lastIdx; rowIdx++) { |
|
382 if (selCount == aIndex) |
|
383 return GetTreeItemAccessible(rowIdx); |
|
384 |
|
385 selCount++; |
|
386 } |
|
387 } |
|
388 |
|
389 return nullptr; |
|
390 } |
|
391 |
|
392 bool |
|
393 XULTreeAccessible::SelectAll() |
|
394 { |
|
395 // see if we are multiple select if so set ourselves as such |
|
396 if (!mTreeView) |
|
397 return false; |
|
398 |
|
399 nsCOMPtr<nsITreeSelection> selection; |
|
400 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
401 if (selection) { |
|
402 bool single = false; |
|
403 selection->GetSingle(&single); |
|
404 if (!single) { |
|
405 selection->SelectAll(); |
|
406 return true; |
|
407 } |
|
408 } |
|
409 |
|
410 return false; |
|
411 } |
|
412 |
|
413 //////////////////////////////////////////////////////////////////////////////// |
|
414 // XULTreeAccessible: Accessible implementation |
|
415 |
|
416 Accessible* |
|
417 XULTreeAccessible::GetChildAt(uint32_t aIndex) const |
|
418 { |
|
419 uint32_t childCount = Accessible::ChildCount(); |
|
420 if (aIndex < childCount) |
|
421 return Accessible::GetChildAt(aIndex); |
|
422 |
|
423 return GetTreeItemAccessible(aIndex - childCount); |
|
424 } |
|
425 |
|
426 uint32_t |
|
427 XULTreeAccessible::ChildCount() const |
|
428 { |
|
429 // Tree's children count is row count + treecols count. |
|
430 uint32_t childCount = Accessible::ChildCount(); |
|
431 if (!mTreeView) |
|
432 return childCount; |
|
433 |
|
434 int32_t rowCount = 0; |
|
435 mTreeView->GetRowCount(&rowCount); |
|
436 childCount += rowCount; |
|
437 |
|
438 return childCount; |
|
439 } |
|
440 |
|
441 Relation |
|
442 XULTreeAccessible::RelationByType(RelationType aType) |
|
443 { |
|
444 if (aType == RelationType::NODE_PARENT_OF) { |
|
445 if (mTreeView) |
|
446 return Relation(new XULTreeItemIterator(this, mTreeView, -1)); |
|
447 |
|
448 return Relation(); |
|
449 } |
|
450 |
|
451 return Accessible::RelationByType(aType); |
|
452 } |
|
453 |
|
454 //////////////////////////////////////////////////////////////////////////////// |
|
455 // XULTreeAccessible: Widgets |
|
456 |
|
457 bool |
|
458 XULTreeAccessible::IsWidget() const |
|
459 { |
|
460 return true; |
|
461 } |
|
462 |
|
463 bool |
|
464 XULTreeAccessible::IsActiveWidget() const |
|
465 { |
|
466 if (IsAutoCompletePopup()) { |
|
467 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = |
|
468 do_QueryInterface(mContent->GetParent()); |
|
469 |
|
470 if (autoCompletePopupElm) { |
|
471 bool isOpen = false; |
|
472 autoCompletePopupElm->GetPopupOpen(&isOpen); |
|
473 return isOpen; |
|
474 } |
|
475 } |
|
476 return FocusMgr()->HasDOMFocus(mContent); |
|
477 } |
|
478 |
|
479 bool |
|
480 XULTreeAccessible::AreItemsOperable() const |
|
481 { |
|
482 if (IsAutoCompletePopup()) { |
|
483 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm = |
|
484 do_QueryInterface(mContent->GetParent()); |
|
485 |
|
486 if (autoCompletePopupElm) { |
|
487 bool isOpen = false; |
|
488 autoCompletePopupElm->GetPopupOpen(&isOpen); |
|
489 return isOpen; |
|
490 } |
|
491 } |
|
492 return true; |
|
493 } |
|
494 |
|
495 Accessible* |
|
496 XULTreeAccessible::ContainerWidget() const |
|
497 { |
|
498 if (IsAutoCompletePopup()) { |
|
499 // This works for XUL autocompletes. It doesn't work for HTML forms |
|
500 // autocomplete because of potential crossprocess calls (when autocomplete |
|
501 // lives in content process while popup lives in chrome process). If that's |
|
502 // a problem then rethink Widgets interface. |
|
503 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm = |
|
504 do_QueryInterface(mContent->GetParent()); |
|
505 if (menuListElm) { |
|
506 nsCOMPtr<nsIDOMNode> inputElm; |
|
507 menuListElm->GetInputField(getter_AddRefs(inputElm)); |
|
508 if (inputElm) { |
|
509 nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm); |
|
510 if (inputNode) { |
|
511 Accessible* input = |
|
512 mDoc->GetAccessible(inputNode); |
|
513 return input ? input->ContainerWidget() : nullptr; |
|
514 } |
|
515 } |
|
516 } |
|
517 } |
|
518 return nullptr; |
|
519 } |
|
520 |
|
521 //////////////////////////////////////////////////////////////////////////////// |
|
522 // XULTreeAccessible: public implementation |
|
523 |
|
524 Accessible* |
|
525 XULTreeAccessible::GetTreeItemAccessible(int32_t aRow) const |
|
526 { |
|
527 if (aRow < 0 || IsDefunct() || !mTreeView) |
|
528 return nullptr; |
|
529 |
|
530 int32_t rowCount = 0; |
|
531 nsresult rv = mTreeView->GetRowCount(&rowCount); |
|
532 if (NS_FAILED(rv) || aRow >= rowCount) |
|
533 return nullptr; |
|
534 |
|
535 void *key = reinterpret_cast<void*>(aRow); |
|
536 Accessible* cachedTreeItem = mAccessibleCache.GetWeak(key); |
|
537 if (cachedTreeItem) |
|
538 return cachedTreeItem; |
|
539 |
|
540 nsRefPtr<Accessible> treeItem = CreateTreeItemAccessible(aRow); |
|
541 if (treeItem) { |
|
542 mAccessibleCache.Put(key, treeItem); |
|
543 Document()->BindToDocument(treeItem, nullptr); |
|
544 return treeItem; |
|
545 } |
|
546 |
|
547 return nullptr; |
|
548 } |
|
549 |
|
550 void |
|
551 XULTreeAccessible::InvalidateCache(int32_t aRow, int32_t aCount) |
|
552 { |
|
553 if (IsDefunct()) |
|
554 return; |
|
555 |
|
556 if (!mTreeView) { |
|
557 ClearCache(mAccessibleCache); |
|
558 return; |
|
559 } |
|
560 |
|
561 // Do not invalidate the cache if rows have been inserted. |
|
562 if (aCount > 0) |
|
563 return; |
|
564 |
|
565 DocAccessible* document = Document(); |
|
566 |
|
567 // Fire destroy event for removed tree items and delete them from caches. |
|
568 for (int32_t rowIdx = aRow; rowIdx < aRow - aCount; rowIdx++) { |
|
569 |
|
570 void* key = reinterpret_cast<void*>(rowIdx); |
|
571 Accessible* treeItem = mAccessibleCache.GetWeak(key); |
|
572 |
|
573 if (treeItem) { |
|
574 nsRefPtr<AccEvent> event = |
|
575 new AccEvent(nsIAccessibleEvent::EVENT_HIDE, treeItem); |
|
576 nsEventShell::FireEvent(event); |
|
577 |
|
578 // Unbind from document, shutdown and remove from tree cache. |
|
579 document->UnbindFromDocument(treeItem); |
|
580 mAccessibleCache.Remove(key); |
|
581 } |
|
582 } |
|
583 |
|
584 // We dealt with removed tree items already however we may keep tree items |
|
585 // having row indexes greater than row count. We should remove these dead tree |
|
586 // items silently from caches. |
|
587 int32_t newRowCount = 0; |
|
588 nsresult rv = mTreeView->GetRowCount(&newRowCount); |
|
589 if (NS_FAILED(rv)) |
|
590 return; |
|
591 |
|
592 int32_t oldRowCount = newRowCount - aCount; |
|
593 |
|
594 for (int32_t rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) { |
|
595 |
|
596 void *key = reinterpret_cast<void*>(rowIdx); |
|
597 Accessible* treeItem = mAccessibleCache.GetWeak(key); |
|
598 |
|
599 if (treeItem) { |
|
600 // Unbind from document, shutdown and remove from tree cache. |
|
601 document->UnbindFromDocument(treeItem); |
|
602 mAccessibleCache.Remove(key); |
|
603 } |
|
604 } |
|
605 } |
|
606 |
|
607 void |
|
608 XULTreeAccessible::TreeViewInvalidated(int32_t aStartRow, int32_t aEndRow, |
|
609 int32_t aStartCol, int32_t aEndCol) |
|
610 { |
|
611 if (IsDefunct()) |
|
612 return; |
|
613 |
|
614 if (!mTreeView) { |
|
615 ClearCache(mAccessibleCache); |
|
616 return; |
|
617 } |
|
618 |
|
619 int32_t endRow = aEndRow; |
|
620 |
|
621 nsresult rv; |
|
622 if (endRow == -1) { |
|
623 int32_t rowCount = 0; |
|
624 rv = mTreeView->GetRowCount(&rowCount); |
|
625 if (NS_FAILED(rv)) |
|
626 return; |
|
627 |
|
628 endRow = rowCount - 1; |
|
629 } |
|
630 |
|
631 nsCOMPtr<nsITreeColumns> treeColumns; |
|
632 mTree->GetColumns(getter_AddRefs(treeColumns)); |
|
633 if (!treeColumns) |
|
634 return; |
|
635 |
|
636 int32_t endCol = aEndCol; |
|
637 |
|
638 if (endCol == -1) { |
|
639 int32_t colCount = 0; |
|
640 rv = treeColumns->GetCount(&colCount); |
|
641 if (NS_FAILED(rv)) |
|
642 return; |
|
643 |
|
644 endCol = colCount - 1; |
|
645 } |
|
646 |
|
647 for (int32_t rowIdx = aStartRow; rowIdx <= endRow; ++rowIdx) { |
|
648 |
|
649 void *key = reinterpret_cast<void*>(rowIdx); |
|
650 Accessible* accessible = mAccessibleCache.GetWeak(key); |
|
651 |
|
652 if (accessible) { |
|
653 nsRefPtr<XULTreeItemAccessibleBase> treeitemAcc = do_QueryObject(accessible); |
|
654 NS_ASSERTION(treeitemAcc, "Wrong accessible at the given key!"); |
|
655 |
|
656 treeitemAcc->RowInvalidated(aStartCol, endCol); |
|
657 } |
|
658 } |
|
659 } |
|
660 |
|
661 void |
|
662 XULTreeAccessible::TreeViewChanged(nsITreeView* aView) |
|
663 { |
|
664 if (IsDefunct()) |
|
665 return; |
|
666 |
|
667 // Fire reorder event on tree accessible on accessible tree (do not fire |
|
668 // show/hide events on tree items because it can be expensive to fire them for |
|
669 // each tree item. |
|
670 nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this); |
|
671 Document()->FireDelayedEvent(reorderEvent); |
|
672 |
|
673 // Clear cache. |
|
674 ClearCache(mAccessibleCache); |
|
675 mTreeView = aView; |
|
676 } |
|
677 |
|
678 //////////////////////////////////////////////////////////////////////////////// |
|
679 // XULTreeAccessible: protected implementation |
|
680 |
|
681 already_AddRefed<Accessible> |
|
682 XULTreeAccessible::CreateTreeItemAccessible(int32_t aRow) const |
|
683 { |
|
684 nsRefPtr<Accessible> accessible = |
|
685 new XULTreeItemAccessible(mContent, mDoc, const_cast<XULTreeAccessible*>(this), |
|
686 mTree, mTreeView, aRow); |
|
687 |
|
688 return accessible.forget(); |
|
689 } |
|
690 |
|
691 //////////////////////////////////////////////////////////////////////////////// |
|
692 // XULTreeItemAccessibleBase |
|
693 //////////////////////////////////////////////////////////////////////////////// |
|
694 |
|
695 XULTreeItemAccessibleBase:: |
|
696 XULTreeItemAccessibleBase(nsIContent* aContent, DocAccessible* aDoc, |
|
697 Accessible* aParent, nsITreeBoxObject* aTree, |
|
698 nsITreeView* aTreeView, int32_t aRow) : |
|
699 AccessibleWrap(aContent, aDoc), |
|
700 mTree(aTree), mTreeView(aTreeView), mRow(aRow) |
|
701 { |
|
702 mParent = aParent; |
|
703 mStateFlags |= eSharedNode; |
|
704 } |
|
705 |
|
706 //////////////////////////////////////////////////////////////////////////////// |
|
707 // XULTreeItemAccessibleBase: nsISupports implementation |
|
708 |
|
709 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase, Accessible, |
|
710 mTree) |
|
711 |
|
712 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase) |
|
713 NS_INTERFACE_TABLE_INHERITED(XULTreeItemAccessibleBase, |
|
714 XULTreeItemAccessibleBase) |
|
715 NS_INTERFACE_TABLE_TAIL_INHERITING(Accessible) |
|
716 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessibleBase, Accessible) |
|
717 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessibleBase, Accessible) |
|
718 |
|
719 //////////////////////////////////////////////////////////////////////////////// |
|
720 // XULTreeItemAccessibleBase: nsIAccessible implementation |
|
721 |
|
722 Accessible* |
|
723 XULTreeItemAccessibleBase::FocusedChild() |
|
724 { |
|
725 return FocusMgr()->FocusedAccessible() == this ? this : nullptr; |
|
726 } |
|
727 |
|
728 NS_IMETHODIMP |
|
729 XULTreeItemAccessibleBase::GetBounds(int32_t* aX, int32_t* aY, |
|
730 int32_t* aWidth, int32_t* aHeight) |
|
731 { |
|
732 NS_ENSURE_ARG_POINTER(aX); |
|
733 *aX = 0; |
|
734 NS_ENSURE_ARG_POINTER(aY); |
|
735 *aY = 0; |
|
736 NS_ENSURE_ARG_POINTER(aWidth); |
|
737 *aWidth = 0; |
|
738 NS_ENSURE_ARG_POINTER(aHeight); |
|
739 *aHeight = 0; |
|
740 |
|
741 if (IsDefunct()) |
|
742 return NS_ERROR_FAILURE; |
|
743 |
|
744 // Get x coordinate and width from treechildren element, get y coordinate and |
|
745 // height from tree cell. |
|
746 |
|
747 nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree); |
|
748 NS_ENSURE_STATE(boxObj); |
|
749 |
|
750 nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree); |
|
751 |
|
752 int32_t x = 0, y = 0, width = 0, height = 0; |
|
753 nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyCString(), |
|
754 &x, &y, &width, &height); |
|
755 NS_ENSURE_SUCCESS(rv, rv); |
|
756 |
|
757 boxObj->GetWidth(&width); |
|
758 |
|
759 int32_t tcX = 0, tcY = 0; |
|
760 boxObj->GetScreenX(&tcX); |
|
761 boxObj->GetScreenY(&tcY); |
|
762 |
|
763 x = tcX; |
|
764 y += tcY; |
|
765 |
|
766 nsPresContext* presContext = mDoc->PresContext(); |
|
767 *aX = presContext->CSSPixelsToDevPixels(x); |
|
768 *aY = presContext->CSSPixelsToDevPixels(y); |
|
769 *aWidth = presContext->CSSPixelsToDevPixels(width); |
|
770 *aHeight = presContext->CSSPixelsToDevPixels(height); |
|
771 |
|
772 return NS_OK; |
|
773 } |
|
774 |
|
775 NS_IMETHODIMP |
|
776 XULTreeItemAccessibleBase::SetSelected(bool aSelect) |
|
777 { |
|
778 if (IsDefunct()) |
|
779 return NS_ERROR_FAILURE; |
|
780 |
|
781 nsCOMPtr<nsITreeSelection> selection; |
|
782 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
783 if (selection) { |
|
784 bool isSelected; |
|
785 selection->IsSelected(mRow, &isSelected); |
|
786 if (isSelected != aSelect) |
|
787 selection->ToggleSelect(mRow); |
|
788 } |
|
789 |
|
790 return NS_OK; |
|
791 } |
|
792 |
|
793 NS_IMETHODIMP |
|
794 XULTreeItemAccessibleBase::TakeFocus() |
|
795 { |
|
796 if (IsDefunct()) |
|
797 return NS_ERROR_FAILURE; |
|
798 |
|
799 nsCOMPtr<nsITreeSelection> selection; |
|
800 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
801 if (selection) |
|
802 selection->SetCurrentIndex(mRow); |
|
803 |
|
804 // focus event will be fired here |
|
805 return Accessible::TakeFocus(); |
|
806 } |
|
807 |
|
808 Relation |
|
809 XULTreeItemAccessibleBase::RelationByType(RelationType aType) |
|
810 { |
|
811 |
|
812 switch (aType) { |
|
813 case RelationType::NODE_CHILD_OF: { |
|
814 int32_t parentIndex = -1; |
|
815 if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex))) |
|
816 return Relation(); |
|
817 |
|
818 if (parentIndex == -1) |
|
819 return Relation(mParent); |
|
820 |
|
821 XULTreeAccessible* treeAcc = mParent->AsXULTree(); |
|
822 return Relation(treeAcc->GetTreeItemAccessible(parentIndex)); |
|
823 } |
|
824 |
|
825 case RelationType::NODE_PARENT_OF: { |
|
826 bool isTrue = false; |
|
827 if (NS_FAILED(mTreeView->IsContainerEmpty(mRow, &isTrue)) || isTrue) |
|
828 return Relation(); |
|
829 |
|
830 if (NS_FAILED(mTreeView->IsContainerOpen(mRow, &isTrue)) || !isTrue) |
|
831 return Relation(); |
|
832 |
|
833 XULTreeAccessible* tree = mParent->AsXULTree(); |
|
834 return Relation(new XULTreeItemIterator(tree, mTreeView, mRow)); |
|
835 } |
|
836 |
|
837 default: |
|
838 return Relation(); |
|
839 } |
|
840 } |
|
841 |
|
842 uint8_t |
|
843 XULTreeItemAccessibleBase::ActionCount() |
|
844 { |
|
845 // "activate" action is available for all treeitems, "expand/collapse" action |
|
846 // is avaible for treeitem which is container. |
|
847 return IsExpandable() ? 2 : 1; |
|
848 } |
|
849 |
|
850 NS_IMETHODIMP |
|
851 XULTreeItemAccessibleBase::GetActionName(uint8_t aIndex, nsAString& aName) |
|
852 { |
|
853 if (IsDefunct()) |
|
854 return NS_ERROR_FAILURE; |
|
855 |
|
856 if (aIndex == eAction_Click) { |
|
857 aName.AssignLiteral("activate"); |
|
858 return NS_OK; |
|
859 } |
|
860 |
|
861 if (aIndex == eAction_Expand && IsExpandable()) { |
|
862 bool isContainerOpen; |
|
863 mTreeView->IsContainerOpen(mRow, &isContainerOpen); |
|
864 if (isContainerOpen) |
|
865 aName.AssignLiteral("collapse"); |
|
866 else |
|
867 aName.AssignLiteral("expand"); |
|
868 |
|
869 return NS_OK; |
|
870 } |
|
871 |
|
872 return NS_ERROR_INVALID_ARG; |
|
873 } |
|
874 |
|
875 NS_IMETHODIMP |
|
876 XULTreeItemAccessibleBase::DoAction(uint8_t aIndex) |
|
877 { |
|
878 if (IsDefunct()) |
|
879 return NS_ERROR_FAILURE; |
|
880 |
|
881 if (aIndex != eAction_Click && |
|
882 (aIndex != eAction_Expand || !IsExpandable())) |
|
883 return NS_ERROR_INVALID_ARG; |
|
884 |
|
885 DoCommand(nullptr, aIndex); |
|
886 return NS_OK; |
|
887 } |
|
888 |
|
889 //////////////////////////////////////////////////////////////////////////////// |
|
890 // XULTreeItemAccessibleBase: Accessible implementation |
|
891 |
|
892 void |
|
893 XULTreeItemAccessibleBase::Shutdown() |
|
894 { |
|
895 mTree = nullptr; |
|
896 mTreeView = nullptr; |
|
897 mRow = -1; |
|
898 |
|
899 AccessibleWrap::Shutdown(); |
|
900 } |
|
901 |
|
902 GroupPos |
|
903 XULTreeItemAccessibleBase::GroupPosition() |
|
904 { |
|
905 GroupPos groupPos; |
|
906 |
|
907 int32_t level; |
|
908 nsresult rv = mTreeView->GetLevel(mRow, &level); |
|
909 NS_ENSURE_SUCCESS(rv, groupPos); |
|
910 |
|
911 int32_t topCount = 1; |
|
912 for (int32_t index = mRow - 1; index >= 0; index--) { |
|
913 int32_t lvl = -1; |
|
914 if (NS_SUCCEEDED(mTreeView->GetLevel(index, &lvl))) { |
|
915 if (lvl < level) |
|
916 break; |
|
917 |
|
918 if (lvl == level) |
|
919 topCount++; |
|
920 } |
|
921 } |
|
922 |
|
923 int32_t rowCount = 0; |
|
924 rv = mTreeView->GetRowCount(&rowCount); |
|
925 NS_ENSURE_SUCCESS(rv, groupPos); |
|
926 |
|
927 int32_t bottomCount = 0; |
|
928 for (int32_t index = mRow + 1; index < rowCount; index++) { |
|
929 int32_t lvl = -1; |
|
930 if (NS_SUCCEEDED(mTreeView->GetLevel(index, &lvl))) { |
|
931 if (lvl < level) |
|
932 break; |
|
933 |
|
934 if (lvl == level) |
|
935 bottomCount++; |
|
936 } |
|
937 } |
|
938 |
|
939 groupPos.level = level + 1; |
|
940 groupPos.setSize = topCount + bottomCount; |
|
941 groupPos.posInSet = topCount; |
|
942 |
|
943 return groupPos; |
|
944 } |
|
945 |
|
946 uint64_t |
|
947 XULTreeItemAccessibleBase::NativeState() |
|
948 { |
|
949 |
|
950 // focusable and selectable states |
|
951 uint64_t state = NativeInteractiveState(); |
|
952 |
|
953 // expanded/collapsed state |
|
954 if (IsExpandable()) { |
|
955 bool isContainerOpen; |
|
956 mTreeView->IsContainerOpen(mRow, &isContainerOpen); |
|
957 state |= isContainerOpen ? states::EXPANDED : states::COLLAPSED; |
|
958 } |
|
959 |
|
960 // selected state |
|
961 nsCOMPtr<nsITreeSelection> selection; |
|
962 mTreeView->GetSelection(getter_AddRefs(selection)); |
|
963 if (selection) { |
|
964 bool isSelected; |
|
965 selection->IsSelected(mRow, &isSelected); |
|
966 if (isSelected) |
|
967 state |= states::SELECTED; |
|
968 } |
|
969 |
|
970 // focused state |
|
971 if (FocusMgr()->IsFocused(this)) |
|
972 state |= states::FOCUSED; |
|
973 |
|
974 // invisible state |
|
975 int32_t firstVisibleRow, lastVisibleRow; |
|
976 mTree->GetFirstVisibleRow(&firstVisibleRow); |
|
977 mTree->GetLastVisibleRow(&lastVisibleRow); |
|
978 if (mRow < firstVisibleRow || mRow > lastVisibleRow) |
|
979 state |= states::INVISIBLE; |
|
980 |
|
981 return state; |
|
982 } |
|
983 |
|
984 uint64_t |
|
985 XULTreeItemAccessibleBase::NativeInteractiveState() const |
|
986 { |
|
987 return states::FOCUSABLE | states::SELECTABLE; |
|
988 } |
|
989 |
|
990 int32_t |
|
991 XULTreeItemAccessibleBase::IndexInParent() const |
|
992 { |
|
993 return mParent ? mParent->ContentChildCount() + mRow : -1; |
|
994 } |
|
995 |
|
996 //////////////////////////////////////////////////////////////////////////////// |
|
997 // XULTreeItemAccessibleBase: Widgets |
|
998 |
|
999 Accessible* |
|
1000 XULTreeItemAccessibleBase::ContainerWidget() const |
|
1001 { |
|
1002 return mParent; |
|
1003 } |
|
1004 |
|
1005 //////////////////////////////////////////////////////////////////////////////// |
|
1006 // XULTreeItemAccessibleBase: Accessible protected methods |
|
1007 |
|
1008 void |
|
1009 XULTreeItemAccessibleBase::DispatchClickEvent(nsIContent* aContent, |
|
1010 uint32_t aActionIndex) |
|
1011 { |
|
1012 if (IsDefunct()) |
|
1013 return; |
|
1014 |
|
1015 nsCOMPtr<nsITreeColumns> columns; |
|
1016 mTree->GetColumns(getter_AddRefs(columns)); |
|
1017 if (!columns) |
|
1018 return; |
|
1019 |
|
1020 // Get column and pseudo element. |
|
1021 nsCOMPtr<nsITreeColumn> column; |
|
1022 nsAutoCString pseudoElm; |
|
1023 |
|
1024 if (aActionIndex == eAction_Click) { |
|
1025 // Key column is visible and clickable. |
|
1026 columns->GetKeyColumn(getter_AddRefs(column)); |
|
1027 } else { |
|
1028 // Primary column contains a twisty we should click on. |
|
1029 columns->GetPrimaryColumn(getter_AddRefs(column)); |
|
1030 pseudoElm = NS_LITERAL_CSTRING("twisty"); |
|
1031 } |
|
1032 |
|
1033 if (column) |
|
1034 nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm); |
|
1035 } |
|
1036 |
|
1037 Accessible* |
|
1038 XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset, |
|
1039 nsresult* aError) const |
|
1040 { |
|
1041 if (aError) |
|
1042 *aError = NS_OK; // fail peacefully |
|
1043 |
|
1044 return mParent->GetChildAt(IndexInParent() + aOffset); |
|
1045 } |
|
1046 |
|
1047 //////////////////////////////////////////////////////////////////////////////// |
|
1048 // XULTreeItemAccessibleBase: protected implementation |
|
1049 |
|
1050 bool |
|
1051 XULTreeItemAccessibleBase::IsExpandable() |
|
1052 { |
|
1053 |
|
1054 bool isContainer = false; |
|
1055 mTreeView->IsContainer(mRow, &isContainer); |
|
1056 if (isContainer) { |
|
1057 bool isEmpty = false; |
|
1058 mTreeView->IsContainerEmpty(mRow, &isEmpty); |
|
1059 if (!isEmpty) { |
|
1060 nsCOMPtr<nsITreeColumns> columns; |
|
1061 mTree->GetColumns(getter_AddRefs(columns)); |
|
1062 nsCOMPtr<nsITreeColumn> primaryColumn; |
|
1063 if (columns) { |
|
1064 columns->GetPrimaryColumn(getter_AddRefs(primaryColumn)); |
|
1065 if (primaryColumn && |
|
1066 !nsCoreUtils::IsColumnHidden(primaryColumn)) |
|
1067 return true; |
|
1068 } |
|
1069 } |
|
1070 } |
|
1071 |
|
1072 return false; |
|
1073 } |
|
1074 |
|
1075 void |
|
1076 XULTreeItemAccessibleBase::GetCellName(nsITreeColumn* aColumn, nsAString& aName) |
|
1077 { |
|
1078 |
|
1079 mTreeView->GetCellText(mRow, aColumn, aName); |
|
1080 |
|
1081 // If there is still no name try the cell value: |
|
1082 // This is for graphical cells. We need tree/table view implementors to |
|
1083 // implement FooView::GetCellValue to return a meaningful string for cases |
|
1084 // where there is something shown in the cell (non-text) such as a star icon; |
|
1085 // in which case GetCellValue for that cell would return "starred" or |
|
1086 // "flagged" for example. |
|
1087 if (aName.IsEmpty()) |
|
1088 mTreeView->GetCellValue(mRow, aColumn, aName); |
|
1089 } |
|
1090 |
|
1091 |
|
1092 //////////////////////////////////////////////////////////////////////////////// |
|
1093 // XULTreeItemAccessible |
|
1094 //////////////////////////////////////////////////////////////////////////////// |
|
1095 |
|
1096 XULTreeItemAccessible:: |
|
1097 XULTreeItemAccessible(nsIContent* aContent, DocAccessible* aDoc, |
|
1098 Accessible* aParent, nsITreeBoxObject* aTree, |
|
1099 nsITreeView* aTreeView, int32_t aRow) : |
|
1100 XULTreeItemAccessibleBase(aContent, aDoc, aParent, aTree, aTreeView, aRow) |
|
1101 { |
|
1102 mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree); |
|
1103 GetCellName(mColumn, mCachedName); |
|
1104 } |
|
1105 |
|
1106 //////////////////////////////////////////////////////////////////////////////// |
|
1107 // XULTreeItemAccessible: nsISupports implementation |
|
1108 |
|
1109 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible, |
|
1110 XULTreeItemAccessibleBase, |
|
1111 mColumn) |
|
1112 |
|
1113 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible) |
|
1114 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase) |
|
1115 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase) |
|
1116 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase) |
|
1117 |
|
1118 //////////////////////////////////////////////////////////////////////////////// |
|
1119 // XULTreeItemAccessible: nsIAccessible implementation |
|
1120 |
|
1121 ENameValueFlag |
|
1122 XULTreeItemAccessible::Name(nsString& aName) |
|
1123 { |
|
1124 aName.Truncate(); |
|
1125 |
|
1126 GetCellName(mColumn, aName); |
|
1127 return eNameOK; |
|
1128 } |
|
1129 |
|
1130 //////////////////////////////////////////////////////////////////////////////// |
|
1131 // XULTreeItemAccessible: Accessible implementation |
|
1132 |
|
1133 void |
|
1134 XULTreeItemAccessible::Shutdown() |
|
1135 { |
|
1136 mColumn = nullptr; |
|
1137 XULTreeItemAccessibleBase::Shutdown(); |
|
1138 } |
|
1139 |
|
1140 role |
|
1141 XULTreeItemAccessible::NativeRole() |
|
1142 { |
|
1143 nsCOMPtr<nsITreeColumns> columns; |
|
1144 mTree->GetColumns(getter_AddRefs(columns)); |
|
1145 if (!columns) { |
|
1146 NS_ERROR("No tree columns object in the tree!"); |
|
1147 return roles::NOTHING; |
|
1148 } |
|
1149 |
|
1150 nsCOMPtr<nsITreeColumn> primaryColumn; |
|
1151 columns->GetPrimaryColumn(getter_AddRefs(primaryColumn)); |
|
1152 |
|
1153 return primaryColumn ? roles::OUTLINEITEM : roles::LISTITEM; |
|
1154 } |
|
1155 |
|
1156 //////////////////////////////////////////////////////////////////////////////// |
|
1157 // XULTreeItemAccessible: XULTreeItemAccessibleBase implementation |
|
1158 |
|
1159 void |
|
1160 XULTreeItemAccessible::RowInvalidated(int32_t aStartColIdx, int32_t aEndColIdx) |
|
1161 { |
|
1162 nsAutoString name; |
|
1163 Name(name); |
|
1164 |
|
1165 if (name != mCachedName) { |
|
1166 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this); |
|
1167 mCachedName = name; |
|
1168 } |
|
1169 } |
|
1170 |
|
1171 //////////////////////////////////////////////////////////////////////////////// |
|
1172 // XULTreeItemAccessible: Accessible protected implementation |
|
1173 |
|
1174 void |
|
1175 XULTreeItemAccessible::CacheChildren() |
|
1176 { |
|
1177 } |
|
1178 |
|
1179 |
|
1180 //////////////////////////////////////////////////////////////////////////////// |
|
1181 // XULTreeColumAccessible |
|
1182 //////////////////////////////////////////////////////////////////////////////// |
|
1183 |
|
1184 XULTreeColumAccessible:: |
|
1185 XULTreeColumAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
1186 XULColumAccessible(aContent, aDoc) |
|
1187 { |
|
1188 } |
|
1189 |
|
1190 Accessible* |
|
1191 XULTreeColumAccessible::GetSiblingAtOffset(int32_t aOffset, |
|
1192 nsresult* aError) const |
|
1193 { |
|
1194 if (aOffset < 0) |
|
1195 return XULColumAccessible::GetSiblingAtOffset(aOffset, aError); |
|
1196 |
|
1197 if (aError) |
|
1198 *aError = NS_OK; // fail peacefully |
|
1199 |
|
1200 nsCOMPtr<nsITreeBoxObject> tree = nsCoreUtils::GetTreeBoxObject(mContent); |
|
1201 if (tree) { |
|
1202 nsCOMPtr<nsITreeView> treeView; |
|
1203 tree->GetView(getter_AddRefs(treeView)); |
|
1204 if (treeView) { |
|
1205 int32_t rowCount = 0; |
|
1206 treeView->GetRowCount(&rowCount); |
|
1207 if (rowCount > 0 && aOffset <= rowCount) { |
|
1208 XULTreeAccessible* treeAcc = Parent()->AsXULTree(); |
|
1209 |
|
1210 if (treeAcc) |
|
1211 return treeAcc->GetTreeItemAccessible(aOffset - 1); |
|
1212 } |
|
1213 } |
|
1214 } |
|
1215 |
|
1216 return nullptr; |
|
1217 } |
|
1218 |