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