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