accessible/src/xul/XULTreeGridAccessible.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:316896b22732
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "XULTreeGridAccessibleWrap.h"
7
8 #include "nsAccCache.h"
9 #include "nsAccessibilityService.h"
10 #include "nsAccUtils.h"
11 #include "DocAccessible.h"
12 #include "nsEventShell.h"
13 #include "Relation.h"
14 #include "Role.h"
15 #include "States.h"
16
17 #include "nsIBoxObject.h"
18 #include "nsIMutableArray.h"
19 #include "nsIPersistentProperties2.h"
20 #include "nsITreeSelection.h"
21 #include "nsComponentManagerUtils.h"
22
23 using namespace mozilla::a11y;
24
25 ////////////////////////////////////////////////////////////////////////////////
26 // XULTreeGridAccessible: nsISupports implementation
27
28 NS_IMPL_ISUPPORTS_INHERITED(XULTreeGridAccessible,
29 XULTreeAccessible,
30 nsIAccessibleTable)
31
32 ////////////////////////////////////////////////////////////////////////////////
33 // XULTreeGridAccessible: nsIAccessibleTable implementation
34
35 uint32_t
36 XULTreeGridAccessible::ColCount()
37 {
38 return nsCoreUtils::GetSensibleColumnCount(mTree);
39 }
40
41 uint32_t
42 XULTreeGridAccessible::RowCount()
43 {
44 if (!mTreeView)
45 return 0;
46
47 int32_t rowCount = 0;
48 mTreeView->GetRowCount(&rowCount);
49 return rowCount >= 0 ? rowCount : 0;
50 }
51
52 uint32_t
53 XULTreeGridAccessible::SelectedCellCount()
54 {
55 return SelectedRowCount() * ColCount();
56 }
57
58 uint32_t
59 XULTreeGridAccessible::SelectedColCount()
60 {
61 // If all the row has been selected, then all the columns are selected,
62 // because we can't select a column alone.
63
64 uint32_t selectedRowCount = SelectedItemCount();
65 return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0;
66 }
67
68 uint32_t
69 XULTreeGridAccessible::SelectedRowCount()
70 {
71 return SelectedItemCount();
72 }
73
74 void
75 XULTreeGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
76 {
77 uint32_t colCount = ColCount(), rowCount = RowCount();
78
79 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
80 if (IsRowSelected(rowIdx)) {
81 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) {
82 Accessible* cell = CellAt(rowIdx, colIdx);
83 aCells->AppendElement(cell);
84 }
85 }
86 }
87 }
88
89 void
90 XULTreeGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
91 {
92 uint32_t colCount = ColCount(), rowCount = RowCount();
93
94 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++)
95 if (IsRowSelected(rowIdx))
96 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
97 aCells->AppendElement(rowIdx * colCount + colIdx);
98 }
99
100 void
101 XULTreeGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
102 {
103 if (RowCount() != SelectedRowCount())
104 return;
105
106 uint32_t colCount = ColCount();
107 aCols->SetCapacity(colCount);
108 for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
109 aCols->AppendElement(colIdx);
110 }
111
112 void
113 XULTreeGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
114 {
115 uint32_t rowCount = RowCount();
116 for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++)
117 if (IsRowSelected(rowIdx))
118 aRows->AppendElement(rowIdx);
119 }
120
121 Accessible*
122 XULTreeGridAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
123 {
124 Accessible* row = GetTreeItemAccessible(aRowIndex);
125 if (!row)
126 return nullptr;
127
128 nsCOMPtr<nsITreeColumn> column =
129 nsCoreUtils::GetSensibleColumnAt(mTree, aColumnIndex);
130 if (!column)
131 return nullptr;
132
133 nsRefPtr<XULTreeItemAccessibleBase> rowAcc = do_QueryObject(row);
134 if (!rowAcc)
135 return nullptr;
136
137 return rowAcc->GetCellAccessible(column);
138 }
139
140 void
141 XULTreeGridAccessible::ColDescription(uint32_t aColIdx, nsString& aDescription)
142 {
143 aDescription.Truncate();
144
145 nsCOMPtr<nsIAccessible> treeColumns;
146 Accessible::GetFirstChild(getter_AddRefs(treeColumns));
147 if (treeColumns) {
148 nsCOMPtr<nsIAccessible> treeColumnItem;
149 treeColumns->GetChildAt(aColIdx, getter_AddRefs(treeColumnItem));
150 if (treeColumnItem)
151 treeColumnItem->GetName(aDescription);
152 }
153 }
154
155 bool
156 XULTreeGridAccessible::IsColSelected(uint32_t aColIdx)
157 {
158 // If all the row has been selected, then all the columns are selected.
159 // Because we can't select a column alone.
160 return SelectedItemCount() == RowCount();
161 }
162
163 bool
164 XULTreeGridAccessible::IsRowSelected(uint32_t aRowIdx)
165 {
166 if (!mTreeView)
167 return false;
168
169 nsCOMPtr<nsITreeSelection> selection;
170 nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
171 NS_ENSURE_SUCCESS(rv, false);
172
173 bool isSelected = false;
174 selection->IsSelected(aRowIdx, &isSelected);
175 return isSelected;
176 }
177
178 bool
179 XULTreeGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
180 {
181 return IsRowSelected(aRowIdx);
182 }
183
184 void
185 XULTreeGridAccessible::SelectRow(uint32_t aRowIdx)
186 {
187 if (!mTreeView)
188 return;
189
190 nsCOMPtr<nsITreeSelection> selection;
191 mTreeView->GetSelection(getter_AddRefs(selection));
192 NS_ASSERTION(selection, "GetSelection() Shouldn't fail!");
193
194 selection->Select(aRowIdx);
195 }
196
197 void
198 XULTreeGridAccessible::UnselectRow(uint32_t aRowIdx)
199 {
200 if (!mTreeView)
201 return;
202
203 nsCOMPtr<nsITreeSelection> selection;
204 mTreeView->GetSelection(getter_AddRefs(selection));
205
206 if (selection)
207 selection->ClearRange(aRowIdx, aRowIdx);
208 }
209
210 ////////////////////////////////////////////////////////////////////////////////
211 // XULTreeGridAccessible: Accessible implementation
212
213 void
214 XULTreeGridAccessible::Shutdown()
215 {
216 mTable = nullptr;
217 XULTreeAccessible::Shutdown();
218 }
219
220 role
221 XULTreeGridAccessible::NativeRole()
222 {
223 nsCOMPtr<nsITreeColumns> treeColumns;
224 mTree->GetColumns(getter_AddRefs(treeColumns));
225 if (!treeColumns) {
226 NS_ERROR("No treecolumns object for tree!");
227 return roles::NOTHING;
228 }
229
230 nsCOMPtr<nsITreeColumn> primaryColumn;
231 treeColumns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
232
233 return primaryColumn ? roles::TREE_TABLE : roles::TABLE;
234 }
235
236 ////////////////////////////////////////////////////////////////////////////////
237 // XULTreeGridAccessible: XULTreeAccessible implementation
238
239 already_AddRefed<Accessible>
240 XULTreeGridAccessible::CreateTreeItemAccessible(int32_t aRow) const
241 {
242 nsRefPtr<Accessible> accessible =
243 new XULTreeGridRowAccessible(mContent, mDoc,
244 const_cast<XULTreeGridAccessible*>(this),
245 mTree, mTreeView, aRow);
246
247 return accessible.forget();
248 }
249
250
251 ////////////////////////////////////////////////////////////////////////////////
252 // XULTreeGridRowAccessible
253 ////////////////////////////////////////////////////////////////////////////////
254
255 XULTreeGridRowAccessible::
256 XULTreeGridRowAccessible(nsIContent* aContent, DocAccessible* aDoc,
257 Accessible* aTreeAcc, nsITreeBoxObject* aTree,
258 nsITreeView* aTreeView, int32_t aRow) :
259 XULTreeItemAccessibleBase(aContent, aDoc, aTreeAcc, aTree, aTreeView, aRow),
260 mAccessibleCache(kDefaultTreeCacheSize)
261 {
262 mGenericTypes |= eTableRow;
263 }
264
265 ////////////////////////////////////////////////////////////////////////////////
266 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation
267
268 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible,
269 XULTreeItemAccessibleBase,
270 mAccessibleCache)
271
272 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible)
273 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
274
275 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible,
276 XULTreeItemAccessibleBase)
277 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
278 XULTreeItemAccessibleBase)
279
280 ////////////////////////////////////////////////////////////////////////////////
281 // XULTreeGridRowAccessible: Accessible implementation
282
283 void
284 XULTreeGridRowAccessible::Shutdown()
285 {
286 ClearCache(mAccessibleCache);
287 XULTreeItemAccessibleBase::Shutdown();
288 }
289
290 role
291 XULTreeGridRowAccessible::NativeRole()
292 {
293 return roles::ROW;
294 }
295
296 ENameValueFlag
297 XULTreeGridRowAccessible::Name(nsString& aName)
298 {
299 aName.Truncate();
300
301 // XXX: the row name sholdn't be a concatenation of cell names (bug 664384).
302 nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
303 while (column) {
304 if (!aName.IsEmpty())
305 aName.AppendLiteral(" ");
306
307 nsAutoString cellName;
308 GetCellName(column, cellName);
309 aName.Append(cellName);
310
311 column = nsCoreUtils::GetNextSensibleColumn(column);
312 }
313
314 return eNameOK;
315 }
316
317 Accessible*
318 XULTreeGridRowAccessible::ChildAtPoint(int32_t aX, int32_t aY,
319 EWhichChildAtPoint aWhichChild)
320 {
321 nsIFrame *frame = GetFrame();
322 if (!frame)
323 return nullptr;
324
325 nsPresContext *presContext = frame->PresContext();
326 nsIPresShell* presShell = presContext->PresShell();
327
328 nsIFrame *rootFrame = presShell->GetRootFrame();
329 NS_ENSURE_TRUE(rootFrame, nullptr);
330
331 nsIntRect rootRect = rootFrame->GetScreenRect();
332
333 int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
334 int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
335
336 int32_t row = -1;
337 nsCOMPtr<nsITreeColumn> column;
338 nsAutoCString childEltUnused;
339 mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
340 childEltUnused);
341
342 // Return if we failed to find tree cell in the row for the given point.
343 if (row != mRow || !column)
344 return nullptr;
345
346 return GetCellAccessible(column);
347 }
348
349 Accessible*
350 XULTreeGridRowAccessible::GetChildAt(uint32_t aIndex) const
351 {
352 if (IsDefunct())
353 return nullptr;
354
355 nsCOMPtr<nsITreeColumn> column =
356 nsCoreUtils::GetSensibleColumnAt(mTree, aIndex);
357 if (!column)
358 return nullptr;
359
360 return GetCellAccessible(column);
361 }
362
363 uint32_t
364 XULTreeGridRowAccessible::ChildCount() const
365 {
366 return nsCoreUtils::GetSensibleColumnCount(mTree);
367 }
368
369 ////////////////////////////////////////////////////////////////////////////////
370 // XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation
371
372 Accessible*
373 XULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn) const
374 {
375 NS_PRECONDITION(aColumn, "No tree column!");
376
377 void* key = static_cast<void*>(aColumn);
378 Accessible* cachedCell = mAccessibleCache.GetWeak(key);
379 if (cachedCell)
380 return cachedCell;
381
382 nsRefPtr<Accessible> cell =
383 new XULTreeGridCellAccessibleWrap(mContent, mDoc,
384 const_cast<XULTreeGridRowAccessible*>(this),
385 mTree, mTreeView, mRow, aColumn);
386 mAccessibleCache.Put(key, cell);
387 Document()->BindToDocument(cell, nullptr);
388 return cell;
389 }
390
391 void
392 XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx,
393 int32_t aEndColIdx)
394 {
395 nsCOMPtr<nsITreeColumns> treeColumns;
396 mTree->GetColumns(getter_AddRefs(treeColumns));
397 if (!treeColumns)
398 return;
399
400 bool nameChanged = false;
401 for (int32_t colIdx = aStartColIdx; colIdx <= aEndColIdx; ++colIdx) {
402 nsCOMPtr<nsITreeColumn> column;
403 treeColumns->GetColumnAt(colIdx, getter_AddRefs(column));
404 if (column && !nsCoreUtils::IsColumnHidden(column)) {
405 Accessible* cellAccessible = GetCellAccessible(column);
406 if (cellAccessible) {
407 nsRefPtr<XULTreeGridCellAccessible> cellAcc = do_QueryObject(cellAccessible);
408
409 nameChanged |= cellAcc->CellInvalidated();
410 }
411 }
412 }
413
414 if (nameChanged)
415 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
416
417 }
418
419 ////////////////////////////////////////////////////////////////////////////////
420 // XULTreeGridRowAccessible: Accessible protected implementation
421
422 void
423 XULTreeGridRowAccessible::CacheChildren()
424 {
425 }
426
427 ////////////////////////////////////////////////////////////////////////////////
428 // XULTreeGridCellAccessible
429 ////////////////////////////////////////////////////////////////////////////////
430
431 XULTreeGridCellAccessible::
432 XULTreeGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc,
433 XULTreeGridRowAccessible* aRowAcc,
434 nsITreeBoxObject* aTree, nsITreeView* aTreeView,
435 int32_t aRow, nsITreeColumn* aColumn) :
436 LeafAccessible(aContent, aDoc), xpcAccessibleTableCell(this), mTree(aTree),
437 mTreeView(aTreeView), mRow(aRow), mColumn(aColumn)
438 {
439 mParent = aRowAcc;
440 mStateFlags |= eSharedNode;
441 mGenericTypes |= eTableCell;
442
443 NS_ASSERTION(mTreeView, "mTreeView is null");
444
445 int16_t type = -1;
446 mColumn->GetType(&type);
447 if (type == nsITreeColumn::TYPE_CHECKBOX)
448 mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
449 else
450 mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
451 }
452
453 ////////////////////////////////////////////////////////////////////////////////
454 // XULTreeGridCellAccessible: nsISupports implementation
455
456 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible,
457 mTree, mColumn)
458
459 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible)
460 NS_INTERFACE_TABLE_INHERITED(XULTreeGridCellAccessible,
461 nsIAccessibleTableCell,
462 XULTreeGridCellAccessible)
463 NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible)
464 NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
465 NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
466
467 ////////////////////////////////////////////////////////////////////////////////
468 // XULTreeGridCellAccessible: nsIAccessible implementation
469
470 void
471 XULTreeGridCellAccessible::Shutdown()
472 {
473 mTableCell = nullptr;
474 LeafAccessible::Shutdown();
475 }
476
477 Accessible*
478 XULTreeGridCellAccessible::FocusedChild()
479 {
480 return nullptr;
481 }
482
483 ENameValueFlag
484 XULTreeGridCellAccessible::Name(nsString& aName)
485 {
486 aName.Truncate();
487
488 if (!mTreeView)
489 return eNameOK;
490
491 mTreeView->GetCellText(mRow, mColumn, aName);
492
493 // If there is still no name try the cell value:
494 // This is for graphical cells. We need tree/table view implementors to implement
495 // FooView::GetCellValue to return a meaningful string for cases where there is
496 // something shown in the cell (non-text) such as a star icon; in which case
497 // GetCellValue for that cell would return "starred" or "flagged" for example.
498 if (aName.IsEmpty())
499 mTreeView->GetCellValue(mRow, mColumn, aName);
500
501 return eNameOK;
502 }
503
504 NS_IMETHODIMP
505 XULTreeGridCellAccessible::GetBounds(int32_t* aX, int32_t* aY,
506 int32_t* aWidth, int32_t* aHeight)
507 {
508 NS_ENSURE_ARG_POINTER(aX);
509 *aX = 0;
510 NS_ENSURE_ARG_POINTER(aY);
511 *aY = 0;
512 NS_ENSURE_ARG_POINTER(aWidth);
513 *aWidth = 0;
514 NS_ENSURE_ARG_POINTER(aHeight);
515 *aHeight = 0;
516
517 if (IsDefunct())
518 return NS_ERROR_FAILURE;
519
520 // Get bounds for tree cell and add x and y of treechildren element to
521 // x and y of the cell.
522 nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
523 NS_ENSURE_STATE(boxObj);
524
525 int32_t x = 0, y = 0, width = 0, height = 0;
526 nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn,
527 NS_LITERAL_CSTRING("cell"),
528 &x, &y, &width, &height);
529 NS_ENSURE_SUCCESS(rv, rv);
530
531 int32_t tcX = 0, tcY = 0;
532 boxObj->GetScreenX(&tcX);
533 boxObj->GetScreenY(&tcY);
534 x += tcX;
535 y += tcY;
536
537 nsPresContext* presContext = mDoc->PresContext();
538 *aX = presContext->CSSPixelsToDevPixels(x);
539 *aY = presContext->CSSPixelsToDevPixels(y);
540 *aWidth = presContext->CSSPixelsToDevPixels(width);
541 *aHeight = presContext->CSSPixelsToDevPixels(height);
542
543 return NS_OK;
544 }
545
546 uint8_t
547 XULTreeGridCellAccessible::ActionCount()
548 {
549 bool isCycler = false;
550 mColumn->GetCycler(&isCycler);
551 if (isCycler)
552 return 1;
553
554 int16_t type;
555 mColumn->GetType(&type);
556 if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable())
557 return 1;
558
559 return 0;
560 }
561
562 NS_IMETHODIMP
563 XULTreeGridCellAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
564 {
565 aName.Truncate();
566
567 if (aIndex != eAction_Click)
568 return NS_ERROR_INVALID_ARG;
569
570 if (IsDefunct() || !mTreeView)
571 return NS_ERROR_FAILURE;
572
573 bool isCycler = false;
574 mColumn->GetCycler(&isCycler);
575 if (isCycler) {
576 aName.AssignLiteral("cycle");
577 return NS_OK;
578 }
579
580 int16_t type;
581 mColumn->GetType(&type);
582 if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
583 nsAutoString value;
584 mTreeView->GetCellValue(mRow, mColumn, value);
585 if (value.EqualsLiteral("true"))
586 aName.AssignLiteral("uncheck");
587 else
588 aName.AssignLiteral("check");
589
590 return NS_OK;
591 }
592
593 return NS_ERROR_INVALID_ARG;
594 }
595
596 NS_IMETHODIMP
597 XULTreeGridCellAccessible::DoAction(uint8_t aIndex)
598 {
599 if (aIndex != eAction_Click)
600 return NS_ERROR_INVALID_ARG;
601
602 if (IsDefunct())
603 return NS_ERROR_FAILURE;
604
605 bool isCycler = false;
606 mColumn->GetCycler(&isCycler);
607 if (isCycler) {
608 DoCommand();
609 return NS_OK;
610 }
611
612 int16_t type;
613 mColumn->GetType(&type);
614 if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
615 DoCommand();
616 return NS_OK;
617 }
618
619 return NS_ERROR_INVALID_ARG;
620 }
621
622 ////////////////////////////////////////////////////////////////////////////////
623 // XULTreeGridCellAccessible: nsIAccessibleTableCell implementation
624
625 TableAccessible*
626 XULTreeGridCellAccessible::Table() const
627 {
628 Accessible* grandParent = mParent->Parent();
629 if (grandParent)
630 return grandParent->AsTable();
631
632 return nullptr;
633 }
634
635 uint32_t
636 XULTreeGridCellAccessible::ColIdx() const
637 {
638 uint32_t colIdx = 0;
639 nsCOMPtr<nsITreeColumn> column = mColumn;
640 while ((column = nsCoreUtils::GetPreviousSensibleColumn(column)))
641 colIdx++;
642
643 return colIdx;
644 }
645
646 uint32_t
647 XULTreeGridCellAccessible::RowIdx() const
648 {
649 return mRow;
650 }
651
652 void
653 XULTreeGridCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aHeaderCells)
654 {
655 nsCOMPtr<nsIDOMElement> columnElm;
656 mColumn->GetElement(getter_AddRefs(columnElm));
657
658 nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
659 Accessible* headerCell = mDoc->GetAccessible(columnContent);
660 if (headerCell)
661 aHeaderCells->AppendElement(headerCell);
662 }
663
664 bool
665 XULTreeGridCellAccessible::Selected()
666 {
667 nsCOMPtr<nsITreeSelection> selection;
668 nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
669 NS_ENSURE_SUCCESS(rv, false);
670
671 bool selected = false;
672 selection->IsSelected(mRow, &selected);
673 return selected;
674 }
675
676 ////////////////////////////////////////////////////////////////////////////////
677 // XULTreeGridCellAccessible: Accessible public implementation
678
679 already_AddRefed<nsIPersistentProperties>
680 XULTreeGridCellAccessible::NativeAttributes()
681 {
682 nsCOMPtr<nsIPersistentProperties> attributes =
683 do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
684
685 // "table-cell-index" attribute
686 TableAccessible* table = Table();
687 if (!table)
688 return attributes.forget();
689
690 nsAutoString stringIdx;
691 stringIdx.AppendInt(table->CellIndexAt(mRow, ColIdx()));
692 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
693
694 // "cycles" attribute
695 bool isCycler = false;
696 nsresult rv = mColumn->GetCycler(&isCycler);
697 if (NS_SUCCEEDED(rv) && isCycler)
698 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::cycles,
699 NS_LITERAL_STRING("true"));
700
701 return attributes.forget();
702 }
703
704 role
705 XULTreeGridCellAccessible::NativeRole()
706 {
707 return roles::GRID_CELL;
708 }
709
710 uint64_t
711 XULTreeGridCellAccessible::NativeState()
712 {
713 if (!mTreeView)
714 return states::DEFUNCT;
715
716 // selectable/selected state
717 uint64_t states = states::SELECTABLE; // keep in sync with NativeInteractiveState
718
719 nsCOMPtr<nsITreeSelection> selection;
720 mTreeView->GetSelection(getter_AddRefs(selection));
721 if (selection) {
722 bool isSelected = false;
723 selection->IsSelected(mRow, &isSelected);
724 if (isSelected)
725 states |= states::SELECTED;
726 }
727
728 // checked state
729 int16_t type;
730 mColumn->GetType(&type);
731 if (type == nsITreeColumn::TYPE_CHECKBOX) {
732 states |= states::CHECKABLE;
733 nsAutoString checked;
734 mTreeView->GetCellValue(mRow, mColumn, checked);
735 if (checked.EqualsIgnoreCase("true"))
736 states |= states::CHECKED;
737 }
738
739 return states;
740 }
741
742 uint64_t
743 XULTreeGridCellAccessible::NativeInteractiveState() const
744 {
745 return states::SELECTABLE;
746 }
747
748 int32_t
749 XULTreeGridCellAccessible::IndexInParent() const
750 {
751 return ColIdx();
752 }
753
754 Relation
755 XULTreeGridCellAccessible::RelationByType(RelationType aType)
756 {
757 return Relation();
758 }
759
760 ////////////////////////////////////////////////////////////////////////////////
761 // XULTreeGridCellAccessible: public implementation
762
763 bool
764 XULTreeGridCellAccessible::CellInvalidated()
765 {
766
767 nsAutoString textEquiv;
768
769 int16_t type;
770 mColumn->GetType(&type);
771 if (type == nsITreeColumn::TYPE_CHECKBOX) {
772 mTreeView->GetCellValue(mRow, mColumn, textEquiv);
773 if (mCachedTextEquiv != textEquiv) {
774 bool isEnabled = textEquiv.EqualsLiteral("true");
775 nsRefPtr<AccEvent> accEvent =
776 new AccStateChangeEvent(this, states::CHECKED, isEnabled);
777 nsEventShell::FireEvent(accEvent);
778
779 mCachedTextEquiv = textEquiv;
780 return true;
781 }
782
783 return false;
784 }
785
786 mTreeView->GetCellText(mRow, mColumn, textEquiv);
787 if (mCachedTextEquiv != textEquiv) {
788 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
789 mCachedTextEquiv = textEquiv;
790 return true;
791 }
792
793 return false;
794 }
795
796 ////////////////////////////////////////////////////////////////////////////////
797 // XULTreeGridCellAccessible: Accessible protected implementation
798
799 Accessible*
800 XULTreeGridCellAccessible::GetSiblingAtOffset(int32_t aOffset,
801 nsresult* aError) const
802 {
803 if (aError)
804 *aError = NS_OK; // fail peacefully
805
806 nsCOMPtr<nsITreeColumn> columnAtOffset(mColumn), column;
807 if (aOffset < 0) {
808 for (int32_t index = aOffset; index < 0 && columnAtOffset; index++) {
809 column = nsCoreUtils::GetPreviousSensibleColumn(columnAtOffset);
810 column.swap(columnAtOffset);
811 }
812 } else {
813 for (int32_t index = aOffset; index > 0 && columnAtOffset; index--) {
814 column = nsCoreUtils::GetNextSensibleColumn(columnAtOffset);
815 column.swap(columnAtOffset);
816 }
817 }
818
819 if (!columnAtOffset)
820 return nullptr;
821
822 nsRefPtr<XULTreeItemAccessibleBase> rowAcc = do_QueryObject(Parent());
823 return rowAcc->GetCellAccessible(columnAtOffset);
824 }
825
826 void
827 XULTreeGridCellAccessible::DispatchClickEvent(nsIContent* aContent,
828 uint32_t aActionIndex)
829 {
830 if (IsDefunct())
831 return;
832
833 nsCoreUtils::DispatchClickEvent(mTree, mRow, mColumn);
834 }
835
836 ////////////////////////////////////////////////////////////////////////////////
837 // XULTreeGridCellAccessible: protected implementation
838
839 bool
840 XULTreeGridCellAccessible::IsEditable() const
841 {
842
843 // XXX: logic corresponds to tree.xml, it's preferable to have interface
844 // method to check it.
845 bool isEditable = false;
846 nsresult rv = mTreeView->IsEditable(mRow, mColumn, &isEditable);
847 if (NS_FAILED(rv) || !isEditable)
848 return false;
849
850 nsCOMPtr<nsIDOMElement> columnElm;
851 mColumn->GetElement(getter_AddRefs(columnElm));
852 if (!columnElm)
853 return false;
854
855 nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
856 if (!columnContent->AttrValueIs(kNameSpaceID_None,
857 nsGkAtoms::editable,
858 nsGkAtoms::_true,
859 eCaseMatters))
860 return false;
861
862 return mContent->AttrValueIs(kNameSpaceID_None,
863 nsGkAtoms::editable,
864 nsGkAtoms::_true, eCaseMatters);
865 }

mercurial