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_chart2.hxx"
26
27 #include "AccessibleBase.hxx"
28 #include "AccessibleChartShape.hxx"
29 #include "ObjectHierarchy.hxx"
30 #include "ObjectIdentifier.hxx"
31 #include "chartview/ExplicitValueProvider.hxx"
32 #include "macros.hxx"
33
34 #include <com/sun/star/awt/XDevice.hpp>
35 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
36 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
37 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
38 #include <com/sun/star/accessibility/AccessibleRole.hpp>
39 #include <comphelper/serviceinfohelper.hxx>
40 #include <com/sun/star/drawing/LineStyle.hpp>
41 #include <com/sun/star/drawing/FillStyle.hpp>
42 #include <rtl/ustrbuf.hxx>
43 // for SolarMutex
44 #include <vcl/svapp.hxx>
45 #include <rtl/uuid.h>
46 #include <cppuhelper/queryinterface.hxx>
47 #include <svl/itemset.hxx>
48 #include <editeng/unofdesc.hxx>
49 #include <editeng/outliner.hxx>
50 #include <svx/svdoutl.hxx>
51 #include <svx/svdetc.hxx>
52 #include <svx/unoshape.hxx>
53 #include <svx/unoprov.hxx>
54 #include <vcl/unohelp.hxx>
55 #include <toolkit/helper/vclunohelper.hxx>
56 #include <vcl/window.hxx>
57
58 #include <algorithm>
59
60 #include "ChartElementFactory.hxx"
61
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::accessibility;
64
65 using ::com::sun::star::uno::UNO_QUERY;
66 using ::rtl::OUString;
67 using ::rtl::OUStringBuffer;
68 using ::com::sun::star::uno::Reference;
69 using ::osl::MutexGuard;
70 using ::osl::ClearableMutexGuard;
71 using ::osl::ResettableMutexGuard;
72 using ::com::sun::star::uno::RuntimeException;
73 using ::com::sun::star::uno::Any;
74
75 namespace chart
76 {
77
78 /** @param bMayHaveChildren is false per default
79 */
AccessibleBase(const AccessibleElementInfo & rAccInfo,bool bMayHaveChildren,bool bAlwaysTransparent)80 AccessibleBase::AccessibleBase(
81 const AccessibleElementInfo & rAccInfo,
82 bool bMayHaveChildren,
83 bool bAlwaysTransparent /* default: false */ ) :
84 impl::AccessibleBase_Base( m_aMutex ),
85 m_bIsDisposed( false ),
86 m_bMayHaveChildren( bMayHaveChildren ),
87 m_bChildrenInitialized( false ),
88 m_nEventNotifierId(0),
89 m_pStateSetHelper( new ::utl::AccessibleStateSetHelper() ),
90 m_aStateSet( m_pStateSetHelper ),
91 m_aAccInfo( rAccInfo ),
92 m_bAlwaysTransparent( bAlwaysTransparent ),
93 m_bStateSetInitialized( false )
94 {
95 // initialize some states
96 OSL_ASSERT( m_pStateSetHelper );
97 m_pStateSetHelper->AddState( AccessibleStateType::ENABLED );
98 m_pStateSetHelper->AddState( AccessibleStateType::SHOWING );
99 m_pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
100 m_pStateSetHelper->AddState( AccessibleStateType::SELECTABLE );
101 m_pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
102 }
103
~AccessibleBase()104 AccessibleBase::~AccessibleBase()
105 {
106 OSL_ASSERT( m_bIsDisposed );
107 }
108
109 // ________ public ________
110
CheckDisposeState(bool bThrowException) const111 bool AccessibleBase::CheckDisposeState( bool bThrowException /* default: true */ ) const
112 throw (lang::DisposedException)
113 {
114 if( bThrowException &&
115 m_bIsDisposed )
116 {
117 throw lang::DisposedException(
118 C2U("component has state DEFUNC" ),
119 static_cast< uno::XWeak * >( const_cast< AccessibleBase * >( this )));
120 }
121 return m_bIsDisposed;
122 }
123
NotifyEvent(EventType eEventType,const AccessibleUniqueId & rId)124 bool AccessibleBase::NotifyEvent( EventType eEventType, const AccessibleUniqueId & rId )
125 {
126 if( GetId() == rId )
127 {
128 // event is addressed to this object
129
130 ::com::sun::star::uno::Any aEmpty;
131 ::com::sun::star::uno::Any aSelected;
132 aSelected <<= AccessibleStateType::SELECTED;
133 switch( eEventType )
134 {
135 case OBJECT_CHANGE:
136 {
137 BroadcastAccEvent( AccessibleEventId::VISIBLE_DATA_CHANGED, aEmpty, aEmpty );
138 #if OSL_DEBUG_LEVEL > 1
139 OSL_TRACE(
140 ::rtl::OUStringToOString(
141 OUString( RTL_CONSTASCII_USTRINGPARAM(
142 "Visible data event sent by: " )) +
143 getAccessibleName(),
144 RTL_TEXTENCODING_ASCII_US ).getStr() );
145 #endif
146 }
147 break;
148
149 case GOT_SELECTION:
150 {
151 AddState( AccessibleStateType::SELECTED );
152 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty );
153
154 AddState( AccessibleStateType::FOCUSED );
155 aSelected <<= AccessibleStateType::FOCUSED;
156 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aSelected, aEmpty, true );
157 #if OSL_DEBUG_LEVEL > 1
158 OSL_TRACE(
159 ::rtl::OUStringToOString(
160 OUString( RTL_CONSTASCII_USTRINGPARAM(
161 "Selection acquired by: " )) +
162 getAccessibleName(),
163 RTL_TEXTENCODING_ASCII_US ).getStr() );
164 #endif
165 }
166 break;
167
168 case LOST_SELECTION:
169 {
170 RemoveState( AccessibleStateType::SELECTED );
171 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected );
172
173 AddState( AccessibleStateType::FOCUSED );
174 aSelected <<= AccessibleStateType::FOCUSED;
175 BroadcastAccEvent( AccessibleEventId::STATE_CHANGED, aEmpty, aSelected, true );
176 #if OSL_DEBUG_LEVEL > 1
177 OSL_TRACE(
178 ::rtl::OUStringToOString(
179 OUString( RTL_CONSTASCII_USTRINGPARAM(
180 "Selection lost by: " )) +
181 getAccessibleName(),
182 RTL_TEXTENCODING_ASCII_US ).getStr() );
183 #endif
184 }
185 break;
186
187 case PROPERTY_CHANGE:
188 {
189 //not implemented --> rebuild all
190 }
191 break;
192 }
193 return true;
194 }
195 else if( m_bMayHaveChildren )
196 {
197 bool bStop = false;
198 // /--
199 ClearableMutexGuard aGuard( GetMutex() );
200 // make local copy for notification
201 ChildListVectorType aLocalChildList( m_aChildList );
202 aGuard.clear();
203 // \--
204
205 ChildListVectorType::iterator aEndIter = aLocalChildList.end();
206 for( ChildListVectorType::iterator aIter = aLocalChildList.begin() ;
207 ( aIter != aEndIter ) && ( ! bStop ) ;
208 ++aIter )
209 {
210 // Note: at this place we must be sure to have an AccessibleBase
211 // object in the UNO reference to XAccessible !
212 bStop = (*static_cast< AccessibleBase * >
213 ( (*aIter).get() )).NotifyEvent( eEventType, rId );
214 }
215 return bStop;
216 }
217
218 return false;
219 }
220
AddState(sal_Int16 aState)221 void AccessibleBase::AddState( sal_Int16 aState )
222 throw (RuntimeException)
223 {
224 CheckDisposeState();
225 OSL_ASSERT( m_pStateSetHelper );
226 m_pStateSetHelper->AddState( aState );
227 }
228
RemoveState(sal_Int16 aState)229 void AccessibleBase::RemoveState( sal_Int16 aState )
230 throw (RuntimeException)
231 {
232 CheckDisposeState();
233 OSL_ASSERT( m_pStateSetHelper );
234 m_pStateSetHelper->RemoveState( aState );
235 }
236
237 // ________ protected ________
238
UpdateChildren()239 bool AccessibleBase::UpdateChildren()
240 {
241 bool bMustUpdateChildren = false;
242 {
243 // /--
244 MutexGuard aGuard( GetMutex() );
245 if( ! m_bMayHaveChildren ||
246 m_bIsDisposed )
247 return false;
248
249 bMustUpdateChildren = ( m_bMayHaveChildren &&
250 ! m_bChildrenInitialized );
251 // \--
252 }
253
254 // update unguarded
255 if( bMustUpdateChildren )
256 m_bChildrenInitialized = ImplUpdateChildren();
257
258 return m_bChildrenInitialized;
259 }
260
ImplUpdateChildren()261 bool AccessibleBase::ImplUpdateChildren()
262 {
263 bool bResult = false;
264
265 if( m_aAccInfo.m_spObjectHierarchy )
266 {
267 ObjectHierarchy::tChildContainer aModelChildren(
268 m_aAccInfo.m_spObjectHierarchy->getChildren( GetId() ));
269 ::std::vector< ChildOIDMap::key_type > aAccChildren;
270 aAccChildren.reserve( aModelChildren.size());
271 ::std::transform( m_aChildOIDMap.begin(), m_aChildOIDMap.end(),
272 ::std::back_inserter( aAccChildren ),
273 ::std::select1st< ChildOIDMap::value_type >());
274
275 ::std::sort( aModelChildren.begin(), aModelChildren.end());
276
277 ::std::vector< ObjectHierarchy::tOID > aChildrenToRemove, aChildrenToAdd;
278 ::std::set_difference( aModelChildren.begin(), aModelChildren.end(),
279 aAccChildren.begin(), aAccChildren.end(),
280 ::std::back_inserter( aChildrenToAdd ));
281 ::std::set_difference( aAccChildren.begin(), aAccChildren.end(),
282 aModelChildren.begin(), aModelChildren.end(),
283 ::std::back_inserter( aChildrenToRemove ));
284
285 ::std::vector< ObjectHierarchy::tOID >::const_iterator aIt( aChildrenToRemove.begin());
286 for( ; aIt != aChildrenToRemove.end(); ++aIt )
287 {
288 RemoveChildByOId( *aIt );
289 }
290
291 AccessibleElementInfo aAccInfo( GetInfo());
292 aAccInfo.m_pParent = this;
293
294 for( aIt = aChildrenToAdd.begin(); aIt != aChildrenToAdd.end(); ++aIt )
295 {
296 aAccInfo.m_aOID = *aIt;
297 if ( aIt->isAutoGeneratedObject() )
298 {
299 AddChild( ChartElementFactory::CreateChartElement( aAccInfo ) );
300 }
301 else if ( aIt->isAdditionalShape() )
302 {
303 AddChild( new AccessibleChartShape( aAccInfo, true, false ) );
304 }
305 }
306 bResult = true;
307 }
308
309 return bResult;
310 }
311
AddChild(AccessibleBase * pChild)312 void AccessibleBase::AddChild( AccessibleBase * pChild )
313 {
314 OSL_ENSURE( pChild != NULL, "Invalid Child" );
315 if( pChild )
316 {
317 // /--
318 ClearableMutexGuard aGuard( GetMutex() );
319
320 Reference< XAccessible > xChild( pChild );
321 m_aChildList.push_back( xChild );
322
323 m_aChildOIDMap[ pChild->GetId() ] = xChild;
324
325 // inform listeners of new child
326 if( m_bChildrenInitialized )
327 {
328 Any aEmpty, aNew;
329 aNew <<= xChild;
330
331 aGuard.clear();
332 // \-- (1st)
333 BroadcastAccEvent( AccessibleEventId::CHILD, aNew, aEmpty );
334 }
335 // \-- (2nd)
336 }
337 }
338
339 /** in this method we imply that the Reference< XAccessible > elements in the
340 vector are AccessibleBase objects !
341 */
RemoveChildByOId(const ObjectIdentifier & rOId)342 void AccessibleBase::RemoveChildByOId( const ObjectIdentifier& rOId )
343 {
344 // /--
345 ClearableMutexGuard aGuard( GetMutex() );
346
347 ChildOIDMap::iterator aIt( m_aChildOIDMap.find( rOId ));
348 if( aIt != m_aChildOIDMap.end())
349 {
350 Reference< XAccessible > xChild( aIt->second );
351
352 // remove from map
353 m_aChildOIDMap.erase( aIt );
354
355 // search child in vector
356 ChildListVectorType::iterator aVecIter =
357 ::std::find( m_aChildList.begin(), m_aChildList.end(), xChild );
358
359 OSL_ENSURE( aVecIter != m_aChildList.end(),
360 "Inconsistent ChildMap" );
361
362 // remove child from vector
363 m_aChildList.erase( aVecIter );
364 bool bInitialized = m_bChildrenInitialized;
365
366 // call listeners unguarded
367 aGuard.clear();
368 // \-- (1st)
369
370 // inform listeners of removed child
371 if( bInitialized )
372 {
373 Any aEmpty, aOld;
374 aOld <<= xChild;
375
376 BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld );
377 }
378
379 // dispose the child
380 Reference< lang::XComponent > xComp( xChild, UNO_QUERY );
381 if( xComp.is())
382 xComp->dispose();
383 }
384 }
385
GetUpperLeftOnScreen() const386 awt::Point AccessibleBase::GetUpperLeftOnScreen() const
387 {
388 awt::Point aResult;
389 if( m_aAccInfo.m_pParent )
390 {
391 // /--
392 ClearableMutexGuard aGuard( GetMutex() );
393 AccessibleBase * pParent = m_aAccInfo.m_pParent;
394 aGuard.clear();
395 // \--
396
397 if( pParent )
398 {
399 aResult = pParent->GetUpperLeftOnScreen();
400 }
401 else
402 OSL_ENSURE( false, "Default position used is probably incorrect." );
403 }
404
405 return aResult;
406 }
407
BroadcastAccEvent(sal_Int16 nId,const Any & rNew,const Any & rOld,bool bSendGlobally) const408 void AccessibleBase::BroadcastAccEvent(
409 sal_Int16 nId,
410 const Any & rNew,
411 const Any & rOld,
412 bool bSendGlobally ) const
413 {
414 // /--
415 ClearableMutexGuard aGuard( GetMutex() );
416
417 if ( !m_nEventNotifierId && !bSendGlobally )
418 return;
419 // if we don't have a client id for the notifier, then we don't have listeners, then
420 // we don't need to notify anything
421 //except SendGlobally for focus handling?
422
423 // the const cast is needed, because UNO parameters are never const
424 const AccessibleEventObject aEvent(
425 const_cast< uno::XWeak * >( static_cast< const uno::XWeak * >( this )),
426 nId, rNew, rOld );
427
428 if ( m_nEventNotifierId ) // let the notifier handle this event
429 ::comphelper::AccessibleEventNotifier::addEvent( m_nEventNotifierId, aEvent );
430
431 aGuard.clear();
432 // \--
433
434 // send event to global message queue
435 if( bSendGlobally )
436 {
437 ::vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent );
438 }
439 }
440
KillAllChildren()441 void AccessibleBase::KillAllChildren()
442 {
443 // /--
444 ClearableMutexGuard aGuard( GetMutex() );
445
446 // make local copy for notification
447 ChildListVectorType aLocalChildList( m_aChildList );
448
449 // remove all children
450 m_aChildList.clear();
451 m_aChildOIDMap.clear();
452
453 aGuard.clear();
454 // \--
455
456 // call dispose for all children
457 // and notify listeners
458 Reference< lang::XComponent > xComp;
459 Any aEmpty, aOld;
460 ChildListVectorType::const_iterator aEndIter = aLocalChildList.end();
461 for( ChildListVectorType::const_iterator aIter = aLocalChildList.begin();
462 aIter != aEndIter; ++aIter )
463 {
464 aOld <<= (*aIter);
465 BroadcastAccEvent( AccessibleEventId::CHILD, aEmpty, aOld );
466
467 xComp.set( *aIter, UNO_QUERY );
468 if( xComp.is())
469 xComp->dispose();
470 }
471 m_bChildrenInitialized = false;
472 }
473
GetInfo() const474 AccessibleElementInfo AccessibleBase::GetInfo() const
475 {
476 return m_aAccInfo;
477 }
478
SetInfo(const AccessibleElementInfo & rNewInfo)479 void AccessibleBase::SetInfo( const AccessibleElementInfo & rNewInfo )
480 {
481 m_aAccInfo = rNewInfo;
482 if( m_bMayHaveChildren )
483 {
484 KillAllChildren();
485 }
486 BroadcastAccEvent( AccessibleEventId::INVALIDATE_ALL_CHILDREN, uno::Any(), uno::Any(),
487 true /* global notification */ );
488 }
489
GetId() const490 AccessibleUniqueId AccessibleBase::GetId() const
491 {
492 return m_aAccInfo.m_aOID;
493 }
494
495 // ____________________________________
496 // ____________________________________
497 //
498 // Interfaces
499 // ____________________________________
500 // ____________________________________
501
502 // ________ (XComponent::dispose) ________
disposing()503 void SAL_CALL AccessibleBase::disposing()
504 {
505 // /--
506 ClearableMutexGuard aGuard( GetMutex() );
507 OSL_ENSURE( ! m_bIsDisposed, "dispose() called twice" );
508
509 // notify disposing to all AccessibleEvent listeners asynchron
510 if ( m_nEventNotifierId )
511 {
512 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( m_nEventNotifierId, *this );
513 m_nEventNotifierId = 0;
514 }
515
516 // reset pointers
517 m_aAccInfo.m_pParent = NULL;
518
519 // invalidate implementation for helper, but keep UNO reference to still
520 // allow a tool to query the DEFUNC state.
521 // Note: The object will be deleted when the last reference is released
522 m_pStateSetHelper = NULL;
523
524 // attach new empty state set helper to member reference
525 ::utl::AccessibleStateSetHelper * pHelper = new ::utl::AccessibleStateSetHelper();
526 pHelper->AddState( AccessibleStateType::DEFUNC );
527 // release old helper and attach new one
528 m_aStateSet.set( pHelper );
529
530 m_bIsDisposed = true;
531
532 // call listeners unguarded
533 aGuard.clear();
534 // \--
535
536 if( m_bMayHaveChildren )
537 {
538 KillAllChildren();
539 }
540 else
541 OSL_ENSURE( m_aChildList.empty(), "Child list should be empty" );
542 }
543
544 // ________ XAccessible ________
getAccessibleContext()545 Reference< XAccessibleContext > SAL_CALL AccessibleBase::getAccessibleContext()
546 throw (RuntimeException)
547 {
548 return this;
549 }
550
551 // ________ AccessibleBase::XAccessibleContext ________
getAccessibleChildCount()552 sal_Int32 SAL_CALL AccessibleBase::getAccessibleChildCount()
553 throw (RuntimeException)
554 {
555 // /--
556 ClearableMutexGuard aGuard( GetMutex() );
557 if( ! m_bMayHaveChildren ||
558 m_bIsDisposed )
559 return 0;
560
561 bool bMustUpdateChildren = ( m_bMayHaveChildren &&
562 ! m_bChildrenInitialized );
563
564 aGuard.clear();
565 // \--
566
567 // update unguarded
568 if( bMustUpdateChildren )
569 UpdateChildren();
570
571 return ImplGetAccessibleChildCount();
572 }
573
ImplGetAccessibleChildCount() const574 sal_Int32 AccessibleBase::ImplGetAccessibleChildCount() const
575 throw (RuntimeException)
576 {
577 return m_aChildList.size();
578 }
579
getAccessibleChild(sal_Int32 i)580 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleChild( sal_Int32 i )
581 throw (lang::IndexOutOfBoundsException, RuntimeException)
582 {
583 CheckDisposeState();
584 Reference< XAccessible > xResult;
585
586 // /--
587 ResettableMutexGuard aGuard( GetMutex() );
588 bool bMustUpdateChildren = ( m_bMayHaveChildren &&
589 ! m_bChildrenInitialized );
590
591 aGuard.clear();
592 // \--
593
594 if( bMustUpdateChildren )
595 UpdateChildren();
596
597 xResult.set( ImplGetAccessibleChildById( i ));
598
599 return xResult;
600 // \--
601 }
602
ImplGetAccessibleChildById(sal_Int32 i) const603 Reference< XAccessible > AccessibleBase::ImplGetAccessibleChildById( sal_Int32 i ) const
604 throw (lang::IndexOutOfBoundsException, RuntimeException)
605 {
606 Reference< XAccessible > xResult;
607 // /--
608 MutexGuard aGuard( GetMutex());
609 if( ! m_bMayHaveChildren ||
610 i < 0 ||
611 static_cast< ChildListVectorType::size_type >( i ) >= m_aChildList.size() )
612 {
613 OUStringBuffer aBuf;
614 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "Index " ));
615 aBuf.append( i );
616 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " is invalid for range [ 0, " ));
617 aBuf.append( static_cast< sal_Int32 >( m_aChildList.size() - 1 ) );
618 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " ]" ) );
619 lang::IndexOutOfBoundsException aEx( aBuf.makeStringAndClear(),
620 const_cast< ::cppu::OWeakObject * >(
621 static_cast< const ::cppu::OWeakObject * >( this )));
622 throw aEx;
623 }
624 else
625 xResult.set( m_aChildList[ i ] );
626
627 return xResult;
628 }
629
getAccessibleParent()630 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleParent()
631 throw (RuntimeException)
632 {
633 CheckDisposeState();
634 Reference< XAccessible > aResult;
635 if( m_aAccInfo.m_pParent )
636 aResult.set( m_aAccInfo.m_pParent );
637
638 return aResult;
639 }
640
getAccessibleIndexInParent()641 sal_Int32 SAL_CALL AccessibleBase::getAccessibleIndexInParent()
642 throw (RuntimeException)
643 {
644 CheckDisposeState();
645
646 if( m_aAccInfo.m_spObjectHierarchy )
647 return m_aAccInfo.m_spObjectHierarchy->getIndexInParent( GetId() );
648 return -1;
649 }
650
getAccessibleRole()651 sal_Int16 SAL_CALL AccessibleBase::getAccessibleRole()
652 throw (RuntimeException)
653 {
654 return AccessibleRole::SHAPE/*LIST_ITEM*/; // #i73747# role SHAPE seems more appropriate, but is not read
655 }
656
getAccessibleRelationSet()657 Reference< XAccessibleRelationSet > SAL_CALL AccessibleBase::getAccessibleRelationSet()
658 throw (RuntimeException)
659 {
660 Reference< XAccessibleRelationSet > aResult;
661 return aResult;
662 }
663
getAccessibleStateSet()664 Reference< XAccessibleStateSet > SAL_CALL AccessibleBase::getAccessibleStateSet()
665 throw (RuntimeException)
666 {
667 if( ! m_bStateSetInitialized )
668 {
669 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier );
670 if ( xSelSupp.is() )
671 {
672 ObjectIdentifier aOID( xSelSupp->getSelection() );
673 if ( aOID.isValid() && GetId() == aOID )
674 {
675 AddState( AccessibleStateType::SELECTED );
676 AddState( AccessibleStateType::FOCUSED );
677 }
678 }
679 m_bStateSetInitialized = true;
680 }
681
682 return m_aStateSet;
683 }
684
685
getLocale()686 lang::Locale SAL_CALL AccessibleBase::getLocale()
687 throw (IllegalAccessibleComponentStateException, RuntimeException)
688 {
689 CheckDisposeState();
690
691 return Application::GetSettings().GetLocale();
692 }
693
694 // ________ AccessibleBase::XAccessibleComponent ________
containsPoint(const awt::Point & aPoint)695 sal_Bool SAL_CALL AccessibleBase::containsPoint( const awt::Point& aPoint )
696 throw (RuntimeException)
697 {
698 awt::Rectangle aRect( getBounds() );
699
700 // contains() works with relative coordinates
701 aRect.X = 0;
702 aRect.Y = 0;
703
704 return ( aPoint.X >= aRect.X &&
705 aPoint.Y >= aRect.Y &&
706 aPoint.X < (aRect.X + aRect.Width) &&
707 aPoint.Y < (aRect.Y + aRect.Height) );
708 }
709
getAccessibleAtPoint(const awt::Point & aPoint)710 Reference< XAccessible > SAL_CALL AccessibleBase::getAccessibleAtPoint( const awt::Point& aPoint )
711 throw (RuntimeException)
712 {
713 CheckDisposeState();
714 Reference< XAccessible > aResult;
715 awt::Rectangle aRect( getBounds());
716
717 // children are positioned relative to this object, so translate bound rect
718 aRect.X = 0;
719 aRect.Y = 0;
720
721 // children must be inside the own bound rect
722 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
723 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
724 {
725 // /--
726 ClearableMutexGuard aGuard( GetMutex() );
727 ChildListVectorType aLocalChildList( m_aChildList );
728 aGuard.clear();
729 // \--
730
731 Reference< XAccessibleComponent > aComp;
732 for( ChildListVectorType::const_iterator aIter = aLocalChildList.begin();
733 aIter != aLocalChildList.end(); ++aIter )
734 {
735 aComp.set( *aIter, UNO_QUERY );
736 if( aComp.is())
737 {
738 aRect = aComp->getBounds();
739 if( ( aRect.X <= aPoint.X && aPoint.X <= (aRect.X + aRect.Width) ) &&
740 ( aRect.Y <= aPoint.Y && aPoint.Y <= (aRect.Y + aRect.Height)))
741 {
742 aResult = (*aIter);
743 break;
744 }
745 }
746 }
747 }
748
749 return aResult;
750 }
751
getBounds()752 awt::Rectangle SAL_CALL AccessibleBase::getBounds()
753 throw (RuntimeException)
754 {
755 ExplicitValueProvider *pExplicitValueProvider(
756 ExplicitValueProvider::getExplicitValueProvider( m_aAccInfo.m_xView ));
757 if( pExplicitValueProvider )
758 {
759 Window* pWindow( VCLUnoHelper::GetWindow( m_aAccInfo.m_xWindow ));
760 awt::Rectangle aLogicRect( pExplicitValueProvider->getRectangleOfObject( m_aAccInfo.m_aOID.getObjectCID() ));
761 if( pWindow )
762 {
763 Rectangle aRect( aLogicRect.X, aLogicRect.Y,
764 aLogicRect.X + aLogicRect.Width,
765 aLogicRect.Y + aLogicRect.Height );
766 // /-- solar
767 ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
768 aRect = pWindow->LogicToPixel( aRect );
769
770 // aLogicRect ist relative to the page, but we need a value relative
771 // to the parent object
772 awt::Point aParentLocOnScreen;
773 uno::Reference< XAccessibleComponent > xParent( getAccessibleParent(), uno::UNO_QUERY );
774 if( xParent.is() )
775 aParentLocOnScreen = xParent->getLocationOnScreen();
776
777 // aOffset = aParentLocOnScreen - GetUpperLeftOnScreen()
778 awt::Point aULOnScreen = GetUpperLeftOnScreen();
779 awt::Point aOffset( aParentLocOnScreen.X - aULOnScreen.X,
780 aParentLocOnScreen.Y - aULOnScreen.Y );
781
782 return awt::Rectangle( aRect.getX() - aOffset.X, aRect.getY() - aOffset.Y,
783 aRect.getWidth(), aRect.getHeight());
784 // \-- solar
785 }
786 }
787
788 return awt::Rectangle();
789 }
790
getLocation()791 awt::Point SAL_CALL AccessibleBase::getLocation()
792 throw (RuntimeException)
793 {
794 CheckDisposeState();
795 awt::Rectangle aBBox( getBounds() );
796 return awt::Point( aBBox.X, aBBox.Y );
797 }
798
getLocationOnScreen()799 awt::Point SAL_CALL AccessibleBase::getLocationOnScreen()
800 throw (RuntimeException)
801 {
802 CheckDisposeState();
803
804 if( m_aAccInfo.m_pParent != NULL )
805 {
806 AccessibleBase * pParent = m_aAccInfo.m_pParent;
807 awt::Point aLocThisRel( getLocation());
808 awt::Point aUpperLeft;
809
810 if( pParent != NULL )
811 aUpperLeft = pParent->getLocationOnScreen();
812
813 return awt::Point( aUpperLeft.X + aLocThisRel.X,
814 aUpperLeft.Y + aLocThisRel.Y );
815 }
816 else
817 return getLocation();
818 }
819
getSize()820 awt::Size SAL_CALL AccessibleBase::getSize()
821 throw (RuntimeException)
822 {
823 CheckDisposeState();
824 awt::Rectangle aBBox( getBounds() );
825 return awt::Size( aBBox.Width, aBBox.Height );
826 }
827
grabFocus()828 void SAL_CALL AccessibleBase::grabFocus()
829 throw (RuntimeException)
830 {
831 CheckDisposeState();
832
833 Reference< view::XSelectionSupplier > xSelSupp( GetInfo().m_xSelectionSupplier );
834 if ( xSelSupp.is() )
835 {
836 xSelSupp->select( GetId().getAny() );
837 }
838 }
839
getForeground()840 sal_Int32 SAL_CALL AccessibleBase::getForeground()
841 throw (RuntimeException)
842 {
843 return getColor( ACC_BASE_FOREGROUND );
844 }
845
getBackground()846 sal_Int32 SAL_CALL AccessibleBase::getBackground()
847 throw (RuntimeException)
848 {
849 return getColor( ACC_BASE_BACKGROUND );
850 }
851
getColor(eColorType eColType)852 sal_Int32 AccessibleBase::getColor( eColorType eColType )
853 {
854 sal_Int32 nResult = static_cast< sal_Int32 >( Color( COL_TRANSPARENT ).GetColor());
855 if( m_bAlwaysTransparent )
856 return nResult;
857
858 ObjectIdentifier aOID( m_aAccInfo.m_aOID );
859 ObjectType eType( aOID.getObjectType() );
860 Reference< beans::XPropertySet > xObjProp;
861 OUString aObjectCID = aOID.getObjectCID();
862 if( eType == OBJECTTYPE_LEGEND_ENTRY )
863 {
864 // for colors get the data series/point properties
865 OUString aParentParticle( ObjectIdentifier::getFullParentParticle( aObjectCID ));
866 aObjectCID = ObjectIdentifier::createClassifiedIdentifierForParticle( aParentParticle );
867 }
868
869 xObjProp.set(
870 ObjectIdentifier::getObjectPropertySet(
871 aObjectCID, Reference< chart2::XChartDocument >( m_aAccInfo.m_xChartDocument )), uno::UNO_QUERY );
872 if( xObjProp.is())
873 {
874 try
875 {
876 OUString aPropName;
877 OUString aStylePropName;
878
879 switch( eType )
880 {
881 case OBJECTTYPE_LEGEND_ENTRY:
882 case OBJECTTYPE_DATA_SERIES:
883 case OBJECTTYPE_DATA_POINT:
884 if( eColType == ACC_BASE_FOREGROUND )
885 {
886 aPropName = C2U("BorderColor");
887 aStylePropName = C2U("BorderTransparency");
888 }
889 else
890 {
891 aPropName = C2U("Color");
892 aStylePropName = C2U("Transparency");
893 }
894 break;
895 default:
896 if( eColType == ACC_BASE_FOREGROUND )
897 {
898 aPropName = C2U("LineColor");
899 aStylePropName = C2U("LineTransparence");
900 }
901 else
902 {
903 aPropName = C2U("FillColor");
904 aStylePropName = C2U("FillTransparence");
905 }
906 break;
907 }
908
909 bool bTransparent = m_bAlwaysTransparent;
910 Reference< beans::XPropertySetInfo > xInfo( xObjProp->getPropertySetInfo(), uno::UNO_QUERY );
911 if( xInfo.is() &&
912 xInfo->hasPropertyByName( aStylePropName ))
913 {
914 if( eColType == ACC_BASE_FOREGROUND )
915 {
916 drawing::LineStyle aLStyle;
917 if( xObjProp->getPropertyValue( aStylePropName ) >>= aLStyle )
918 bTransparent = (aLStyle == drawing::LineStyle_NONE);
919 }
920 else
921 {
922 drawing::FillStyle aFStyle;
923 if( xObjProp->getPropertyValue( aStylePropName ) >>= aFStyle )
924 bTransparent = (aFStyle == drawing::FillStyle_NONE);
925 }
926 }
927
928 if( !bTransparent &&
929 xInfo.is() &&
930 xInfo->hasPropertyByName( aPropName ))
931 {
932 xObjProp->getPropertyValue( aPropName ) >>= nResult;
933 }
934 }
935 catch( const uno::Exception & ex )
936 {
937 ASSERT_EXCEPTION( ex );
938 }
939 }
940
941 return nResult;
942 }
943
944 // ________ AccessibleBase::XServiceInfo ________
getImplementationName()945 OUString SAL_CALL AccessibleBase::getImplementationName()
946 throw (RuntimeException)
947 {
948 return OUString( RTL_CONSTASCII_USTRINGPARAM( "AccessibleBase" ));
949 }
950
supportsService(const OUString & ServiceName)951 sal_Bool SAL_CALL AccessibleBase::supportsService( const OUString& ServiceName )
952 throw (RuntimeException)
953 {
954 return comphelper::ServiceInfoHelper::supportsService( ServiceName, getSupportedServiceNames() );
955 }
956
getSupportedServiceNames()957 uno::Sequence< OUString > SAL_CALL AccessibleBase::getSupportedServiceNames()
958 throw (RuntimeException)
959 {
960 uno::Sequence< ::rtl::OUString > aSeq( 2 );
961 ::rtl::OUString* pStr = aSeq.getArray();
962 pStr[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.Accessible" ));
963 pStr[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ));
964
965 return aSeq;
966 }
967
968 // ________ AccessibleBase::XEventListener ________
disposing(const lang::EventObject &)969 void SAL_CALL AccessibleBase::disposing( const lang::EventObject& /*Source*/ )
970 throw (RuntimeException)
971 {
972 }
973
974 // ________ XAccessibleEventBroadcasters ________
addEventListener(const Reference<XAccessibleEventListener> & xListener)975 void SAL_CALL AccessibleBase::addEventListener( const Reference< XAccessibleEventListener >& xListener )
976 throw (RuntimeException)
977 {
978 MutexGuard aGuard( GetMutex() );
979
980 if ( xListener.is() )
981 {
982 if ( !m_nEventNotifierId )
983 m_nEventNotifierId = ::comphelper::AccessibleEventNotifier::registerClient();
984
985 ::comphelper::AccessibleEventNotifier::addEventListener( m_nEventNotifierId, xListener );
986 }
987 }
988
removeEventListener(const Reference<XAccessibleEventListener> & xListener)989 void SAL_CALL AccessibleBase::removeEventListener( const Reference< XAccessibleEventListener >& xListener )
990 throw (RuntimeException)
991 {
992 MutexGuard aGuard( GetMutex() );
993
994 if ( xListener.is() )
995 {
996 sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( m_nEventNotifierId, xListener );
997 if ( !nListenerCount )
998 {
999 // no listeners anymore
1000 ::comphelper::AccessibleEventNotifier::revokeClient( m_nEventNotifierId );
1001 m_nEventNotifierId = 0;
1002 }
1003 }
1004 }
1005
1006 } // namespace chart
1007