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