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