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/standard/vclxaccessibletabcontrol.hxx> 27 #include <accessibility/standard/vclxaccessibletabpage.hxx> 28 29 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 30 #include <com/sun/star/accessibility/AccessibleRole.hpp> 31 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 32 #include <unotools/accessiblestatesethelper.hxx> 33 #include <vcl/tabctrl.hxx> 34 #include <vcl/tabpage.hxx> 35 36 #include <vector> 37 38 using namespace ::com::sun::star; 39 using namespace ::com::sun::star::uno; 40 using namespace ::com::sun::star::lang; 41 using namespace ::com::sun::star::accessibility; 42 using namespace ::comphelper; 43 44 45 // ---------------------------------------------------- 46 // class VCLXAccessibleTabControl 47 // ---------------------------------------------------- 48 49 VCLXAccessibleTabControl::VCLXAccessibleTabControl( VCLXWindow* pVCLXWindow ) 50 :VCLXAccessibleComponent( pVCLXWindow ) 51 { 52 m_pTabControl = static_cast< TabControl* >( GetWindow() ); 53 54 if ( m_pTabControl ) 55 m_aAccessibleChildren.assign( m_pTabControl->GetPageCount(), Reference< XAccessible >() ); 56 } 57 58 // ----------------------------------------------------------------------------- 59 60 VCLXAccessibleTabControl::~VCLXAccessibleTabControl() 61 { 62 } 63 64 // ----------------------------------------------------------------------------- 65 66 void VCLXAccessibleTabControl::UpdateFocused() 67 { 68 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i ) 69 { 70 Reference< XAccessible > xChild( m_aAccessibleChildren[i] ); 71 if ( xChild.is() ) 72 { 73 VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() ); 74 if ( pVCLXAccessibleTabPage ) 75 pVCLXAccessibleTabPage->SetFocused( pVCLXAccessibleTabPage->IsFocused() ); 76 } 77 } 78 } 79 80 // ----------------------------------------------------------------------------- 81 82 void VCLXAccessibleTabControl::UpdateSelected( sal_Int32 i, bool bSelected ) 83 { 84 // IAccessible2 implementation, 2009 85 //NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); 86 87 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() ) 88 { 89 Reference< XAccessible > xChild( m_aAccessibleChildren[i] ); 90 if ( xChild.is() ) 91 { 92 VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() ); 93 if ( pVCLXAccessibleTabPage ) 94 pVCLXAccessibleTabPage->SetSelected( bSelected ); 95 } 96 } 97 } 98 99 // ----------------------------------------------------------------------------- 100 101 void VCLXAccessibleTabControl::UpdatePageText( sal_Int32 i ) 102 { 103 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() ) 104 { 105 Reference< XAccessible > xChild( m_aAccessibleChildren[i] ); 106 if ( xChild.is() ) 107 { 108 VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() ); 109 if ( pVCLXAccessibleTabPage ) 110 pVCLXAccessibleTabPage->SetPageText( pVCLXAccessibleTabPage->GetPageText() ); 111 } 112 } 113 } 114 115 // ----------------------------------------------------------------------------- 116 117 void VCLXAccessibleTabControl::UpdateTabPage( sal_Int32 i, bool bNew ) 118 { 119 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() ) 120 { 121 Reference< XAccessible > xChild( m_aAccessibleChildren[i] ); 122 if ( xChild.is() ) 123 { 124 VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() ); 125 if ( pVCLXAccessibleTabPage ) 126 pVCLXAccessibleTabPage->Update( bNew ); 127 } 128 } 129 } 130 131 // ----------------------------------------------------------------------------- 132 133 void VCLXAccessibleTabControl::InsertChild( sal_Int32 i ) 134 { 135 if ( i >= 0 && i <= (sal_Int32)m_aAccessibleChildren.size() ) 136 { 137 // insert entry in child list 138 m_aAccessibleChildren.insert( m_aAccessibleChildren.begin() + i, Reference< XAccessible >() ); 139 140 // send accessible child event 141 Reference< XAccessible > xChild( getAccessibleChild( i ) ); 142 if ( xChild.is() ) 143 { 144 Any aOldValue, aNewValue; 145 aNewValue <<= xChild; 146 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue ); 147 } 148 } 149 } 150 151 // ----------------------------------------------------------------------------- 152 153 void VCLXAccessibleTabControl::RemoveChild( sal_Int32 i ) 154 { 155 if ( i >= 0 && i < (sal_Int32)m_aAccessibleChildren.size() ) 156 { 157 // get the accessible of the removed page 158 Reference< XAccessible > xChild( m_aAccessibleChildren[i] ); 159 160 // remove entry in child list 161 m_aAccessibleChildren.erase( m_aAccessibleChildren.begin() + i ); 162 163 // send accessible child event 164 if ( xChild.is() ) 165 { 166 Any aOldValue, aNewValue; 167 aOldValue <<= xChild; 168 NotifyAccessibleEvent( AccessibleEventId::CHILD, aOldValue, aNewValue ); 169 170 Reference< XComponent > xComponent( xChild, UNO_QUERY ); 171 if ( xComponent.is() ) 172 xComponent->dispose(); 173 } 174 } 175 } 176 177 // ----------------------------------------------------------------------------- 178 179 void VCLXAccessibleTabControl::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) 180 { 181 switch ( rVclWindowEvent.GetId() ) 182 { 183 case VCLEVENT_TABPAGE_ACTIVATE: 184 case VCLEVENT_TABPAGE_DEACTIVATE: 185 { 186 if ( m_pTabControl ) 187 { 188 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData(); 189 sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId ); 190 UpdateFocused(); 191 UpdateSelected( nPagePos, rVclWindowEvent.GetId() == VCLEVENT_TABPAGE_ACTIVATE ); 192 } 193 } 194 break; 195 case VCLEVENT_TABPAGE_PAGETEXTCHANGED: 196 { 197 if ( m_pTabControl ) 198 { 199 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData(); 200 sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId ); 201 UpdatePageText( nPagePos ); 202 } 203 } 204 break; 205 case VCLEVENT_TABPAGE_INSERTED: 206 { 207 if ( m_pTabControl ) 208 { 209 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData(); 210 sal_uInt16 nPagePos = m_pTabControl->GetPagePos( nPageId ); 211 InsertChild( nPagePos ); 212 } 213 } 214 break; 215 case VCLEVENT_TABPAGE_REMOVED: 216 { 217 if ( m_pTabControl ) 218 { 219 sal_uInt16 nPageId = (sal_uInt16)(sal_IntPtr) rVclWindowEvent.GetData(); 220 for ( sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i ) 221 { 222 Reference< XAccessible > xChild( getAccessibleChild( i ) ); 223 if ( xChild.is() ) 224 { 225 VCLXAccessibleTabPage* pVCLXAccessibleTabPage = static_cast< VCLXAccessibleTabPage* >( xChild.get() ); 226 if ( pVCLXAccessibleTabPage && pVCLXAccessibleTabPage->GetPageId() == nPageId ) 227 { 228 RemoveChild( i ); 229 break; 230 } 231 } 232 } 233 } 234 } 235 break; 236 case VCLEVENT_TABPAGE_REMOVEDALL: 237 { 238 for ( sal_Int32 i = m_aAccessibleChildren.size() - 1; i >= 0; --i ) 239 RemoveChild( i ); 240 } 241 break; 242 case VCLEVENT_WINDOW_GETFOCUS: 243 case VCLEVENT_WINDOW_LOSEFOCUS: 244 { 245 UpdateFocused(); 246 } 247 break; 248 case VCLEVENT_OBJECT_DYING: 249 { 250 if ( m_pTabControl ) 251 { 252 m_pTabControl = NULL; 253 254 // dispose all tab pages 255 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i ) 256 { 257 Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY ); 258 if ( xComponent.is() ) 259 xComponent->dispose(); 260 } 261 m_aAccessibleChildren.clear(); 262 } 263 264 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent ); 265 } 266 break; 267 default: 268 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent ); 269 } 270 } 271 272 // ----------------------------------------------------------------------------- 273 274 void VCLXAccessibleTabControl::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent ) 275 { 276 switch ( rVclWindowEvent.GetId() ) 277 { 278 case VCLEVENT_WINDOW_SHOW: 279 case VCLEVENT_WINDOW_HIDE: 280 { 281 if ( m_pTabControl ) 282 { 283 Window* pChild = static_cast< Window* >( rVclWindowEvent.GetData() ); 284 if ( pChild && pChild->GetType() == WINDOW_TABPAGE ) 285 { 286 for ( sal_Int32 i = 0, nCount = m_pTabControl->GetPageCount(); i < nCount; ++i ) 287 { 288 sal_uInt16 nPageId = m_pTabControl->GetPageId( (sal_uInt16)i ); 289 TabPage* pTabPage = m_pTabControl->GetTabPage( nPageId ); 290 if ( pTabPage == (TabPage*) pChild ) 291 UpdateTabPage( i, rVclWindowEvent.GetId() == VCLEVENT_WINDOW_SHOW ); 292 } 293 } 294 } 295 } 296 break; 297 default: 298 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent ); 299 } 300 } 301 302 303 // ----------------------------------------------------------------------------- 304 305 void VCLXAccessibleTabControl::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) 306 { 307 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet ); 308 309 if ( m_pTabControl ) 310 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 311 } 312 313 // ----------------------------------------------------------------------------- 314 // XInterface 315 // ----------------------------------------------------------------------------- 316 317 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE ) 318 319 // ----------------------------------------------------------------------------- 320 // XTypeProvider 321 // ----------------------------------------------------------------------------- 322 323 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTabControl, VCLXAccessibleComponent, VCLXAccessibleTabControl_BASE ) 324 325 // ----------------------------------------------------------------------------- 326 // XComponent 327 // ----------------------------------------------------------------------------- 328 329 void VCLXAccessibleTabControl::disposing() 330 { 331 VCLXAccessibleComponent::disposing(); 332 333 if ( m_pTabControl ) 334 { 335 m_pTabControl = NULL; 336 337 // dispose all tab pages 338 for ( sal_uInt32 i = 0; i < m_aAccessibleChildren.size(); ++i ) 339 { 340 Reference< XComponent > xComponent( m_aAccessibleChildren[i], UNO_QUERY ); 341 if ( xComponent.is() ) 342 xComponent->dispose(); 343 } 344 m_aAccessibleChildren.clear(); 345 } 346 } 347 348 // ----------------------------------------------------------------------------- 349 // XServiceInfo 350 // ----------------------------------------------------------------------------- 351 352 ::rtl::OUString VCLXAccessibleTabControl::getImplementationName() throw (RuntimeException) 353 { 354 return ::rtl::OUString::createFromAscii( "com.sun.star.comp.toolkit.AccessibleTabControl" ); 355 } 356 357 // ----------------------------------------------------------------------------- 358 359 Sequence< ::rtl::OUString > VCLXAccessibleTabControl::getSupportedServiceNames() throw (RuntimeException) 360 { 361 Sequence< ::rtl::OUString > aNames(1); 362 aNames[0] = ::rtl::OUString::createFromAscii( "com.sun.star.awt.AccessibleTabControl" ); 363 return aNames; 364 } 365 366 // ----------------------------------------------------------------------------- 367 // XAccessibleContext 368 // ----------------------------------------------------------------------------- 369 370 sal_Int32 VCLXAccessibleTabControl::getAccessibleChildCount() throw (RuntimeException) 371 { 372 OExternalLockGuard aGuard( this ); 373 374 return m_aAccessibleChildren.size(); 375 } 376 377 // ----------------------------------------------------------------------------- 378 379 Reference< XAccessible > VCLXAccessibleTabControl::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException, RuntimeException) 380 { 381 OExternalLockGuard aGuard( this ); 382 383 if ( i < 0 || i >= getAccessibleChildCount() ) 384 throw IndexOutOfBoundsException(); 385 386 Reference< XAccessible > xChild = m_aAccessibleChildren[i]; 387 if ( !xChild.is() ) 388 { 389 if ( m_pTabControl ) 390 { 391 sal_uInt16 nPageId = m_pTabControl->GetPageId( (sal_uInt16)i ); 392 393 xChild = new VCLXAccessibleTabPage( m_pTabControl, nPageId ); 394 395 // insert into tab page list 396 m_aAccessibleChildren[i] = xChild; 397 } 398 } 399 400 return xChild; 401 } 402 403 // ----------------------------------------------------------------------------- 404 405 sal_Int16 VCLXAccessibleTabControl::getAccessibleRole( ) throw (RuntimeException) 406 { 407 OExternalLockGuard aGuard( this ); 408 409 return AccessibleRole::PAGE_TAB_LIST; 410 } 411 412 // ----------------------------------------------------------------------------- 413 414 ::rtl::OUString VCLXAccessibleTabControl::getAccessibleName( ) throw (RuntimeException) 415 { 416 OExternalLockGuard aGuard( this ); 417 418 return ::rtl::OUString(); 419 } 420 421 // ----------------------------------------------------------------------------- 422 // XAccessibleSelection 423 // ----------------------------------------------------------------------------- 424 425 void VCLXAccessibleTabControl::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 426 { 427 OExternalLockGuard aGuard( this ); 428 429 if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) 430 throw IndexOutOfBoundsException(); 431 432 if ( m_pTabControl ) 433 m_pTabControl->SelectTabPage( m_pTabControl->GetPageId( (sal_uInt16)nChildIndex ) ); 434 } 435 436 // ----------------------------------------------------------------------------- 437 438 sal_Bool VCLXAccessibleTabControl::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 439 { 440 OExternalLockGuard aGuard( this ); 441 442 if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) 443 throw IndexOutOfBoundsException(); 444 445 sal_Bool bSelected = sal_False; 446 if ( m_pTabControl && m_pTabControl->GetCurPageId() == m_pTabControl->GetPageId( (sal_uInt16)nChildIndex ) ) 447 bSelected = sal_True; 448 449 return bSelected; 450 } 451 452 // ----------------------------------------------------------------------------- 453 454 void VCLXAccessibleTabControl::clearAccessibleSelection( ) throw (RuntimeException) 455 { 456 // This method makes no sense in a tab control, and so does nothing. 457 } 458 459 // ----------------------------------------------------------------------------- 460 461 void VCLXAccessibleTabControl::selectAllAccessibleChildren( ) throw (RuntimeException) 462 { 463 OExternalLockGuard aGuard( this ); 464 465 selectAccessibleChild( 0 ); 466 } 467 468 // ----------------------------------------------------------------------------- 469 470 sal_Int32 VCLXAccessibleTabControl::getSelectedAccessibleChildCount( ) throw (RuntimeException) 471 { 472 OExternalLockGuard aGuard( this ); 473 474 return 1; 475 } 476 477 // ----------------------------------------------------------------------------- 478 479 Reference< XAccessible > VCLXAccessibleTabControl::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 480 { 481 OExternalLockGuard aGuard( this ); 482 483 if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() ) 484 throw IndexOutOfBoundsException(); 485 486 Reference< XAccessible > xChild; 487 488 for ( sal_Int32 i = 0, j = 0, nCount = getAccessibleChildCount(); i < nCount; i++ ) 489 { 490 if ( isAccessibleChildSelected( i ) && ( j++ == nSelectedChildIndex ) ) 491 { 492 xChild = getAccessibleChild( i ); 493 break; 494 } 495 } 496 497 return xChild; 498 } 499 500 // ----------------------------------------------------------------------------- 501 502 void VCLXAccessibleTabControl::deselectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 503 { 504 OExternalLockGuard aGuard( this ); 505 506 if ( nChildIndex < 0 || nChildIndex >= getAccessibleChildCount() ) 507 throw IndexOutOfBoundsException(); 508 509 // This method makes no sense in a tab control, and so does nothing. 510 } 511 512 // ----------------------------------------------------------------------------- 513