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