1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_accessibility.hxx" 26 27 #ifndef ACCESSIBILITY_EXT_ACCESSIBLETABLISTBOXTABLE_HXX_ 28 #include "accessibility/extended/accessibletablistboxtable.hxx" 29 #endif 30 #include "accessibility/extended/AccessibleBrowseBoxTableCell.hxx" 31 #include "accessibility/extended/AccessibleBrowseBoxCheckBoxCell.hxx" 32 #include <svtools/svtabbx.hxx> 33 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 34 35 //........................................................................ 36 namespace accessibility 37 { 38 //........................................................................ 39 40 // class TLBSolarGuard --------------------------------------------------------- 41 42 /** Aquire the solar mutex. */ 43 class TLBSolarGuard : public ::vos::OGuard 44 { 45 public: 46 inline TLBSolarGuard() : ::vos::OGuard( Application::GetSolarMutex() ) {} 47 }; 48 49 // class AccessibleTabListBoxTable --------------------------------------------- 50 51 using namespace ::com::sun::star::accessibility; 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::lang; 54 using namespace ::com::sun::star; 55 56 DBG_NAME(AccessibleTabListBoxTable) 57 58 // ----------------------------------------------------------------------------- 59 // Ctor() and Dtor() 60 // ----------------------------------------------------------------------------- 61 AccessibleTabListBoxTable::AccessibleTabListBoxTable( const Reference< XAccessible >& rxParent, SvHeaderTabListBox& rBox ) : 62 63 AccessibleBrowseBoxTable( rxParent, rBox ), 64 65 m_pTabListBox ( &rBox ) 66 67 { 68 DBG_CTOR( AccessibleTabListBoxTable, NULL ); 69 70 m_pTabListBox->AddEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) ); 71 } 72 // ----------------------------------------------------------------------------- 73 AccessibleTabListBoxTable::~AccessibleTabListBoxTable() 74 { 75 DBG_DTOR( AccessibleTabListBoxTable, NULL ); 76 77 if ( isAlive() ) 78 { 79 m_pTabListBox = NULL; 80 81 // increment ref count to prevent double call of Dtor 82 osl_incrementInterlockedCount( &m_refCount ); 83 dispose(); 84 } 85 } 86 // ----------------------------------------------------------------------------- 87 void AccessibleTabListBoxTable::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) 88 { 89 if ( isAlive() ) 90 { 91 sal_uLong nEventId = rVclWindowEvent.GetId(); 92 switch ( nEventId ) 93 { 94 case VCLEVENT_OBJECT_DYING : 95 { 96 m_pTabListBox->RemoveEventListener( LINK( this, AccessibleTabListBoxTable, WindowEventListener ) ); 97 m_pTabListBox = NULL; 98 break; 99 } 100 101 case VCLEVENT_CONTROL_GETFOCUS : 102 case VCLEVENT_CONTROL_LOSEFOCUS : 103 { 104 uno::Any aOldValue, aNewValue; 105 if ( VCLEVENT_CONTROL_GETFOCUS == nEventId ) 106 aNewValue <<= AccessibleStateType::FOCUSED; 107 else 108 aOldValue <<= AccessibleStateType::FOCUSED; 109 commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue ); 110 break; 111 } 112 113 case VCLEVENT_LISTBOX_SELECT : 114 { 115 // First send an event that tells the listeners of a 116 // modified selection. The active descendant event is 117 // send after that so that the receiving AT has time to 118 // read the text or name of the active child. 119 commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); 120 if ( m_pTabListBox && m_pTabListBox->HasFocus() ) 121 { 122 SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); 123 if ( pEntry ) 124 { 125 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry ); 126 sal_uInt16 nCol = m_pTabListBox->GetCurrColumn(); 127 Reference< XAccessible > xChild = 128 m_pTabListBox->CreateAccessibleCell( nRow, nCol ); 129 uno::Any aOldValue, aNewValue; 130 131 if ( m_pTabListBox->IsTransientChildrenDisabled() ) 132 { 133 aNewValue <<= AccessibleStateType::FOCUSED; 134 TriState eState = STATE_DONTKNOW; 135 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) ) 136 { 137 AccessibleCheckBoxCell* pCell = 138 static_cast< AccessibleCheckBoxCell* >( xChild.get() ); 139 pCell->commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue ); 140 } 141 else 142 { 143 AccessibleBrowseBoxTableCell* pCell = 144 static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() ); 145 pCell->commitEvent( AccessibleEventId::STATE_CHANGED, aNewValue, aOldValue ); 146 } 147 } 148 else 149 { 150 aNewValue <<= xChild; 151 commitEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aNewValue, aOldValue ); 152 } 153 } 154 } 155 break; 156 } 157 158 case VCLEVENT_CHECKBOX_TOGGLE : 159 { 160 if ( m_pTabListBox && m_pTabListBox->HasFocus() ) 161 { 162 SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); 163 if ( pEntry ) 164 { 165 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry ); 166 sal_uInt16 nCol = m_pTabListBox->GetCurrColumn(); 167 TriState eState = STATE_DONTKNOW; 168 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) ) 169 { 170 Reference< XAccessible > xChild = 171 m_pTabListBox->CreateAccessibleCell( nRow, nCol ); 172 AccessibleCheckBoxCell* pCell = 173 static_cast< AccessibleCheckBoxCell* >( xChild.get() ); 174 pCell->SetChecked( m_pTabListBox->IsItemChecked( pEntry, nCol ) ); 175 } 176 } 177 } 178 break; 179 } 180 181 case VCLEVENT_TABLECELL_NAMECHANGED : 182 { 183 if ( m_pTabListBox->IsTransientChildrenDisabled() ) 184 { 185 commitEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); 186 TabListBoxEventData* pData = static_cast< TabListBoxEventData* >( rVclWindowEvent.GetData() ); 187 SvLBoxEntry* pEntry = pData != NULL ? pData->m_pEntry : NULL; 188 if ( pEntry ) 189 { 190 sal_Int32 nRow = m_pTabListBox->GetEntryPos( pEntry ); 191 sal_uInt16 nCol = pData->m_nColumn; 192 Reference< XAccessible > xChild = 193 m_pTabListBox->CreateAccessibleCell( nRow, nCol ); 194 uno::Any aOldValue, aNewValue; 195 aOldValue <<= ::rtl::OUString( pData->m_sOldText ); 196 ::rtl::OUString sNewText( m_pTabListBox->GetCellText( nRow, nCol ) ); 197 aNewValue <<= sNewText; 198 TriState eState = STATE_DONTKNOW; 199 200 if ( m_pTabListBox->IsCellCheckBox( nRow, nCol, eState ) ) 201 { 202 AccessibleCheckBoxCell* pCell = 203 static_cast< AccessibleCheckBoxCell* >( xChild.get() ); 204 pCell->commitEvent( AccessibleEventId::NAME_CHANGED, aOldValue, aNewValue ); 205 } 206 else 207 { 208 AccessibleBrowseBoxTableCell* pCell = 209 static_cast< AccessibleBrowseBoxTableCell* >( xChild.get() ); 210 pCell->nameChanged( sNewText, pData->m_sOldText ); 211 } 212 } 213 } 214 break; 215 } 216 } 217 } 218 } 219 // ----------------------------------------------------------------------------- 220 IMPL_LINK( AccessibleTabListBoxTable, WindowEventListener, VclSimpleEvent*, pEvent ) 221 { 222 DBG_ASSERT( pEvent && pEvent->ISA( VclWindowEvent ), "Unknown WindowEvent!" ); 223 if ( pEvent && pEvent->ISA( VclWindowEvent ) ) 224 { 225 DBG_ASSERT( ( (VclWindowEvent*)pEvent )->GetWindow() && m_pTabListBox, "no event window" ); 226 ProcessWindowEvent( *(VclWindowEvent*)pEvent ); 227 } 228 return 0; 229 } 230 // helpers -------------------------------------------------------------------- 231 232 void AccessibleTabListBoxTable::ensureValidIndex( sal_Int32 _nIndex ) const 233 SAL_THROW( ( IndexOutOfBoundsException ) ) 234 { 235 if ( ( _nIndex < 0 ) || ( _nIndex >= implGetCellCount() ) ) 236 throw IndexOutOfBoundsException(); 237 } 238 239 sal_Bool AccessibleTabListBoxTable::implIsRowSelected( sal_Int32 _nRow ) const 240 { 241 return m_pTabListBox ? m_pTabListBox->IsSelected( m_pTabListBox->GetEntry( _nRow ) ) : sal_False; 242 } 243 244 void AccessibleTabListBoxTable::implSelectRow( sal_Int32 _nRow, sal_Bool _bSelect ) 245 { 246 if ( m_pTabListBox ) 247 m_pTabListBox->Select( m_pTabListBox->GetEntry( _nRow ), _bSelect ); 248 } 249 250 sal_Int32 AccessibleTabListBoxTable::implGetRowCount() const 251 { 252 return m_pTabListBox ? m_pTabListBox->GetEntryCount() : 0; 253 } 254 255 sal_Int32 AccessibleTabListBoxTable::implGetColumnCount() const 256 { 257 return m_pTabListBox ? m_pTabListBox->GetColumnCount() : 0; 258 } 259 260 sal_Int32 AccessibleTabListBoxTable::implGetSelRowCount() const 261 { 262 return m_pTabListBox ? m_pTabListBox->GetSelectionCount() : 0; 263 } 264 265 sal_Int32 AccessibleTabListBoxTable::implGetSelRow( sal_Int32 nSelRow ) const 266 { 267 if ( m_pTabListBox ) 268 { 269 sal_Int32 nRow = 0; 270 SvLBoxEntry* pEntry = m_pTabListBox->FirstSelected(); 271 while ( pEntry ) 272 { 273 ++nRow; 274 if ( nRow == nSelRow ) 275 return m_pTabListBox->GetEntryPos( pEntry ); 276 pEntry = m_pTabListBox->NextSelected( pEntry ); 277 } 278 } 279 280 return 0; 281 } 282 // ----------------------------------------------------------------------------- 283 // XInterface & XTypeProvider 284 // ----------------------------------------------------------------------------- 285 IMPLEMENT_FORWARD_XINTERFACE2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper) 286 IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleTabListBoxTable, AccessibleBrowseBoxTable, AccessibleTabListBoxTableImplHelper) 287 // ----------------------------------------------------------------------------- 288 // XServiceInfo 289 // ----------------------------------------------------------------------------- 290 ::rtl::OUString AccessibleTabListBoxTable::getImplementationName (void) throw (RuntimeException) 291 { 292 return ::rtl::OUString::createFromAscii("com.sun.star.comp.svtools.AccessibleTabListBoxTable"); 293 } 294 // ----------------------------------------------------------------------------- 295 // XAccessibleSelection 296 // ----------------------------------------------------------------------------- 297 void SAL_CALL AccessibleTabListBoxTable::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 298 { 299 TLBSolarGuard aSolarGuard; 300 ::osl::MutexGuard aGuard( getOslMutex() ); 301 302 ensureIsAlive(); 303 ensureValidIndex( nChildIndex ); 304 305 implSelectRow( implGetRow( nChildIndex ), sal_True ); 306 } 307 // ----------------------------------------------------------------------------- 308 sal_Bool SAL_CALL AccessibleTabListBoxTable::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 309 { 310 TLBSolarGuard aSolarGuard; 311 ::osl::MutexGuard aGuard( getOslMutex() ); 312 313 ensureIsAlive(); 314 ensureValidIndex( nChildIndex ); 315 316 return implIsRowSelected( implGetRow( nChildIndex ) ); 317 } 318 // ----------------------------------------------------------------------------- 319 void SAL_CALL AccessibleTabListBoxTable::clearAccessibleSelection( ) throw (RuntimeException) 320 { 321 TLBSolarGuard aSolarGuard; 322 ::osl::MutexGuard aGuard( getOslMutex() ); 323 324 ensureIsAlive(); 325 326 m_pTabListBox->SetNoSelection(); 327 } 328 // ----------------------------------------------------------------------------- 329 void SAL_CALL AccessibleTabListBoxTable::selectAllAccessibleChildren( ) throw (RuntimeException) 330 { 331 TLBSolarGuard aSolarGuard; 332 ::osl::MutexGuard aGuard( getOslMutex() ); 333 334 ensureIsAlive(); 335 336 m_pTabListBox->SelectAll(); 337 } 338 // ----------------------------------------------------------------------------- 339 sal_Int32 SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChildCount( ) throw (RuntimeException) 340 { 341 TLBSolarGuard aSolarGuard; 342 ::osl::MutexGuard aGuard( getOslMutex() ); 343 344 ensureIsAlive(); 345 346 return implGetColumnCount() * implGetSelRowCount(); 347 } 348 // ----------------------------------------------------------------------------- 349 Reference< XAccessible > SAL_CALL AccessibleTabListBoxTable::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 350 { 351 TLBSolarGuard aSolarGuard; 352 ::osl::MutexGuard aGuard( getOslMutex() ); 353 354 ensureIsAlive(); 355 356 sal_Int32 nRows = implGetSelRowCount(); 357 if ( nRows == 0 ) 358 throw IndexOutOfBoundsException(); 359 360 sal_Int32 nRow = implGetSelRow( nSelectedChildIndex % nRows ); 361 sal_Int32 nColumn = nSelectedChildIndex / nRows; 362 return getAccessibleCellAt( nRow, nColumn ); 363 } 364 // ----------------------------------------------------------------------------- 365 void SAL_CALL AccessibleTabListBoxTable::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 366 { 367 TLBSolarGuard aSolarGuard; 368 ::osl::MutexGuard aGuard( getOslMutex() ); 369 370 ensureIsAlive(); 371 ensureValidIndex( nSelectedChildIndex ); 372 373 implSelectRow( implGetRow( nSelectedChildIndex ), sal_False ); 374 } 375 376 //........................................................................ 377 }// namespace accessibility 378 //........................................................................ 379 380