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