accessible/src/xul/XULTreeGridAccessible.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     6 #include "XULTreeGridAccessibleWrap.h"
     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"
    17 #include "nsIBoxObject.h"
    18 #include "nsIMutableArray.h"
    19 #include "nsIPersistentProperties2.h"
    20 #include "nsITreeSelection.h"
    21 #include "nsComponentManagerUtils.h"
    23 using namespace mozilla::a11y;
    25 ////////////////////////////////////////////////////////////////////////////////
    26 // XULTreeGridAccessible: nsISupports implementation
    28 NS_IMPL_ISUPPORTS_INHERITED(XULTreeGridAccessible,
    29                             XULTreeAccessible,
    30                             nsIAccessibleTable)
    32 ////////////////////////////////////////////////////////////////////////////////
    33 // XULTreeGridAccessible: nsIAccessibleTable implementation
    35 uint32_t
    36 XULTreeGridAccessible::ColCount()
    37 {
    38   return nsCoreUtils::GetSensibleColumnCount(mTree);
    39 }
    41 uint32_t
    42 XULTreeGridAccessible::RowCount()
    43 {
    44   if (!mTreeView)
    45     return 0;
    47   int32_t rowCount = 0;
    48   mTreeView->GetRowCount(&rowCount);
    49   return rowCount >= 0 ? rowCount : 0;
    50 }
    52 uint32_t
    53 XULTreeGridAccessible::SelectedCellCount()
    54 {
    55   return SelectedRowCount() * ColCount();
    56 }
    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.
    64   uint32_t selectedRowCount = SelectedItemCount();
    65   return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0;
    66 }
    68 uint32_t
    69 XULTreeGridAccessible::SelectedRowCount()
    70 {
    71   return SelectedItemCount();
    72 }
    74 void
    75 XULTreeGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
    76 {
    77   uint32_t colCount = ColCount(), rowCount = RowCount();
    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 }
    89 void
    90 XULTreeGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
    91 {
    92   uint32_t colCount = ColCount(), rowCount = RowCount();
    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 }
   100 void
   101 XULTreeGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
   102 {
   103   if (RowCount() != SelectedRowCount())
   104     return;
   106   uint32_t colCount = ColCount();
   107   aCols->SetCapacity(colCount);
   108   for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
   109     aCols->AppendElement(colIdx);
   110 }
   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 }
   121 Accessible*
   122 XULTreeGridAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
   123 { 
   124   Accessible* row = GetTreeItemAccessible(aRowIndex);
   125   if (!row)
   126     return nullptr;
   128   nsCOMPtr<nsITreeColumn> column =
   129     nsCoreUtils::GetSensibleColumnAt(mTree, aColumnIndex);
   130   if (!column)
   131     return nullptr;
   133   nsRefPtr<XULTreeItemAccessibleBase> rowAcc = do_QueryObject(row);
   134   if (!rowAcc)
   135     return nullptr;
   137   return rowAcc->GetCellAccessible(column);
   138 }
   140 void
   141 XULTreeGridAccessible::ColDescription(uint32_t aColIdx, nsString& aDescription)
   142 {
   143   aDescription.Truncate();
   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 }
   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 }
   163 bool
   164 XULTreeGridAccessible::IsRowSelected(uint32_t aRowIdx)
   165 {
   166   if (!mTreeView)
   167     return false;
   169   nsCOMPtr<nsITreeSelection> selection;
   170   nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
   171   NS_ENSURE_SUCCESS(rv, false);
   173   bool isSelected = false;
   174   selection->IsSelected(aRowIdx, &isSelected);
   175   return isSelected;
   176 }
   178 bool
   179 XULTreeGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
   180 {
   181   return IsRowSelected(aRowIdx);
   182 }
   184 void
   185 XULTreeGridAccessible::SelectRow(uint32_t aRowIdx)
   186 {
   187   if (!mTreeView)
   188     return;
   190   nsCOMPtr<nsITreeSelection> selection;
   191   mTreeView->GetSelection(getter_AddRefs(selection));
   192   NS_ASSERTION(selection, "GetSelection() Shouldn't fail!");
   194   selection->Select(aRowIdx);
   195 }
   197 void
   198 XULTreeGridAccessible::UnselectRow(uint32_t aRowIdx)
   199 {
   200   if (!mTreeView)
   201     return;
   203   nsCOMPtr<nsITreeSelection> selection;
   204   mTreeView->GetSelection(getter_AddRefs(selection));
   206   if (selection)
   207     selection->ClearRange(aRowIdx, aRowIdx);
   208 }
   210 ////////////////////////////////////////////////////////////////////////////////
   211 // XULTreeGridAccessible: Accessible implementation
   213 void
   214 XULTreeGridAccessible::Shutdown()
   215 {
   216   mTable = nullptr;
   217   XULTreeAccessible::Shutdown();
   218 }
   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   }
   230   nsCOMPtr<nsITreeColumn> primaryColumn;
   231   treeColumns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
   233   return primaryColumn ? roles::TREE_TABLE : roles::TABLE;
   234 }
   236 ////////////////////////////////////////////////////////////////////////////////
   237 // XULTreeGridAccessible: XULTreeAccessible implementation
   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);
   247   return accessible.forget();
   248 }
   251 ////////////////////////////////////////////////////////////////////////////////
   252 // XULTreeGridRowAccessible
   253 ////////////////////////////////////////////////////////////////////////////////
   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 }
   265 ////////////////////////////////////////////////////////////////////////////////
   266 // XULTreeGridRowAccessible: nsISupports and cycle collection implementation
   268 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible,
   269                                    XULTreeItemAccessibleBase,
   270                                    mAccessibleCache)
   272 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible)
   273 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
   275 NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible,
   276                          XULTreeItemAccessibleBase)
   277 NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
   278                           XULTreeItemAccessibleBase)
   280 ////////////////////////////////////////////////////////////////////////////////
   281 // XULTreeGridRowAccessible: Accessible implementation
   283 void
   284 XULTreeGridRowAccessible::Shutdown()
   285 {
   286   ClearCache(mAccessibleCache);
   287   XULTreeItemAccessibleBase::Shutdown();
   288 }
   290 role
   291 XULTreeGridRowAccessible::NativeRole()
   292 {
   293   return roles::ROW;
   294 }
   296 ENameValueFlag
   297 XULTreeGridRowAccessible::Name(nsString& aName)
   298 {
   299   aName.Truncate();
   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(" ");
   307     nsAutoString cellName;
   308     GetCellName(column, cellName);
   309     aName.Append(cellName);
   311     column = nsCoreUtils::GetNextSensibleColumn(column);
   312   }
   314   return eNameOK;
   315 }
   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;
   325   nsPresContext *presContext = frame->PresContext();
   326   nsIPresShell* presShell = presContext->PresShell();
   328   nsIFrame *rootFrame = presShell->GetRootFrame();
   329   NS_ENSURE_TRUE(rootFrame, nullptr);
   331   nsIntRect rootRect = rootFrame->GetScreenRect();
   333   int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
   334   int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
   336   int32_t row = -1;
   337   nsCOMPtr<nsITreeColumn> column;
   338   nsAutoCString childEltUnused;
   339   mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
   340                    childEltUnused);
   342   // Return if we failed to find tree cell in the row for the given point.
   343   if (row != mRow || !column)
   344     return nullptr;
   346   return GetCellAccessible(column);
   347 }
   349 Accessible*
   350 XULTreeGridRowAccessible::GetChildAt(uint32_t aIndex) const
   351 {
   352   if (IsDefunct())
   353     return nullptr;
   355   nsCOMPtr<nsITreeColumn> column =
   356     nsCoreUtils::GetSensibleColumnAt(mTree, aIndex);
   357   if (!column)
   358     return nullptr;
   360   return GetCellAccessible(column);
   361 }
   363 uint32_t
   364 XULTreeGridRowAccessible::ChildCount() const
   365 {
   366   return nsCoreUtils::GetSensibleColumnCount(mTree);
   367 }
   369 ////////////////////////////////////////////////////////////////////////////////
   370 // XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation
   372 Accessible*
   373 XULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn) const
   374 {
   375   NS_PRECONDITION(aColumn, "No tree column!");
   377   void* key = static_cast<void*>(aColumn);
   378   Accessible* cachedCell = mAccessibleCache.GetWeak(key);
   379   if (cachedCell)
   380     return cachedCell;
   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 }
   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;
   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);
   409         nameChanged |= cellAcc->CellInvalidated();
   410       }
   411     }
   412   }
   414   if (nameChanged)
   415     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
   417 }
   419 ////////////////////////////////////////////////////////////////////////////////
   420 // XULTreeGridRowAccessible: Accessible protected implementation
   422 void
   423 XULTreeGridRowAccessible::CacheChildren()
   424 {
   425 }
   427 ////////////////////////////////////////////////////////////////////////////////
   428 // XULTreeGridCellAccessible
   429 ////////////////////////////////////////////////////////////////////////////////
   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;
   443   NS_ASSERTION(mTreeView, "mTreeView is null");
   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 }
   453 ////////////////////////////////////////////////////////////////////////////////
   454 // XULTreeGridCellAccessible: nsISupports implementation
   456 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible,
   457                                    mTree, mColumn)
   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)
   467 ////////////////////////////////////////////////////////////////////////////////
   468 // XULTreeGridCellAccessible: nsIAccessible implementation
   470 void
   471 XULTreeGridCellAccessible::Shutdown()
   472 {
   473   mTableCell = nullptr;
   474   LeafAccessible::Shutdown();
   475 }
   477 Accessible*
   478 XULTreeGridCellAccessible::FocusedChild()
   479 {
   480   return nullptr;
   481 }
   483 ENameValueFlag
   484 XULTreeGridCellAccessible::Name(nsString& aName)
   485 {
   486   aName.Truncate();
   488   if (!mTreeView)
   489     return eNameOK;
   491   mTreeView->GetCellText(mRow, mColumn, aName);
   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);
   501   return eNameOK;
   502 }
   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;
   517   if (IsDefunct())
   518     return NS_ERROR_FAILURE;
   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);
   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);
   531   int32_t tcX = 0, tcY = 0;
   532   boxObj->GetScreenX(&tcX);
   533   boxObj->GetScreenY(&tcY);
   534   x += tcX;
   535   y += tcY;
   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);
   543   return NS_OK;
   544 }
   546 uint8_t
   547 XULTreeGridCellAccessible::ActionCount()
   548 {
   549   bool isCycler = false;
   550   mColumn->GetCycler(&isCycler);
   551   if (isCycler)
   552     return 1;
   554   int16_t type;
   555   mColumn->GetType(&type);
   556   if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable())
   557     return 1;
   559   return 0;
   560 }
   562 NS_IMETHODIMP
   563 XULTreeGridCellAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
   564 {
   565   aName.Truncate();
   567   if (aIndex != eAction_Click)
   568     return NS_ERROR_INVALID_ARG;
   570   if (IsDefunct() || !mTreeView)
   571     return NS_ERROR_FAILURE;
   573   bool isCycler = false;
   574   mColumn->GetCycler(&isCycler);
   575   if (isCycler) {
   576     aName.AssignLiteral("cycle");
   577     return NS_OK;
   578   }
   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");
   590     return NS_OK;
   591   }
   593   return NS_ERROR_INVALID_ARG;
   594 }
   596 NS_IMETHODIMP
   597 XULTreeGridCellAccessible::DoAction(uint8_t aIndex)
   598 {
   599   if (aIndex != eAction_Click)
   600     return NS_ERROR_INVALID_ARG;
   602   if (IsDefunct())
   603     return NS_ERROR_FAILURE;
   605   bool isCycler = false;
   606   mColumn->GetCycler(&isCycler);
   607   if (isCycler) {
   608     DoCommand();
   609     return NS_OK;
   610   }
   612   int16_t type;
   613   mColumn->GetType(&type);
   614   if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
   615     DoCommand();
   616     return NS_OK;
   617   }
   619   return NS_ERROR_INVALID_ARG;
   620 }
   622 ////////////////////////////////////////////////////////////////////////////////
   623 // XULTreeGridCellAccessible: nsIAccessibleTableCell implementation
   625 TableAccessible*
   626 XULTreeGridCellAccessible::Table() const
   627 {
   628   Accessible* grandParent = mParent->Parent();
   629   if (grandParent)
   630     return grandParent->AsTable();
   632   return nullptr;
   633 }
   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++;
   643   return colIdx;
   644 }
   646 uint32_t
   647 XULTreeGridCellAccessible::RowIdx() const
   648 {
   649   return mRow;
   650 }
   652 void
   653 XULTreeGridCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aHeaderCells)
   654 {
   655   nsCOMPtr<nsIDOMElement> columnElm;
   656   mColumn->GetElement(getter_AddRefs(columnElm));
   658   nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
   659   Accessible* headerCell = mDoc->GetAccessible(columnContent);
   660   if (headerCell)
   661     aHeaderCells->AppendElement(headerCell);
   662 }
   664 bool
   665 XULTreeGridCellAccessible::Selected()
   666 {
   667   nsCOMPtr<nsITreeSelection> selection;
   668   nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
   669   NS_ENSURE_SUCCESS(rv, false);
   671   bool selected = false;
   672   selection->IsSelected(mRow, &selected);
   673   return selected;
   674 }
   676 ////////////////////////////////////////////////////////////////////////////////
   677 // XULTreeGridCellAccessible: Accessible public implementation
   679 already_AddRefed<nsIPersistentProperties>
   680 XULTreeGridCellAccessible::NativeAttributes()
   681 {
   682   nsCOMPtr<nsIPersistentProperties> attributes =
   683     do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
   685   // "table-cell-index" attribute
   686   TableAccessible* table = Table();
   687   if (!table)
   688     return attributes.forget();
   690   nsAutoString stringIdx;
   691   stringIdx.AppendInt(table->CellIndexAt(mRow, ColIdx()));
   692   nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
   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"));
   701   return attributes.forget();
   702 }
   704 role
   705 XULTreeGridCellAccessible::NativeRole()
   706 {
   707   return roles::GRID_CELL;
   708 }
   710 uint64_t
   711 XULTreeGridCellAccessible::NativeState()
   712 {
   713   if (!mTreeView)
   714     return states::DEFUNCT;
   716   // selectable/selected state
   717   uint64_t states = states::SELECTABLE; // keep in sync with NativeInteractiveState
   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   }
   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   }
   739   return states;
   740 }
   742 uint64_t
   743 XULTreeGridCellAccessible::NativeInteractiveState() const
   744 {
   745   return states::SELECTABLE;
   746 }
   748 int32_t
   749 XULTreeGridCellAccessible::IndexInParent() const
   750 {
   751   return ColIdx();
   752 }
   754 Relation
   755 XULTreeGridCellAccessible::RelationByType(RelationType aType)
   756 {
   757   return Relation();
   758 }
   760 ////////////////////////////////////////////////////////////////////////////////
   761 // XULTreeGridCellAccessible: public implementation
   763 bool
   764 XULTreeGridCellAccessible::CellInvalidated()
   765 {
   767   nsAutoString textEquiv;
   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);
   779       mCachedTextEquiv = textEquiv;
   780       return true;
   781     }
   783     return false;
   784   }
   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   }
   793   return false;
   794 }
   796 ////////////////////////////////////////////////////////////////////////////////
   797 // XULTreeGridCellAccessible: Accessible protected implementation
   799 Accessible*
   800 XULTreeGridCellAccessible::GetSiblingAtOffset(int32_t aOffset,
   801                                               nsresult* aError) const
   802 {
   803   if (aError)
   804     *aError =  NS_OK; // fail peacefully
   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   }
   819   if (!columnAtOffset)
   820     return nullptr;
   822   nsRefPtr<XULTreeItemAccessibleBase> rowAcc = do_QueryObject(Parent());
   823   return rowAcc->GetCellAccessible(columnAtOffset);
   824 }
   826 void
   827 XULTreeGridCellAccessible::DispatchClickEvent(nsIContent* aContent,
   828                                               uint32_t aActionIndex)
   829 {
   830   if (IsDefunct())
   831     return;
   833   nsCoreUtils::DispatchClickEvent(mTree, mRow, mColumn);
   834 }
   836 ////////////////////////////////////////////////////////////////////////////////
   837 // XULTreeGridCellAccessible: protected implementation
   839 bool
   840 XULTreeGridCellAccessible::IsEditable() const
   841 {
   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;
   850   nsCOMPtr<nsIDOMElement> columnElm;
   851   mColumn->GetElement(getter_AddRefs(columnElm));
   852   if (!columnElm)
   853     return false;
   855   nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
   856   if (!columnContent->AttrValueIs(kNameSpaceID_None,
   857                                   nsGkAtoms::editable,
   858                                   nsGkAtoms::_true,
   859                                   eCaseMatters))
   860     return false;
   862   return mContent->AttrValueIs(kNameSpaceID_None,
   863                                nsGkAtoms::editable,
   864                                nsGkAtoms::_true, eCaseMatters);
   865 }

mercurial