Coverage Report

Created: 2018-09-25 14:53

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