xref: /trunk/main/accessibility/source/extended/AccessibleBrowseBoxBase.cxx (revision 9c15e1abd703a7953928d7a80655ae1a76a41f6d)
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/AccessibleBrowseBoxBase.hxx"
27 #include <svtools/accessibletableprovider.hxx>
28 #include <rtl/uuid.h>
29 //
30 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
31 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
32 #include <unotools/accessiblerelationsethelper.hxx>
33 
34 // ============================================================================
35 
36 using ::rtl::OUString;
37 
38 using ::com::sun::star::uno::Reference;
39 using ::com::sun::star::uno::Sequence;
40 using ::com::sun::star::uno::Any;
41 
42 using namespace ::com::sun::star;
43 using namespace ::com::sun::star::accessibility;
44 using namespace ::comphelper;
45 using namespace ::svt;
46 
47 
48 // ============================================================================
49 
50 namespace accessibility {
51 
52 using namespace com::sun::star::accessibility::AccessibleStateType;
53 // ============================================================================
54 
55 // Ctor/Dtor/disposing --------------------------------------------------------
56 
57 DBG_NAME( AccessibleBrowseBoxBase )
58 
59 AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
60         const Reference< XAccessible >& rxParent,
61         IAccessibleTableProvider&                      rBrowseBox,
62         const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& _xFocusWindow,
63         AccessibleBrowseBoxObjType      eObjType ) :
64     AccessibleBrowseBoxImplHelper( m_aMutex ),
65     mxParent( rxParent ),
66     mpBrowseBox( &rBrowseBox ),
67     m_xFocusWindow(_xFocusWindow),
68     maName( rBrowseBox.GetAccessibleObjectName( eObjType ) ),
69     maDescription( rBrowseBox.GetAccessibleObjectDescription( eObjType ) ),
70     meObjType( eObjType ),
71     m_aClientId(0)
72 {
73     DBG_CTOR( AccessibleBrowseBoxBase, NULL );
74     if ( m_xFocusWindow.is() )
75         m_xFocusWindow->addFocusListener( this );
76 }
77 
78 AccessibleBrowseBoxBase::AccessibleBrowseBoxBase(
79         const Reference< XAccessible >& rxParent,
80         IAccessibleTableProvider&                      rBrowseBox,
81         const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XWindow >& _xFocusWindow,
82         AccessibleBrowseBoxObjType      eObjType,
83         const ::rtl::OUString&          rName,
84         const ::rtl::OUString&          rDescription ) :
85     AccessibleBrowseBoxImplHelper( m_aMutex ),
86     mxParent( rxParent ),
87     mpBrowseBox( &rBrowseBox ),
88     m_xFocusWindow(_xFocusWindow),
89     maName( rName ),
90     maDescription( rDescription ),
91     meObjType( eObjType ),
92     m_aClientId(0)
93 {
94     DBG_CTOR( AccessibleBrowseBoxBase, NULL );
95     if ( m_xFocusWindow.is() )
96         m_xFocusWindow->addFocusListener( this );
97 }
98 
99 AccessibleBrowseBoxBase::~AccessibleBrowseBoxBase()
100 {
101     DBG_DTOR( AccessibleBrowseBoxBase, NULL );
102 
103     if( isAlive() )
104     {
105         // increment ref count to prevent double call of Dtor
106         osl_incrementInterlockedCount( &m_refCount );
107         dispose();
108     }
109 }
110 
111 void SAL_CALL AccessibleBrowseBoxBase::disposing()
112 {
113     ::osl::MutexGuard aGuard( getOslMutex() );
114     if ( m_xFocusWindow.is() )
115     {
116         BBSolarGuard aSolarGuard;
117         m_xFocusWindow->removeFocusListener( this );
118     }
119 
120     if ( getClientId( ) )
121     {
122         AccessibleEventNotifier::TClientId nId( getClientId( ) );
123         setClientId( 0 );
124         AccessibleEventNotifier::revokeClientNotifyDisposing( nId, *this );
125     }
126 
127     mxParent = NULL;
128     mpBrowseBox = NULL;
129 }
130 
131 // XAccessibleContext ---------------------------------------------------------
132 
133 Reference< XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleParent()
134 {
135     ::osl::MutexGuard aGuard( getOslMutex() );
136     ensureIsAlive();
137     return mxParent;
138 }
139 
140 sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getAccessibleIndexInParent()
141 {
142     ::osl::MutexGuard aGuard( getOslMutex() );
143     ensureIsAlive();
144 
145     // -1 for child not found/no parent (according to specification)
146     sal_Int32 nRet = -1;
147 
148     Reference< uno::XInterface > xMeMyselfAndI( static_cast< XAccessibleContext* >( this ), uno::UNO_QUERY );
149 
150     //  iterate over parent's children and search for this object
151     if( mxParent.is() )
152     {
153         Reference< XAccessibleContext >
154             xParentContext( mxParent->getAccessibleContext() );
155         if( xParentContext.is() )
156         {
157             Reference< uno::XInterface > xChild;
158 
159             sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
160             for( sal_Int32 nChild = 0; nChild < nChildCount; ++nChild )
161             {
162                 xChild = xChild.query( xParentContext->getAccessibleChild( nChild ) );
163 
164                 if ( xMeMyselfAndI.get() == xChild.get() )
165                 {
166                     nRet = nChild;
167                     break;
168                 }
169             }
170         }
171    }
172    return nRet;
173 }
174 
175 OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleDescription()
176 {
177     ::osl::MutexGuard aGuard( getOslMutex() );
178     ensureIsAlive();
179     return maDescription;
180 }
181 
182 OUString SAL_CALL AccessibleBrowseBoxBase::getAccessibleName()
183 {
184     ::osl::MutexGuard aGuard( getOslMutex() );
185     ensureIsAlive();
186     return maName;
187 }
188 
189 Reference< XAccessibleRelationSet > SAL_CALL
190 AccessibleBrowseBoxBase::getAccessibleRelationSet()
191 {
192     ensureIsAlive();
193     // BrowseBox does not have relations.
194     return new utl::AccessibleRelationSetHelper;
195 }
196 
197 Reference< XAccessibleStateSet > SAL_CALL
198 AccessibleBrowseBoxBase::getAccessibleStateSet()
199 {
200     BBSolarGuard aSolarGuard;
201     ::osl::MutexGuard aGuard( getOslMutex() );
202     // don't check whether alive -> StateSet may contain DEFUNC
203     return implCreateStateSetHelper();
204 }
205 
206 lang::Locale SAL_CALL AccessibleBrowseBoxBase::getLocale()
207 {
208     ::osl::MutexGuard aGuard( getOslMutex() );
209     ensureIsAlive();
210     if( mxParent.is() )
211     {
212         Reference< XAccessibleContext >
213             xParentContext( mxParent->getAccessibleContext() );
214         if( xParentContext.is() )
215             return xParentContext->getLocale();
216     }
217     throw IllegalAccessibleComponentStateException();
218 }
219 
220 // XAccessibleComponent -------------------------------------------------------
221 
222 sal_Bool SAL_CALL AccessibleBrowseBoxBase::containsPoint( const awt::Point& rPoint )
223 {
224     return Rectangle( Point(), getBoundingBox().GetSize() ).IsInside( VCLPoint( rPoint ) );
225 }
226 
227 awt::Rectangle SAL_CALL AccessibleBrowseBoxBase::getBounds()
228 {
229     return AWTRectangle( getBoundingBox() );
230 }
231 
232 awt::Point SAL_CALL AccessibleBrowseBoxBase::getLocation()
233 {
234     return AWTPoint( getBoundingBox().TopLeft() );
235 }
236 
237 awt::Point SAL_CALL AccessibleBrowseBoxBase::getLocationOnScreen()
238 {
239     return AWTPoint( getBoundingBoxOnScreen().TopLeft() );
240 }
241 
242 awt::Size SAL_CALL AccessibleBrowseBoxBase::getSize()
243 {
244     return AWTSize( getBoundingBox().GetSize() );
245 }
246 
247 sal_Bool SAL_CALL AccessibleBrowseBoxBase::isShowing()
248 {
249     BBSolarGuard aSolarGuard;
250     ::osl::MutexGuard aGuard( getOslMutex() );
251     ensureIsAlive();
252     return implIsShowing();
253 }
254 
255 sal_Bool SAL_CALL AccessibleBrowseBoxBase::isVisible()
256 {
257     Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet();
258     return xStateSet.is() ?
259         xStateSet->contains( AccessibleStateType::VISIBLE ) : sal_False;
260 }
261 
262 sal_Bool SAL_CALL AccessibleBrowseBoxBase::isFocusTraversable()
263 {
264     Reference< XAccessibleStateSet > xStateSet = getAccessibleStateSet();
265     return xStateSet.is() ?
266         xStateSet->contains( AccessibleStateType::FOCUSABLE ) : sal_False;
267 }
268 
269 void SAL_CALL AccessibleBrowseBoxBase::focusGained( const ::com::sun::star::awt::FocusEvent& )
270 {
271     com::sun::star::uno::Any aFocused;
272     com::sun::star::uno::Any aEmpty;
273     aFocused <<= FOCUSED;
274 
275     commitEvent(AccessibleEventId::STATE_CHANGED,aFocused,aEmpty);
276 }
277 // -----------------------------------------------------------------------------
278 
279 void SAL_CALL AccessibleBrowseBoxBase::focusLost( const ::com::sun::star::awt::FocusEvent& )
280 {
281     com::sun::star::uno::Any aFocused;
282     com::sun::star::uno::Any aEmpty;
283     aFocused <<= FOCUSED;
284 
285     commitEvent(AccessibleEventId::STATE_CHANGED,aEmpty,aFocused);
286 }
287 // XAccessibleEventBroadcaster ------------------------------------------------
288 
289 void SAL_CALL AccessibleBrowseBoxBase::addEventListener(
290         const Reference< XAccessibleEventListener>& _rxListener )
291 {
292     if ( _rxListener.is() )
293     {
294         ::osl::MutexGuard aGuard( getOslMutex() );
295         if ( !getClientId( ) )
296             setClientId( AccessibleEventNotifier::registerClient( ) );
297 
298         AccessibleEventNotifier::addEventListener( getClientId( ), _rxListener );
299     }
300 }
301 
302 void SAL_CALL AccessibleBrowseBoxBase::removeEventListener(
303         const Reference< XAccessibleEventListener>& _rxListener )
304 {
305     if( _rxListener.is() && getClientId( ) )
306     {
307         ::osl::MutexGuard aGuard( getOslMutex() );
308         sal_Int32 nListenerCount = AccessibleEventNotifier::removeEventListener( getClientId( ), _rxListener );
309         if ( !nListenerCount )
310         {
311             // no listeners anymore
312             // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
313             // and at least to us not firing any events anymore, in case somebody calls
314             // NotifyAccessibleEvent, again
315 
316             AccessibleEventNotifier::TClientId nId( getClientId( ) );
317             setClientId( 0 );
318             AccessibleEventNotifier::revokeClient( nId );
319         }
320     }
321 }
322 
323 // XTypeProvider --------------------------------------------------------------
324 
325 Sequence< sal_Int8 > SAL_CALL AccessibleBrowseBoxBase::getImplementationId()
326 {
327     ::osl::MutexGuard aGuard( getOslGlobalMutex() );
328     static Sequence< sal_Int8 > aId;
329     implCreateUuid( aId );
330     return aId;
331 }
332 
333 // XServiceInfo ---------------------------------------------------------------
334 
335 sal_Bool SAL_CALL AccessibleBrowseBoxBase::supportsService(
336         const OUString& rServiceName )
337 {
338     ::osl::MutexGuard aGuard( getOslMutex() );
339 
340     Sequence< OUString > aSupportedServices( getSupportedServiceNames() );
341     const OUString* pArrBegin = aSupportedServices.getConstArray();
342     const OUString* pArrEnd = pArrBegin + aSupportedServices.getLength();
343     const OUString* pString = pArrBegin;
344 
345     for( ; ( pString != pArrEnd ) && ( rServiceName != *pString ); ++pString )
346         ;
347 
348     return pString != pArrEnd;
349 }
350 
351 Sequence< OUString > SAL_CALL AccessibleBrowseBoxBase::getSupportedServiceNames()
352 {
353     const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ) );
354     return Sequence< OUString >( &aServiceName, 1 );
355 }
356 
357 // other public methods -------------------------------------------------------
358 
359 void AccessibleBrowseBoxBase::setAccessibleName( const OUString& rName )
360 {
361     ::osl::ClearableMutexGuard aGuard( getOslMutex() );
362     Any aOld;
363     aOld <<= maName;
364     maName = rName;
365 
366     aGuard.clear();
367 
368     commitEvent(
369         AccessibleEventId::NAME_CHANGED,
370         uno::makeAny( maName ),
371         aOld );
372 }
373 
374 void AccessibleBrowseBoxBase::setAccessibleDescription( const OUString& rDescription )
375 {
376     ::osl::ClearableMutexGuard aGuard( getOslMutex() );
377     Any aOld;
378     aOld <<= maDescription;
379     maDescription = rDescription;
380 
381     aGuard.clear();
382 
383     commitEvent(
384         AccessibleEventId::DESCRIPTION_CHANGED,
385         uno::makeAny( maDescription ),
386         aOld );
387 }
388 
389 // internal virtual methods ---------------------------------------------------
390 
391 sal_Bool AccessibleBrowseBoxBase::implIsShowing()
392 {
393     sal_Bool bShowing = sal_False;
394     if( mxParent.is() )
395     {
396         Reference< XAccessibleComponent >
397             xParentComp( mxParent->getAccessibleContext(), uno::UNO_QUERY );
398         if( xParentComp.is() )
399             bShowing = implGetBoundingBox().IsOver(
400                 VCLRectangle( xParentComp->getBounds() ) );
401     }
402     return bShowing;
403 }
404 
405 ::utl::AccessibleStateSetHelper* AccessibleBrowseBoxBase::implCreateStateSetHelper()
406 {
407     ::utl::AccessibleStateSetHelper*
408         pStateSetHelper = new ::utl::AccessibleStateSetHelper;
409 
410     if( isAlive() )
411     {
412         // SHOWING done with mxParent
413         if( implIsShowing() )
414             pStateSetHelper->AddState( AccessibleStateType::SHOWING );
415         // BrowseBox fills StateSet with states depending on object type
416         mpBrowseBox->FillAccessibleStateSet( *pStateSetHelper, getType() );
417     }
418     else
419         pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
420 
421     return pStateSetHelper;
422 }
423 
424 // internal helper methods ----------------------------------------------------
425 
426 sal_Bool AccessibleBrowseBoxBase::isAlive() const
427 {
428     return !rBHelper.bDisposed && !rBHelper.bInDispose && mpBrowseBox;
429 }
430 
431 void AccessibleBrowseBoxBase::ensureIsAlive() const
432 {
433     if( !isAlive() )
434         throw lang::DisposedException();
435 }
436 
437 Rectangle AccessibleBrowseBoxBase::getBoundingBox()
438 {
439     BBSolarGuard aSolarGuard;
440     ::osl::MutexGuard aGuard( getOslMutex() );
441     ensureIsAlive();
442     Rectangle aRect = implGetBoundingBox();
443     if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() )
444     {
445         DBG_ERRORFILE( "shit" );
446     }
447     return aRect;
448 }
449 
450 Rectangle AccessibleBrowseBoxBase::getBoundingBoxOnScreen()
451 {
452     BBSolarGuard aSolarGuard;
453     ::osl::MutexGuard aGuard( getOslMutex() );
454     ensureIsAlive();
455     Rectangle aRect = implGetBoundingBoxOnScreen();
456     if ( 0 == aRect.Left() && 0 == aRect.Top() && 0 == aRect.Right() && 0 == aRect.Bottom() )
457     {
458         DBG_ERRORFILE( "shit" );
459     }
460     return aRect;
461 }
462 
463 void AccessibleBrowseBoxBase::commitEvent(
464         sal_Int16 _nEventId, const Any& _rNewValue, const Any& _rOldValue )
465 {
466     ::osl::ClearableMutexGuard aGuard( getOslMutex() );
467     if ( !getClientId( ) )
468             // if we don't have a client id for the notifier, then we don't have listeners, then
469             // we don't need to notify anything
470             return;
471 
472     // build an event object
473     AccessibleEventObject aEvent;
474     aEvent.Source = *this;
475     aEvent.EventId = _nEventId;
476     aEvent.OldValue = _rOldValue;
477     aEvent.NewValue = _rNewValue;
478 
479     // let the notifier handle this event
480 
481     AccessibleEventNotifier::addEvent( getClientId( ), aEvent );
482 }
483 // -----------------------------------------------------------------------------
484 
485 void AccessibleBrowseBoxBase::implCreateUuid( Sequence< sal_Int8 >& rId )
486 {
487     if( !rId.hasElements() )
488     {
489         rId.realloc( 16 );
490         rtl_createUuid( reinterpret_cast< sal_uInt8* >( rId.getArray() ), 0, sal_True );
491     }
492 }
493 // -----------------------------------------------------------------------------
494 sal_Int16 SAL_CALL AccessibleBrowseBoxBase::getAccessibleRole()
495 {
496     ensureIsAlive();
497     sal_Int16 nRole = AccessibleRole::UNKNOWN;
498     switch ( meObjType )
499     {
500         case BBTYPE_ROWHEADERCELL:
501             nRole = AccessibleRole::ROW_HEADER;
502             break;
503         case BBTYPE_COLUMNHEADERCELL:
504             nRole = AccessibleRole::COLUMN_HEADER;
505             break;
506         case BBTYPE_COLUMNHEADERBAR:
507         case BBTYPE_ROWHEADERBAR:
508         case BBTYPE_TABLE:
509             nRole = AccessibleRole::TABLE;
510             break;
511         case BBTYPE_TABLECELL:
512             nRole = AccessibleRole::TABLE_CELL;
513             break;
514         case BBTYPE_BROWSEBOX:
515             nRole = AccessibleRole::PANEL;
516             break;
517         case BBTYPE_CHECKBOXCELL:
518             nRole = AccessibleRole::CHECK_BOX;
519             break;
520     }
521     return nRole;
522 }
523 // -----------------------------------------------------------------------------
524 Any SAL_CALL AccessibleBrowseBoxBase::getAccessibleKeyBinding()
525 {
526     return Any();
527 }
528 // -----------------------------------------------------------------------------
529 Reference<XAccessible > SAL_CALL AccessibleBrowseBoxBase::getAccessibleAtPoint( const ::com::sun::star::awt::Point& )
530 {
531     return NULL;
532 }
533 // -----------------------------------------------------------------------------
534 void SAL_CALL AccessibleBrowseBoxBase::disposing( const ::com::sun::star::lang::EventObject& )
535 {
536     m_xFocusWindow = NULL;
537 }
538 // -----------------------------------------------------------------------------
539 sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getForeground(  )
540 {
541     BBSolarGuard aSolarGuard;
542     ::osl::MutexGuard aGuard( getOslMutex() );
543     ensureIsAlive();
544 
545     sal_Int32 nColor = 0;
546     Window* pInst = mpBrowseBox->GetWindowInstance();
547     if ( pInst )
548     {
549         if ( pInst->IsControlForeground() )
550             nColor = pInst->GetControlForeground().GetColor();
551         else
552         {
553             Font aFont;
554             if ( pInst->IsControlFont() )
555                 aFont = pInst->GetControlFont();
556             else
557                 aFont = pInst->GetFont();
558             nColor = aFont.GetColor().GetColor();
559         }
560     }
561 
562     return nColor;
563 }
564 // -----------------------------------------------------------------------------
565 sal_Int32 SAL_CALL AccessibleBrowseBoxBase::getBackground(  )
566 {
567     BBSolarGuard aSolarGuard;
568     ::osl::MutexGuard aGuard( getOslMutex() );
569     ensureIsAlive();
570     sal_Int32 nColor = 0;
571     Window* pInst = mpBrowseBox->GetWindowInstance();
572     if ( pInst )
573     {
574         if ( pInst->IsControlBackground() )
575             nColor = pInst->GetControlBackground().GetColor();
576         else
577             nColor = pInst->GetBackground().GetColor().GetColor();
578     }
579 
580     return nColor;
581 }
582 
583 // ============================================================================
584 DBG_NAME( BrowseBoxAccessibleElement )
585 
586 // XInterface -----------------------------------------------------------------
587 IMPLEMENT_FORWARD_XINTERFACE2( BrowseBoxAccessibleElement, AccessibleBrowseBoxBase, BrowseBoxAccessibleElement_Base )
588 
589 // XTypeProvider --------------------------------------------------------------
590 IMPLEMENT_FORWARD_XTYPEPROVIDER2( BrowseBoxAccessibleElement, AccessibleBrowseBoxBase, BrowseBoxAccessibleElement_Base )
591 
592 // XAccessible ----------------------------------------------------------------
593 
594 Reference< XAccessibleContext > SAL_CALL BrowseBoxAccessibleElement::getAccessibleContext()
595 {
596     ensureIsAlive();
597     return this;
598 }
599 
600 // ----------------------------------------------------------------------------
601 BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const Reference< XAccessible >& rxParent, IAccessibleTableProvider& rBrowseBox,
602         const Reference< awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType  eObjType )
603     :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType )
604 {
605     DBG_CTOR( BrowseBoxAccessibleElement, NULL );
606 }
607 
608 // ----------------------------------------------------------------------------
609 BrowseBoxAccessibleElement::BrowseBoxAccessibleElement( const Reference< XAccessible >& rxParent, IAccessibleTableProvider& rBrowseBox,
610         const Reference< awt::XWindow >& _xFocusWindow, AccessibleBrowseBoxObjType  eObjType,
611         const ::rtl::OUString& rName, const ::rtl::OUString& rDescription )
612     :AccessibleBrowseBoxBase( rxParent, rBrowseBox, _xFocusWindow, eObjType, rName, rDescription )
613 {
614     DBG_CTOR( BrowseBoxAccessibleElement, NULL );
615 }
616 
617 // ----------------------------------------------------------------------------
618 BrowseBoxAccessibleElement::~BrowseBoxAccessibleElement( )
619 {
620     DBG_DTOR( BrowseBoxAccessibleElement, NULL );
621 }
622 
623 // ============================================================================
624 
625 } // namespace accessibility
626 
627 // ============================================================================
628