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