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