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/accessiblelistbox.hxx> 31 #include <accessibility/extended/accessiblelistboxentry.hxx> 32 #include <svtools/svtreebx.hxx> 33 #include <com/sun/star/awt/Point.hpp> 34 #include <com/sun/star/awt/Rectangle.hpp> 35 #include <com/sun/star/awt/Size.hpp> 36 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 37 #include <com/sun/star/accessibility/AccessibleRole.hpp> 38 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 39 #include <tools/debug.hxx> 40 #include <vcl/svapp.hxx> 41 #include <toolkit/awt/vclxwindow.hxx> 42 #include <toolkit/helper/convert.hxx> 43 #include <unotools/accessiblestatesethelper.hxx> 44 45 //........................................................................ 46 namespace accessibility 47 { 48 //........................................................................ 49 50 // class AccessibleListBox ----------------------------------------------------- 51 52 using namespace ::com::sun::star::accessibility; 53 using namespace ::com::sun::star::uno; 54 using namespace ::com::sun::star::lang; 55 using namespace ::com::sun::star; 56 57 DBG_NAME(AccessibleListBox) 58 59 // ----------------------------------------------------------------------------- 60 // Ctor() and Dtor() 61 // ----------------------------------------------------------------------------- 62 AccessibleListBox::AccessibleListBox( SvTreeListBox& _rListBox, const Reference< XAccessible >& _xParent ) : 63 64 VCLXAccessibleComponent( _rListBox.GetWindowPeer() ), 65 m_xParent( _xParent ) 66 { 67 DBG_CTOR( AccessibleListBox, NULL ); 68 } 69 // ----------------------------------------------------------------------------- 70 AccessibleListBox::~AccessibleListBox() 71 { 72 DBG_DTOR( AccessibleListBox, NULL ); 73 if ( isAlive() ) 74 { 75 // increment ref count to prevent double call of Dtor 76 osl_incrementInterlockedCount( &m_refCount ); 77 dispose(); 78 } 79 } 80 IMPLEMENT_FORWARD_XINTERFACE2(AccessibleListBox, VCLXAccessibleComponent, AccessibleListBox_BASE) 81 IMPLEMENT_FORWARD_XTYPEPROVIDER2(AccessibleListBox, VCLXAccessibleComponent, AccessibleListBox_BASE) 82 // ----------------------------------------------------------------------------- 83 SvTreeListBox* AccessibleListBox::getListBox() const 84 { 85 return static_cast< SvTreeListBox* >( const_cast<AccessibleListBox*>(this)->GetWindow() ); 86 } 87 // ----------------------------------------------------------------------------- 88 void AccessibleListBox::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) 89 { 90 if ( isAlive() ) 91 { 92 switch ( rVclWindowEvent.GetId() ) 93 { 94 case VCLEVENT_CHECKBOX_TOGGLE : 95 { 96 if ( getListBox() && getListBox()->HasFocus() ) 97 { 98 SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); 99 if ( !pEntry ) 100 pEntry = getListBox()->GetCurEntry(); 101 102 if ( pEntry ) 103 { 104 Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this ); 105 uno::Any aOldValue, aNewValue; 106 aNewValue <<= xChild; 107 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue ); 108 } 109 } 110 break; 111 } 112 113 case VCLEVENT_LISTBOX_SELECT : 114 { 115 // First send an event that tells the listeners of a 116 // modified selection. The active descendant event is 117 // send after that so that the receiving AT has time to 118 // read the text or name of the active child. 119 NotifyAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), Any() ); 120 if ( getListBox() && getListBox()->HasFocus() ) 121 { 122 SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); 123 if ( pEntry ) 124 { 125 Reference< XAccessible > xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this ); 126 uno::Any aOldValue, aNewValue; 127 aNewValue <<= xChild; 128 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, aOldValue, aNewValue ); 129 } 130 } 131 break; 132 133 // --> OD 2009-04-01 #i92103# 134 case VCLEVENT_ITEM_EXPANDED : 135 case VCLEVENT_ITEM_COLLAPSED : 136 { 137 SvLBoxEntry* pEntry = static_cast< SvLBoxEntry* >( rVclWindowEvent.GetData() ); 138 if ( pEntry ) 139 { 140 AccessibleListBoxEntry* pAccListBoxEntry = 141 new AccessibleListBoxEntry( *getListBox(), pEntry, this ); 142 Reference< XAccessible > xChild = pAccListBoxEntry; 143 const short nAccEvent = 144 ( rVclWindowEvent.GetId() == VCLEVENT_ITEM_EXPANDED ) 145 ? AccessibleEventId::LISTBOX_ENTRY_EXPANDED 146 : AccessibleEventId::LISTBOX_ENTRY_COLLAPSED; 147 uno::Any aListBoxEntry; 148 aListBoxEntry <<= xChild; 149 NotifyAccessibleEvent( nAccEvent, Any(), aListBoxEntry ); 150 if ( getListBox() && getListBox()->HasFocus() ) 151 { 152 NotifyAccessibleEvent( AccessibleEventId::ACTIVE_DESCENDANT_CHANGED, Any(), aListBoxEntry ); 153 } 154 } 155 break; 156 } 157 // <-- 158 } 159 default: 160 VCLXAccessibleComponent::ProcessWindowEvent (rVclWindowEvent); 161 } 162 } 163 } 164 // ----------------------------------------------------------------------------- 165 void AccessibleListBox::ProcessWindowChildEvent( const VclWindowEvent& rVclWindowEvent ) 166 { 167 switch ( rVclWindowEvent.GetId() ) 168 { 169 case VCLEVENT_WINDOW_SHOW: 170 case VCLEVENT_WINDOW_HIDE: 171 { 172 } 173 break; 174 default: 175 { 176 VCLXAccessibleComponent::ProcessWindowChildEvent( rVclWindowEvent ); 177 } 178 break; 179 } 180 } 181 182 // ----------------------------------------------------------------------------- 183 // XComponent 184 // ----------------------------------------------------------------------------- 185 void SAL_CALL AccessibleListBox::disposing() 186 { 187 ::osl::MutexGuard aGuard( m_aMutex ); 188 189 VCLXAccessibleComponent::disposing(); 190 m_xParent = NULL; 191 } 192 // ----------------------------------------------------------------------------- 193 // XServiceInfo 194 // ----------------------------------------------------------------------------- 195 ::rtl::OUString SAL_CALL AccessibleListBox::getImplementationName() throw(RuntimeException) 196 { 197 return getImplementationName_Static(); 198 } 199 // ----------------------------------------------------------------------------- 200 Sequence< ::rtl::OUString > SAL_CALL AccessibleListBox::getSupportedServiceNames() throw(RuntimeException) 201 { 202 return getSupportedServiceNames_Static(); 203 } 204 // ----------------------------------------------------------------------------- 205 sal_Bool SAL_CALL AccessibleListBox::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) 206 { 207 Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); 208 const ::rtl::OUString* pSupported = aSupported.getConstArray(); 209 const ::rtl::OUString* pEnd = pSupported + aSupported.getLength(); 210 for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported ) 211 ; 212 213 return pSupported != pEnd; 214 } 215 // ----------------------------------------------------------------------------- 216 // XServiceInfo - static methods 217 // ----------------------------------------------------------------------------- 218 Sequence< ::rtl::OUString > AccessibleListBox::getSupportedServiceNames_Static(void) throw( RuntimeException ) 219 { 220 Sequence< ::rtl::OUString > aSupported(3); 221 aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") ); 222 aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") ); 223 aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleTreeListBox") ); 224 return aSupported; 225 } 226 // ----------------------------------------------------------------------------- 227 ::rtl::OUString AccessibleListBox::getImplementationName_Static(void) throw( RuntimeException ) 228 { 229 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleTreeListBox") ); 230 } 231 // ----------------------------------------------------------------------------- 232 // XAccessible 233 // ----------------------------------------------------------------------------- 234 Reference< XAccessibleContext > SAL_CALL AccessibleListBox::getAccessibleContext( ) throw (RuntimeException) 235 { 236 ensureAlive(); 237 return this; 238 } 239 // ----------------------------------------------------------------------------- 240 // XAccessibleContext 241 // ----------------------------------------------------------------------------- 242 sal_Int32 SAL_CALL AccessibleListBox::getAccessibleChildCount( ) throw (RuntimeException) 243 { 244 ::comphelper::OExternalLockGuard aGuard( this ); 245 246 ensureAlive(); 247 248 sal_Int32 nCount = 0; 249 SvTreeListBox* pSvTreeListBox = getListBox(); 250 if ( pSvTreeListBox ) 251 nCount = pSvTreeListBox->GetLevelChildCount( NULL ); 252 253 return nCount; 254 } 255 // ----------------------------------------------------------------------------- 256 Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException) 257 { 258 ::comphelper::OExternalLockGuard aGuard( this ); 259 260 ensureAlive(); 261 SvLBoxEntry* pEntry = getListBox()->GetEntry(i); 262 if ( !pEntry ) 263 throw IndexOutOfBoundsException(); 264 265 return new AccessibleListBoxEntry( *getListBox(), pEntry, this ); 266 } 267 // ----------------------------------------------------------------------------- 268 Reference< XAccessible > SAL_CALL AccessibleListBox::getAccessibleParent( ) throw (RuntimeException) 269 { 270 ::osl::MutexGuard aGuard( m_aMutex ); 271 272 ensureAlive(); 273 return m_xParent; 274 } 275 // ----------------------------------------------------------------------------- 276 sal_Int16 SAL_CALL AccessibleListBox::getAccessibleRole( ) throw (RuntimeException) 277 { 278 return AccessibleRole::TREE; 279 } 280 // ----------------------------------------------------------------------------- 281 ::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleDescription( ) throw (RuntimeException) 282 { 283 ::comphelper::OExternalLockGuard aGuard( this ); 284 285 ensureAlive(); 286 return getListBox()->GetAccessibleDescription(); 287 } 288 // ----------------------------------------------------------------------------- 289 ::rtl::OUString SAL_CALL AccessibleListBox::getAccessibleName( ) throw (RuntimeException) 290 { 291 ::comphelper::OExternalLockGuard aGuard( this ); 292 293 ensureAlive(); 294 return getListBox()->GetAccessibleName(); 295 } 296 // ----------------------------------------------------------------------------- 297 // XAccessibleSelection 298 // ----------------------------------------------------------------------------- 299 void SAL_CALL AccessibleListBox::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 300 { 301 ::comphelper::OExternalLockGuard aGuard( this ); 302 303 ensureAlive(); 304 305 SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex ); 306 if ( !pEntry ) 307 throw IndexOutOfBoundsException(); 308 309 getListBox()->Select( pEntry, sal_True ); 310 } 311 // ----------------------------------------------------------------------------- 312 sal_Bool SAL_CALL AccessibleListBox::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 313 { 314 ::comphelper::OExternalLockGuard aGuard( this ); 315 316 ensureAlive(); 317 318 SvLBoxEntry* pEntry = getListBox()->GetEntry( nChildIndex ); 319 if ( !pEntry ) 320 throw IndexOutOfBoundsException(); 321 322 return getListBox()->IsSelected( pEntry ); 323 } 324 // ----------------------------------------------------------------------------- 325 void SAL_CALL AccessibleListBox::clearAccessibleSelection( ) throw (RuntimeException) 326 { 327 ::comphelper::OExternalLockGuard aGuard( this ); 328 329 ensureAlive(); 330 331 sal_Int32 i, nCount = 0; 332 nCount = getListBox()->GetLevelChildCount( NULL ); 333 for ( i = 0; i < nCount; ++i ) 334 { 335 SvLBoxEntry* pEntry = getListBox()->GetEntry( i ); 336 if ( getListBox()->IsSelected( pEntry ) ) 337 getListBox()->Select( pEntry, sal_False ); 338 } 339 } 340 // ----------------------------------------------------------------------------- 341 void SAL_CALL AccessibleListBox::selectAllAccessibleChildren( ) throw (RuntimeException) 342 { 343 ::comphelper::OExternalLockGuard aGuard( this ); 344 345 ensureAlive(); 346 347 sal_Int32 i, nCount = 0; 348 nCount = getListBox()->GetLevelChildCount( NULL ); 349 for ( i = 0; i < nCount; ++i ) 350 { 351 SvLBoxEntry* pEntry = getListBox()->GetEntry( i ); 352 if ( !getListBox()->IsSelected( pEntry ) ) 353 getListBox()->Select( pEntry, sal_True ); 354 } 355 } 356 // ----------------------------------------------------------------------------- 357 sal_Int32 SAL_CALL AccessibleListBox::getSelectedAccessibleChildCount( ) throw (RuntimeException) 358 { 359 ::comphelper::OExternalLockGuard aGuard( this ); 360 361 ensureAlive(); 362 363 sal_Int32 i, nSelCount = 0, nCount = 0; 364 nCount = getListBox()->GetLevelChildCount( NULL ); 365 for ( i = 0; i < nCount; ++i ) 366 { 367 SvLBoxEntry* pEntry = getListBox()->GetEntry( i ); 368 if ( getListBox()->IsSelected( pEntry ) ) 369 ++nSelCount; 370 } 371 372 return nSelCount; 373 } 374 // ----------------------------------------------------------------------------- 375 Reference< XAccessible > SAL_CALL AccessibleListBox::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 376 { 377 ::comphelper::OExternalLockGuard aGuard( this ); 378 379 ensureAlive(); 380 381 if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() ) 382 throw IndexOutOfBoundsException(); 383 384 Reference< XAccessible > xChild; 385 sal_Int32 i, nSelCount = 0, nCount = 0; 386 nCount = getListBox()->GetLevelChildCount( NULL ); 387 for ( i = 0; i < nCount; ++i ) 388 { 389 SvLBoxEntry* pEntry = getListBox()->GetEntry( i ); 390 if ( getListBox()->IsSelected( pEntry ) ) 391 ++nSelCount; 392 393 if ( nSelCount == ( nSelectedChildIndex + 1 ) ) 394 { 395 xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this ); 396 break; 397 } 398 } 399 400 return xChild; 401 } 402 // ----------------------------------------------------------------------------- 403 void SAL_CALL AccessibleListBox::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException) 404 { 405 ::comphelper::OExternalLockGuard aGuard( this ); 406 407 ensureAlive(); 408 409 SvLBoxEntry* pEntry = getListBox()->GetEntry( nSelectedChildIndex ); 410 if ( !pEntry ) 411 throw IndexOutOfBoundsException(); 412 413 getListBox()->Select( pEntry, sal_False ); 414 } 415 // ----------------------------------------------------------------------------- 416 void AccessibleListBox::FillAccessibleStateSet( utl::AccessibleStateSetHelper& rStateSet ) 417 { 418 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet ); 419 if ( getListBox() && isAlive() ) 420 { 421 rStateSet.AddState( AccessibleStateType::FOCUSABLE ); 422 rStateSet.AddState( AccessibleStateType::MANAGES_DESCENDANTS ); 423 if ( getListBox()->GetSelectionMode() == MULTIPLE_SELECTION ) 424 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE ); 425 } 426 } 427 428 429 //........................................................................ 430 }// namespace accessibility 431 //........................................................................ 432 433