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