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