accessible/src/xul/XULTreeAccessible.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set ts=2 et sw=2 tw=80: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "XULTreeAccessible.h"
michael@0 8
michael@0 9 #include "Accessible-inl.h"
michael@0 10 #include "DocAccessible-inl.h"
michael@0 11 #include "nsAccCache.h"
michael@0 12 #include "nsAccUtils.h"
michael@0 13 #include "nsCoreUtils.h"
michael@0 14 #include "nsEventShell.h"
michael@0 15 #include "DocAccessible.h"
michael@0 16 #include "Relation.h"
michael@0 17 #include "Role.h"
michael@0 18 #include "States.h"
michael@0 19
michael@0 20 #include "nsComponentManagerUtils.h"
michael@0 21 #include "nsIAccessibleRelation.h"
michael@0 22 #include "nsIAutoCompleteInput.h"
michael@0 23 #include "nsIAutoCompletePopup.h"
michael@0 24 #include "nsIBoxObject.h"
michael@0 25 #include "nsIDOMXULElement.h"
michael@0 26 #include "nsIDOMXULMenuListElement.h"
michael@0 27 #include "nsIDOMXULMultSelectCntrlEl.h"
michael@0 28 #include "nsIDOMXULTreeElement.h"
michael@0 29 #include "nsITreeSelection.h"
michael@0 30 #include "nsIMutableArray.h"
michael@0 31 #include "nsTreeBodyFrame.h"
michael@0 32 #include "nsTreeColumns.h"
michael@0 33 #include "nsTreeUtils.h"
michael@0 34
michael@0 35 using namespace mozilla::a11y;
michael@0 36
michael@0 37 ////////////////////////////////////////////////////////////////////////////////
michael@0 38 // XULTreeAccessible
michael@0 39 ////////////////////////////////////////////////////////////////////////////////
michael@0 40
michael@0 41 XULTreeAccessible::
michael@0 42 XULTreeAccessible(nsIContent* aContent, DocAccessible* aDoc,
michael@0 43 nsTreeBodyFrame* aTreeFrame) :
michael@0 44 AccessibleWrap(aContent, aDoc),
michael@0 45 mAccessibleCache(kDefaultTreeCacheSize)
michael@0 46 {
michael@0 47 mType = eXULTreeType;
michael@0 48 mGenericTypes |= eSelect;
michael@0 49
michael@0 50 nsCOMPtr<nsITreeView> view = aTreeFrame->GetExistingView();
michael@0 51 mTreeView = view;
michael@0 52
michael@0 53 mTree = nsCoreUtils::GetTreeBoxObject(aContent);
michael@0 54 NS_ASSERTION(mTree, "Can't get mTree!\n");
michael@0 55
michael@0 56 nsIContent* parentContent = mContent->GetParent();
michael@0 57 if (parentContent) {
michael@0 58 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
michael@0 59 do_QueryInterface(parentContent);
michael@0 60 if (autoCompletePopupElm)
michael@0 61 mGenericTypes |= eAutoCompletePopup;
michael@0 62 }
michael@0 63 }
michael@0 64
michael@0 65 ////////////////////////////////////////////////////////////////////////////////
michael@0 66 // XULTreeAccessible: nsISupports and cycle collection implementation
michael@0 67
michael@0 68 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeAccessible, Accessible,
michael@0 69 mTree, mAccessibleCache)
michael@0 70
michael@0 71 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeAccessible)
michael@0 72 NS_INTERFACE_MAP_END_INHERITING(Accessible)
michael@0 73
michael@0 74 NS_IMPL_ADDREF_INHERITED(XULTreeAccessible, Accessible)
michael@0 75 NS_IMPL_RELEASE_INHERITED(XULTreeAccessible, Accessible)
michael@0 76
michael@0 77 ////////////////////////////////////////////////////////////////////////////////
michael@0 78 // XULTreeAccessible: Accessible implementation
michael@0 79
michael@0 80 uint64_t
michael@0 81 XULTreeAccessible::NativeState()
michael@0 82 {
michael@0 83 // Get focus status from base class.
michael@0 84 uint64_t state = Accessible::NativeState();
michael@0 85
michael@0 86 // readonly state
michael@0 87 state |= states::READONLY;
michael@0 88
michael@0 89 // multiselectable state.
michael@0 90 if (!mTreeView)
michael@0 91 return state;
michael@0 92
michael@0 93 nsCOMPtr<nsITreeSelection> selection;
michael@0 94 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 95 NS_ENSURE_TRUE(selection, state);
michael@0 96
michael@0 97 bool isSingle = false;
michael@0 98 nsresult rv = selection->GetSingle(&isSingle);
michael@0 99 NS_ENSURE_SUCCESS(rv, state);
michael@0 100
michael@0 101 if (!isSingle)
michael@0 102 state |= states::MULTISELECTABLE;
michael@0 103
michael@0 104 return state;
michael@0 105 }
michael@0 106
michael@0 107 void
michael@0 108 XULTreeAccessible::Value(nsString& aValue)
michael@0 109 {
michael@0 110 aValue.Truncate();
michael@0 111 if (!mTreeView)
michael@0 112 return;
michael@0 113
michael@0 114 // Return the value is the first selected child.
michael@0 115 nsCOMPtr<nsITreeSelection> selection;
michael@0 116 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 117 if (!selection)
michael@0 118 return;
michael@0 119
michael@0 120 int32_t currentIndex;
michael@0 121 nsCOMPtr<nsIDOMElement> selectItem;
michael@0 122 selection->GetCurrentIndex(&currentIndex);
michael@0 123 if (currentIndex >= 0) {
michael@0 124 nsCOMPtr<nsITreeColumn> keyCol;
michael@0 125
michael@0 126 nsCOMPtr<nsITreeColumns> cols;
michael@0 127 mTree->GetColumns(getter_AddRefs(cols));
michael@0 128 if (cols)
michael@0 129 cols->GetKeyColumn(getter_AddRefs(keyCol));
michael@0 130
michael@0 131 mTreeView->GetCellText(currentIndex, keyCol, aValue);
michael@0 132 }
michael@0 133
michael@0 134 }
michael@0 135
michael@0 136 ////////////////////////////////////////////////////////////////////////////////
michael@0 137 // XULTreeAccessible: Accessible implementation
michael@0 138
michael@0 139 void
michael@0 140 XULTreeAccessible::Shutdown()
michael@0 141 {
michael@0 142 // XXX: we don't remove accessible from document cache if shutdown wasn't
michael@0 143 // initiated by document destroying. Note, we can't remove accessible from
michael@0 144 // document cache here while document is going to be shutdown. Note, this is
michael@0 145 // not unique place where we have similar problem.
michael@0 146 ClearCache(mAccessibleCache);
michael@0 147
michael@0 148 mTree = nullptr;
michael@0 149 mTreeView = nullptr;
michael@0 150
michael@0 151 AccessibleWrap::Shutdown();
michael@0 152 }
michael@0 153
michael@0 154 role
michael@0 155 XULTreeAccessible::NativeRole()
michael@0 156 {
michael@0 157 // No primary column means we're in a list. In fact, history and mail turn off
michael@0 158 // the primary flag when switching to a flat view.
michael@0 159
michael@0 160 nsIContent* child = nsTreeUtils::GetDescendantChild(mContent, nsGkAtoms::treechildren);
michael@0 161 NS_ASSERTION(child, "tree without treechildren!");
michael@0 162 nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame());
michael@0 163 NS_ASSERTION(treeFrame, "xul tree accessible for tree without a frame!");
michael@0 164 if (!treeFrame)
michael@0 165 return roles::LIST;
michael@0 166
michael@0 167 nsRefPtr<nsTreeColumns> cols = treeFrame->Columns();
michael@0 168 nsCOMPtr<nsITreeColumn> primaryCol;
michael@0 169 cols->GetPrimaryColumn(getter_AddRefs(primaryCol));
michael@0 170
michael@0 171 return primaryCol ? roles::OUTLINE : roles::LIST;
michael@0 172 }
michael@0 173
michael@0 174 ////////////////////////////////////////////////////////////////////////////////
michael@0 175 // XULTreeAccessible: Accessible implementation (DON'T put methods here)
michael@0 176
michael@0 177 Accessible*
michael@0 178 XULTreeAccessible::ChildAtPoint(int32_t aX, int32_t aY,
michael@0 179 EWhichChildAtPoint aWhichChild)
michael@0 180 {
michael@0 181 nsIFrame *frame = GetFrame();
michael@0 182 if (!frame)
michael@0 183 return nullptr;
michael@0 184
michael@0 185 nsPresContext *presContext = frame->PresContext();
michael@0 186 nsIPresShell* presShell = presContext->PresShell();
michael@0 187
michael@0 188 nsIFrame *rootFrame = presShell->GetRootFrame();
michael@0 189 NS_ENSURE_TRUE(rootFrame, nullptr);
michael@0 190
michael@0 191 nsIntRect rootRect = rootFrame->GetScreenRect();
michael@0 192
michael@0 193 int32_t clientX = presContext->DevPixelsToIntCSSPixels(aX) - rootRect.x;
michael@0 194 int32_t clientY = presContext->DevPixelsToIntCSSPixels(aY) - rootRect.y;
michael@0 195
michael@0 196 int32_t row = -1;
michael@0 197 nsCOMPtr<nsITreeColumn> column;
michael@0 198 nsAutoCString childEltUnused;
michael@0 199 mTree->GetCellAt(clientX, clientY, &row, getter_AddRefs(column),
michael@0 200 childEltUnused);
michael@0 201
michael@0 202 // If we failed to find tree cell for the given point then it might be
michael@0 203 // tree columns.
michael@0 204 if (row == -1 || !column)
michael@0 205 return AccessibleWrap::ChildAtPoint(aX, aY, aWhichChild);
michael@0 206
michael@0 207 Accessible* child = GetTreeItemAccessible(row);
michael@0 208 if (aWhichChild == eDeepestChild && child) {
michael@0 209 // Look for accessible cell for the found item accessible.
michael@0 210 nsRefPtr<XULTreeItemAccessibleBase> treeitem = do_QueryObject(child);
michael@0 211
michael@0 212 Accessible* cell = treeitem->GetCellAccessible(column);
michael@0 213 if (cell)
michael@0 214 child = cell;
michael@0 215 }
michael@0 216
michael@0 217 return child;
michael@0 218 }
michael@0 219
michael@0 220 ////////////////////////////////////////////////////////////////////////////////
michael@0 221 // XULTreeAccessible: SelectAccessible
michael@0 222
michael@0 223 Accessible*
michael@0 224 XULTreeAccessible::CurrentItem()
michael@0 225 {
michael@0 226 if (!mTreeView)
michael@0 227 return nullptr;
michael@0 228
michael@0 229 nsCOMPtr<nsITreeSelection> selection;
michael@0 230 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 231 if (selection) {
michael@0 232 int32_t currentIndex = -1;
michael@0 233 selection->GetCurrentIndex(&currentIndex);
michael@0 234 if (currentIndex >= 0)
michael@0 235 return GetTreeItemAccessible(currentIndex);
michael@0 236 }
michael@0 237
michael@0 238 return nullptr;
michael@0 239 }
michael@0 240
michael@0 241 void
michael@0 242 XULTreeAccessible::SetCurrentItem(Accessible* aItem)
michael@0 243 {
michael@0 244 NS_ERROR("XULTreeAccessible::SetCurrentItem not implemented");
michael@0 245 }
michael@0 246
michael@0 247 already_AddRefed<nsIArray>
michael@0 248 XULTreeAccessible::SelectedItems()
michael@0 249 {
michael@0 250 if (!mTreeView)
michael@0 251 return nullptr;
michael@0 252
michael@0 253 nsCOMPtr<nsITreeSelection> selection;
michael@0 254 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 255 if (!selection)
michael@0 256 return nullptr;
michael@0 257
michael@0 258 nsCOMPtr<nsIMutableArray> selectedItems =
michael@0 259 do_CreateInstance(NS_ARRAY_CONTRACTID);
michael@0 260 if (!selectedItems)
michael@0 261 return nullptr;
michael@0 262
michael@0 263 int32_t rangeCount = 0;
michael@0 264 selection->GetRangeCount(&rangeCount);
michael@0 265 for (int32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) {
michael@0 266 int32_t firstIdx = 0, lastIdx = -1;
michael@0 267 selection->GetRangeAt(rangeIdx, &firstIdx, &lastIdx);
michael@0 268 for (int32_t rowIdx = firstIdx; rowIdx <= lastIdx; rowIdx++) {
michael@0 269 nsIAccessible* item = GetTreeItemAccessible(rowIdx);
michael@0 270 if (item)
michael@0 271 selectedItems->AppendElement(item, false);
michael@0 272 }
michael@0 273 }
michael@0 274
michael@0 275 return selectedItems.forget();
michael@0 276 }
michael@0 277
michael@0 278 uint32_t
michael@0 279 XULTreeAccessible::SelectedItemCount()
michael@0 280 {
michael@0 281 if (!mTreeView)
michael@0 282 return 0;
michael@0 283
michael@0 284 nsCOMPtr<nsITreeSelection> selection;
michael@0 285 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 286 if (selection) {
michael@0 287 int32_t count = 0;
michael@0 288 selection->GetCount(&count);
michael@0 289 return count;
michael@0 290 }
michael@0 291
michael@0 292 return 0;
michael@0 293 }
michael@0 294
michael@0 295 bool
michael@0 296 XULTreeAccessible::AddItemToSelection(uint32_t aIndex)
michael@0 297 {
michael@0 298 if (!mTreeView)
michael@0 299 return false;
michael@0 300
michael@0 301 nsCOMPtr<nsITreeSelection> selection;
michael@0 302 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 303 if (selection) {
michael@0 304 bool isSelected = false;
michael@0 305 selection->IsSelected(aIndex, &isSelected);
michael@0 306 if (!isSelected)
michael@0 307 selection->ToggleSelect(aIndex);
michael@0 308
michael@0 309 return true;
michael@0 310 }
michael@0 311 return false;
michael@0 312 }
michael@0 313
michael@0 314 bool
michael@0 315 XULTreeAccessible::RemoveItemFromSelection(uint32_t aIndex)
michael@0 316 {
michael@0 317 if (!mTreeView)
michael@0 318 return false;
michael@0 319
michael@0 320 nsCOMPtr<nsITreeSelection> selection;
michael@0 321 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 322 if (selection) {
michael@0 323 bool isSelected = false;
michael@0 324 selection->IsSelected(aIndex, &isSelected);
michael@0 325 if (isSelected)
michael@0 326 selection->ToggleSelect(aIndex);
michael@0 327
michael@0 328 return true;
michael@0 329 }
michael@0 330 return false;
michael@0 331 }
michael@0 332
michael@0 333 bool
michael@0 334 XULTreeAccessible::IsItemSelected(uint32_t aIndex)
michael@0 335 {
michael@0 336 if (!mTreeView)
michael@0 337 return false;
michael@0 338
michael@0 339 nsCOMPtr<nsITreeSelection> selection;
michael@0 340 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 341 if (selection) {
michael@0 342 bool isSelected = false;
michael@0 343 selection->IsSelected(aIndex, &isSelected);
michael@0 344 return isSelected;
michael@0 345 }
michael@0 346 return false;
michael@0 347 }
michael@0 348
michael@0 349 bool
michael@0 350 XULTreeAccessible::UnselectAll()
michael@0 351 {
michael@0 352 if (!mTreeView)
michael@0 353 return false;
michael@0 354
michael@0 355 nsCOMPtr<nsITreeSelection> selection;
michael@0 356 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 357 if (!selection)
michael@0 358 return false;
michael@0 359
michael@0 360 selection->ClearSelection();
michael@0 361 return true;
michael@0 362 }
michael@0 363
michael@0 364 Accessible*
michael@0 365 XULTreeAccessible::GetSelectedItem(uint32_t aIndex)
michael@0 366 {
michael@0 367 if (!mTreeView)
michael@0 368 return nullptr;
michael@0 369
michael@0 370 nsCOMPtr<nsITreeSelection> selection;
michael@0 371 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 372 if (!selection)
michael@0 373 return nullptr;
michael@0 374
michael@0 375 uint32_t selCount = 0;
michael@0 376 int32_t rangeCount = 0;
michael@0 377 selection->GetRangeCount(&rangeCount);
michael@0 378 for (int32_t rangeIdx = 0; rangeIdx < rangeCount; rangeIdx++) {
michael@0 379 int32_t firstIdx = 0, lastIdx = -1;
michael@0 380 selection->GetRangeAt(rangeIdx, &firstIdx, &lastIdx);
michael@0 381 for (int32_t rowIdx = firstIdx; rowIdx <= lastIdx; rowIdx++) {
michael@0 382 if (selCount == aIndex)
michael@0 383 return GetTreeItemAccessible(rowIdx);
michael@0 384
michael@0 385 selCount++;
michael@0 386 }
michael@0 387 }
michael@0 388
michael@0 389 return nullptr;
michael@0 390 }
michael@0 391
michael@0 392 bool
michael@0 393 XULTreeAccessible::SelectAll()
michael@0 394 {
michael@0 395 // see if we are multiple select if so set ourselves as such
michael@0 396 if (!mTreeView)
michael@0 397 return false;
michael@0 398
michael@0 399 nsCOMPtr<nsITreeSelection> selection;
michael@0 400 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 401 if (selection) {
michael@0 402 bool single = false;
michael@0 403 selection->GetSingle(&single);
michael@0 404 if (!single) {
michael@0 405 selection->SelectAll();
michael@0 406 return true;
michael@0 407 }
michael@0 408 }
michael@0 409
michael@0 410 return false;
michael@0 411 }
michael@0 412
michael@0 413 ////////////////////////////////////////////////////////////////////////////////
michael@0 414 // XULTreeAccessible: Accessible implementation
michael@0 415
michael@0 416 Accessible*
michael@0 417 XULTreeAccessible::GetChildAt(uint32_t aIndex) const
michael@0 418 {
michael@0 419 uint32_t childCount = Accessible::ChildCount();
michael@0 420 if (aIndex < childCount)
michael@0 421 return Accessible::GetChildAt(aIndex);
michael@0 422
michael@0 423 return GetTreeItemAccessible(aIndex - childCount);
michael@0 424 }
michael@0 425
michael@0 426 uint32_t
michael@0 427 XULTreeAccessible::ChildCount() const
michael@0 428 {
michael@0 429 // Tree's children count is row count + treecols count.
michael@0 430 uint32_t childCount = Accessible::ChildCount();
michael@0 431 if (!mTreeView)
michael@0 432 return childCount;
michael@0 433
michael@0 434 int32_t rowCount = 0;
michael@0 435 mTreeView->GetRowCount(&rowCount);
michael@0 436 childCount += rowCount;
michael@0 437
michael@0 438 return childCount;
michael@0 439 }
michael@0 440
michael@0 441 Relation
michael@0 442 XULTreeAccessible::RelationByType(RelationType aType)
michael@0 443 {
michael@0 444 if (aType == RelationType::NODE_PARENT_OF) {
michael@0 445 if (mTreeView)
michael@0 446 return Relation(new XULTreeItemIterator(this, mTreeView, -1));
michael@0 447
michael@0 448 return Relation();
michael@0 449 }
michael@0 450
michael@0 451 return Accessible::RelationByType(aType);
michael@0 452 }
michael@0 453
michael@0 454 ////////////////////////////////////////////////////////////////////////////////
michael@0 455 // XULTreeAccessible: Widgets
michael@0 456
michael@0 457 bool
michael@0 458 XULTreeAccessible::IsWidget() const
michael@0 459 {
michael@0 460 return true;
michael@0 461 }
michael@0 462
michael@0 463 bool
michael@0 464 XULTreeAccessible::IsActiveWidget() const
michael@0 465 {
michael@0 466 if (IsAutoCompletePopup()) {
michael@0 467 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
michael@0 468 do_QueryInterface(mContent->GetParent());
michael@0 469
michael@0 470 if (autoCompletePopupElm) {
michael@0 471 bool isOpen = false;
michael@0 472 autoCompletePopupElm->GetPopupOpen(&isOpen);
michael@0 473 return isOpen;
michael@0 474 }
michael@0 475 }
michael@0 476 return FocusMgr()->HasDOMFocus(mContent);
michael@0 477 }
michael@0 478
michael@0 479 bool
michael@0 480 XULTreeAccessible::AreItemsOperable() const
michael@0 481 {
michael@0 482 if (IsAutoCompletePopup()) {
michael@0 483 nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
michael@0 484 do_QueryInterface(mContent->GetParent());
michael@0 485
michael@0 486 if (autoCompletePopupElm) {
michael@0 487 bool isOpen = false;
michael@0 488 autoCompletePopupElm->GetPopupOpen(&isOpen);
michael@0 489 return isOpen;
michael@0 490 }
michael@0 491 }
michael@0 492 return true;
michael@0 493 }
michael@0 494
michael@0 495 Accessible*
michael@0 496 XULTreeAccessible::ContainerWidget() const
michael@0 497 {
michael@0 498 if (IsAutoCompletePopup()) {
michael@0 499 // This works for XUL autocompletes. It doesn't work for HTML forms
michael@0 500 // autocomplete because of potential crossprocess calls (when autocomplete
michael@0 501 // lives in content process while popup lives in chrome process). If that's
michael@0 502 // a problem then rethink Widgets interface.
michael@0 503 nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
michael@0 504 do_QueryInterface(mContent->GetParent());
michael@0 505 if (menuListElm) {
michael@0 506 nsCOMPtr<nsIDOMNode> inputElm;
michael@0 507 menuListElm->GetInputField(getter_AddRefs(inputElm));
michael@0 508 if (inputElm) {
michael@0 509 nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
michael@0 510 if (inputNode) {
michael@0 511 Accessible* input =
michael@0 512 mDoc->GetAccessible(inputNode);
michael@0 513 return input ? input->ContainerWidget() : nullptr;
michael@0 514 }
michael@0 515 }
michael@0 516 }
michael@0 517 }
michael@0 518 return nullptr;
michael@0 519 }
michael@0 520
michael@0 521 ////////////////////////////////////////////////////////////////////////////////
michael@0 522 // XULTreeAccessible: public implementation
michael@0 523
michael@0 524 Accessible*
michael@0 525 XULTreeAccessible::GetTreeItemAccessible(int32_t aRow) const
michael@0 526 {
michael@0 527 if (aRow < 0 || IsDefunct() || !mTreeView)
michael@0 528 return nullptr;
michael@0 529
michael@0 530 int32_t rowCount = 0;
michael@0 531 nsresult rv = mTreeView->GetRowCount(&rowCount);
michael@0 532 if (NS_FAILED(rv) || aRow >= rowCount)
michael@0 533 return nullptr;
michael@0 534
michael@0 535 void *key = reinterpret_cast<void*>(aRow);
michael@0 536 Accessible* cachedTreeItem = mAccessibleCache.GetWeak(key);
michael@0 537 if (cachedTreeItem)
michael@0 538 return cachedTreeItem;
michael@0 539
michael@0 540 nsRefPtr<Accessible> treeItem = CreateTreeItemAccessible(aRow);
michael@0 541 if (treeItem) {
michael@0 542 mAccessibleCache.Put(key, treeItem);
michael@0 543 Document()->BindToDocument(treeItem, nullptr);
michael@0 544 return treeItem;
michael@0 545 }
michael@0 546
michael@0 547 return nullptr;
michael@0 548 }
michael@0 549
michael@0 550 void
michael@0 551 XULTreeAccessible::InvalidateCache(int32_t aRow, int32_t aCount)
michael@0 552 {
michael@0 553 if (IsDefunct())
michael@0 554 return;
michael@0 555
michael@0 556 if (!mTreeView) {
michael@0 557 ClearCache(mAccessibleCache);
michael@0 558 return;
michael@0 559 }
michael@0 560
michael@0 561 // Do not invalidate the cache if rows have been inserted.
michael@0 562 if (aCount > 0)
michael@0 563 return;
michael@0 564
michael@0 565 DocAccessible* document = Document();
michael@0 566
michael@0 567 // Fire destroy event for removed tree items and delete them from caches.
michael@0 568 for (int32_t rowIdx = aRow; rowIdx < aRow - aCount; rowIdx++) {
michael@0 569
michael@0 570 void* key = reinterpret_cast<void*>(rowIdx);
michael@0 571 Accessible* treeItem = mAccessibleCache.GetWeak(key);
michael@0 572
michael@0 573 if (treeItem) {
michael@0 574 nsRefPtr<AccEvent> event =
michael@0 575 new AccEvent(nsIAccessibleEvent::EVENT_HIDE, treeItem);
michael@0 576 nsEventShell::FireEvent(event);
michael@0 577
michael@0 578 // Unbind from document, shutdown and remove from tree cache.
michael@0 579 document->UnbindFromDocument(treeItem);
michael@0 580 mAccessibleCache.Remove(key);
michael@0 581 }
michael@0 582 }
michael@0 583
michael@0 584 // We dealt with removed tree items already however we may keep tree items
michael@0 585 // having row indexes greater than row count. We should remove these dead tree
michael@0 586 // items silently from caches.
michael@0 587 int32_t newRowCount = 0;
michael@0 588 nsresult rv = mTreeView->GetRowCount(&newRowCount);
michael@0 589 if (NS_FAILED(rv))
michael@0 590 return;
michael@0 591
michael@0 592 int32_t oldRowCount = newRowCount - aCount;
michael@0 593
michael@0 594 for (int32_t rowIdx = newRowCount; rowIdx < oldRowCount; ++rowIdx) {
michael@0 595
michael@0 596 void *key = reinterpret_cast<void*>(rowIdx);
michael@0 597 Accessible* treeItem = mAccessibleCache.GetWeak(key);
michael@0 598
michael@0 599 if (treeItem) {
michael@0 600 // Unbind from document, shutdown and remove from tree cache.
michael@0 601 document->UnbindFromDocument(treeItem);
michael@0 602 mAccessibleCache.Remove(key);
michael@0 603 }
michael@0 604 }
michael@0 605 }
michael@0 606
michael@0 607 void
michael@0 608 XULTreeAccessible::TreeViewInvalidated(int32_t aStartRow, int32_t aEndRow,
michael@0 609 int32_t aStartCol, int32_t aEndCol)
michael@0 610 {
michael@0 611 if (IsDefunct())
michael@0 612 return;
michael@0 613
michael@0 614 if (!mTreeView) {
michael@0 615 ClearCache(mAccessibleCache);
michael@0 616 return;
michael@0 617 }
michael@0 618
michael@0 619 int32_t endRow = aEndRow;
michael@0 620
michael@0 621 nsresult rv;
michael@0 622 if (endRow == -1) {
michael@0 623 int32_t rowCount = 0;
michael@0 624 rv = mTreeView->GetRowCount(&rowCount);
michael@0 625 if (NS_FAILED(rv))
michael@0 626 return;
michael@0 627
michael@0 628 endRow = rowCount - 1;
michael@0 629 }
michael@0 630
michael@0 631 nsCOMPtr<nsITreeColumns> treeColumns;
michael@0 632 mTree->GetColumns(getter_AddRefs(treeColumns));
michael@0 633 if (!treeColumns)
michael@0 634 return;
michael@0 635
michael@0 636 int32_t endCol = aEndCol;
michael@0 637
michael@0 638 if (endCol == -1) {
michael@0 639 int32_t colCount = 0;
michael@0 640 rv = treeColumns->GetCount(&colCount);
michael@0 641 if (NS_FAILED(rv))
michael@0 642 return;
michael@0 643
michael@0 644 endCol = colCount - 1;
michael@0 645 }
michael@0 646
michael@0 647 for (int32_t rowIdx = aStartRow; rowIdx <= endRow; ++rowIdx) {
michael@0 648
michael@0 649 void *key = reinterpret_cast<void*>(rowIdx);
michael@0 650 Accessible* accessible = mAccessibleCache.GetWeak(key);
michael@0 651
michael@0 652 if (accessible) {
michael@0 653 nsRefPtr<XULTreeItemAccessibleBase> treeitemAcc = do_QueryObject(accessible);
michael@0 654 NS_ASSERTION(treeitemAcc, "Wrong accessible at the given key!");
michael@0 655
michael@0 656 treeitemAcc->RowInvalidated(aStartCol, endCol);
michael@0 657 }
michael@0 658 }
michael@0 659 }
michael@0 660
michael@0 661 void
michael@0 662 XULTreeAccessible::TreeViewChanged(nsITreeView* aView)
michael@0 663 {
michael@0 664 if (IsDefunct())
michael@0 665 return;
michael@0 666
michael@0 667 // Fire reorder event on tree accessible on accessible tree (do not fire
michael@0 668 // show/hide events on tree items because it can be expensive to fire them for
michael@0 669 // each tree item.
michael@0 670 nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this);
michael@0 671 Document()->FireDelayedEvent(reorderEvent);
michael@0 672
michael@0 673 // Clear cache.
michael@0 674 ClearCache(mAccessibleCache);
michael@0 675 mTreeView = aView;
michael@0 676 }
michael@0 677
michael@0 678 ////////////////////////////////////////////////////////////////////////////////
michael@0 679 // XULTreeAccessible: protected implementation
michael@0 680
michael@0 681 already_AddRefed<Accessible>
michael@0 682 XULTreeAccessible::CreateTreeItemAccessible(int32_t aRow) const
michael@0 683 {
michael@0 684 nsRefPtr<Accessible> accessible =
michael@0 685 new XULTreeItemAccessible(mContent, mDoc, const_cast<XULTreeAccessible*>(this),
michael@0 686 mTree, mTreeView, aRow);
michael@0 687
michael@0 688 return accessible.forget();
michael@0 689 }
michael@0 690
michael@0 691 ////////////////////////////////////////////////////////////////////////////////
michael@0 692 // XULTreeItemAccessibleBase
michael@0 693 ////////////////////////////////////////////////////////////////////////////////
michael@0 694
michael@0 695 XULTreeItemAccessibleBase::
michael@0 696 XULTreeItemAccessibleBase(nsIContent* aContent, DocAccessible* aDoc,
michael@0 697 Accessible* aParent, nsITreeBoxObject* aTree,
michael@0 698 nsITreeView* aTreeView, int32_t aRow) :
michael@0 699 AccessibleWrap(aContent, aDoc),
michael@0 700 mTree(aTree), mTreeView(aTreeView), mRow(aRow)
michael@0 701 {
michael@0 702 mParent = aParent;
michael@0 703 mStateFlags |= eSharedNode;
michael@0 704 }
michael@0 705
michael@0 706 ////////////////////////////////////////////////////////////////////////////////
michael@0 707 // XULTreeItemAccessibleBase: nsISupports implementation
michael@0 708
michael@0 709 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase, Accessible,
michael@0 710 mTree)
michael@0 711
michael@0 712 NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessibleBase)
michael@0 713 NS_INTERFACE_TABLE_INHERITED(XULTreeItemAccessibleBase,
michael@0 714 XULTreeItemAccessibleBase)
michael@0 715 NS_INTERFACE_TABLE_TAIL_INHERITING(Accessible)
michael@0 716 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessibleBase, Accessible)
michael@0 717 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessibleBase, Accessible)
michael@0 718
michael@0 719 ////////////////////////////////////////////////////////////////////////////////
michael@0 720 // XULTreeItemAccessibleBase: nsIAccessible implementation
michael@0 721
michael@0 722 Accessible*
michael@0 723 XULTreeItemAccessibleBase::FocusedChild()
michael@0 724 {
michael@0 725 return FocusMgr()->FocusedAccessible() == this ? this : nullptr;
michael@0 726 }
michael@0 727
michael@0 728 NS_IMETHODIMP
michael@0 729 XULTreeItemAccessibleBase::GetBounds(int32_t* aX, int32_t* aY,
michael@0 730 int32_t* aWidth, int32_t* aHeight)
michael@0 731 {
michael@0 732 NS_ENSURE_ARG_POINTER(aX);
michael@0 733 *aX = 0;
michael@0 734 NS_ENSURE_ARG_POINTER(aY);
michael@0 735 *aY = 0;
michael@0 736 NS_ENSURE_ARG_POINTER(aWidth);
michael@0 737 *aWidth = 0;
michael@0 738 NS_ENSURE_ARG_POINTER(aHeight);
michael@0 739 *aHeight = 0;
michael@0 740
michael@0 741 if (IsDefunct())
michael@0 742 return NS_ERROR_FAILURE;
michael@0 743
michael@0 744 // Get x coordinate and width from treechildren element, get y coordinate and
michael@0 745 // height from tree cell.
michael@0 746
michael@0 747 nsCOMPtr<nsIBoxObject> boxObj = nsCoreUtils::GetTreeBodyBoxObject(mTree);
michael@0 748 NS_ENSURE_STATE(boxObj);
michael@0 749
michael@0 750 nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
michael@0 751
michael@0 752 int32_t x = 0, y = 0, width = 0, height = 0;
michael@0 753 nsresult rv = mTree->GetCoordsForCellItem(mRow, column, EmptyCString(),
michael@0 754 &x, &y, &width, &height);
michael@0 755 NS_ENSURE_SUCCESS(rv, rv);
michael@0 756
michael@0 757 boxObj->GetWidth(&width);
michael@0 758
michael@0 759 int32_t tcX = 0, tcY = 0;
michael@0 760 boxObj->GetScreenX(&tcX);
michael@0 761 boxObj->GetScreenY(&tcY);
michael@0 762
michael@0 763 x = tcX;
michael@0 764 y += tcY;
michael@0 765
michael@0 766 nsPresContext* presContext = mDoc->PresContext();
michael@0 767 *aX = presContext->CSSPixelsToDevPixels(x);
michael@0 768 *aY = presContext->CSSPixelsToDevPixels(y);
michael@0 769 *aWidth = presContext->CSSPixelsToDevPixels(width);
michael@0 770 *aHeight = presContext->CSSPixelsToDevPixels(height);
michael@0 771
michael@0 772 return NS_OK;
michael@0 773 }
michael@0 774
michael@0 775 NS_IMETHODIMP
michael@0 776 XULTreeItemAccessibleBase::SetSelected(bool aSelect)
michael@0 777 {
michael@0 778 if (IsDefunct())
michael@0 779 return NS_ERROR_FAILURE;
michael@0 780
michael@0 781 nsCOMPtr<nsITreeSelection> selection;
michael@0 782 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 783 if (selection) {
michael@0 784 bool isSelected;
michael@0 785 selection->IsSelected(mRow, &isSelected);
michael@0 786 if (isSelected != aSelect)
michael@0 787 selection->ToggleSelect(mRow);
michael@0 788 }
michael@0 789
michael@0 790 return NS_OK;
michael@0 791 }
michael@0 792
michael@0 793 NS_IMETHODIMP
michael@0 794 XULTreeItemAccessibleBase::TakeFocus()
michael@0 795 {
michael@0 796 if (IsDefunct())
michael@0 797 return NS_ERROR_FAILURE;
michael@0 798
michael@0 799 nsCOMPtr<nsITreeSelection> selection;
michael@0 800 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 801 if (selection)
michael@0 802 selection->SetCurrentIndex(mRow);
michael@0 803
michael@0 804 // focus event will be fired here
michael@0 805 return Accessible::TakeFocus();
michael@0 806 }
michael@0 807
michael@0 808 Relation
michael@0 809 XULTreeItemAccessibleBase::RelationByType(RelationType aType)
michael@0 810 {
michael@0 811
michael@0 812 switch (aType) {
michael@0 813 case RelationType::NODE_CHILD_OF: {
michael@0 814 int32_t parentIndex = -1;
michael@0 815 if (!NS_SUCCEEDED(mTreeView->GetParentIndex(mRow, &parentIndex)))
michael@0 816 return Relation();
michael@0 817
michael@0 818 if (parentIndex == -1)
michael@0 819 return Relation(mParent);
michael@0 820
michael@0 821 XULTreeAccessible* treeAcc = mParent->AsXULTree();
michael@0 822 return Relation(treeAcc->GetTreeItemAccessible(parentIndex));
michael@0 823 }
michael@0 824
michael@0 825 case RelationType::NODE_PARENT_OF: {
michael@0 826 bool isTrue = false;
michael@0 827 if (NS_FAILED(mTreeView->IsContainerEmpty(mRow, &isTrue)) || isTrue)
michael@0 828 return Relation();
michael@0 829
michael@0 830 if (NS_FAILED(mTreeView->IsContainerOpen(mRow, &isTrue)) || !isTrue)
michael@0 831 return Relation();
michael@0 832
michael@0 833 XULTreeAccessible* tree = mParent->AsXULTree();
michael@0 834 return Relation(new XULTreeItemIterator(tree, mTreeView, mRow));
michael@0 835 }
michael@0 836
michael@0 837 default:
michael@0 838 return Relation();
michael@0 839 }
michael@0 840 }
michael@0 841
michael@0 842 uint8_t
michael@0 843 XULTreeItemAccessibleBase::ActionCount()
michael@0 844 {
michael@0 845 // "activate" action is available for all treeitems, "expand/collapse" action
michael@0 846 // is avaible for treeitem which is container.
michael@0 847 return IsExpandable() ? 2 : 1;
michael@0 848 }
michael@0 849
michael@0 850 NS_IMETHODIMP
michael@0 851 XULTreeItemAccessibleBase::GetActionName(uint8_t aIndex, nsAString& aName)
michael@0 852 {
michael@0 853 if (IsDefunct())
michael@0 854 return NS_ERROR_FAILURE;
michael@0 855
michael@0 856 if (aIndex == eAction_Click) {
michael@0 857 aName.AssignLiteral("activate");
michael@0 858 return NS_OK;
michael@0 859 }
michael@0 860
michael@0 861 if (aIndex == eAction_Expand && IsExpandable()) {
michael@0 862 bool isContainerOpen;
michael@0 863 mTreeView->IsContainerOpen(mRow, &isContainerOpen);
michael@0 864 if (isContainerOpen)
michael@0 865 aName.AssignLiteral("collapse");
michael@0 866 else
michael@0 867 aName.AssignLiteral("expand");
michael@0 868
michael@0 869 return NS_OK;
michael@0 870 }
michael@0 871
michael@0 872 return NS_ERROR_INVALID_ARG;
michael@0 873 }
michael@0 874
michael@0 875 NS_IMETHODIMP
michael@0 876 XULTreeItemAccessibleBase::DoAction(uint8_t aIndex)
michael@0 877 {
michael@0 878 if (IsDefunct())
michael@0 879 return NS_ERROR_FAILURE;
michael@0 880
michael@0 881 if (aIndex != eAction_Click &&
michael@0 882 (aIndex != eAction_Expand || !IsExpandable()))
michael@0 883 return NS_ERROR_INVALID_ARG;
michael@0 884
michael@0 885 DoCommand(nullptr, aIndex);
michael@0 886 return NS_OK;
michael@0 887 }
michael@0 888
michael@0 889 ////////////////////////////////////////////////////////////////////////////////
michael@0 890 // XULTreeItemAccessibleBase: Accessible implementation
michael@0 891
michael@0 892 void
michael@0 893 XULTreeItemAccessibleBase::Shutdown()
michael@0 894 {
michael@0 895 mTree = nullptr;
michael@0 896 mTreeView = nullptr;
michael@0 897 mRow = -1;
michael@0 898
michael@0 899 AccessibleWrap::Shutdown();
michael@0 900 }
michael@0 901
michael@0 902 GroupPos
michael@0 903 XULTreeItemAccessibleBase::GroupPosition()
michael@0 904 {
michael@0 905 GroupPos groupPos;
michael@0 906
michael@0 907 int32_t level;
michael@0 908 nsresult rv = mTreeView->GetLevel(mRow, &level);
michael@0 909 NS_ENSURE_SUCCESS(rv, groupPos);
michael@0 910
michael@0 911 int32_t topCount = 1;
michael@0 912 for (int32_t index = mRow - 1; index >= 0; index--) {
michael@0 913 int32_t lvl = -1;
michael@0 914 if (NS_SUCCEEDED(mTreeView->GetLevel(index, &lvl))) {
michael@0 915 if (lvl < level)
michael@0 916 break;
michael@0 917
michael@0 918 if (lvl == level)
michael@0 919 topCount++;
michael@0 920 }
michael@0 921 }
michael@0 922
michael@0 923 int32_t rowCount = 0;
michael@0 924 rv = mTreeView->GetRowCount(&rowCount);
michael@0 925 NS_ENSURE_SUCCESS(rv, groupPos);
michael@0 926
michael@0 927 int32_t bottomCount = 0;
michael@0 928 for (int32_t index = mRow + 1; index < rowCount; index++) {
michael@0 929 int32_t lvl = -1;
michael@0 930 if (NS_SUCCEEDED(mTreeView->GetLevel(index, &lvl))) {
michael@0 931 if (lvl < level)
michael@0 932 break;
michael@0 933
michael@0 934 if (lvl == level)
michael@0 935 bottomCount++;
michael@0 936 }
michael@0 937 }
michael@0 938
michael@0 939 groupPos.level = level + 1;
michael@0 940 groupPos.setSize = topCount + bottomCount;
michael@0 941 groupPos.posInSet = topCount;
michael@0 942
michael@0 943 return groupPos;
michael@0 944 }
michael@0 945
michael@0 946 uint64_t
michael@0 947 XULTreeItemAccessibleBase::NativeState()
michael@0 948 {
michael@0 949
michael@0 950 // focusable and selectable states
michael@0 951 uint64_t state = NativeInteractiveState();
michael@0 952
michael@0 953 // expanded/collapsed state
michael@0 954 if (IsExpandable()) {
michael@0 955 bool isContainerOpen;
michael@0 956 mTreeView->IsContainerOpen(mRow, &isContainerOpen);
michael@0 957 state |= isContainerOpen ? states::EXPANDED : states::COLLAPSED;
michael@0 958 }
michael@0 959
michael@0 960 // selected state
michael@0 961 nsCOMPtr<nsITreeSelection> selection;
michael@0 962 mTreeView->GetSelection(getter_AddRefs(selection));
michael@0 963 if (selection) {
michael@0 964 bool isSelected;
michael@0 965 selection->IsSelected(mRow, &isSelected);
michael@0 966 if (isSelected)
michael@0 967 state |= states::SELECTED;
michael@0 968 }
michael@0 969
michael@0 970 // focused state
michael@0 971 if (FocusMgr()->IsFocused(this))
michael@0 972 state |= states::FOCUSED;
michael@0 973
michael@0 974 // invisible state
michael@0 975 int32_t firstVisibleRow, lastVisibleRow;
michael@0 976 mTree->GetFirstVisibleRow(&firstVisibleRow);
michael@0 977 mTree->GetLastVisibleRow(&lastVisibleRow);
michael@0 978 if (mRow < firstVisibleRow || mRow > lastVisibleRow)
michael@0 979 state |= states::INVISIBLE;
michael@0 980
michael@0 981 return state;
michael@0 982 }
michael@0 983
michael@0 984 uint64_t
michael@0 985 XULTreeItemAccessibleBase::NativeInteractiveState() const
michael@0 986 {
michael@0 987 return states::FOCUSABLE | states::SELECTABLE;
michael@0 988 }
michael@0 989
michael@0 990 int32_t
michael@0 991 XULTreeItemAccessibleBase::IndexInParent() const
michael@0 992 {
michael@0 993 return mParent ? mParent->ContentChildCount() + mRow : -1;
michael@0 994 }
michael@0 995
michael@0 996 ////////////////////////////////////////////////////////////////////////////////
michael@0 997 // XULTreeItemAccessibleBase: Widgets
michael@0 998
michael@0 999 Accessible*
michael@0 1000 XULTreeItemAccessibleBase::ContainerWidget() const
michael@0 1001 {
michael@0 1002 return mParent;
michael@0 1003 }
michael@0 1004
michael@0 1005 ////////////////////////////////////////////////////////////////////////////////
michael@0 1006 // XULTreeItemAccessibleBase: Accessible protected methods
michael@0 1007
michael@0 1008 void
michael@0 1009 XULTreeItemAccessibleBase::DispatchClickEvent(nsIContent* aContent,
michael@0 1010 uint32_t aActionIndex)
michael@0 1011 {
michael@0 1012 if (IsDefunct())
michael@0 1013 return;
michael@0 1014
michael@0 1015 nsCOMPtr<nsITreeColumns> columns;
michael@0 1016 mTree->GetColumns(getter_AddRefs(columns));
michael@0 1017 if (!columns)
michael@0 1018 return;
michael@0 1019
michael@0 1020 // Get column and pseudo element.
michael@0 1021 nsCOMPtr<nsITreeColumn> column;
michael@0 1022 nsAutoCString pseudoElm;
michael@0 1023
michael@0 1024 if (aActionIndex == eAction_Click) {
michael@0 1025 // Key column is visible and clickable.
michael@0 1026 columns->GetKeyColumn(getter_AddRefs(column));
michael@0 1027 } else {
michael@0 1028 // Primary column contains a twisty we should click on.
michael@0 1029 columns->GetPrimaryColumn(getter_AddRefs(column));
michael@0 1030 pseudoElm = NS_LITERAL_CSTRING("twisty");
michael@0 1031 }
michael@0 1032
michael@0 1033 if (column)
michael@0 1034 nsCoreUtils::DispatchClickEvent(mTree, mRow, column, pseudoElm);
michael@0 1035 }
michael@0 1036
michael@0 1037 Accessible*
michael@0 1038 XULTreeItemAccessibleBase::GetSiblingAtOffset(int32_t aOffset,
michael@0 1039 nsresult* aError) const
michael@0 1040 {
michael@0 1041 if (aError)
michael@0 1042 *aError = NS_OK; // fail peacefully
michael@0 1043
michael@0 1044 return mParent->GetChildAt(IndexInParent() + aOffset);
michael@0 1045 }
michael@0 1046
michael@0 1047 ////////////////////////////////////////////////////////////////////////////////
michael@0 1048 // XULTreeItemAccessibleBase: protected implementation
michael@0 1049
michael@0 1050 bool
michael@0 1051 XULTreeItemAccessibleBase::IsExpandable()
michael@0 1052 {
michael@0 1053
michael@0 1054 bool isContainer = false;
michael@0 1055 mTreeView->IsContainer(mRow, &isContainer);
michael@0 1056 if (isContainer) {
michael@0 1057 bool isEmpty = false;
michael@0 1058 mTreeView->IsContainerEmpty(mRow, &isEmpty);
michael@0 1059 if (!isEmpty) {
michael@0 1060 nsCOMPtr<nsITreeColumns> columns;
michael@0 1061 mTree->GetColumns(getter_AddRefs(columns));
michael@0 1062 nsCOMPtr<nsITreeColumn> primaryColumn;
michael@0 1063 if (columns) {
michael@0 1064 columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
michael@0 1065 if (primaryColumn &&
michael@0 1066 !nsCoreUtils::IsColumnHidden(primaryColumn))
michael@0 1067 return true;
michael@0 1068 }
michael@0 1069 }
michael@0 1070 }
michael@0 1071
michael@0 1072 return false;
michael@0 1073 }
michael@0 1074
michael@0 1075 void
michael@0 1076 XULTreeItemAccessibleBase::GetCellName(nsITreeColumn* aColumn, nsAString& aName)
michael@0 1077 {
michael@0 1078
michael@0 1079 mTreeView->GetCellText(mRow, aColumn, aName);
michael@0 1080
michael@0 1081 // If there is still no name try the cell value:
michael@0 1082 // This is for graphical cells. We need tree/table view implementors to
michael@0 1083 // implement FooView::GetCellValue to return a meaningful string for cases
michael@0 1084 // where there is something shown in the cell (non-text) such as a star icon;
michael@0 1085 // in which case GetCellValue for that cell would return "starred" or
michael@0 1086 // "flagged" for example.
michael@0 1087 if (aName.IsEmpty())
michael@0 1088 mTreeView->GetCellValue(mRow, aColumn, aName);
michael@0 1089 }
michael@0 1090
michael@0 1091
michael@0 1092 ////////////////////////////////////////////////////////////////////////////////
michael@0 1093 // XULTreeItemAccessible
michael@0 1094 ////////////////////////////////////////////////////////////////////////////////
michael@0 1095
michael@0 1096 XULTreeItemAccessible::
michael@0 1097 XULTreeItemAccessible(nsIContent* aContent, DocAccessible* aDoc,
michael@0 1098 Accessible* aParent, nsITreeBoxObject* aTree,
michael@0 1099 nsITreeView* aTreeView, int32_t aRow) :
michael@0 1100 XULTreeItemAccessibleBase(aContent, aDoc, aParent, aTree, aTreeView, aRow)
michael@0 1101 {
michael@0 1102 mColumn = nsCoreUtils::GetFirstSensibleColumn(mTree);
michael@0 1103 GetCellName(mColumn, mCachedName);
michael@0 1104 }
michael@0 1105
michael@0 1106 ////////////////////////////////////////////////////////////////////////////////
michael@0 1107 // XULTreeItemAccessible: nsISupports implementation
michael@0 1108
michael@0 1109 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible,
michael@0 1110 XULTreeItemAccessibleBase,
michael@0 1111 mColumn)
michael@0 1112
michael@0 1113 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(XULTreeItemAccessible)
michael@0 1114 NS_INTERFACE_MAP_END_INHERITING(XULTreeItemAccessibleBase)
michael@0 1115 NS_IMPL_ADDREF_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase)
michael@0 1116 NS_IMPL_RELEASE_INHERITED(XULTreeItemAccessible, XULTreeItemAccessibleBase)
michael@0 1117
michael@0 1118 ////////////////////////////////////////////////////////////////////////////////
michael@0 1119 // XULTreeItemAccessible: nsIAccessible implementation
michael@0 1120
michael@0 1121 ENameValueFlag
michael@0 1122 XULTreeItemAccessible::Name(nsString& aName)
michael@0 1123 {
michael@0 1124 aName.Truncate();
michael@0 1125
michael@0 1126 GetCellName(mColumn, aName);
michael@0 1127 return eNameOK;
michael@0 1128 }
michael@0 1129
michael@0 1130 ////////////////////////////////////////////////////////////////////////////////
michael@0 1131 // XULTreeItemAccessible: Accessible implementation
michael@0 1132
michael@0 1133 void
michael@0 1134 XULTreeItemAccessible::Shutdown()
michael@0 1135 {
michael@0 1136 mColumn = nullptr;
michael@0 1137 XULTreeItemAccessibleBase::Shutdown();
michael@0 1138 }
michael@0 1139
michael@0 1140 role
michael@0 1141 XULTreeItemAccessible::NativeRole()
michael@0 1142 {
michael@0 1143 nsCOMPtr<nsITreeColumns> columns;
michael@0 1144 mTree->GetColumns(getter_AddRefs(columns));
michael@0 1145 if (!columns) {
michael@0 1146 NS_ERROR("No tree columns object in the tree!");
michael@0 1147 return roles::NOTHING;
michael@0 1148 }
michael@0 1149
michael@0 1150 nsCOMPtr<nsITreeColumn> primaryColumn;
michael@0 1151 columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
michael@0 1152
michael@0 1153 return primaryColumn ? roles::OUTLINEITEM : roles::LISTITEM;
michael@0 1154 }
michael@0 1155
michael@0 1156 ////////////////////////////////////////////////////////////////////////////////
michael@0 1157 // XULTreeItemAccessible: XULTreeItemAccessibleBase implementation
michael@0 1158
michael@0 1159 void
michael@0 1160 XULTreeItemAccessible::RowInvalidated(int32_t aStartColIdx, int32_t aEndColIdx)
michael@0 1161 {
michael@0 1162 nsAutoString name;
michael@0 1163 Name(name);
michael@0 1164
michael@0 1165 if (name != mCachedName) {
michael@0 1166 nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_NAME_CHANGE, this);
michael@0 1167 mCachedName = name;
michael@0 1168 }
michael@0 1169 }
michael@0 1170
michael@0 1171 ////////////////////////////////////////////////////////////////////////////////
michael@0 1172 // XULTreeItemAccessible: Accessible protected implementation
michael@0 1173
michael@0 1174 void
michael@0 1175 XULTreeItemAccessible::CacheChildren()
michael@0 1176 {
michael@0 1177 }
michael@0 1178
michael@0 1179
michael@0 1180 ////////////////////////////////////////////////////////////////////////////////
michael@0 1181 // XULTreeColumAccessible
michael@0 1182 ////////////////////////////////////////////////////////////////////////////////
michael@0 1183
michael@0 1184 XULTreeColumAccessible::
michael@0 1185 XULTreeColumAccessible(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 1186 XULColumAccessible(aContent, aDoc)
michael@0 1187 {
michael@0 1188 }
michael@0 1189
michael@0 1190 Accessible*
michael@0 1191 XULTreeColumAccessible::GetSiblingAtOffset(int32_t aOffset,
michael@0 1192 nsresult* aError) const
michael@0 1193 {
michael@0 1194 if (aOffset < 0)
michael@0 1195 return XULColumAccessible::GetSiblingAtOffset(aOffset, aError);
michael@0 1196
michael@0 1197 if (aError)
michael@0 1198 *aError = NS_OK; // fail peacefully
michael@0 1199
michael@0 1200 nsCOMPtr<nsITreeBoxObject> tree = nsCoreUtils::GetTreeBoxObject(mContent);
michael@0 1201 if (tree) {
michael@0 1202 nsCOMPtr<nsITreeView> treeView;
michael@0 1203 tree->GetView(getter_AddRefs(treeView));
michael@0 1204 if (treeView) {
michael@0 1205 int32_t rowCount = 0;
michael@0 1206 treeView->GetRowCount(&rowCount);
michael@0 1207 if (rowCount > 0 && aOffset <= rowCount) {
michael@0 1208 XULTreeAccessible* treeAcc = Parent()->AsXULTree();
michael@0 1209
michael@0 1210 if (treeAcc)
michael@0 1211 return treeAcc->GetTreeItemAccessible(aOffset - 1);
michael@0 1212 }
michael@0 1213 }
michael@0 1214 }
michael@0 1215
michael@0 1216 return nullptr;
michael@0 1217 }
michael@0 1218

mercurial