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