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