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