xref: /trunk/main/accessibility/source/extended/accessiblelistboxentry.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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/accessiblelistboxentry.hxx"
31 #include <svtools/svtreebx.hxx>
32 #include <svtools/stringtransfer.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/AccessibleRelationType.hpp>
38 #include <com/sun/star/accessibility/AccessibleRole.hpp>
39 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
40 #include <tools/debug.hxx>
41 #include <vcl/svapp.hxx>
42 #include <vcl/controllayout.hxx>
43 #include <toolkit/awt/vclxwindow.hxx>
44 #include <toolkit/helper/convert.hxx>
45 #include <unotools/accessiblestatesethelper.hxx>
46 #include <unotools/accessiblerelationsethelper.hxx>
47 #include <cppuhelper/typeprovider.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <comphelper/accessibleeventnotifier.hxx>
50 #include <toolkit/helper/vclunohelper.hxx>
51 
52 #define ACCESSIBLE_ACTION_COUNT 1
53 
54 namespace
55 {
56     void checkActionIndex_Impl( sal_Int32 _nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException)
57     {
58         if ( _nIndex < 0 || _nIndex >= ACCESSIBLE_ACTION_COUNT )
59             // only three actions
60             throw ::com::sun::star::lang::IndexOutOfBoundsException();
61     }
62 }
63 
64 //........................................................................
65 namespace accessibility
66 {
67     //........................................................................
68     // class ALBSolarGuard ---------------------------------------------------------
69 
70     /** Aquire the solar mutex. */
71     class ALBSolarGuard : public ::vos::OGuard
72     {
73     public:
74         inline ALBSolarGuard() : ::vos::OGuard( Application::GetSolarMutex() ) {}
75     };
76 
77     // class AccessibleListBoxEntry -----------------------------------------------------
78 
79     using namespace ::com::sun::star::accessibility;
80     using namespace ::com::sun::star::uno;
81     using namespace ::com::sun::star::lang;
82     using namespace ::com::sun::star;
83 
84     DBG_NAME(AccessibleListBoxEntry)
85 
86     // -----------------------------------------------------------------------------
87     // Ctor() and Dtor()
88     // -----------------------------------------------------------------------------
89     AccessibleListBoxEntry::AccessibleListBoxEntry( SvTreeListBox& _rListBox,
90                                                     SvLBoxEntry* _pEntry,
91                                                     const Reference< XAccessible >& _xParent ) :
92 
93         AccessibleListBoxEntry_BASE ( m_aMutex ),
94         ListBoxAccessibleBase( _rListBox ),
95 
96         m_nClientId     ( 0 ),
97         m_aParent       ( _xParent )
98 
99     {
100         DBG_CTOR( AccessibleListBoxEntry, NULL );
101 
102         _rListBox.FillEntryPath( _pEntry, m_aEntryPath );
103     }
104     // -----------------------------------------------------------------------------
105     AccessibleListBoxEntry::~AccessibleListBoxEntry()
106     {
107         DBG_DTOR( AccessibleListBoxEntry, NULL );
108 
109         if ( IsAlive_Impl() )
110         {
111             // increment ref count to prevent double call of Dtor
112             osl_incrementInterlockedCount( &m_refCount );
113             dispose();
114         }
115     }
116 
117     // -----------------------------------------------------------------------------
118     Rectangle AccessibleListBoxEntry::GetBoundingBox_Impl() const
119     {
120         Rectangle aRect;
121         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
122         if ( pEntry )
123         {
124             aRect = getListBox()->GetBoundingRect( pEntry );
125             SvLBoxEntry* pParent = getListBox()->GetParent( pEntry );
126             if ( pParent )
127             {
128                 // position relative to parent entry
129                 Point aTopLeft = aRect.TopLeft();
130                 aTopLeft -= getListBox()->GetBoundingRect( pParent ).TopLeft();
131                 aRect = Rectangle( aTopLeft, aRect.GetSize() );
132             }
133         }
134 
135         return aRect;
136     }
137     // -----------------------------------------------------------------------------
138     Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen_Impl() const
139     {
140         Rectangle aRect;
141         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
142         if ( pEntry )
143         {
144             aRect = getListBox()->GetBoundingRect( pEntry );
145             Point aTopLeft = aRect.TopLeft();
146             aTopLeft += getListBox()->GetWindowExtentsRelative( NULL ).TopLeft();
147             aRect = Rectangle( aTopLeft, aRect.GetSize() );
148         }
149 
150         return aRect;
151     }
152     // -----------------------------------------------------------------------------
153     sal_Bool AccessibleListBoxEntry::IsAlive_Impl() const
154     {
155         return ( !rBHelper.bDisposed && !rBHelper.bInDispose && isAlive() );
156     }
157     // -----------------------------------------------------------------------------
158     sal_Bool AccessibleListBoxEntry::IsShowing_Impl() const
159     {
160         Reference< XAccessible > xParent = implGetParentAccessible( );
161 
162         sal_Bool bShowing = sal_False;
163         Reference< XAccessibleContext > m_xParentContext =
164             xParent.is() ? xParent->getAccessibleContext() : Reference< XAccessibleContext >();
165         if( m_xParentContext.is() )
166         {
167             Reference< XAccessibleComponent > xParentComp( m_xParentContext, uno::UNO_QUERY );
168             if( xParentComp.is() )
169                 bShowing = GetBoundingBox_Impl().IsOver( VCLRectangle( xParentComp->getBounds() ) );
170         }
171 
172         return bShowing;
173     }
174     // -----------------------------------------------------------------------------
175     Rectangle AccessibleListBoxEntry::GetBoundingBox() throw ( lang::DisposedException )
176     {
177         ALBSolarGuard aSolarGuard;
178         ::osl::MutexGuard aGuard( m_aMutex );
179 
180         EnsureIsAlive();
181         return GetBoundingBox_Impl();
182     }
183     // -----------------------------------------------------------------------------
184     Rectangle AccessibleListBoxEntry::GetBoundingBoxOnScreen() throw ( lang::DisposedException )
185     {
186         ALBSolarGuard aSolarGuard;
187         ::osl::MutexGuard aGuard( m_aMutex );
188 
189         EnsureIsAlive();
190         return GetBoundingBoxOnScreen_Impl();
191     }
192     // -----------------------------------------------------------------------------
193     void AccessibleListBoxEntry::EnsureIsAlive() const throw ( lang::DisposedException )
194     {
195         if ( !IsAlive_Impl() )
196             throw lang::DisposedException();
197     }
198     // -----------------------------------------------------------------------------
199     ::rtl::OUString AccessibleListBoxEntry::implGetText()
200     {
201         ::rtl::OUString sRet;
202         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
203         if ( pEntry )
204             sRet = getListBox()->SearchEntryText( pEntry );
205         return sRet;
206     }
207     // -----------------------------------------------------------------------------
208     Locale AccessibleListBoxEntry::implGetLocale()
209     {
210         Locale aLocale;
211         aLocale = Application::GetSettings().GetUILocale();
212 
213         return aLocale;
214     }
215     void AccessibleListBoxEntry::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
216     {
217         nStartIndex = 0;
218         nEndIndex = 0;
219     }
220     // -----------------------------------------------------------------------------
221     // XTypeProvider
222     // -----------------------------------------------------------------------------
223     // -----------------------------------------------------------------------------
224     Sequence< sal_Int8 > AccessibleListBoxEntry::getImplementationId() throw (RuntimeException)
225     {
226         static ::cppu::OImplementationId* pId = NULL;
227 
228         if ( !pId )
229         {
230             ::osl::Guard< ::osl::Mutex > aGuard( m_aMutex );
231 
232             if ( !pId )
233             {
234                 static ::cppu::OImplementationId aId;
235                 pId = &aId;
236             }
237         }
238         return pId->getImplementationId();
239     }
240 
241     // -----------------------------------------------------------------------------
242     // XComponent/ListBoxAccessibleBase
243     // -----------------------------------------------------------------------------
244     void SAL_CALL AccessibleListBoxEntry::dispose() throw ( uno::RuntimeException )
245     {
246         AccessibleListBoxEntry_BASE::dispose();
247     }
248 
249     // -----------------------------------------------------------------------------
250     // XComponent
251     // -----------------------------------------------------------------------------
252     void SAL_CALL AccessibleListBoxEntry::disposing()
253     {
254         ALBSolarGuard();
255         ::osl::MutexGuard aGuard( m_aMutex );
256 
257         Reference< XAccessible > xKeepAlive( this );
258 
259         // Send a disposing to all listeners.
260         if ( m_nClientId )
261         {
262             ::comphelper::AccessibleEventNotifier::TClientId nId = m_nClientId;
263             m_nClientId =  0;
264             ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
265         }
266 
267         // clean up
268         {
269 
270             ListBoxAccessibleBase::disposing();
271         }
272         m_aParent = WeakReference< XAccessible >();
273     }
274     // -----------------------------------------------------------------------------
275     // XServiceInfo
276     // -----------------------------------------------------------------------------
277     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getImplementationName() throw(RuntimeException)
278     {
279         return getImplementationName_Static();
280     }
281     // -----------------------------------------------------------------------------
282     Sequence< ::rtl::OUString > SAL_CALL AccessibleListBoxEntry::getSupportedServiceNames() throw(RuntimeException)
283     {
284         return getSupportedServiceNames_Static();
285     }
286     // -----------------------------------------------------------------------------
287     sal_Bool SAL_CALL AccessibleListBoxEntry::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException)
288     {
289         Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() );
290         const ::rtl::OUString* pSupported = aSupported.getConstArray();
291         const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
292         for ( ; pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported )
293             ;
294 
295         return pSupported != pEnd;
296     }
297     // -----------------------------------------------------------------------------
298     // XServiceInfo - static methods
299     // -----------------------------------------------------------------------------
300     Sequence< ::rtl::OUString > AccessibleListBoxEntry::getSupportedServiceNames_Static(void) throw( RuntimeException )
301     {
302         Sequence< ::rtl::OUString > aSupported(3);
303         aSupported[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext") );
304         aSupported[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleComponent") );
305         aSupported[2] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.AccessibleTreeListBoxEntry") );
306         return aSupported;
307     }
308     // -----------------------------------------------------------------------------
309     ::rtl::OUString AccessibleListBoxEntry::getImplementationName_Static(void) throw( RuntimeException )
310     {
311         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.svtools.AccessibleTreeListBoxEntry") );
312     }
313     // -----------------------------------------------------------------------------
314     // XAccessible
315     // -----------------------------------------------------------------------------
316     Reference< XAccessibleContext > SAL_CALL AccessibleListBoxEntry::getAccessibleContext(  ) throw (RuntimeException)
317     {
318         EnsureIsAlive();
319         return this;
320     }
321     // -----------------------------------------------------------------------------
322     // XAccessibleContext
323     // -----------------------------------------------------------------------------
324     sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleChildCount(  ) throw (RuntimeException)
325     {
326         ALBSolarGuard aSolarGuard;
327         ::osl::MutexGuard aGuard( m_aMutex );
328 
329         EnsureIsAlive();
330         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
331         sal_Int32 nCount = 0;
332         if ( pEntry )
333             nCount = getListBox()->GetLevelChildCount( pEntry );
334 
335         return nCount;
336     }
337     // -----------------------------------------------------------------------------
338     Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleChild( sal_Int32 i ) throw (IndexOutOfBoundsException,RuntimeException)
339     {
340         ALBSolarGuard aSolarGuard;
341         ::osl::MutexGuard aGuard( m_aMutex );
342         EnsureIsAlive();
343 
344         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
345         SvLBoxEntry* pEntry = pParent ? getListBox()->GetEntry( pParent, i ) : NULL;
346         if ( !pEntry )
347             throw IndexOutOfBoundsException();
348 
349         return new AccessibleListBoxEntry( *getListBox(), pEntry, this );
350     }
351 
352     // -----------------------------------------------------------------------------
353     Reference< XAccessible > AccessibleListBoxEntry::implGetParentAccessible( ) const
354     {
355         Reference< XAccessible > xParent = (Reference< XAccessible >)m_aParent;
356         if ( !xParent.is() )
357         {
358             DBG_ASSERT( m_aEntryPath.size(), "AccessibleListBoxEntry::getAccessibleParent: invalid path!" );
359             if ( 1 == m_aEntryPath.size() )
360             {   // we're a top level entry
361                 // -> our parent is the tree listbox itself
362                 if ( getListBox() )
363                     xParent = getListBox()->GetAccessible( );
364             }
365             else
366             {   // we have a entry as parent -> get it's accessible
367 
368                 // shorten our access path by one
369                 ::std::deque< sal_Int32 > aParentPath( m_aEntryPath );
370                 aParentPath.pop_back();
371 
372                 // get the entry for this shortened access path
373                 SvLBoxEntry* pParentEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
374                 DBG_ASSERT( pParentEntry, "AccessibleListBoxEntry::implGetParentAccessible: could not obtain a parent entry!" );
375 
376                 if ( pParentEntry )
377                     xParent = new AccessibleListBoxEntry( *getListBox(), pParentEntry, NULL );
378                     // note that we pass NULL here as parent-accessible:
379                     // this is allowed, as the AccessibleListBoxEntry class will create it's parent
380                     // when needed
381             }
382         }
383 
384         return xParent;
385     }
386 
387     // -----------------------------------------------------------------------------
388     Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleParent(  ) throw (RuntimeException)
389     {
390         ALBSolarGuard aSolarGuard;
391         ::osl::MutexGuard aGuard( m_aMutex );
392         EnsureIsAlive();
393 
394         return implGetParentAccessible( );
395     }
396     // -----------------------------------------------------------------------------
397     sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleIndexInParent(  ) throw (RuntimeException)
398     {
399         ::osl::MutexGuard aGuard( m_aMutex );
400 
401         DBG_ASSERT( !m_aEntryPath.empty(), "empty path" );
402         return m_aEntryPath.empty() ? -1 : m_aEntryPath.back();
403     }
404     // -----------------------------------------------------------------------------
405     sal_Int16 SAL_CALL AccessibleListBoxEntry::getAccessibleRole(  ) throw (RuntimeException)
406     {
407         return AccessibleRole::LABEL;
408     }
409     // -----------------------------------------------------------------------------
410     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getAccessibleDescription(  ) throw (RuntimeException)
411     {
412         // no description for every item
413         return ::rtl::OUString();
414     }
415     // -----------------------------------------------------------------------------
416     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getAccessibleName(  ) throw (RuntimeException)
417     {
418         ::osl::MutexGuard aGuard( m_aMutex );
419 
420         EnsureIsAlive();
421         return implGetText();
422     }
423     // -----------------------------------------------------------------------------
424     Reference< XAccessibleRelationSet > SAL_CALL AccessibleListBoxEntry::getAccessibleRelationSet(  ) throw (RuntimeException)
425     {
426         Reference< XAccessibleRelationSet > xRelSet;
427         Reference< XAccessible > xParent;
428         if ( m_aEntryPath.size() > 1 ) // not a root entry
429             xParent = implGetParentAccessible();
430         if ( xParent.is() )
431         {
432             utl::AccessibleRelationSetHelper* pRelationSetHelper = new utl::AccessibleRelationSetHelper;
433             Sequence< Reference< XInterface > > aSequence(1);
434             aSequence[0] = xParent;
435             pRelationSetHelper->AddRelation(
436                 AccessibleRelation( AccessibleRelationType::NODE_CHILD_OF, aSequence ) );
437             xRelSet = pRelationSetHelper;
438         }
439         return xRelSet;
440     }
441     // -----------------------------------------------------------------------------
442     Reference< XAccessibleStateSet > SAL_CALL AccessibleListBoxEntry::getAccessibleStateSet(  ) throw (RuntimeException)
443     {
444         ::osl::MutexGuard aGuard( m_aMutex );
445 
446         utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
447         Reference< XAccessibleStateSet > xStateSet = pStateSetHelper;
448 
449         if ( IsAlive_Impl() )
450         {
451             pStateSetHelper->AddState( AccessibleStateType::TRANSIENT );
452             pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
453             pStateSetHelper->AddState( AccessibleStateType::ENABLED );
454             pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
455             if ( getListBox()->IsInplaceEditingEnabled() )
456                 pStateSetHelper->AddState( AccessibleStateType::EDITABLE );
457             if ( IsShowing_Impl() )
458                 pStateSetHelper->AddState( AccessibleStateType::SHOWING );
459             getListBox()->FillAccessibleEntryStateSet(
460                 getListBox()->GetEntryFromPath( m_aEntryPath ), *pStateSetHelper );
461         }
462         else
463             pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
464 
465         return xStateSet;
466     }
467     // -----------------------------------------------------------------------------
468     Locale SAL_CALL AccessibleListBoxEntry::getLocale(  ) throw (IllegalAccessibleComponentStateException, RuntimeException)
469     {
470         ALBSolarGuard aSolarGuard;
471         ::osl::MutexGuard aGuard( m_aMutex );
472 
473         return implGetLocale();
474     }
475     // -----------------------------------------------------------------------------
476     // XAccessibleComponent
477     // -----------------------------------------------------------------------------
478     sal_Bool SAL_CALL AccessibleListBoxEntry::containsPoint( const awt::Point& rPoint ) throw (RuntimeException)
479     {
480         return Rectangle( Point(), GetBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) );
481     }
482     // -----------------------------------------------------------------------------
483     Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (RuntimeException)
484     {
485         ALBSolarGuard aSolarGuard;
486         ::osl::MutexGuard aGuard( m_aMutex );
487 
488         EnsureIsAlive();
489         SvLBoxEntry* pEntry = getListBox()->GetEntry( VCLPoint( _aPoint ) );
490         if ( !pEntry )
491             throw RuntimeException();
492 
493         Reference< XAccessible > xAcc;
494         AccessibleListBoxEntry* pAccEntry = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
495         Rectangle aRect = pAccEntry->GetBoundingBox_Impl();
496         if ( aRect.IsInside( VCLPoint( _aPoint ) ) )
497             xAcc = pAccEntry;
498         return xAcc;
499     }
500     // -----------------------------------------------------------------------------
501     awt::Rectangle SAL_CALL AccessibleListBoxEntry::getBounds(  ) throw (RuntimeException)
502     {
503         return AWTRectangle( GetBoundingBox() );
504     }
505     // -----------------------------------------------------------------------------
506     awt::Point SAL_CALL AccessibleListBoxEntry::getLocation(  ) throw (RuntimeException)
507     {
508         return AWTPoint( GetBoundingBox().TopLeft() );
509     }
510     // -----------------------------------------------------------------------------
511     awt::Point SAL_CALL AccessibleListBoxEntry::getLocationOnScreen(  ) throw (RuntimeException)
512     {
513         return AWTPoint( GetBoundingBoxOnScreen().TopLeft() );
514     }
515     // -----------------------------------------------------------------------------
516     awt::Size SAL_CALL AccessibleListBoxEntry::getSize(  ) throw (RuntimeException)
517     {
518         return AWTSize( GetBoundingBox().GetSize() );
519     }
520     // -----------------------------------------------------------------------------
521     void SAL_CALL AccessibleListBoxEntry::grabFocus(  ) throw (RuntimeException)
522     {
523         // do nothing, because no focus for each item
524     }
525     // -----------------------------------------------------------------------------
526     sal_Int32 AccessibleListBoxEntry::getForeground(    ) throw (RuntimeException)
527     {
528         ALBSolarGuard aSolarGuard;
529         ::osl::MutexGuard aGuard( m_aMutex );
530 
531         sal_Int32 nColor = 0;
532         Reference< XAccessible > xParent = getAccessibleParent();
533         if ( xParent.is() )
534         {
535             Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
536             if ( xParentComp.is() )
537                 nColor = xParentComp->getForeground();
538         }
539 
540         return nColor;
541     }
542     // -----------------------------------------------------------------------------
543     sal_Int32 AccessibleListBoxEntry::getBackground(  ) throw (RuntimeException)
544     {
545         ALBSolarGuard aSolarGuard;
546         ::osl::MutexGuard aGuard( m_aMutex );
547 
548         sal_Int32 nColor = 0;
549         Reference< XAccessible > xParent = getAccessibleParent();
550         if ( xParent.is() )
551         {
552             Reference< XAccessibleComponent > xParentComp( xParent->getAccessibleContext(), UNO_QUERY );
553             if ( xParentComp.is() )
554                 nColor = xParentComp->getBackground();
555         }
556 
557         return nColor;
558     }
559     // -----------------------------------------------------------------------------
560     // XAccessibleText
561     // -----------------------------------------------------------------------------
562     // -----------------------------------------------------------------------------
563     awt::Rectangle SAL_CALL AccessibleListBoxEntry::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
564     {
565         ALBSolarGuard aSolarGuard;
566         ::osl::MutexGuard aGuard( m_aMutex );
567 
568         EnsureIsAlive();
569 
570         if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
571             throw IndexOutOfBoundsException();
572 
573         awt::Rectangle aBounds( 0, 0, 0, 0 );
574         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
575         if ( pEntry )
576         {
577             ::vcl::ControlLayoutData aLayoutData;
578             Rectangle aItemRect = GetBoundingBox();
579             getListBox()->RecordLayoutData( &aLayoutData, aItemRect );
580             Rectangle aCharRect = aLayoutData.GetCharacterBounds( nIndex );
581             aCharRect.Move( -aItemRect.Left(), -aItemRect.Top() );
582             aBounds = AWTRectangle( aCharRect );
583         }
584 
585         return aBounds;
586     }
587     // -----------------------------------------------------------------------------
588     sal_Int32 SAL_CALL AccessibleListBoxEntry::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException)
589     {
590         ALBSolarGuard aSolarGuard;
591         ::osl::MutexGuard aGuard( m_aMutex );
592         EnsureIsAlive();
593 
594         sal_Int32 nIndex = -1;
595         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
596         if ( pEntry )
597         {
598             ::vcl::ControlLayoutData aLayoutData;
599             Rectangle aItemRect = GetBoundingBox();
600             getListBox()->RecordLayoutData( &aLayoutData, aItemRect );
601             Point aPnt( VCLPoint( aPoint ) );
602             aPnt += aItemRect.TopLeft();
603             nIndex = aLayoutData.GetIndexForPoint( aPnt );
604         }
605 
606         return nIndex;
607     }
608     // -----------------------------------------------------------------------------
609     sal_Bool SAL_CALL AccessibleListBoxEntry::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
610     {
611         ALBSolarGuard aSolarGuard;
612         ::osl::MutexGuard aGuard( m_aMutex );
613         EnsureIsAlive();
614 
615         String sText = getText();
616         if  ( ( 0 > nStartIndex ) || ( sText.Len() <= nStartIndex )
617             || ( 0 > nEndIndex ) || ( sText.Len() <= nEndIndex ) )
618             throw IndexOutOfBoundsException();
619 
620         sal_Int32 nLen = nEndIndex - nStartIndex + 1;
621         ::svt::OStringTransfer::CopyString( sText.Copy( (sal_uInt16)nStartIndex, (sal_uInt16)nLen ), getListBox() );
622 
623         return sal_True;
624     }
625     // -----------------------------------------------------------------------------
626     // XAccessibleEventBroadcaster
627     // -----------------------------------------------------------------------------
628     void SAL_CALL AccessibleListBoxEntry::addEventListener( const Reference< XAccessibleEventListener >& xListener ) throw (RuntimeException)
629     {
630         if (xListener.is())
631         {
632             ::osl::MutexGuard aGuard( m_aMutex );
633             if (!m_nClientId)
634                 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
635             comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, xListener );
636         }
637     }
638     // -----------------------------------------------------------------------------
639     void SAL_CALL AccessibleListBoxEntry::removeEventListener( const Reference< XAccessibleEventListener >& xListener ) throw (RuntimeException)
640     {
641         if (xListener.is())
642         {
643             ::osl::MutexGuard aGuard( m_aMutex );
644 
645             sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, xListener );
646             if ( !nListenerCount )
647             {
648                 // no listeners anymore
649                 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
650                 // and at least to us not firing any events anymore, in case somebody calls
651                 // NotifyAccessibleEvent, again
652                 sal_Int32 nId = m_nClientId;
653                 m_nClientId = 0;
654                 comphelper::AccessibleEventNotifier::revokeClient( nId );
655 
656             }
657         }
658     }
659     // -----------------------------------------------------------------------------
660     // XAccessibleAction
661     // -----------------------------------------------------------------------------
662     sal_Int32 SAL_CALL AccessibleListBoxEntry::getAccessibleActionCount(  ) throw (RuntimeException)
663     {
664         ::osl::MutexGuard aGuard( m_aMutex );
665 
666         // three actions supported
667         return ACCESSIBLE_ACTION_COUNT;
668     }
669     // -----------------------------------------------------------------------------
670     sal_Bool SAL_CALL AccessibleListBoxEntry::doAccessibleAction( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
671     {
672         ALBSolarGuard aSolarGuard;
673         ::osl::MutexGuard aGuard( m_aMutex );
674 
675         sal_Bool bRet = sal_False;
676         checkActionIndex_Impl( nIndex );
677         EnsureIsAlive();
678 
679         SvLBoxEntry* pEntry = getListBox()->GetEntryFromPath( m_aEntryPath );
680         if ( pEntry )
681         {
682             if ( getListBox()->IsExpanded( pEntry ) )
683                 getListBox()->Collapse( pEntry );
684             else
685                 getListBox()->Expand( pEntry );
686             bRet = sal_True;
687         }
688 
689         return bRet;
690     }
691     // -----------------------------------------------------------------------------
692     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getAccessibleActionDescription( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
693     {
694         ALBSolarGuard aSolarGuard;
695         ::osl::MutexGuard aGuard( m_aMutex );
696 
697         checkActionIndex_Impl( nIndex );
698         EnsureIsAlive();
699 
700         static const ::rtl::OUString sActionDesc( RTL_CONSTASCII_USTRINGPARAM( "toggleExpand" ) );
701         return sActionDesc;
702     }
703     // -----------------------------------------------------------------------------
704     Reference< XAccessibleKeyBinding > AccessibleListBoxEntry::getAccessibleActionKeyBinding( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
705     {
706         ::osl::MutexGuard aGuard( m_aMutex );
707 
708         Reference< XAccessibleKeyBinding > xRet;
709         checkActionIndex_Impl( nIndex );
710         // ... which key?
711         return xRet;
712     }
713     // -----------------------------------------------------------------------------
714     // XAccessibleSelection
715     // -----------------------------------------------------------------------------
716     void SAL_CALL AccessibleListBoxEntry::selectAccessibleChild( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
717     {
718         ALBSolarGuard aSolarGuard;
719         ::osl::MutexGuard aGuard( m_aMutex );
720 
721         EnsureIsAlive();
722 
723         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
724         SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, nChildIndex );
725         if ( !pEntry )
726             throw IndexOutOfBoundsException();
727 
728         getListBox()->Select( pEntry, sal_True );
729     }
730     // -----------------------------------------------------------------------------
731     sal_Bool SAL_CALL AccessibleListBoxEntry::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
732     {
733         ALBSolarGuard aSolarGuard;
734         ::osl::MutexGuard aGuard( m_aMutex );
735 
736         EnsureIsAlive();
737 
738         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
739         SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, nChildIndex );
740         if ( !pEntry )
741             throw IndexOutOfBoundsException();
742 
743         return getListBox()->IsSelected( pEntry );
744     }
745     // -----------------------------------------------------------------------------
746     void SAL_CALL AccessibleListBoxEntry::clearAccessibleSelection(  ) throw (RuntimeException)
747     {
748         ALBSolarGuard aSolarGuard;
749         ::osl::MutexGuard aGuard( m_aMutex );
750 
751         EnsureIsAlive();
752 
753         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
754         if ( !pParent )
755             throw RuntimeException();
756         sal_Int32 i, nCount = 0;
757         nCount = getListBox()->GetLevelChildCount( pParent );
758         for ( i = 0; i < nCount; ++i )
759         {
760             SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
761             if ( getListBox()->IsSelected( pEntry ) )
762                 getListBox()->Select( pEntry, sal_False );
763         }
764     }
765     // -----------------------------------------------------------------------------
766     void SAL_CALL AccessibleListBoxEntry::selectAllAccessibleChildren(  ) throw (RuntimeException)
767     {
768         ALBSolarGuard aSolarGuard;
769         ::osl::MutexGuard aGuard( m_aMutex );
770 
771         EnsureIsAlive();
772 
773         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
774         if ( !pParent )
775             throw RuntimeException();
776         sal_Int32 i, nCount = 0;
777         nCount = getListBox()->GetLevelChildCount( pParent );
778         for ( i = 0; i < nCount; ++i )
779         {
780             SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
781             if ( !getListBox()->IsSelected( pEntry ) )
782                 getListBox()->Select( pEntry, sal_True );
783         }
784     }
785     // -----------------------------------------------------------------------------
786     sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChildCount(  ) throw (RuntimeException)
787     {
788         ALBSolarGuard aSolarGuard;
789         ::osl::MutexGuard aGuard( m_aMutex );
790 
791         EnsureIsAlive();
792 
793         sal_Int32 i, nSelCount = 0, nCount = 0;
794 
795         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
796         if ( !pParent )
797             throw RuntimeException();
798         nCount = getListBox()->GetLevelChildCount( pParent );
799         for ( i = 0; i < nCount; ++i )
800         {
801             SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
802             if ( getListBox()->IsSelected( pEntry ) )
803                 ++nSelCount;
804         }
805 
806         return nSelCount;
807     }
808     // -----------------------------------------------------------------------------
809     Reference< XAccessible > SAL_CALL AccessibleListBoxEntry::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
810     {
811         ALBSolarGuard aSolarGuard;
812         ::osl::MutexGuard aGuard( m_aMutex );
813 
814         EnsureIsAlive();
815 
816         if ( nSelectedChildIndex < 0 || nSelectedChildIndex >= getSelectedAccessibleChildCount() )
817             throw IndexOutOfBoundsException();
818 
819         Reference< XAccessible > xChild;
820         sal_Int32 i, nSelCount = 0, nCount = 0;
821 
822         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
823         if ( !pParent )
824             throw RuntimeException();
825         nCount = getListBox()->GetLevelChildCount( pParent );
826         for ( i = 0; i < nCount; ++i )
827         {
828             SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, i );
829             if ( getListBox()->IsSelected( pEntry ) )
830                 ++nSelCount;
831 
832             if ( nSelCount == ( nSelectedChildIndex + 1 ) )
833             {
834                 xChild = new AccessibleListBoxEntry( *getListBox(), pEntry, this );
835                 break;
836             }
837         }
838 
839         return xChild;
840     }
841     // -----------------------------------------------------------------------------
842     void SAL_CALL AccessibleListBoxEntry::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (IndexOutOfBoundsException, RuntimeException)
843     {
844         ALBSolarGuard aSolarGuard;
845         ::osl::MutexGuard aGuard( m_aMutex );
846 
847         EnsureIsAlive();
848 
849         SvLBoxEntry* pParent = getListBox()->GetEntryFromPath( m_aEntryPath );
850         SvLBoxEntry* pEntry = getListBox()->GetEntry( pParent, nSelectedChildIndex );
851         if ( !pEntry )
852             throw IndexOutOfBoundsException();
853 
854         getListBox()->Select( pEntry, sal_False );
855     }
856     sal_Int32 SAL_CALL AccessibleListBoxEntry::getCaretPosition(  ) throw (::com::sun::star::uno::RuntimeException)
857     {
858         return -1;
859     }
860     sal_Bool SAL_CALL AccessibleListBoxEntry::setCaretPosition ( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
861     {
862         ALBSolarGuard aSolarGuard;
863         ::osl::MutexGuard aGuard( m_aMutex );
864         EnsureIsAlive();
865 
866         if ( !implIsValidRange( nIndex, nIndex, implGetText().getLength() ) )
867             throw IndexOutOfBoundsException();
868 
869         return sal_False;
870     }
871     sal_Unicode SAL_CALL AccessibleListBoxEntry::getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
872     {
873         ALBSolarGuard aSolarGuard;
874         ::osl::MutexGuard aGuard( m_aMutex );
875         EnsureIsAlive();
876         return OCommonAccessibleText::getCharacter( nIndex );
877     }
878     ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL AccessibleListBoxEntry::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
879     {
880         ALBSolarGuard aSolarGuard;
881         ::osl::MutexGuard aGuard( m_aMutex );
882         EnsureIsAlive();
883 
884         ::rtl::OUString sText( implGetText() );
885 
886         if ( !implIsValidIndex( nIndex, sText.getLength() ) )
887             throw IndexOutOfBoundsException();
888 
889         return ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >();
890     }
891     sal_Int32 SAL_CALL AccessibleListBoxEntry::getCharacterCount(  ) throw (::com::sun::star::uno::RuntimeException)
892     {
893         ALBSolarGuard aSolarGuard;
894         ::osl::MutexGuard aGuard( m_aMutex );
895         EnsureIsAlive();
896         return OCommonAccessibleText::getCharacterCount(  );
897     }
898 
899     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getSelectedText(  ) throw (::com::sun::star::uno::RuntimeException)
900     {
901         ALBSolarGuard aSolarGuard;
902         ::osl::MutexGuard aGuard( m_aMutex );
903         EnsureIsAlive();
904         return OCommonAccessibleText::getSelectedText(  );
905     }
906     sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionStart(  ) throw (::com::sun::star::uno::RuntimeException)
907     {
908         ALBSolarGuard aSolarGuard;
909         ::osl::MutexGuard aGuard( m_aMutex );
910         EnsureIsAlive();
911         return OCommonAccessibleText::getSelectionStart(  );
912     }
913     sal_Int32 SAL_CALL AccessibleListBoxEntry::getSelectionEnd(  ) throw (::com::sun::star::uno::RuntimeException)
914     {
915         ALBSolarGuard aSolarGuard;
916         ::osl::MutexGuard aGuard( m_aMutex );
917         EnsureIsAlive();
918         return OCommonAccessibleText::getSelectionEnd(  );
919     }
920     sal_Bool SAL_CALL AccessibleListBoxEntry::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
921     {
922         ALBSolarGuard aSolarGuard;
923         ::osl::MutexGuard aGuard( m_aMutex );
924         EnsureIsAlive();
925 
926         if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
927             throw IndexOutOfBoundsException();
928 
929         return sal_False;
930     }
931     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getText(  ) throw (::com::sun::star::uno::RuntimeException)
932     {
933         ALBSolarGuard aSolarGuard;
934         ::osl::MutexGuard aGuard( m_aMutex );
935         EnsureIsAlive();
936         return OCommonAccessibleText::getText(  );
937     }
938     ::rtl::OUString SAL_CALL AccessibleListBoxEntry::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
939     {
940         ALBSolarGuard aSolarGuard;
941         ::osl::MutexGuard aGuard( m_aMutex );
942         EnsureIsAlive();
943         return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
944     }
945     ::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)
946     {
947         ALBSolarGuard aSolarGuard;
948         ::osl::MutexGuard aGuard( m_aMutex );
949         EnsureIsAlive();
950         return OCommonAccessibleText::getTextAtIndex( nIndex ,aTextType);
951     }
952     ::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)
953     {
954         ALBSolarGuard aSolarGuard;
955         ::osl::MutexGuard aGuard( m_aMutex );
956         EnsureIsAlive();
957         return OCommonAccessibleText::getTextBeforeIndex( nIndex ,aTextType);
958     }
959     ::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)
960     {
961         ALBSolarGuard aSolarGuard;
962         ::osl::MutexGuard aGuard( m_aMutex );
963         EnsureIsAlive();
964 
965         return OCommonAccessibleText::getTextBehindIndex( nIndex ,aTextType);
966     }
967 //........................................................................
968 }// namespace accessibility
969 //........................................................................
970 
971