Branch libreoffice-5-0-4
[LibreOffice.git] / accessibility / source / extended / accessiblelistboxentry.cxx
blobe145b98459f754c7ea8fad0a73c36151ba22bf9c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "accessibility/extended/accessiblelistboxentry.hxx"
21 #include <svtools/treelistbox.hxx>
22 #include <svtools/stringtransfer.hxx>
23 #include <svtools/svlbitm.hxx>
24 #include <com/sun/star/awt/Point.hpp>
25 #include <com/sun/star/awt/Rectangle.hpp>
26 #include <com/sun/star/awt/Size.hpp>
27 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
29 #include <com/sun/star/accessibility/AccessibleRole.hpp>
30 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
31 #include <vcl/svapp.hxx>
32 #include <vcl/controllayout.hxx>
33 #include <vcl/settings.hxx>
34 #include <toolkit/awt/vclxwindow.hxx>
35 #include <toolkit/helper/convert.hxx>
36 #include <unotools/accessiblestatesethelper.hxx>
37 #include <unotools/accessiblerelationsethelper.hxx>
38 #include <cppuhelper/supportsservice.hxx>
39 #include <cppuhelper/typeprovider.hxx>
40 #include <comphelper/sequence.hxx>
41 #include <comphelper/accessibleeventnotifier.hxx>
42 #include <toolkit/helper/vclunohelper.hxx>
43 #include <accessibility/helper/accresmgr.hxx>
44 #include <accessibility/helper/accessiblestrings.hrc>
45 #include <com/sun/star/accessibility/XAccessibleValue.hpp>
46 #define ACCESSIBLE_ACTION_COUNT 1
48 namespace
50 void checkActionIndex_Impl( sal_Int32 _nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException)
52 if ( _nIndex < 0 || _nIndex >= ACCESSIBLE_ACTION_COUNT )
53 // only three actions
54 throw ::com::sun::star::lang::IndexOutOfBoundsException();
59 namespace accessibility
61 // class AccessibleListBoxEntry -----------------------------------------------------
63 using namespace ::com::sun::star::accessibility;
64 using namespace ::com::sun::star::uno;
65 using namespace ::com::sun::star::lang;
66 using namespace ::com::sun::star;
67 using namespace ::comphelper;
70 // Ctor() and Dtor()
72 AccessibleListBoxEntry::AccessibleListBoxEntry( SvTreeListBox& _rListBox,
73 SvTreeListEntry* _pEntry,
74 const Reference< XAccessible >& _xParent ) :
76 AccessibleListBoxEntry_BASE ( m_aMutex ),
77 ListBoxAccessibleBase( _rListBox ),
79 m_pSvLBoxEntry ( _pEntry ),
80 m_nClientId ( 0 ),
81 m_aParent ( _xParent )
84 _rListBox.FillEntryPath( _pEntry, m_aEntryPath );
87 AccessibleListBoxEntry::~AccessibleListBoxEntry()
89 if ( IsAlive_Impl() )
91 // increment ref count to prevent double call of Dtor
92 osl_atomic_increment( &m_refCount );
93 dispose();
97 void AccessibleListBoxEntry::NotifyAccessibleEvent( sal_Int16 _nEventId,
98 const ::com::sun::star::uno::Any& _aOldValue,
99 const ::com::sun::star::uno::Any& _aNewValue )
101 Reference< uno::XInterface > xSource( *this );
102 AccessibleEventObject aEventObj( xSource, _nEventId, _aNewValue, _aOldValue );
104 if (m_nClientId)
105 comphelper::AccessibleEventNotifier::addEvent( m_nClientId, aEventObj );
110 Rectangle AccessibleListBoxEntry::GetBoundingBox_Impl() const
112 Rectangle aRect;
113 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
114 if ( pEntry )
116 aRect = getListBox()->GetBoundingRect( pEntry );
117 SvTreeListEntry* pParent = getListBox()->GetParent( pEntry );
118 if ( pParent )
120 // position relative to parent entry
121 Point aTopLeft = aRect.TopLeft();
122 aTopLeft -= getListBox()->GetBoundingRect( pParent ).TopLeft();
123 aRect = Rectangle( aTopLeft, aRect.GetSize() );
127 return aRect;
130 Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen_Impl() const
132 Rectangle aRect;
133 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
134 if ( pEntry )
136 aRect = getListBox()->GetBoundingRect( pEntry );
137 Point aTopLeft = aRect.TopLeft();
138 aTopLeft += getListBox()->GetWindowExtentsRelative( NULL ).TopLeft();
139 aRect = Rectangle( aTopLeft, aRect.GetSize() );
142 return aRect;
145 bool AccessibleListBoxEntry::IsAlive_Impl() const
147 return ( !rBHelper.bDisposed && !rBHelper.bInDispose && isAlive() );
150 bool AccessibleListBoxEntry::IsShowing_Impl() const
152 Reference< XAccessible > xParent = implGetParentAccessible( );
154 bool bShowing = false;
155 Reference< XAccessibleContext > m_xParentContext =
156 xParent.is() ? xParent->getAccessibleContext() : Reference< XAccessibleContext >();
157 if( m_xParentContext.is() )
159 Reference< XAccessibleComponent > xParentComp( m_xParentContext, uno::UNO_QUERY );
160 if( xParentComp.is() )
161 bShowing = GetBoundingBox_Impl().IsOver( VCLRectangle( xParentComp->getBounds() ) );
164 return bShowing;
167 Rectangle AccessibleListBoxEntry::GetBoundingBox()
168 throw (lang::DisposedException, uno::RuntimeException)
170 SolarMutexGuard aSolarGuard;
171 ::osl::MutexGuard aGuard( m_aMutex );
173 EnsureIsAlive();
174 return GetBoundingBox_Impl();
177 Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen()
178 throw (lang::DisposedException, uno::RuntimeException)
180 SolarMutexGuard aSolarGuard;
181 ::osl::MutexGuard aGuard( m_aMutex );
183 EnsureIsAlive();
184 return GetBoundingBoxOnScreen_Impl();
187 void AccessibleListBoxEntry::EnsureIsAlive() const throw ( lang::DisposedException )
189 if ( !IsAlive_Impl() )
190 throw lang::DisposedException();
193 OUString AccessibleListBoxEntry::implGetText()
195 OUString sRet;
196 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
197 if ( pEntry )
198 sRet = getListBox()->SearchEntryTextWithHeadTitle( pEntry );
199 return sRet;
202 Locale AccessibleListBoxEntry::implGetLocale()
204 Locale aLocale;
205 aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
207 return aLocale;
209 void AccessibleListBoxEntry::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
211 nStartIndex = 0;
212 nEndIndex = 0;
215 // XTypeProvider
218 Sequence< sal_Int8 > AccessibleListBoxEntry::getImplementationId() throw (RuntimeException, std::exception)
220 return css::uno::Sequence<sal_Int8>();
224 // XComponent/ListBoxAccessibleBase
226 void SAL_CALL AccessibleListBoxEntry::dispose() throw ( uno::RuntimeException, std::exception )
228 AccessibleListBoxEntry_BASE::dispose();
232 // XComponent
234 void SAL_CALL AccessibleListBoxEntry::disposing()
236 SolarMutexGuard();
237 ::osl::MutexGuard aGuard( m_aMutex );
239 Reference< XAccessible > xKeepAlive( this );
241 // Send a disposing to all listeners.
242 if ( m_nClientId )
244 ::comphelper::AccessibleEventNotifier::TClientId nId = m_nClientId;
245 m_nClientId = 0;
246 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
249 // clean up
252 ListBoxAccessibleBase::disposing();
254 m_aParent = WeakReference< XAccessible >();
257 // XServiceInfo
259 OUString SAL_CALL AccessibleListBoxEntry::getImplementationName() throw(RuntimeException, std::exception)
261 return getImplementationName_Static();
264 Sequence< OUString > SAL_CALL AccessibleListBoxEntry::getSupportedServiceNames() throw(RuntimeException, std::exception)
266 return getSupportedServiceNames_Static();
269 sal_Bool SAL_CALL AccessibleListBoxEntry::supportsService( const OUString& _rServiceName ) throw (RuntimeException, std::exception)
271 return cppu::supportsService(this, _rServiceName);
274 // XServiceInfo - static methods
276 Sequence< OUString > AccessibleListBoxEntry::getSupportedServiceNames_Static() throw( RuntimeException )
278 Sequence< OUString > aSupported(3);
279 aSupported[0] = "com.sun.star.accessibility.AccessibleContext";
280 aSupported[1] = "com.sun.star.accessibility.AccessibleComponent";
281 aSupported[2] = "com.sun.star.awt.AccessibleTreeListBoxEntry";
282 return aSupported;
285 OUString AccessibleListBoxEntry::getImplementationName_Static() throw( RuntimeException )
287 return OUString( "com.sun.star.comp.svtools.AccessibleTreeListBoxEntry" );
290 // XAccessible
292 Reference< XAccessibleContext > SAL_CALL AccessibleListBoxEntry::getAccessibleContext( ) throw (RuntimeException, std::exception)
294 EnsureIsAlive();
295 return this;
298 // XAccessibleContext
300 sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleChildCount( ) throw (RuntimeException, std::exception)
302 SolarMutexGuard aSolarGuard;
303 ::osl::MutexGuard aGuard( m_aMutex );
305 EnsureIsAlive();
306 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
307 sal_Int32 nCount = 0;
308 if ( pEntry )
309 nCount = getListBox()->GetLevelChildCount( pEntry );
311 return nCount;
314 Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException, std::exception)
316 SolarMutexGuard aSolarGuard;
317 ::osl::MutexGuard aGuard( m_aMutex );
318 EnsureIsAlive();
320 SvTreeListEntry* pEntry = GetRealChild(i);
321 if ( !pEntry )
322 throw IndexOutOfBoundsException();
324 return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
328 Reference< XAccessible > AccessibleListBoxEntry::implGetParentAccessible( ) const
330 Reference< XAccessible > xParent(m_aParent);
331 if ( !xParent.is() )
333 OSL_ENSURE( m_aEntryPath.size(), "AccessibleListBoxEntry::getAccessibleParent: invalid path!" );
334 if ( 1 == m_aEntryPath.size() )
335 { // we're a top level entry
336 // -> our parent is the tree listbox itself
337 if ( getListBox() )
338 xParent = getListBox()->GetAccessible( );
340 else
341 { // we have a entry as parent -> get its accessible
343 // shorten our access path by one
344 ::std::deque< sal_Int32 > aParentPath( m_aEntryPath );
345 aParentPath.pop_back();
347 // get the entry for this shortened access path
348 SvTreeListEntry* pParentEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
349 OSL_ENSURE( pParentEntry, "AccessibleListBoxEntry::implGetParentAccessible: could not obtain a parent entry!" );
351 if ( pParentEntry )
352 pParentEntry = getListBox()->GetParent(pParentEntry);
353 if ( pParentEntry )
354 xParent = new AccessibleListBoxEntry( *getListBox(), pParentEntry, NULL );
355 // note that we pass NULL here as parent-accessible:
356 // this is allowed, as the AccessibleListBoxEntry class will create its parent
357 // when needed
361 return xParent;
365 Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleParent( ) throw (RuntimeException, std::exception)
367 SolarMutexGuard aSolarGuard;
368 ::osl::MutexGuard aGuard( m_aMutex );
369 EnsureIsAlive();
371 return implGetParentAccessible( );
374 sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleIndexInParent( ) throw (RuntimeException, std::exception)
376 ::osl::MutexGuard aGuard( m_aMutex );
378 OSL_ENSURE( !m_aEntryPath.empty(), "empty path" );
379 return m_aEntryPath.empty() ? -1 : m_aEntryPath.back();
382 sal_Int32 AccessibleListBoxEntry::GetRoleType()
384 sal_Int32 nCase = 0;
385 SvTreeListEntry* pEntry = getListBox()->GetEntry(0);
386 if ( pEntry )
388 if( pEntry->HasChildrenOnDemand() || getListBox()->GetChildCount(pEntry) > 0 )
390 nCase = 1;
391 return nCase;
395 bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
396 if( !(getListBox()->GetTreeFlags() & SvTreeFlags::CHKBTN) )
398 if( bHasButtons )
399 nCase = 1;
401 else
403 if( bHasButtons )
404 nCase = 2;
405 else
406 nCase = 3;
408 return nCase;
411 sal_Int16 SAL_CALL AccessibleListBoxEntry::getAccessibleRole( ) throw (RuntimeException, std::exception)
413 SolarMutexGuard aSolarGuard;
414 ::osl::MutexGuard aGuard( m_aMutex );
416 SvTreeListBox* pBox = getListBox();
417 if(pBox)
419 SvTreeAccRoleType nType = pBox->GetAllEntriesAccessibleRoleType();
420 if( nType == SvTreeAccRoleType::TREE)
421 return AccessibleRole::TREE_ITEM;
422 else if( nType == SvTreeAccRoleType::LIST)
423 return AccessibleRole::LIST_ITEM;
425 SvTreeFlags treeFlag = pBox->GetTreeFlags();
426 if(treeFlag & SvTreeFlags::CHKBTN )
428 SvTreeListEntry* pEntry = pBox->GetEntryFromPath( m_aEntryPath );
429 SvButtonState eState = pBox->GetCheckButtonState( pEntry );
430 switch( eState )
432 case SV_BUTTON_CHECKED:
433 case SV_BUTTON_UNCHECKED:
434 return AccessibleRole::CHECK_BOX;
435 case SV_BUTTON_TRISTATE:
436 default:
437 return AccessibleRole::LABEL;
440 if (GetRoleType() == 0)
441 return AccessibleRole::LIST_ITEM;
442 else
443 //o is: return AccessibleRole::LABEL;
444 return AccessibleRole::TREE_ITEM;
446 return AccessibleRole::UNKNOWN;
449 OUString SAL_CALL AccessibleListBoxEntry::getAccessibleDescription( ) throw (RuntimeException, std::exception)
451 SolarMutexGuard aSolarGuard;
452 ::osl::MutexGuard aGuard( m_aMutex );
454 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
455 if( getAccessibleRole() == AccessibleRole::TREE_ITEM )
457 return getListBox()->GetEntryLongDescription( pEntry );
459 //want to cout the real column nubmer in the list box.
460 sal_uInt16 iRealItemCount = 0;
461 sal_uInt16 iCount = 0;
462 sal_uInt16 iTotleItemCount = pEntry->ItemCount();
463 while( iCount < iTotleItemCount )
465 const SvLBoxItem* pItem = pEntry->GetItem( iCount );
466 if ( pItem->GetType() == SV_ITEM_ID_LBOXSTRING &&
467 !static_cast<const SvLBoxString*>( pItem )->GetText().isEmpty() )
469 iRealItemCount++;
471 iCount++;
473 if(iRealItemCount<=1 )
475 return OUString();
477 else
479 return getListBox()->SearchEntryTextWithHeadTitle( pEntry );
483 OUString SAL_CALL AccessibleListBoxEntry::getAccessibleName( ) throw (RuntimeException, std::exception)
485 ::osl::MutexGuard aGuard( m_aMutex );
487 EnsureIsAlive();
489 OUString sRet(implGetText());
491 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
493 OUString altText = getListBox()->GetEntryAltText( pEntry );
494 if (!altText.isEmpty())
496 sRet += " ";
497 sRet += altText;
500 return sRet;
503 Reference< XAccessibleRelationSet > SAL_CALL AccessibleListBoxEntry::getAccessibleRelationSet( ) throw (RuntimeException, std::exception)
505 Reference< XAccessibleRelationSet > xRelSet;
506 Reference< XAccessible > xParent;
507 if ( m_aEntryPath.size() > 1 ) // not a root entry
508 xParent = implGetParentAccessible();
509 if ( xParent.is() )
511 utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
512 Sequence< Reference< XInterface > > aSequence(1);
513 aSequence[0] = xParent;
514 pRelationSetHelper->AddRelation(
515 AccessibleRelation( AccessibleRelationType::NODE_CHILD_OF, aSequence ) );
516 xRelSet = pRelationSetHelper;
518 return xRelSet;
521 Reference< XAccessibleStateSet > SAL_CALL AccessibleListBoxEntry::getAccessibleStateSet( ) throw (RuntimeException, std::exception)
523 ::osl::MutexGuard aGuard( m_aMutex );
525 utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
526 Reference< XAccessibleStateSet > xStateSet = pStateSetHelper;
528 if ( IsAlive_Impl() )
530 switch(getAccessibleRole())
532 case AccessibleRole::LABEL:
533 pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
534 pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
535 pStateSetHelper->AddState( AccessibleStateType::ENABLED );
536 if (getListBox()->IsInplaceEditingEnabled())
537 pStateSetHelper->AddState( AccessibleStateType::EDITABLE );
538 if (IsShowing_Impl())
539 pStateSetHelper->AddState( AccessibleStateType::SHOWING );
540 break;
541 case AccessibleRole::CHECK_BOX:
542 pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
543 pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
544 pStateSetHelper->AddState( AccessibleStateType::ENABLED );
545 if (IsShowing_Impl())
546 pStateSetHelper->AddState( AccessibleStateType::SHOWING );
547 break;
549 SvTreeListEntry *pEntry = getListBox()->GetEntryFromPath(m_aEntryPath);
550 if (pEntry)
551 getListBox()->FillAccessibleEntryStateSet(pEntry, *pStateSetHelper);
553 else
554 pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
556 return xStateSet;
559 Locale SAL_CALL AccessibleListBoxEntry::getLocale( ) throw (IllegalAccessibleComponentStateException, RuntimeException, std::exception)
561 SolarMutexGuard aSolarGuard;
562 ::osl::MutexGuard aGuard( m_aMutex );
564 return implGetLocale();
567 // XAccessibleComponent
569 sal_Bool SAL_CALL AccessibleListBoxEntry::containsPoint( const awt::Point& rPoint ) throw (RuntimeException, std::exception)
571 return Rectangle( Point(), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) );
574 Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (RuntimeException, std::exception)
576 SolarMutexGuard aSolarGuard;
577 ::osl::MutexGuard aGuard( m_aMutex );
579 EnsureIsAlive();
580 SvTreeListEntry* pEntry = getListBox()->GetEntry( VCLPoint( _aPoint ) );
581 if ( !pEntry )
582 throw RuntimeException();
584 Reference< XAccessible > xAcc;
585 AccessibleListBoxEntry* pAccEntry = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
586 Rectangle aRect = pAccEntry->GetBoundingBox_Impl();
587 if ( aRect.IsInside( VCLPoint( _aPoint ) ) )
588 xAcc = pAccEntry;
589 return xAcc;
592 awt::Rectangle SAL_CALL AccessibleListBoxEntry::getBounds( ) throw (RuntimeException, std::exception)
594 return AWTRectangle( GetBoundingBox() );
597 awt::Point SAL_CALL AccessibleListBoxEntry::getLocation( ) throw (RuntimeException, std::exception)
599 return AWTPoint( GetBoundingBox().TopLeft() );
602 awt::Point SAL_CALL AccessibleListBoxEntry::getLocationOnScreen( ) throw (RuntimeException, std::exception)
604 return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
607 awt::Size SAL_CALL AccessibleListBoxEntry::getSize( ) throw (RuntimeException, std::exception)
609 return AWTSize( GetBoundingBox().GetSize() );
612 void SAL_CALL AccessibleListBoxEntry::grabFocus( ) throw (RuntimeException, std::exception)
614 // do nothing, because no focus for each item
617 sal_Int32 AccessibleListBoxEntry::getForeground( ) throw (RuntimeException, std::exception)
619 SolarMutexGuard aSolarGuard;
620 ::osl::MutexGuard aGuard( m_aMutex );
622 sal_Int32 nColor = 0;
623 Reference< XAccessible > xParent = getAccessibleParent();
624 if ( xParent.is() )
626 Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
627 if ( xParentComp.is() )
628 nColor = xParentComp->getForeground();
631 return nColor;
634 sal_Int32 AccessibleListBoxEntry::getBackground( ) throw (RuntimeException, std::exception)
636 SolarMutexGuard aSolarGuard;
637 ::osl::MutexGuard aGuard( m_aMutex );
639 sal_Int32 nColor = 0;
640 Reference< XAccessible > xParent = getAccessibleParent();
641 if ( xParent.is() )
643 Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
644 if ( xParentComp.is() )
645 nColor = xParentComp->getBackground();
648 return nColor;
651 // XAccessibleText
654 awt::Rectangle SAL_CALL AccessibleListBoxEntry::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
656 SolarMutexGuard aSolarGuard;
657 ::osl::MutexGuard aGuard( m_aMutex );
659 EnsureIsAlive();
661 if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
662 throw IndexOutOfBoundsException();
664 awt::Rectangle aBounds( 0, 0, 0, 0 );
665 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
666 if ( pEntry )
668 vcl::ControlLayoutData aLayoutData;
669 Rectangle aItemRect = GetBoundingBox();
670 getListBox()->RecordLayoutData( &aLayoutData, aItemRect );
671 Rectangle aCharRect = aLayoutData.GetCharacterBounds( nIndex );
672 aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
673 aBounds = AWTRectangle( aCharRect );
676 return aBounds;
679 sal_Int32 SAL_CALL AccessibleListBoxEntry::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException, std::exception)
681 SolarMutexGuard aSolarGuard;
682 ::osl::MutexGuard aGuard( m_aMutex );
683 EnsureIsAlive();
684 if(aPoint.X==0 && aPoint.Y==0) return 0;
686 sal_Int32 nIndex = -1;
687 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
688 if ( pEntry )
690 vcl::ControlLayoutData aLayoutData;
691 Rectangle aItemRect = GetBoundingBox();
692 getListBox()->RecordLayoutData( &aLayoutData, aItemRect );
693 Point aPnt( VCLPoint( aPoint ) );
694 aPnt += aItemRect.TopLeft();
695 nIndex = aLayoutData.GetIndexForPoint( aPnt );
698 return nIndex;
701 sal_Bool SAL_CALL AccessibleListBoxEntry::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
703 SolarMutexGuard aSolarGuard;
704 ::osl::MutexGuard aGuard( m_aMutex );
705 EnsureIsAlive();
707 OUString sText = getText();
708 if ( ( 0 > nStartIndex ) || ( sText.getLength() <= nStartIndex )
709 || ( 0 > nEndIndex ) || ( sText.getLength() <= nEndIndex ) )
710 throw IndexOutOfBoundsException();
712 sal_Int32 nLen = nEndIndex - nStartIndex + 1;
713 ::svt::OStringTransfer::CopyString( sText.copy( nStartIndex, nLen ), getListBox() );
715 return true;
718 // XAccessibleEventBroadcaster
720 void SAL_CALL AccessibleListBoxEntry::addAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener ) throw (RuntimeException, std::exception)
722 if (xListener.is())
724 ::osl::MutexGuard aGuard( m_aMutex );
725 if (!m_nClientId)
726 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
727 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
731 void SAL_CALL AccessibleListBoxEntry::removeAccessibleEventListener( const Reference< XAccessibleEventListener >& xListener ) throw (RuntimeException, std::exception)
733 if (xListener.is())
735 ::osl::MutexGuard aGuard( m_aMutex );
737 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
738 if ( !nListenerCount )
740 // no listeners anymore
741 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
742 // and at least to us not firing any events anymore, in case somebody calls
743 // NotifyAccessibleEvent, again
744 sal_Int32 nId = m_nClientId;
745 m_nClientId = 0;
746 comphelper::AccessibleEventNotifier::revokeClient( nId );
752 // XAccessibleAction
754 sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleActionCount( ) throw (RuntimeException, std::exception)
756 ::osl::MutexGuard aGuard( m_aMutex );
758 // three actions supported
759 SvTreeListBox* pBox = getListBox();
760 SvTreeFlags treeFlag = pBox->GetTreeFlags();
761 bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
762 if( (treeFlag & SvTreeFlags::CHKBTN) && !bHasButtons)
764 sal_Int16 role = getAccessibleRole();
765 if ( role == AccessibleRole::CHECK_BOX )
766 return 2;
767 else if ( role == AccessibleRole::LABEL )
768 return 0;
770 else
771 return ACCESSIBLE_ACTION_COUNT;
772 return 0;
775 sal_Bool SAL_CALL AccessibleListBoxEntry::doAccessibleAction( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
777 SolarMutexGuard aSolarGuard;
778 ::osl::MutexGuard aGuard( m_aMutex );
780 bool bRet = false;
781 checkActionIndex_Impl( nIndex );
782 EnsureIsAlive();
784 SvTreeFlags treeFlag = getListBox()->GetTreeFlags();
785 if( nIndex == 0 && (treeFlag & SvTreeFlags::CHKBTN) )
787 if(getAccessibleRole() == AccessibleRole::CHECK_BOX)
789 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
790 SvButtonState state = getListBox()->GetCheckButtonState( pEntry );
791 if ( state == SV_BUTTON_CHECKED )
792 getListBox()->SetCheckButtonState(pEntry, SV_BUTTON_UNCHECKED);
793 else if (state == SV_BUTTON_UNCHECKED)
794 getListBox()->SetCheckButtonState(pEntry, SV_BUTTON_CHECKED);
797 else if( (nIndex == 1 && (treeFlag & SvTreeFlags::CHKBTN) ) || (nIndex == 0) )
799 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
800 if ( pEntry )
802 if ( getListBox()->IsExpanded( pEntry ) )
803 getListBox()->Collapse( pEntry );
804 else
805 getListBox()->Expand( pEntry );
806 bRet = true;
810 return bRet;
813 OUString SAL_CALL AccessibleListBoxEntry::getAccessibleActionDescription( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
815 SolarMutexGuard aSolarGuard;
816 ::osl::MutexGuard aGuard( m_aMutex );
818 checkActionIndex_Impl( nIndex );
819 EnsureIsAlive();
821 static const char sActionDesc1[] = "Check";
822 static const char sActionDesc2[] = "UnCheck";
823 // sal_Bool bHasButtons = (getListBox()->GetStyle() & WB_HASBUTTONS)!=0;
824 SvTreeListEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
825 SvButtonState state = getListBox()->GetCheckButtonState( pEntry );
826 SvTreeFlags treeFlag = getListBox()->GetTreeFlags();
827 if(nIndex == 0 && (treeFlag & SvTreeFlags::CHKBTN))
829 if(getAccessibleRole() == AccessibleRole::CHECK_BOX)
831 if ( state == SV_BUTTON_CHECKED )
832 return OUString(sActionDesc2);
833 else if (state == SV_BUTTON_UNCHECKED)
834 return OUString(sActionDesc1);
836 else
838 //Sometimes, a List or Tree may have both checkbox and label at the same time
839 return OUString();
841 }else if( (nIndex == 1 && (treeFlag & SvTreeFlags::CHKBTN)) || nIndex == 0 )
843 if( pEntry->HasChildren() || pEntry->HasChildrenOnDemand() )
844 return getListBox()->IsExpanded( pEntry ) ? \
845 OUString(TK_RES_STRING(STR_SVT_ACC_ACTION_COLLAPSE)) :
846 OUString(TK_RES_STRING(STR_SVT_ACC_ACTION_EXPAND));
847 return OUString();
850 throw IndexOutOfBoundsException();
853 Reference< XAccessibleKeyBinding > AccessibleListBoxEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
855 ::osl::MutexGuard aGuard( m_aMutex );
857 Reference< XAccessibleKeyBinding > xRet;
858 checkActionIndex_Impl( nIndex );
859 // ... which key?
860 return xRet;
863 // XAccessibleSelection
865 void SAL_CALL AccessibleListBoxEntry::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
867 SolarMutexGuard aSolarGuard;
868 ::osl::MutexGuard aGuard( m_aMutex );
870 EnsureIsAlive();
872 SvTreeListEntry* pEntry = GetRealChild(nChildIndex);
873 if ( !pEntry )
874 throw IndexOutOfBoundsException();
876 getListBox()->Select( pEntry, true );
879 sal_Bool SAL_CALL AccessibleListBoxEntry::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
881 SolarMutexGuard aSolarGuard;
882 ::osl::MutexGuard aGuard( m_aMutex );
884 EnsureIsAlive();
886 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
887 SvTreeListEntry* pEntry = getListBox()->GetEntry( pParent, nChildIndex );
888 if ( !pEntry )
889 throw IndexOutOfBoundsException();
891 return getListBox()->IsSelected( pEntry );
894 void SAL_CALL AccessibleListBoxEntry::clearAccessibleSelection( ) throw (RuntimeException, std::exception)
896 SolarMutexGuard aSolarGuard;
897 ::osl::MutexGuard aGuard( m_aMutex );
899 EnsureIsAlive();
901 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
902 if ( !pParent )
903 throw RuntimeException();
904 sal_Int32 nCount = getListBox()->GetLevelChildCount( pParent );
905 for ( sal_Int32 i = 0; i < nCount; ++i )
907 SvTreeListEntry* pEntry = getListBox()->GetEntry( pParent, i );
908 if ( getListBox()->IsSelected( pEntry ) )
909 getListBox()->Select( pEntry, false );
913 void SAL_CALL AccessibleListBoxEntry::selectAllAccessibleChildren( ) throw (RuntimeException, std::exception)
915 SolarMutexGuard aSolarGuard;
916 ::osl::MutexGuard aGuard( m_aMutex );
918 EnsureIsAlive();
920 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
921 if ( !pParent )
922 throw RuntimeException();
923 sal_Int32 nCount = getListBox()->GetLevelChildCount( pParent );
924 for ( sal_Int32 i = 0; i < nCount; ++i )
926 SvTreeListEntry* pEntry = getListBox()->GetEntry( pParent, i );
927 if ( !getListBox()->IsSelected( pEntry ) )
928 getListBox()->Select( pEntry, true );
932 sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChildCount( ) throw (RuntimeException, std::exception)
934 SolarMutexGuard aSolarGuard;
935 ::osl::MutexGuard aGuard( m_aMutex );
937 EnsureIsAlive();
939 sal_Int32 i, nSelCount = 0, nCount = 0;
941 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
942 if ( !pParent )
943 throw RuntimeException();
944 nCount = getListBox()->GetLevelChildCount( pParent );
945 for ( i = 0; i < nCount; ++i )
947 SvTreeListEntry* pEntry = getListBox()->GetEntry( pParent, i );
948 if ( getListBox()->IsSelected( pEntry ) )
949 ++nSelCount;
952 return nSelCount;
955 Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
957 SolarMutexGuard aSolarGuard;
958 ::osl::MutexGuard aGuard( m_aMutex );
960 EnsureIsAlive();
962 if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
963 throw IndexOutOfBoundsException();
965 Reference< XAccessible > xChild;
966 sal_Int32 i, nSelCount = 0, nCount = 0;
968 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
969 if ( !pParent )
970 throw RuntimeException();
971 nCount = getListBox()->GetLevelChildCount( pParent );
972 for ( i = 0; i < nCount; ++i )
974 SvTreeListEntry* pEntry = getListBox()->GetEntry( pParent, i );
975 if ( getListBox()->IsSelected( pEntry ) )
976 ++nSelCount;
978 if ( nSelCount == ( nSelectedChildIndex + 1 ) )
980 xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
981 break;
985 return xChild;
988 void SAL_CALL AccessibleListBoxEntry::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException, std::exception)
990 SolarMutexGuard aSolarGuard;
991 ::osl::MutexGuard aGuard( m_aMutex );
993 EnsureIsAlive();
995 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
996 SvTreeListEntry* pEntry = getListBox()->GetEntry( pParent, nSelectedChildIndex );
997 if ( !pEntry )
998 throw IndexOutOfBoundsException();
1000 getListBox()->Select( pEntry, false );
1002 sal_Int32 SAL_CALL AccessibleListBoxEntry::getCaretPosition( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1004 return -1;
1006 sal_Bool SAL_CALL AccessibleListBoxEntry::setCaretPosition ( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
1008 SolarMutexGuard aSolarGuard;
1009 ::osl::MutexGuard aGuard( m_aMutex );
1010 EnsureIsAlive();
1012 if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
1013 throw IndexOutOfBoundsException();
1015 return false;
1017 sal_Unicode SAL_CALL AccessibleListBoxEntry::getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
1019 SolarMutexGuard aSolarGuard;
1020 ::osl::MutexGuard aGuard( m_aMutex );
1021 EnsureIsAlive();
1022 return OCommonAccessibleText::getCharacter( nIndex );
1024 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL AccessibleListBoxEntry::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< OUString >& ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
1026 SolarMutexGuard aSolarGuard;
1027 ::osl::MutexGuard aGuard( m_aMutex );
1028 EnsureIsAlive();
1030 OUString sText( implGetText() );
1032 if ( !implIsValidIndex( nIndex, sText.getLength() ) )
1033 throw IndexOutOfBoundsException();
1035 return ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >();
1037 sal_Int32 SAL_CALL AccessibleListBoxEntry::getCharacterCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1039 SolarMutexGuard aSolarGuard;
1040 ::osl::MutexGuard aGuard( m_aMutex );
1041 EnsureIsAlive();
1042 return OCommonAccessibleText::getCharacterCount( );
1045 OUString SAL_CALL AccessibleListBoxEntry::getSelectedText( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1047 SolarMutexGuard aSolarGuard;
1048 ::osl::MutexGuard aGuard( m_aMutex );
1049 EnsureIsAlive();
1050 return OCommonAccessibleText::getSelectedText( );
1052 sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionStart( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1054 SolarMutexGuard aSolarGuard;
1055 ::osl::MutexGuard aGuard( m_aMutex );
1056 EnsureIsAlive();
1057 return OCommonAccessibleText::getSelectionStart( );
1059 sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionEnd( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1061 SolarMutexGuard aSolarGuard;
1062 ::osl::MutexGuard aGuard( m_aMutex );
1063 EnsureIsAlive();
1064 return OCommonAccessibleText::getSelectionEnd( );
1066 sal_Bool SAL_CALL AccessibleListBoxEntry::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
1068 SolarMutexGuard aSolarGuard;
1069 ::osl::MutexGuard aGuard( m_aMutex );
1070 EnsureIsAlive();
1072 if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
1073 throw IndexOutOfBoundsException();
1075 return false;
1077 OUString SAL_CALL AccessibleListBoxEntry::getText( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1079 SolarMutexGuard aSolarGuard;
1080 ::osl::MutexGuard aGuard( m_aMutex );
1081 EnsureIsAlive();
1082 return OCommonAccessibleText::getText( );
1084 OUString SAL_CALL AccessibleListBoxEntry::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
1086 SolarMutexGuard aSolarGuard;
1087 ::osl::MutexGuard aGuard( m_aMutex );
1088 EnsureIsAlive();
1089 return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
1091 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
1093 SolarMutexGuard aSolarGuard;
1094 ::osl::MutexGuard aGuard( m_aMutex );
1095 EnsureIsAlive();
1096 return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
1098 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
1100 SolarMutexGuard aSolarGuard;
1101 ::osl::MutexGuard aGuard( m_aMutex );
1102 EnsureIsAlive();
1103 return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
1105 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleListBoxEntry::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
1107 SolarMutexGuard aSolarGuard;
1108 ::osl::MutexGuard aGuard( m_aMutex );
1109 EnsureIsAlive();
1111 return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
1114 // XAccessibleValue
1117 Any AccessibleListBoxEntry::getCurrentValue( ) throw (RuntimeException, std::exception)
1119 ::osl::MutexGuard aGuard( m_aMutex );
1120 Any aValue;
1121 sal_Int32 level = ((sal_Int32) m_aEntryPath.size() - 1);
1122 level = level < 0 ? 0: level;
1123 aValue <<= level;
1124 return aValue;
1129 sal_Bool AccessibleListBoxEntry::setCurrentValue( const Any& aNumber ) throw (RuntimeException, std::exception)
1131 ::osl::MutexGuard aGuard( m_aMutex );
1134 bool bReturn = false;
1135 SvTreeListBox* pBox = getListBox();
1136 if(getAccessibleRole() == AccessibleRole::CHECK_BOX)
1138 SvTreeListEntry* pEntry = pBox->GetEntryFromPath( m_aEntryPath );
1139 if ( pEntry )
1141 sal_Int32 nValue(0), nValueMin(0), nValueMax(0);
1142 aNumber >>= nValue;
1143 getMinimumValue() >>= nValueMin;
1144 getMaximumValue() >>= nValueMax;
1146 if ( nValue < nValueMin )
1147 nValue = nValueMin;
1148 else if ( nValue > nValueMax )
1149 nValue = nValueMax;
1151 pBox->SetCheckButtonState(pEntry, (SvButtonState) nValue );
1152 bReturn = true;
1156 return bReturn;
1161 Any AccessibleListBoxEntry::getMaximumValue( ) throw (RuntimeException, std::exception)
1163 ::osl::MutexGuard aGuard( m_aMutex );
1165 Any aValue;
1166 // SvTreeListBox* pBox = getListBox();
1167 switch(getAccessibleRole())
1169 case AccessibleRole::CHECK_BOX:
1170 aValue <<= (sal_Int32)1;
1171 break;
1172 case AccessibleRole::LABEL:
1173 default:
1174 break;
1177 return aValue;
1182 Any AccessibleListBoxEntry::getMinimumValue( ) throw (RuntimeException, std::exception)
1184 ::osl::MutexGuard aGuard( m_aMutex );
1186 Any aValue;
1187 // SvTreeListBox* pBox = getListBox();
1188 switch(getAccessibleRole())
1190 case AccessibleRole::CHECK_BOX:
1191 aValue <<= (sal_Int32)0;
1192 break;
1193 case AccessibleRole::LABEL:
1194 default:
1195 break;
1198 return aValue;
1203 SvTreeListEntry* AccessibleListBoxEntry::GetRealChild(sal_Int32 nIndex)
1205 SvTreeListEntry* pEntry = NULL;
1206 SvTreeListEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
1207 if (pParent)
1209 pEntry = getListBox()->GetEntry( pParent, nIndex );
1210 if ( !pEntry && getAccessibleChildCount() > 0 )
1212 getListBox()->RequestingChildren(pParent);
1213 pEntry = getListBox()->GetEntry( pParent, nIndex );
1216 return pEntry;
1219 }// namespace accessibility
1222 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */