accessible/src/xul/XULTreeGridAccessible.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/accessible/src/xul/XULTreeGridAccessible.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,865 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "XULTreeGridAccessibleWrap.h"
    1.10 +
    1.11 +#include "nsAccCache.h"
    1.12 +#include "nsAccessibilityService.h"
    1.13 +#include "nsAccUtils.h"
    1.14 +#include "DocAccessible.h"
    1.15 +#include "nsEventShell.h"
    1.16 +#include "Relation.h"
    1.17 +#include "Role.h"
    1.18 +#include "States.h"
    1.19 +
    1.20 +#include "nsIBoxObject.h"
    1.21 +#include "nsIMutableArray.h"
    1.22 +#include "nsIPersistentProperties2.h"
    1.23 +#include "nsITreeSelection.h"
    1.24 +#include "nsComponentManagerUtils.h"
    1.25 +
    1.26 +using namespace mozilla::a11y;
    1.27 +
    1.28 +////////////////////////////////////////////////////////////////////////////////
    1.29 +// XULTreeGridAccessible: nsISupports implementation
    1.30 +
    1.31 +NS_IMPL_ISUPPORTS_INHERITED(XULTreeGridAccessible,
    1.32 +                            XULTreeAccessible,
    1.33 +                            nsIAccessibleTable)
    1.34 +
    1.35 +////////////////////////////////////////////////////////////////////////////////
    1.36 +// XULTreeGridAccessible: nsIAccessibleTable implementation
    1.37 +
    1.38 +uint32_t
    1.39 +XULTreeGridAccessible::ColCount()
    1.40 +{
    1.41 +  return nsCoreUtils::GetSensibleColumnCount(mTree);
    1.42 +}
    1.43 +
    1.44 +uint32_t
    1.45 +XULTreeGridAccessible::RowCount()
    1.46 +{
    1.47 +  if (!mTreeView)
    1.48 +    return 0;
    1.49 +
    1.50 +  int32_t rowCount = 0;
    1.51 +  mTreeView->GetRowCount(&rowCount);
    1.52 +  return rowCount >= 0 ? rowCount : 0;
    1.53 +}
    1.54 +
    1.55 +uint32_t
    1.56 +XULTreeGridAccessible::SelectedCellCount()
    1.57 +{
    1.58 +  return SelectedRowCount() * ColCount();
    1.59 +}
    1.60 +
    1.61 +uint32_t
    1.62 +XULTreeGridAccessible::SelectedColCount()
    1.63 +{
    1.64 +  // If all the row has been selected, then all the columns are selected,
    1.65 +  // because we can't select a column alone.
    1.66 +
    1.67 +  uint32_t selectedRowCount = SelectedItemCount();
    1.68 +  return selectedRowCount > 0 && selectedRowCount == RowCount() ? ColCount() : 0;
    1.69 +}
    1.70 +
    1.71 +uint32_t
    1.72 +XULTreeGridAccessible::SelectedRowCount()
    1.73 +{
    1.74 +  return SelectedItemCount();
    1.75 +}
    1.76 +
    1.77 +void
    1.78 +XULTreeGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
    1.79 +{
    1.80 +  uint32_t colCount = ColCount(), rowCount = RowCount();
    1.81 +
    1.82 +  for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
    1.83 +    if (IsRowSelected(rowIdx)) {
    1.84 +      for (uint32_t colIdx = 0; colIdx < colCount; colIdx++) {
    1.85 +        Accessible* cell = CellAt(rowIdx, colIdx);
    1.86 +        aCells->AppendElement(cell);
    1.87 +      }
    1.88 +    }
    1.89 +  }
    1.90 +}
    1.91 +
    1.92 +void
    1.93 +XULTreeGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
    1.94 +{
    1.95 +  uint32_t colCount = ColCount(), rowCount = RowCount();
    1.96 +
    1.97 +  for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++)
    1.98 +    if (IsRowSelected(rowIdx))
    1.99 +      for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
   1.100 +        aCells->AppendElement(rowIdx * colCount + colIdx);
   1.101 +}
   1.102 +
   1.103 +void
   1.104 +XULTreeGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
   1.105 +{
   1.106 +  if (RowCount() != SelectedRowCount())
   1.107 +    return;
   1.108 +
   1.109 +  uint32_t colCount = ColCount();
   1.110 +  aCols->SetCapacity(colCount);
   1.111 +  for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
   1.112 +    aCols->AppendElement(colIdx);
   1.113 +}
   1.114 +
   1.115 +void
   1.116 +XULTreeGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
   1.117 +{
   1.118 +  uint32_t rowCount = RowCount();
   1.119 +  for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++)
   1.120 +    if (IsRowSelected(rowIdx))
   1.121 +      aRows->AppendElement(rowIdx);
   1.122 +}
   1.123 +
   1.124 +Accessible*
   1.125 +XULTreeGridAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
   1.126 +{ 
   1.127 +  Accessible* row = GetTreeItemAccessible(aRowIndex);
   1.128 +  if (!row)
   1.129 +    return nullptr;
   1.130 +
   1.131 +  nsCOMPtr<nsITreeColumn> column =
   1.132 +    nsCoreUtils::GetSensibleColumnAt(mTree, aColumnIndex);
   1.133 +  if (!column)
   1.134 +    return nullptr;
   1.135 +
   1.136 +  nsRefPtr<XULTreeItemAccessibleBase> rowAcc = do_QueryObject(row);
   1.137 +  if (!rowAcc)
   1.138 +    return nullptr;
   1.139 +
   1.140 +  return rowAcc->GetCellAccessible(column);
   1.141 +}
   1.142 +
   1.143 +void
   1.144 +XULTreeGridAccessible::ColDescription(uint32_t aColIdx, nsString& aDescription)
   1.145 +{
   1.146 +  aDescription.Truncate();
   1.147 +
   1.148 +  nsCOMPtr<nsIAccessible> treeColumns;
   1.149 +  Accessible::GetFirstChild(getter_AddRefs(treeColumns));
   1.150 +  if (treeColumns) {
   1.151 +    nsCOMPtr<nsIAccessible> treeColumnItem;
   1.152 +    treeColumns->GetChildAt(aColIdx, getter_AddRefs(treeColumnItem));
   1.153 +    if (treeColumnItem)
   1.154 +      treeColumnItem->GetName(aDescription);
   1.155 +  }
   1.156 +}
   1.157 +
   1.158 +bool
   1.159 +XULTreeGridAccessible::IsColSelected(uint32_t aColIdx)
   1.160 +{
   1.161 +  // If all the row has been selected, then all the columns are selected.
   1.162 +  // Because we can't select a column alone.
   1.163 +  return SelectedItemCount() == RowCount();
   1.164 +}
   1.165 +
   1.166 +bool
   1.167 +XULTreeGridAccessible::IsRowSelected(uint32_t aRowIdx)
   1.168 +{
   1.169 +  if (!mTreeView)
   1.170 +    return false;
   1.171 +
   1.172 +  nsCOMPtr<nsITreeSelection> selection;
   1.173 +  nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
   1.174 +  NS_ENSURE_SUCCESS(rv, false);
   1.175 +
   1.176 +  bool isSelected = false;
   1.177 +  selection->IsSelected(aRowIdx, &isSelected);
   1.178 +  return isSelected;
   1.179 +}
   1.180 +
   1.181 +bool
   1.182 +XULTreeGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
   1.183 +{
   1.184 +  return IsRowSelected(aRowIdx);
   1.185 +}
   1.186 +
   1.187 +void
   1.188 +XULTreeGridAccessible::SelectRow(uint32_t aRowIdx)
   1.189 +{
   1.190 +  if (!mTreeView)
   1.191 +    return;
   1.192 +
   1.193 +  nsCOMPtr<nsITreeSelection> selection;
   1.194 +  mTreeView->GetSelection(getter_AddRefs(selection));
   1.195 +  NS_ASSERTION(selection, "GetSelection() Shouldn't fail!");
   1.196 +
   1.197 +  selection->Select(aRowIdx);
   1.198 +}
   1.199 +
   1.200 +void
   1.201 +XULTreeGridAccessible::UnselectRow(uint32_t aRowIdx)
   1.202 +{
   1.203 +  if (!mTreeView)
   1.204 +    return;
   1.205 +
   1.206 +  nsCOMPtr<nsITreeSelection> selection;
   1.207 +  mTreeView->GetSelection(getter_AddRefs(selection));
   1.208 +
   1.209 +  if (selection)
   1.210 +    selection->ClearRange(aRowIdx, aRowIdx);
   1.211 +}
   1.212 +
   1.213 +////////////////////////////////////////////////////////////////////////////////
   1.214 +// XULTreeGridAccessible: Accessible implementation
   1.215 +
   1.216 +void
   1.217 +XULTreeGridAccessible::Shutdown()
   1.218 +{
   1.219 +  mTable = nullptr;
   1.220 +  XULTreeAccessible::Shutdown();
   1.221 +}
   1.222 +
   1.223 +role
   1.224 +XULTreeGridAccessible::NativeRole()
   1.225 +{
   1.226 +  nsCOMPtr<nsITreeColumns> treeColumns;
   1.227 +  mTree->GetColumns(getter_AddRefs(treeColumns));
   1.228 +  if (!treeColumns) {
   1.229 +    NS_ERROR("No treecolumns object for tree!");
   1.230 +    return roles::NOTHING;
   1.231 +  }
   1.232 +
   1.233 +  nsCOMPtr<nsITreeColumn> primaryColumn;
   1.234 +  treeColumns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
   1.235 +
   1.236 +  return primaryColumn ? roles::TREE_TABLE : roles::TABLE;
   1.237 +}
   1.238 +
   1.239 +////////////////////////////////////////////////////////////////////////////////
   1.240 +// XULTreeGridAccessible: XULTreeAccessible implementation
   1.241 +
   1.242 +already_AddRefed<Accessible>
   1.243 +XULTreeGridAccessible::CreateTreeItemAccessible(int32_t aRow) const
   1.244 +{
   1.245 +  nsRefPtr<Accessible> accessible =
   1.246 +    new XULTreeGridRowAccessible(mContent, mDoc,
   1.247 +                                 const_cast<XULTreeGridAccessible*>(this),
   1.248 +                                 mTree, mTreeView, aRow);
   1.249 +
   1.250 +  return accessible.forget();
   1.251 +}
   1.252 +
   1.253 +
   1.254 +////////////////////////////////////////////////////////////////////////////////
   1.255 +// XULTreeGridRowAccessible
   1.256 +////////////////////////////////////////////////////////////////////////////////
   1.257 +
   1.258 +XULTreeGridRowAccessible::
   1.259 +  XULTreeGridRowAccessible(nsIContent* aContent, DocAccessible* aDoc,
   1.260 +                           Accessible* aTreeAcc, nsITreeBoxObject* aTree,
   1.261 +                           nsITreeView* aTreeView, int32_t aRow) :
   1.262 +  XULTreeItemAccessibleBase(aContent, aDoc, aTreeAcc, aTree, aTreeView, aRow),
   1.263 +  mAccessibleCache(kDefaultTreeCacheSize)
   1.264 +{
   1.265 +  mGenericTypes |= eTableRow;
   1.266 +}
   1.267 +
   1.268 +////////////////////////////////////////////////////////////////////////////////
   1.269 +// XULTreeGridRowAccessible: nsISupports and cycle collection implementation
   1.270 +
   1.271 +NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible,
   1.272 +                                   XULTreeItemAccessibleBase,
   1.273 +                                   mAccessibleCache)
   1.274 +
   1.275 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeGridRowAccessible)
   1.276 +NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
   1.277 +
   1.278 +NS_IMPL_ADDREF_INHERITED(XULTreeGridRowAccessible,
   1.279 +                         XULTreeItemAccessibleBase)
   1.280 +NS_IMPL_RELEASE_INHERITED(XULTreeGridRowAccessible,
   1.281 +                          XULTreeItemAccessibleBase)
   1.282 +
   1.283 +////////////////////////////////////////////////////////////////////////////////
   1.284 +// XULTreeGridRowAccessible: Accessible implementation
   1.285 +
   1.286 +void
   1.287 +XULTreeGridRowAccessible::Shutdown()
   1.288 +{
   1.289 +  ClearCache(mAccessibleCache);
   1.290 +  XULTreeItemAccessibleBase::Shutdown();
   1.291 +}
   1.292 +
   1.293 +role
   1.294 +XULTreeGridRowAccessible::NativeRole()
   1.295 +{
   1.296 +  return roles::ROW;
   1.297 +}
   1.298 +
   1.299 +ENameValueFlag
   1.300 +XULTreeGridRowAccessible::Name(nsString& aName)
   1.301 +{
   1.302 +  aName.Truncate();
   1.303 +
   1.304 +  // XXX: the row name sholdn't be a concatenation of cell names (bug 664384).
   1.305 +  nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
   1.306 +  while (column) {
   1.307 +    if (!aName.IsEmpty())
   1.308 +      aName.AppendLiteral(" ");
   1.309 +
   1.310 +    nsAutoString cellName;
   1.311 +    GetCellName(column, cellName);
   1.312 +    aName.Append(cellName);
   1.313 +
   1.314 +    column = nsCoreUtils::GetNextSensibleColumn(column);
   1.315 +  }
   1.316 +
   1.317 +  return eNameOK;
   1.318 +}
   1.319 +
   1.320 +Accessible*
   1.321 +XULTreeGridRowAccessible::ChildAtPoint(int32_t aX, int32_t aY,
   1.322 +                                       EWhichChildAtPoint aWhichChild)
   1.323 +{
   1.324 +  nsIFrame *frame = GetFrame();
   1.325 +  if (!frame)
   1.326 +    return nullptr;
   1.327 +
   1.328 +  nsPresContext *presContext = frame->PresContext();
   1.329 +  nsIPresShell* presShell = presContext->PresShell();
   1.330 +
   1.331 +  nsIFrame *rootFrame = presShell->GetRootFrame();
   1.332 +  NS_ENSURE_TRUE(rootFrame, nullptr);
   1.333 +
   1.334 +  nsIntRect rootRect = rootFrame->GetScreenRect();
   1.335 +
   1.336 +  int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
   1.337 +  int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
   1.338 +
   1.339 +  int32_t row = -1;
   1.340 +  nsCOMPtr<nsITreeColumn> column;
   1.341 +  nsAutoCString childEltUnused;
   1.342 +  mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
   1.343 +                   childEltUnused);
   1.344 +
   1.345 +  // Return if we failed to find tree cell in the row for the given point.
   1.346 +  if (row != mRow || !column)
   1.347 +    return nullptr;
   1.348 +
   1.349 +  return GetCellAccessible(column);
   1.350 +}
   1.351 +
   1.352 +Accessible*
   1.353 +XULTreeGridRowAccessible::GetChildAt(uint32_t aIndex) const
   1.354 +{
   1.355 +  if (IsDefunct())
   1.356 +    return nullptr;
   1.357 +
   1.358 +  nsCOMPtr<nsITreeColumn> column =
   1.359 +    nsCoreUtils::GetSensibleColumnAt(mTree, aIndex);
   1.360 +  if (!column)
   1.361 +    return nullptr;
   1.362 +
   1.363 +  return GetCellAccessible(column);
   1.364 +}
   1.365 +
   1.366 +uint32_t
   1.367 +XULTreeGridRowAccessible::ChildCount() const
   1.368 +{
   1.369 +  return nsCoreUtils::GetSensibleColumnCount(mTree);
   1.370 +}
   1.371 +
   1.372 +////////////////////////////////////////////////////////////////////////////////
   1.373 +// XULTreeGridRowAccessible: XULTreeItemAccessibleBase implementation
   1.374 +
   1.375 +Accessible*
   1.376 +XULTreeGridRowAccessible::GetCellAccessible(nsITreeColumn* aColumn) const
   1.377 +{
   1.378 +  NS_PRECONDITION(aColumn, "No tree column!");
   1.379 +
   1.380 +  void* key = static_cast<void*>(aColumn);
   1.381 +  Accessible* cachedCell = mAccessibleCache.GetWeak(key);
   1.382 +  if (cachedCell)
   1.383 +    return cachedCell;
   1.384 +
   1.385 +  nsRefPtr<Accessible> cell =
   1.386 +    new XULTreeGridCellAccessibleWrap(mContent, mDoc,
   1.387 +                                      const_cast<XULTreeGridRowAccessible*>(this),
   1.388 +                                      mTree, mTreeView, mRow, aColumn);
   1.389 +  mAccessibleCache.Put(key, cell);
   1.390 +  Document()->BindToDocument(cell, nullptr);
   1.391 +  return cell;
   1.392 +}
   1.393 +
   1.394 +void
   1.395 +XULTreeGridRowAccessible::RowInvalidated(int32_t aStartColIdx,
   1.396 +                                         int32_t aEndColIdx)
   1.397 +{
   1.398 +  nsCOMPtr<nsITreeColumns> treeColumns;
   1.399 +  mTree->GetColumns(getter_AddRefs(treeColumns));
   1.400 +  if (!treeColumns)
   1.401 +    return;
   1.402 +
   1.403 +  bool nameChanged = false;
   1.404 +  for (int32_t colIdx = aStartColIdx; colIdx <= aEndColIdx; ++colIdx) {
   1.405 +    nsCOMPtr<nsITreeColumn> column;
   1.406 +    treeColumns->GetColumnAt(colIdx, getter_AddRefs(column));
   1.407 +    if (column && !nsCoreUtils::IsColumnHidden(column)) {
   1.408 +      Accessible* cellAccessible = GetCellAccessible(column);
   1.409 +      if (cellAccessible) {
   1.410 +        nsRefPtr<XULTreeGridCellAccessible> cellAcc = do_QueryObject(cellAccessible);
   1.411 +
   1.412 +        nameChanged |= cellAcc->CellInvalidated();
   1.413 +      }
   1.414 +    }
   1.415 +  }
   1.416 +
   1.417 +  if (nameChanged)
   1.418 +    nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
   1.419 +
   1.420 +}
   1.421 +
   1.422 +////////////////////////////////////////////////////////////////////////////////
   1.423 +// XULTreeGridRowAccessible: Accessible protected implementation
   1.424 +
   1.425 +void
   1.426 +XULTreeGridRowAccessible::CacheChildren()
   1.427 +{
   1.428 +}
   1.429 +
   1.430 +////////////////////////////////////////////////////////////////////////////////
   1.431 +// XULTreeGridCellAccessible
   1.432 +////////////////////////////////////////////////////////////////////////////////
   1.433 +
   1.434 +XULTreeGridCellAccessible::
   1.435 +  XULTreeGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc,
   1.436 +                            XULTreeGridRowAccessible* aRowAcc,
   1.437 +                            nsITreeBoxObject* aTree, nsITreeView* aTreeView,
   1.438 +                            int32_t aRow, nsITreeColumn* aColumn) :
   1.439 +  LeafAccessible(aContent, aDoc), xpcAccessibleTableCell(this), mTree(aTree),
   1.440 +  mTreeView(aTreeView), mRow(aRow), mColumn(aColumn)
   1.441 +{
   1.442 +  mParent = aRowAcc;
   1.443 +  mStateFlags |= eSharedNode;
   1.444 +  mGenericTypes |= eTableCell;
   1.445 +
   1.446 +  NS_ASSERTION(mTreeView, "mTreeView is null");
   1.447 +
   1.448 +  int16_t type = -1;
   1.449 +  mColumn->GetType(&type);
   1.450 +  if (type == nsITreeColumn::TYPE_CHECKBOX)
   1.451 +    mTreeView->GetCellValue(mRow, mColumn, mCachedTextEquiv);
   1.452 +  else
   1.453 +    mTreeView->GetCellText(mRow, mColumn, mCachedTextEquiv);
   1.454 +}
   1.455 +
   1.456 +////////////////////////////////////////////////////////////////////////////////
   1.457 +// XULTreeGridCellAccessible: nsISupports implementation
   1.458 +
   1.459 +NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible, LeafAccessible,
   1.460 +                                   mTree, mColumn)
   1.461 +
   1.462 +NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeGridCellAccessible)
   1.463 +  NS_INTERFACE_TABLE_INHERITED(XULTreeGridCellAccessible,
   1.464 +                               nsIAccessibleTableCell,
   1.465 +                               XULTreeGridCellAccessible)
   1.466 +NS_INTERFACE_TABLE_TAIL_INHERITING(LeafAccessible)
   1.467 +NS_IMPL_ADDREF_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
   1.468 +NS_IMPL_RELEASE_INHERITED(XULTreeGridCellAccessible, LeafAccessible)
   1.469 +
   1.470 +////////////////////////////////////////////////////////////////////////////////
   1.471 +// XULTreeGridCellAccessible: nsIAccessible implementation
   1.472 +
   1.473 +void
   1.474 +XULTreeGridCellAccessible::Shutdown()
   1.475 +{
   1.476 +  mTableCell = nullptr;
   1.477 +  LeafAccessible::Shutdown();
   1.478 +}
   1.479 +
   1.480 +Accessible*
   1.481 +XULTreeGridCellAccessible::FocusedChild()
   1.482 +{
   1.483 +  return nullptr;
   1.484 +}
   1.485 +
   1.486 +ENameValueFlag
   1.487 +XULTreeGridCellAccessible::Name(nsString& aName)
   1.488 +{
   1.489 +  aName.Truncate();
   1.490 +
   1.491 +  if (!mTreeView)
   1.492 +    return eNameOK;
   1.493 +
   1.494 +  mTreeView->GetCellText(mRow, mColumn, aName);
   1.495 +
   1.496 +  // If there is still no name try the cell value:
   1.497 +  // This is for graphical cells. We need tree/table view implementors to implement
   1.498 +  // FooView::GetCellValue to return a meaningful string for cases where there is
   1.499 +  // something shown in the cell (non-text) such as a star icon; in which case
   1.500 +  // GetCellValue for that cell would return "starred" or "flagged" for example.
   1.501 +  if (aName.IsEmpty())
   1.502 +    mTreeView->GetCellValue(mRow, mColumn, aName);
   1.503 +
   1.504 +  return eNameOK;
   1.505 +}
   1.506 +
   1.507 +NS_IMETHODIMP
   1.508 +XULTreeGridCellAccessible::GetBounds(int32_t* aX, int32_t* aY,
   1.509 +                                     int32_t* aWidth, int32_t* aHeight)
   1.510 +{
   1.511 +  NS_ENSURE_ARG_POINTER(aX);
   1.512 +  *aX = 0;
   1.513 +  NS_ENSURE_ARG_POINTER(aY);
   1.514 +  *aY = 0;
   1.515 +  NS_ENSURE_ARG_POINTER(aWidth);
   1.516 +  *aWidth = 0;
   1.517 +  NS_ENSURE_ARG_POINTER(aHeight);
   1.518 +  *aHeight = 0;
   1.519 +
   1.520 +  if (IsDefunct())
   1.521 +    return NS_ERROR_FAILURE;
   1.522 +
   1.523 +  // Get bounds for tree cell and add x and y of treechildren element to
   1.524 +  // x and y of the cell.
   1.525 +  nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
   1.526 +  NS_ENSURE_STATE(boxObj);
   1.527 +
   1.528 +  int32_t x = 0, y = 0, width = 0, height = 0;
   1.529 +  nsresult rv = mTree->GetCoordsForCellItem(mRow, mColumn,
   1.530 +                                            NS_LITERAL_CSTRING("cell"),
   1.531 +                                            &x, &y, &width, &height);
   1.532 +  NS_ENSURE_SUCCESS(rv, rv);
   1.533 +
   1.534 +  int32_t tcX = 0, tcY = 0;
   1.535 +  boxObj->GetScreenX(&tcX);
   1.536 +  boxObj->GetScreenY(&tcY);
   1.537 +  x += tcX;
   1.538 +  y += tcY;
   1.539 +
   1.540 +  nsPresContext* presContext = mDoc->PresContext();
   1.541 +  *aX = presContext->CSSPixelsToDevPixels(x);
   1.542 +  *aY = presContext->CSSPixelsToDevPixels(y);
   1.543 +  *aWidth = presContext->CSSPixelsToDevPixels(width);
   1.544 +  *aHeight = presContext->CSSPixelsToDevPixels(height);
   1.545 +
   1.546 +  return NS_OK;
   1.547 +}
   1.548 +
   1.549 +uint8_t
   1.550 +XULTreeGridCellAccessible::ActionCount()
   1.551 +{
   1.552 +  bool isCycler = false;
   1.553 +  mColumn->GetCycler(&isCycler);
   1.554 +  if (isCycler)
   1.555 +    return 1;
   1.556 +
   1.557 +  int16_t type;
   1.558 +  mColumn->GetType(&type);
   1.559 +  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable())
   1.560 +    return 1;
   1.561 +
   1.562 +  return 0;
   1.563 +}
   1.564 +
   1.565 +NS_IMETHODIMP
   1.566 +XULTreeGridCellAccessible::GetActionName(uint8_t aIndex, nsAString& aName)
   1.567 +{
   1.568 +  aName.Truncate();
   1.569 +
   1.570 +  if (aIndex != eAction_Click)
   1.571 +    return NS_ERROR_INVALID_ARG;
   1.572 +
   1.573 +  if (IsDefunct() || !mTreeView)
   1.574 +    return NS_ERROR_FAILURE;
   1.575 +
   1.576 +  bool isCycler = false;
   1.577 +  mColumn->GetCycler(&isCycler);
   1.578 +  if (isCycler) {
   1.579 +    aName.AssignLiteral("cycle");
   1.580 +    return NS_OK;
   1.581 +  }
   1.582 +
   1.583 +  int16_t type;
   1.584 +  mColumn->GetType(&type);
   1.585 +  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
   1.586 +    nsAutoString value;
   1.587 +    mTreeView->GetCellValue(mRow, mColumn, value);
   1.588 +    if (value.EqualsLiteral("true"))
   1.589 +      aName.AssignLiteral("uncheck");
   1.590 +    else
   1.591 +      aName.AssignLiteral("check");
   1.592 +
   1.593 +    return NS_OK;
   1.594 +  }
   1.595 +
   1.596 +  return NS_ERROR_INVALID_ARG;
   1.597 +}
   1.598 +
   1.599 +NS_IMETHODIMP
   1.600 +XULTreeGridCellAccessible::DoAction(uint8_t aIndex)
   1.601 +{
   1.602 +  if (aIndex != eAction_Click)
   1.603 +    return NS_ERROR_INVALID_ARG;
   1.604 +
   1.605 +  if (IsDefunct())
   1.606 +    return NS_ERROR_FAILURE;
   1.607 +
   1.608 +  bool isCycler = false;
   1.609 +  mColumn->GetCycler(&isCycler);
   1.610 +  if (isCycler) {
   1.611 +    DoCommand();
   1.612 +    return NS_OK;
   1.613 +  }
   1.614 +
   1.615 +  int16_t type;
   1.616 +  mColumn->GetType(&type);
   1.617 +  if (type == nsITreeColumn::TYPE_CHECKBOX && IsEditable()) {
   1.618 +    DoCommand();
   1.619 +    return NS_OK;
   1.620 +  }
   1.621 +
   1.622 +  return NS_ERROR_INVALID_ARG;
   1.623 +}
   1.624 +
   1.625 +////////////////////////////////////////////////////////////////////////////////
   1.626 +// XULTreeGridCellAccessible: nsIAccessibleTableCell implementation
   1.627 +
   1.628 +TableAccessible*
   1.629 +XULTreeGridCellAccessible::Table() const
   1.630 +{
   1.631 +  Accessible* grandParent = mParent->Parent();
   1.632 +  if (grandParent)
   1.633 +    return grandParent->AsTable();
   1.634 +
   1.635 +  return nullptr;
   1.636 +}
   1.637 +
   1.638 +uint32_t
   1.639 +XULTreeGridCellAccessible::ColIdx() const
   1.640 +{
   1.641 +  uint32_t colIdx = 0;
   1.642 +  nsCOMPtr<nsITreeColumn> column = mColumn;
   1.643 +  while ((column = nsCoreUtils::GetPreviousSensibleColumn(column)))
   1.644 +    colIdx++;
   1.645 +
   1.646 +  return colIdx;
   1.647 +}
   1.648 +
   1.649 +uint32_t
   1.650 +XULTreeGridCellAccessible::RowIdx() const
   1.651 +{
   1.652 +  return mRow;
   1.653 +}
   1.654 +
   1.655 +void
   1.656 +XULTreeGridCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aHeaderCells)
   1.657 +{
   1.658 +  nsCOMPtr<nsIDOMElement> columnElm;
   1.659 +  mColumn->GetElement(getter_AddRefs(columnElm));
   1.660 +
   1.661 +  nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
   1.662 +  Accessible* headerCell = mDoc->GetAccessible(columnContent);
   1.663 +  if (headerCell)
   1.664 +    aHeaderCells->AppendElement(headerCell);
   1.665 +}
   1.666 +
   1.667 +bool
   1.668 +XULTreeGridCellAccessible::Selected()
   1.669 +{
   1.670 +  nsCOMPtr<nsITreeSelection> selection;
   1.671 +  nsresult rv = mTreeView->GetSelection(getter_AddRefs(selection));
   1.672 +  NS_ENSURE_SUCCESS(rv, false);
   1.673 +
   1.674 +  bool selected = false;
   1.675 +  selection->IsSelected(mRow, &selected);
   1.676 +  return selected;
   1.677 +}
   1.678 +
   1.679 +////////////////////////////////////////////////////////////////////////////////
   1.680 +// XULTreeGridCellAccessible: Accessible public implementation
   1.681 +
   1.682 +already_AddRefed<nsIPersistentProperties>
   1.683 +XULTreeGridCellAccessible::NativeAttributes()
   1.684 +{
   1.685 +  nsCOMPtr<nsIPersistentProperties> attributes =
   1.686 +    do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
   1.687 +
   1.688 +  // "table-cell-index" attribute
   1.689 +  TableAccessible* table = Table();
   1.690 +  if (!table)
   1.691 +    return attributes.forget();
   1.692 +
   1.693 +  nsAutoString stringIdx;
   1.694 +  stringIdx.AppendInt(table->CellIndexAt(mRow, ColIdx()));
   1.695 +  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
   1.696 +
   1.697 +  // "cycles" attribute
   1.698 +  bool isCycler = false;
   1.699 +  nsresult rv = mColumn->GetCycler(&isCycler);
   1.700 +  if (NS_SUCCEEDED(rv) && isCycler)
   1.701 +    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::cycles,
   1.702 +                           NS_LITERAL_STRING("true"));
   1.703 +
   1.704 +  return attributes.forget();
   1.705 +}
   1.706 +
   1.707 +role
   1.708 +XULTreeGridCellAccessible::NativeRole()
   1.709 +{
   1.710 +  return roles::GRID_CELL;
   1.711 +}
   1.712 +
   1.713 +uint64_t
   1.714 +XULTreeGridCellAccessible::NativeState()
   1.715 +{
   1.716 +  if (!mTreeView)
   1.717 +    return states::DEFUNCT;
   1.718 +
   1.719 +  // selectable/selected state
   1.720 +  uint64_t states = states::SELECTABLE; // keep in sync with NativeInteractiveState
   1.721 +
   1.722 +  nsCOMPtr<nsITreeSelection> selection;
   1.723 +  mTreeView->GetSelection(getter_AddRefs(selection));
   1.724 +  if (selection) {
   1.725 +    bool isSelected = false;
   1.726 +    selection->IsSelected(mRow, &isSelected);
   1.727 +    if (isSelected)
   1.728 +      states |= states::SELECTED;
   1.729 +  }
   1.730 +
   1.731 +  // checked state
   1.732 +  int16_t type;
   1.733 +  mColumn->GetType(&type);
   1.734 +  if (type == nsITreeColumn::TYPE_CHECKBOX) {
   1.735 +    states |= states::CHECKABLE;
   1.736 +    nsAutoString checked;
   1.737 +    mTreeView->GetCellValue(mRow, mColumn, checked);
   1.738 +    if (checked.EqualsIgnoreCase("true"))
   1.739 +      states |= states::CHECKED;
   1.740 +  }
   1.741 +
   1.742 +  return states;
   1.743 +}
   1.744 +
   1.745 +uint64_t
   1.746 +XULTreeGridCellAccessible::NativeInteractiveState() const
   1.747 +{
   1.748 +  return states::SELECTABLE;
   1.749 +}
   1.750 +
   1.751 +int32_t
   1.752 +XULTreeGridCellAccessible::IndexInParent() const
   1.753 +{
   1.754 +  return ColIdx();
   1.755 +}
   1.756 +
   1.757 +Relation
   1.758 +XULTreeGridCellAccessible::RelationByType(RelationType aType)
   1.759 +{
   1.760 +  return Relation();
   1.761 +}
   1.762 +
   1.763 +////////////////////////////////////////////////////////////////////////////////
   1.764 +// XULTreeGridCellAccessible: public implementation
   1.765 +
   1.766 +bool
   1.767 +XULTreeGridCellAccessible::CellInvalidated()
   1.768 +{
   1.769 +
   1.770 +  nsAutoString textEquiv;
   1.771 +
   1.772 +  int16_t type;
   1.773 +  mColumn->GetType(&type);
   1.774 +  if (type == nsITreeColumn::TYPE_CHECKBOX) {
   1.775 +    mTreeView->GetCellValue(mRow, mColumn, textEquiv);
   1.776 +    if (mCachedTextEquiv != textEquiv) {
   1.777 +      bool isEnabled = textEquiv.EqualsLiteral("true");
   1.778 +      nsRefPtr<AccEvent> accEvent =
   1.779 +        new AccStateChangeEvent(this, states::CHECKED, isEnabled);
   1.780 +      nsEventShell::FireEvent(accEvent);
   1.781 +
   1.782 +      mCachedTextEquiv = textEquiv;
   1.783 +      return true;
   1.784 +    }
   1.785 +
   1.786 +    return false;
   1.787 +  }
   1.788 +
   1.789 +  mTreeView->GetCellText(mRow, mColumn, textEquiv);
   1.790 +  if (mCachedTextEquiv != textEquiv) {
   1.791 +    nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
   1.792 +    mCachedTextEquiv = textEquiv;
   1.793 +    return true;
   1.794 +  }
   1.795 +
   1.796 +  return false;
   1.797 +}
   1.798 +
   1.799 +////////////////////////////////////////////////////////////////////////////////
   1.800 +// XULTreeGridCellAccessible: Accessible protected implementation
   1.801 +
   1.802 +Accessible*
   1.803 +XULTreeGridCellAccessible::GetSiblingAtOffset(int32_t aOffset,
   1.804 +                                              nsresult* aError) const
   1.805 +{
   1.806 +  if (aError)
   1.807 +    *aError =  NS_OK; // fail peacefully
   1.808 +
   1.809 +  nsCOMPtr<nsITreeColumn> columnAtOffset(mColumn), column;
   1.810 +  if (aOffset < 0) {
   1.811 +    for (int32_t index = aOffset; index < 0 && columnAtOffset; index++) {
   1.812 +      column = nsCoreUtils::GetPreviousSensibleColumn(columnAtOffset);
   1.813 +      column.swap(columnAtOffset);
   1.814 +    }
   1.815 +  } else {
   1.816 +    for (int32_t index = aOffset; index > 0 && columnAtOffset; index--) {
   1.817 +      column = nsCoreUtils::GetNextSensibleColumn(columnAtOffset);
   1.818 +      column.swap(columnAtOffset);
   1.819 +    }
   1.820 +  }
   1.821 +
   1.822 +  if (!columnAtOffset)
   1.823 +    return nullptr;
   1.824 +
   1.825 +  nsRefPtr<XULTreeItemAccessibleBase> rowAcc = do_QueryObject(Parent());
   1.826 +  return rowAcc->GetCellAccessible(columnAtOffset);
   1.827 +}
   1.828 +
   1.829 +void
   1.830 +XULTreeGridCellAccessible::DispatchClickEvent(nsIContent* aContent,
   1.831 +                                              uint32_t aActionIndex)
   1.832 +{
   1.833 +  if (IsDefunct())
   1.834 +    return;
   1.835 +
   1.836 +  nsCoreUtils::DispatchClickEvent(mTree, mRow, mColumn);
   1.837 +}
   1.838 +
   1.839 +////////////////////////////////////////////////////////////////////////////////
   1.840 +// XULTreeGridCellAccessible: protected implementation
   1.841 +
   1.842 +bool
   1.843 +XULTreeGridCellAccessible::IsEditable() const
   1.844 +{
   1.845 +
   1.846 +  // XXX: logic corresponds to tree.xml, it's preferable to have interface
   1.847 +  // method to check it.
   1.848 +  bool isEditable = false;
   1.849 +  nsresult rv = mTreeView->IsEditable(mRow, mColumn, &isEditable);
   1.850 +  if (NS_FAILED(rv) || !isEditable)
   1.851 +    return false;
   1.852 +
   1.853 +  nsCOMPtr<nsIDOMElement> columnElm;
   1.854 +  mColumn->GetElement(getter_AddRefs(columnElm));
   1.855 +  if (!columnElm)
   1.856 +    return false;
   1.857 +
   1.858 +  nsCOMPtr<nsIContent> columnContent(do_QueryInterface(columnElm));
   1.859 +  if (!columnContent->AttrValueIs(kNameSpaceID_None,
   1.860 +                                  nsGkAtoms::editable,
   1.861 +                                  nsGkAtoms::_true,
   1.862 +                                  eCaseMatters))
   1.863 +    return false;
   1.864 +
   1.865 +  return mContent->AttrValueIs(kNameSpaceID_None,
   1.866 +                               nsGkAtoms::editable,
   1.867 +                               nsGkAtoms::_true, eCaseMatters);
   1.868 +}

mercurial