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 #include "accessibility/extended/AccessibleBrowseBox.hxx" 31 #include "accessibility/extended/AccessibleBrowseBoxTable.hxx" 32 #include "accessibility/extended/AccessibleBrowseBoxHeaderBar.hxx" 33 #include <svtools/accessibletableprovider.hxx> 34 #include <comphelper/types.hxx> 35 #include <toolkit/helper/vclunohelper.hxx> 36 37 // ============================================================================ 38 39 namespace accessibility 40 { 41 42 // ============================================================================ 43 44 using ::rtl::OUString; 45 46 using namespace ::com::sun::star::uno; 47 using namespace ::com::sun::star; 48 using namespace ::com::sun::star::lang; 49 using namespace ::com::sun::star::accessibility; 50 using namespace ::svt; 51 52 // ============================================================================ 53 class AccessibleBrowseBoxImpl 54 { 55 public: 56 /// the XAccessible which created the AccessibleBrowseBox 57 WeakReference< XAccessible > m_aCreator; 58 59 /** The data table child. */ 60 Reference< 61 ::com::sun::star::accessibility::XAccessible > mxTable; 62 AccessibleBrowseBoxTable* m_pTable; 63 64 /** The header bar for rows ("handle column"). */ 65 Reference< 66 ::com::sun::star::accessibility::XAccessible > mxRowHeaderBar; 67 AccessibleBrowseBoxHeaderBar* m_pRowHeaderBar; 68 69 /** The header bar for columns (first row of the table). */ 70 Reference< 71 ::com::sun::star::accessibility::XAccessible > mxColumnHeaderBar; 72 AccessibleBrowseBoxHeaderBar* m_pColumnHeaderBar; 73 }; 74 75 // Ctor/Dtor/disposing -------------------------------------------------------- 76 77 DBG_NAME( AccessibleBrowseBox ) 78 79 AccessibleBrowseBox::AccessibleBrowseBox( 80 const Reference< XAccessible >& _rxParent, const Reference< XAccessible >& _rxCreator, 81 IAccessibleTableProvider& _rBrowseBox ) 82 : AccessibleBrowseBoxBase( _rxParent, _rBrowseBox,NULL, BBTYPE_BROWSEBOX ) 83 { 84 DBG_CTOR( AccessibleBrowseBox, NULL ); 85 m_pImpl.reset( new AccessibleBrowseBoxImpl() ); 86 m_pImpl->m_aCreator = _rxCreator; 87 88 m_xFocusWindow = VCLUnoHelper::GetInterface(mpBrowseBox->GetWindowInstance()); 89 } 90 // ----------------------------------------------------------------------------- 91 void AccessibleBrowseBox::setCreator( const Reference< XAccessible >& _rxCreator ) 92 { 93 #if OSL_DEBUG_LEVEL > 0 94 Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator; 95 DBG_ASSERT( !xCreator.is(), "accessibility/extended/AccessibleBrowseBox::setCreator: creator already set!" ); 96 #endif 97 m_pImpl->m_aCreator = _rxCreator; 98 } 99 100 // ----------------------------------------------------------------------------- 101 AccessibleBrowseBox::~AccessibleBrowseBox() 102 { 103 DBG_DTOR( AccessibleBrowseBox, NULL ); 104 } 105 // ----------------------------------------------------------------------------- 106 107 void SAL_CALL AccessibleBrowseBox::disposing() 108 { 109 ::osl::MutexGuard aGuard( getOslMutex() ); 110 111 m_pImpl->m_pTable = NULL; 112 m_pImpl->m_pColumnHeaderBar = NULL; 113 m_pImpl->m_pRowHeaderBar = NULL; 114 m_pImpl->m_aCreator = Reference< XAccessible >(); 115 116 Reference< XAccessible > xTable = m_pImpl->mxTable; 117 118 Reference< XComponent > xComp( m_pImpl->mxTable, UNO_QUERY ); 119 if ( xComp.is() ) 120 { 121 xComp->dispose(); 122 123 } 124 //! ::comphelper::disposeComponent(m_pImpl->mxTable); 125 ::comphelper::disposeComponent(m_pImpl->mxRowHeaderBar); 126 ::comphelper::disposeComponent(m_pImpl->mxColumnHeaderBar); 127 128 AccessibleBrowseBoxBase::disposing(); 129 } 130 // ----------------------------------------------------------------------------- 131 132 // XAccessibleContext --------------------------------------------------------- 133 134 sal_Int32 SAL_CALL AccessibleBrowseBox::getAccessibleChildCount() 135 throw ( uno::RuntimeException ) 136 { 137 BBSolarGuard aSolarGuard; 138 ::osl::MutexGuard aGuard( getOslMutex() ); 139 ensureIsAlive(); 140 return BBINDEX_FIRSTCONTROL + mpBrowseBox->GetAccessibleControlCount(); 141 } 142 // ----------------------------------------------------------------------------- 143 144 Reference< XAccessible > SAL_CALL 145 AccessibleBrowseBox::getAccessibleChild( sal_Int32 nChildIndex ) 146 throw ( lang::IndexOutOfBoundsException, uno::RuntimeException ) 147 { 148 BBSolarGuard aSolarGuard; 149 ::osl::MutexGuard aGuard( getOslMutex() ); 150 ensureIsAlive(); 151 152 Reference< XAccessible > xRet; 153 if( nChildIndex >= 0 ) 154 { 155 if( nChildIndex < BBINDEX_FIRSTCONTROL ) 156 xRet = implGetFixedChild( nChildIndex ); 157 else 158 { 159 // additional controls 160 nChildIndex -= BBINDEX_FIRSTCONTROL; 161 if( nChildIndex < mpBrowseBox->GetAccessibleControlCount() ) 162 xRet = mpBrowseBox->CreateAccessibleControl( nChildIndex ); 163 } 164 } 165 166 if( !xRet.is() ) 167 throw lang::IndexOutOfBoundsException(); 168 return xRet; 169 } 170 // ----------------------------------------------------------------------------- 171 172 //sal_Int16 SAL_CALL AccessibleBrowseBox::getAccessibleRole() 173 // throw ( uno::RuntimeException ) 174 //{ 175 // ensureIsAlive(); 176 // return AccessibleRole::PANEL; 177 //} 178 // ----------------------------------------------------------------------------- 179 180 // XAccessibleComponent ------------------------------------------------------- 181 182 Reference< XAccessible > SAL_CALL 183 AccessibleBrowseBox::getAccessibleAtPoint( const awt::Point& rPoint ) 184 throw ( uno::RuntimeException ) 185 { 186 BBSolarGuard aSolarGuard; 187 ::osl::MutexGuard aGuard( getOslMutex() ); 188 ensureIsAlive(); 189 190 Reference< XAccessible > xChild; 191 sal_Int32 nIndex = 0; 192 if( mpBrowseBox->ConvertPointToControlIndex( nIndex, VCLPoint( rPoint ) ) ) 193 xChild = mpBrowseBox->CreateAccessibleControl( nIndex ); 194 else 195 { 196 // try whether point is in one of the fixed children 197 // (table, header bars, corner control) 198 Point aPoint( VCLPoint( rPoint ) ); 199 for( nIndex = 0; (nIndex < BBINDEX_FIRSTCONTROL) && !xChild.is(); ++nIndex ) 200 { 201 Reference< XAccessible > xCurrChild( implGetFixedChild( nIndex ) ); 202 Reference< XAccessibleComponent > 203 xCurrChildComp( xCurrChild, uno::UNO_QUERY ); 204 205 if( xCurrChildComp.is() && 206 VCLRectangle( xCurrChildComp->getBounds() ).IsInside( aPoint ) ) 207 xChild = xCurrChild; 208 } 209 } 210 return xChild; 211 } 212 // ----------------------------------------------------------------------------- 213 214 void SAL_CALL AccessibleBrowseBox::grabFocus() 215 throw ( uno::RuntimeException ) 216 { 217 BBSolarGuard aSolarGuard; 218 ::osl::MutexGuard aGuard( getOslMutex() ); 219 ensureIsAlive(); 220 mpBrowseBox->GrabFocus(); 221 } 222 // ----------------------------------------------------------------------------- 223 224 Any SAL_CALL AccessibleBrowseBox::getAccessibleKeyBinding() 225 throw ( uno::RuntimeException ) 226 { 227 ensureIsAlive(); 228 return Any(); 229 } 230 // ----------------------------------------------------------------------------- 231 232 // XServiceInfo --------------------------------------------------------------- 233 234 OUString SAL_CALL AccessibleBrowseBox::getImplementationName() 235 throw ( uno::RuntimeException ) 236 { 237 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.svtools.AccessibleBrowseBox" ) ); 238 } 239 // ----------------------------------------------------------------------------- 240 241 // internal virtual methods --------------------------------------------------- 242 243 Rectangle AccessibleBrowseBox::implGetBoundingBox() 244 { 245 Window* pParent = mpBrowseBox->GetAccessibleParentWindow(); 246 DBG_ASSERT( pParent, "implGetBoundingBox - missing parent window" ); 247 return mpBrowseBox->GetWindowExtentsRelative( pParent ); 248 } 249 // ----------------------------------------------------------------------------- 250 251 Rectangle AccessibleBrowseBox::implGetBoundingBoxOnScreen() 252 { 253 return mpBrowseBox->GetWindowExtentsRelative( NULL ); 254 } 255 // ----------------------------------------------------------------------------- 256 257 // internal helper methods ---------------------------------------------------- 258 259 Reference< XAccessible > AccessibleBrowseBox::implGetTable() 260 { 261 if( !m_pImpl->mxTable.is() ) 262 { 263 m_pImpl->m_pTable = createAccessibleTable(); 264 m_pImpl->mxTable = m_pImpl->m_pTable; 265 266 } 267 return m_pImpl->mxTable; 268 } 269 // ----------------------------------------------------------------------------- 270 271 Reference< XAccessible > 272 AccessibleBrowseBox::implGetHeaderBar( AccessibleBrowseBoxObjType eObjType ) 273 { 274 Reference< XAccessible > xRet; 275 Reference< XAccessible >* pxMember = NULL; 276 277 if( eObjType == BBTYPE_ROWHEADERBAR ) 278 pxMember = &m_pImpl->mxRowHeaderBar; 279 else if( eObjType == BBTYPE_COLUMNHEADERBAR ) 280 pxMember = &m_pImpl->mxColumnHeaderBar; 281 282 if( pxMember ) 283 { 284 if( !pxMember->is() ) 285 { 286 AccessibleBrowseBoxHeaderBar* pHeaderBar = new AccessibleBrowseBoxHeaderBar( 287 (Reference< XAccessible >)m_pImpl->m_aCreator, *mpBrowseBox, eObjType ); 288 289 if ( BBTYPE_COLUMNHEADERBAR == eObjType) 290 m_pImpl->m_pColumnHeaderBar = pHeaderBar; 291 else 292 m_pImpl->m_pRowHeaderBar = pHeaderBar; 293 294 *pxMember = pHeaderBar; 295 } 296 xRet = *pxMember; 297 } 298 return xRet; 299 } 300 // ----------------------------------------------------------------------------- 301 302 Reference< XAccessible > 303 AccessibleBrowseBox::implGetFixedChild( sal_Int32 nChildIndex ) 304 { 305 Reference< XAccessible > xRet; 306 switch( nChildIndex ) 307 { 308 case BBINDEX_COLUMNHEADERBAR: 309 xRet = implGetHeaderBar( BBTYPE_COLUMNHEADERBAR ); 310 break; 311 case BBINDEX_ROWHEADERBAR: 312 xRet = implGetHeaderBar( BBTYPE_ROWHEADERBAR ); 313 break; 314 case BBINDEX_TABLE: 315 xRet = implGetTable(); 316 break; 317 } 318 return xRet; 319 } 320 // ----------------------------------------------------------------------------- 321 AccessibleBrowseBoxTable* AccessibleBrowseBox::createAccessibleTable() 322 { 323 Reference< XAccessible > xCreator = (Reference< XAccessible >)m_pImpl->m_aCreator; 324 DBG_ASSERT( xCreator.is(), "accessibility/extended/AccessibleBrowseBox::createAccessibleTable: my creator died - how this?" ); 325 return new AccessibleBrowseBoxTable( xCreator, *mpBrowseBox ); 326 } 327 // ----------------------------------------------------------------------------- 328 void AccessibleBrowseBox::commitTableEvent(sal_Int16 _nEventId,const Any& _rNewValue,const Any& _rOldValue) 329 { 330 if ( m_pImpl->mxTable.is() ) 331 { 332 m_pImpl->m_pTable->commitEvent(_nEventId,_rNewValue,_rOldValue); 333 } 334 } 335 // ----------------------------------------------------------------------------- 336 void AccessibleBrowseBox::commitHeaderBarEvent( sal_Int16 _nEventId, 337 const Any& _rNewValue, 338 const Any& _rOldValue,sal_Bool _bColumnHeaderBar) 339 { 340 Reference< XAccessible > xHeaderBar = _bColumnHeaderBar ? m_pImpl->mxColumnHeaderBar : m_pImpl->mxRowHeaderBar; 341 AccessibleBrowseBoxHeaderBar* pHeaderBar = _bColumnHeaderBar ? m_pImpl->m_pColumnHeaderBar : m_pImpl->m_pRowHeaderBar; 342 if ( xHeaderBar.is() ) 343 pHeaderBar->commitEvent(_nEventId,_rNewValue,_rOldValue); 344 } 345 346 // ============================================================================ 347 // = AccessibleBrowseBoxAccess 348 // ============================================================================ 349 DBG_NAME( AccessibleBrowseBoxAccess ) 350 // ----------------------------------------------------------------------------- 351 AccessibleBrowseBoxAccess::AccessibleBrowseBoxAccess( const Reference< XAccessible >& _rxParent, IAccessibleTableProvider& _rBrowseBox ) 352 :m_xParent( _rxParent ) 353 ,m_rBrowseBox( _rBrowseBox ) 354 ,m_pContext( NULL ) 355 { 356 DBG_CTOR( AccessibleBrowseBoxAccess, NULL ); 357 } 358 359 // ----------------------------------------------------------------------------- 360 AccessibleBrowseBoxAccess::~AccessibleBrowseBoxAccess() 361 { 362 DBG_DTOR( AccessibleBrowseBoxAccess, NULL ); 363 } 364 365 // ----------------------------------------------------------------------------- 366 void AccessibleBrowseBoxAccess::dispose() 367 { 368 ::osl::MutexGuard aGuard( m_aMutex ); 369 370 m_pContext = NULL; 371 ::comphelper::disposeComponent( m_xContext ); 372 } 373 374 // ----------------------------------------------------------------------------- 375 Reference< XAccessibleContext > SAL_CALL AccessibleBrowseBoxAccess::getAccessibleContext() throw ( RuntimeException ) 376 { 377 ::osl::MutexGuard aGuard( m_aMutex ); 378 379 DBG_ASSERT( ( m_pContext && m_xContext.is() ) || ( !m_pContext && !m_xContext.is() ), 380 "accessibility/extended/AccessibleBrowseBoxAccess::getAccessibleContext: inconsistency!" ); 381 382 // if the context died meanwhile (we're no listener, so it won't tell us explicitily when this happens), 383 // then reset an re-create. 384 if ( m_pContext && !m_pContext->isAlive() ) 385 m_xContext = m_pContext = NULL; 386 387 if ( !m_xContext.is() ) 388 m_xContext = m_pContext = new AccessibleBrowseBox( m_xParent, this, m_rBrowseBox ); 389 390 return m_xContext; 391 } 392 393 // ----------------------------------------------------------------------------- 394 bool AccessibleBrowseBoxAccess::isContextAlive() const 395 { 396 return ( NULL != m_pContext ) && m_pContext->isAlive(); 397 } 398 399 // ============================================================================ 400 401 } // namespace accessibility 402