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