UiaGrid.cpp (3957B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ia2AccessibleTable.h" 8 #include "mozilla/a11y/TableAccessible.h" 9 #include "nsIAccessiblePivot.h" 10 #include "Pivot.h" 11 #include "UiaGrid.h" 12 13 using namespace mozilla; 14 using namespace mozilla::a11y; 15 16 // Helpers 17 18 // Used to search for all row and column headers in a table. This could be slow, 19 // as it potentially walks all cells in the table. However, it's unclear if, 20 // when or how often clients will use this. If this proves to be a performance 21 // problem, we will need to add methods to TableAccessible to get all row and 22 // column headers in a faster way. 23 class HeaderRule : public PivotRule { 24 public: 25 explicit HeaderRule(role aRole) : mRole(aRole) {} 26 27 virtual uint16_t Match(Accessible* aAcc) override { 28 role accRole = aAcc->Role(); 29 if (accRole == mRole) { 30 return nsIAccessibleTraversalRule::FILTER_MATCH | 31 nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE; 32 } 33 if (accRole == roles::CAPTION || aAcc->IsTableCell()) { 34 return nsIAccessibleTraversalRule::FILTER_IGNORE | 35 nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE; 36 } 37 return nsIAccessibleTraversalRule::FILTER_IGNORE; 38 } 39 40 private: 41 role mRole; 42 }; 43 44 static SAFEARRAY* GetAllHeaders(Accessible* aTable, role aRole) { 45 AutoTArray<Accessible*, 20> headers; 46 Pivot pivot(aTable); 47 HeaderRule rule(aRole); 48 for (Accessible* header = pivot.Next(aTable, rule); header; 49 header = pivot.Next(header, rule)) { 50 headers.AppendElement(header); 51 } 52 return AccessibleArrayToUiaArray(headers); 53 } 54 55 // UiaGrid 56 57 Accessible* UiaGrid::Acc() { 58 auto* ia2t = static_cast<ia2AccessibleTable*>(this); 59 return ia2t->MsaaAccessible::Acc(); 60 } 61 62 TableAccessible* UiaGrid::TableAcc() { 63 Accessible* acc = Acc(); 64 return acc ? acc->AsTable() : nullptr; 65 } 66 67 // IGridProvider methods 68 69 STDMETHODIMP 70 UiaGrid::GetItem(int aRow, int aColumn, 71 __RPC__deref_out_opt IRawElementProviderSimple** aRetVal) { 72 if (!aRetVal) { 73 return E_INVALIDARG; 74 } 75 *aRetVal = nullptr; 76 TableAccessible* table = TableAcc(); 77 if (!table) { 78 return CO_E_OBJNOTCONNECTED; 79 } 80 Accessible* cell = table->CellAt(aRow, aColumn); 81 if (!cell) { 82 return E_INVALIDARG; 83 } 84 RefPtr<IRawElementProviderSimple> uia = MsaaAccessible::GetFrom(cell); 85 uia.forget(aRetVal); 86 return S_OK; 87 } 88 89 STDMETHODIMP 90 UiaGrid::get_RowCount(__RPC__out int* aRetVal) { 91 if (!aRetVal) { 92 return E_INVALIDARG; 93 } 94 TableAccessible* table = TableAcc(); 95 if (!table) { 96 return CO_E_OBJNOTCONNECTED; 97 } 98 *aRetVal = table->RowCount(); 99 return S_OK; 100 } 101 102 STDMETHODIMP 103 UiaGrid::get_ColumnCount(__RPC__out int* aRetVal) { 104 if (!aRetVal) { 105 return E_INVALIDARG; 106 } 107 TableAccessible* table = TableAcc(); 108 if (!table) { 109 return CO_E_OBJNOTCONNECTED; 110 } 111 *aRetVal = table->ColCount(); 112 return S_OK; 113 } 114 115 // ITableProvider methods 116 117 STDMETHODIMP 118 UiaGrid::GetRowHeaders(__RPC__deref_out_opt SAFEARRAY** aRetVal) { 119 if (!aRetVal) { 120 return E_INVALIDARG; 121 } 122 Accessible* acc = Acc(); 123 if (!acc) { 124 return CO_E_OBJNOTCONNECTED; 125 } 126 *aRetVal = GetAllHeaders(acc, roles::ROWHEADER); 127 return S_OK; 128 } 129 130 STDMETHODIMP 131 UiaGrid::GetColumnHeaders(__RPC__deref_out_opt SAFEARRAY** aRetVal) { 132 if (!aRetVal) { 133 return E_INVALIDARG; 134 } 135 Accessible* acc = Acc(); 136 if (!acc) { 137 return CO_E_OBJNOTCONNECTED; 138 } 139 *aRetVal = GetAllHeaders(acc, roles::COLUMNHEADER); 140 return S_OK; 141 } 142 143 STDMETHODIMP 144 UiaGrid::get_RowOrColumnMajor(__RPC__out enum RowOrColumnMajor* aRetVal) { 145 if (!aRetVal) { 146 return E_INVALIDARG; 147 } 148 // HTML and ARIA tables are always in row major order. 149 *aRetVal = RowOrColumnMajor_RowMajor; 150 return S_OK; 151 }