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 +}