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