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