1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 #include <com/sun/star/accessibility/AccessibleRole.hpp>
27 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
28 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
29 #include <com/sun/star/lang/DisposedException.hpp>
30 #include <com/sun/star/beans/PropertyChangeEvent.hpp>
31 #include <com/sun/star/awt/XWindow.hpp>
32 #include <unotools/accessiblestatesethelper.hxx>
33 #include <cppuhelper/typeprovider.hxx>
34 #include <toolkit/helper/vclunohelper.hxx>
35 #include <vcl/svapp.hxx>
36 #include <osl/mutex.hxx>
37 #include <rtl/uuid.h>
38 #include <tools/debug.hxx>
39 #include <tools/gen.hxx>
40 #include <svl/smplhint.hxx>
41 #include <toolkit/helper/convert.hxx>
42 #include <svtools/colorcfg.hxx>
43 #include <comphelper/accessibleeventnotifier.hxx>
44 #include <svx/sdrpaintwindow.hxx>
45 
46 //===== local includes ========================================================
47 #include <svx/ShapeTypeHandler.hxx>
48 #include <svx/AccessibleShapeInfo.hxx>
49 #include "GraphCtlAccessibleContext.hxx"
50 #include <svx/graphctl.hxx>
51 #ifndef _SVX_DIALOGS_HRC
52 #include <svx/dialogs.hrc>
53 #endif
54 #ifndef _SVX_ACCESSIBILITY_HRC
55 #include "accessibility.hrc"
56 #endif
57 #include <svx/svdpage.hxx>
58 #include <svx/unomod.hxx>
59 #include <svx/dialmgr.hxx>
60 #include <svx/svdetc.hxx>
61 #include <svx/sdrhittesthelper.hxx>
62 
63 //=====  namespaces ===========================================================
64 
65 using namespace ::vos;
66 using namespace ::cppu;
67 using namespace ::osl;
68 using ::rtl::OUString;
69 using namespace ::accessibility;
70 using namespace	::com::sun::star;
71 using namespace	::com::sun::star::uno;
72 using namespace	::com::sun::star::drawing;
73 using namespace	::com::sun::star::lang;
74 using namespace	::com::sun::star::accessibility;
75 
76 //=====  internal  ============================================================
77 
78 /** initialize this component and set default values */
SvxGraphCtrlAccessibleContext(const Reference<XAccessible> & rxParent,GraphCtrl & rRepr,const OUString * pName,const OUString * pDesc)79 SvxGraphCtrlAccessibleContext::SvxGraphCtrlAccessibleContext(
80 	const Reference< XAccessible >&	rxParent,
81 	GraphCtrl&								rRepr,
82 	const OUString*							pName,
83 	const OUString*							pDesc ) :
84 
85 	SvxGraphCtrlAccessibleContext_Base( m_aMutex ),
86 	mxParent( rxParent ),
87 	mpControl( &rRepr ),
88     mpModel (NULL),
89     mpPage (NULL),
90     mpView (NULL),
91     mnClientId( 0 ),
92     mbDisposed( sal_False )
93 {
94     if (mpControl != NULL)
95     {
96         mpModel = mpControl->GetSdrModel();
97         if (mpModel != NULL)
98             mpPage = (SdrPage*)mpModel->GetPage( 0 );
99         mpView = mpControl->GetSdrView();
100 
101         if( mpModel == NULL || mpPage == NULL || mpView == NULL )
102         {
103             mbDisposed = true;
104             // Set all the pointers to NULL just in case they are used as
105             // a disposed flag.
106             mpModel = NULL;
107             mpPage = NULL;
108             mpView = NULL;
109         }
110     }
111 
112 	if( pName )
113 	{
114 		msName = *pName;
115 	}
116 	else
117 	{
118 		::vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
119 		msName = SVX_RESSTR( RID_SVXSTR_GRAPHCTRL_ACC_NAME );
120 	}
121 
122 	if( pDesc )
123 	{
124 		msDescription = *pDesc;
125 	}
126 	else
127 	{
128 		::vos::OGuard	aSolarGuard( Application::GetSolarMutex() );
129 		msDescription = SVX_RESSTR( RID_SVXSTR_GRAPHCTRL_ACC_DESCRIPTION );
130 	}
131 
132 	maTreeInfo.SetSdrView( mpView );
133 	maTreeInfo.SetWindow( mpControl );
134 	maTreeInfo.SetViewForwarder( const_cast<SvxGraphCtrlAccessibleContext*>(this) );
135 }
136 
137 //-----------------------------------------------------------------------------
138 
139 /** on destruction, this component is disposed and all dispose listeners
140 	are called, except if this component was already disposed */
~SvxGraphCtrlAccessibleContext()141 SvxGraphCtrlAccessibleContext::~SvxGraphCtrlAccessibleContext()
142 {
143 	disposing();
144 }
145 
146 //-----------------------------------------------------------------------------
147 
148 /** returns the XAccessible interface for a given SdrObject.
149 	Multiple calls for the same SdrObject return the same XAccessible.
150 */
getAccessible(const SdrObject * pObj)151 Reference< XAccessible > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessible( const SdrObject* pObj )
152 {
153 	Reference<XAccessible> xAccessibleShape;
154 
155 	if( pObj )
156 	{
157 		// see if we already created an XAccessible for the given SdrObject
158 		ShapesMapType::iterator iter = mxShapes.find( pObj );
159 
160 		if( iter != mxShapes.end() )
161 		{
162 			// if we already have one, return it
163 			xAccessibleShape = (*iter).second;
164 		}
165 		else
166 		{
167 			// create a new one and remember in our internal map
168 			Reference< XShape > xShape( Reference< XShape >::query( (const_cast<SdrObject*>(pObj))->getUnoShape() ) );
169 
170             AccessibleShapeInfo aShapeInfo (xShape,mxParent);
171 			// Create accessible object that corresponds to the descriptor's shape.
172 			AccessibleShape* pAcc = ShapeTypeHandler::Instance().CreateAccessibleObject(
173                 aShapeInfo, maTreeInfo);
174 			xAccessibleShape = pAcc;
175             if (pAcc != NULL)
176             {
177                 pAcc->acquire();
178                 // Now that we acquired the new accessible shape we can
179                 // safely call its Init() method.
180                 pAcc->Init ();
181             }
182 			mxShapes[pObj] = pAcc;
183 
184 			// Create event and inform listeners of the object creation.
185 			CommitChange( AccessibleEventId::CHILD, makeAny( xAccessibleShape ), makeAny( Reference<XAccessible>() ) );
186 		}
187 	}
188 
189     return xAccessibleShape;
190 }
191 
192 //=====  XAccessible  =========================================================
193 
getAccessibleContext(void)194 Reference< XAccessibleContext > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleContext( void ) throw( RuntimeException )
195 {
196 	return this;
197 }
198 
199 //=====  XAccessibleComponent  ================================================
200 
containsPoint(const awt::Point & rPoint)201 sal_Bool SAL_CALL SvxGraphCtrlAccessibleContext::containsPoint( const awt::Point& rPoint ) throw( RuntimeException )
202 {
203 	// no guard -> done in getSize()
204     awt::Size aSize (getSize());
205     return (rPoint.X >= 0)
206         && (rPoint.X < aSize.Width)
207         && (rPoint.Y >= 0)
208         && (rPoint.Y < aSize.Height);
209 }
210 
211 //-----------------------------------------------------------------------------
212 
getAccessibleAtPoint(const awt::Point & rPoint)213 Reference< XAccessible > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleAtPoint( const awt::Point& rPoint ) throw( RuntimeException )
214 {
215 	::osl::MutexGuard	aGuard( m_aMutex );
216 
217 	Reference< XAccessible > xAccessible;
218 
219 	if( mpControl )
220 	{
221 		Point aPnt( rPoint.X, rPoint.Y );
222 		mpControl->PixelToLogic( aPnt );
223 
224         SdrObject* pObj = 0;
225 
226         if(mpView && mpView->GetSdrPageView())
227         {
228             pObj = SdrObjListPrimitiveHit(*mpPage, aPnt, 1, *mpView->GetSdrPageView(), 0, false);
229         }
230 
231 		if( pObj )
232 			xAccessible = getAccessible( pObj );
233 	}
234 	else
235 	{
236 		throw DisposedException();
237 	}
238 
239 	return xAccessible;
240 }
241 
242 //-----------------------------------------------------------------------------
243 
getBounds()244 awt::Rectangle SAL_CALL SvxGraphCtrlAccessibleContext::getBounds() throw( RuntimeException )
245 {
246 	// no guard -> done in GetBoundingBox()
247 	Rectangle			aCoreBounds( GetBoundingBox() );
248 	awt::Rectangle		aBounds;
249 	aBounds.X = aCoreBounds.getX();
250 	aBounds.Y = aCoreBounds.getY();
251 	aBounds.Width = aCoreBounds.getWidth();
252 	aBounds.Height = aCoreBounds.getHeight();
253 	return aBounds;
254 }
255 
256 //-----------------------------------------------------------------------------
257 
getLocation()258 awt::Point SAL_CALL SvxGraphCtrlAccessibleContext::getLocation() throw( RuntimeException )
259 {
260 	// no guard -> done in GetBoundingBox()
261 	Rectangle	aRect( GetBoundingBox() );
262 	return awt::Point( aRect.getX(), aRect.getY() );
263 }
264 
265 //-----------------------------------------------------------------------------
266 
getLocationOnScreen()267 awt::Point SAL_CALL SvxGraphCtrlAccessibleContext::getLocationOnScreen() throw( RuntimeException )
268 {
269 	// no guard -> done in GetBoundingBoxOnScreen()
270 	Rectangle	aRect( GetBoundingBoxOnScreen() );
271 	return awt::Point( aRect.getX(), aRect.getY() );
272 }
273 
274 //-----------------------------------------------------------------------------
275 
getSize()276 awt::Size SAL_CALL SvxGraphCtrlAccessibleContext::getSize() throw( RuntimeException )
277 {
278 	// no guard -> done in GetBoundingBox()
279 	Rectangle	aRect( GetBoundingBox() );
280 	return awt::Size( aRect.getWidth(), aRect.getHeight() );
281 }
282 
283 
284 //=====  XAccessibleContext  ==================================================
285 
getAccessibleChildCount(void)286 sal_Int32 SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleChildCount( void ) throw( RuntimeException )
287 {
288 	OGuard aGuard( Application::GetSolarMutex() );
289 
290 	if( NULL == mpPage )
291 		throw DisposedException();
292 
293 	return mpPage->GetObjCount();
294 }
295 
296 //-----------------------------------------------------------------------------
297 
298 /** returns the SdrObject at index nIndex from the model of this graph */
getSdrObject(sal_Int32 nIndex)299 SdrObject* SvxGraphCtrlAccessibleContext::getSdrObject( sal_Int32 nIndex )
300 	throw( RuntimeException, lang::IndexOutOfBoundsException )
301 {
302 	OGuard aGuard( Application::GetSolarMutex() );
303 
304 	if( NULL == mpPage )
305 		throw DisposedException();
306 
307 	if( (nIndex < 0) || ( static_cast<sal_uInt32>(nIndex) >= mpPage->GetObjCount() ) )
308 		throw lang::IndexOutOfBoundsException();
309 
310 	return mpPage->GetObj( nIndex );
311 }
312 
313 //-----------------------------------------------------------------------------
314 
315 /** sends an AccessibleEventObject to all added XAccessibleEventListeners */
CommitChange(sal_Int16 nEventId,const uno::Any & rNewValue,const uno::Any & rOldValue)316 void SvxGraphCtrlAccessibleContext::CommitChange (
317     sal_Int16 nEventId,
318     const uno::Any& rNewValue,
319     const uno::Any& rOldValue)
320 {
321     AccessibleEventObject aEvent (
322         static_cast<uno::XWeak*>(this),
323         nEventId,
324         rNewValue,
325         rOldValue);
326 
327     FireEvent (aEvent);
328 }
329 
330 /** sends an AccessibleEventObject to all added XAccessibleEventListeners */
FireEvent(const AccessibleEventObject & aEvent)331 void SvxGraphCtrlAccessibleContext::FireEvent (const AccessibleEventObject& aEvent)
332 {
333 	if (mnClientId)
334 		comphelper::AccessibleEventNotifier::addEvent( mnClientId, aEvent );
335 }
336 
337 //-----------------------------------------------------------------------------
338 
getAccessibleChild(sal_Int32 nIndex)339 Reference< XAccessible > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleChild( sal_Int32 nIndex )
340 	throw( RuntimeException, lang::IndexOutOfBoundsException )
341 {
342 	OGuard aGuard( Application::GetSolarMutex() );
343 
344 	return getAccessible( getSdrObject( nIndex ) );
345 }
346 
347 //-----------------------------------------------------------------------------
348 
getAccessibleParent(void)349 Reference< XAccessible > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleParent( void ) throw( RuntimeException )
350 {
351 	return mxParent;
352 }
353 
354 //-----------------------------------------------------------------------------
355 
getAccessibleIndexInParent(void)356 sal_Int32 SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleIndexInParent( void ) throw( RuntimeException )
357 {
358 	OGuard aGuard( Application::GetSolarMutex() );
359 	//	Use a simple but slow solution for now.  Optimize later.
360 
361     //	Iterate over all the parent's children and search for this object.
362     if( mxParent.is() )
363     {
364     	Reference< XAccessibleContext >	xParentContext( mxParent->getAccessibleContext() );
365         if( xParentContext.is() )
366         {
367         	sal_Int32 nChildCount = xParentContext->getAccessibleChildCount();
368             for( sal_Int32 i = 0 ; i < nChildCount ; ++i )
369             {
370             	Reference< XAccessible > xChild( xParentContext->getAccessibleChild( i ) );
371                 if( xChild.is() )
372                 {
373                 	Reference< XAccessibleContext >	xChildContext = xChild->getAccessibleContext();
374 	            	if( xChildContext == ( XAccessibleContext* ) this )
375                     	return i;
376                 }
377             }
378         }
379    }
380 
381    //	Return -1 to indicate that this object's parent does not know about the
382    //	object.
383    return -1;
384 }
385 
386 //-----------------------------------------------------------------------------
387 
getAccessibleRole(void)388 sal_Int16 SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleRole( void ) throw( RuntimeException )
389 {
390 	return AccessibleRole::PANEL;
391 }
392 
393 //-----------------------------------------------------------------------------
394 
getAccessibleDescription(void)395 OUString SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleDescription( void ) throw( RuntimeException )
396 {
397 	OGuard aGuard( Application::GetSolarMutex() );
398 	return msDescription;
399 }
400 
401 //-----------------------------------------------------------------------------
402 
getAccessibleName(void)403 OUString SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleName( void ) throw( RuntimeException )
404 {
405 	OGuard aGuard( Application::GetSolarMutex() );
406 	return msName;
407 }
408 
409 //-----------------------------------------------------------------------------
410 
411 /**	Return empty reference to indicate that the relation set is not
412 	supported.
413 */
getAccessibleRelationSet(void)414 Reference< XAccessibleRelationSet > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleRelationSet( void ) throw( RuntimeException )
415 {
416 	return Reference< XAccessibleRelationSet >();
417 }
418 
419 //-----------------------------------------------------------------------------
420 
getAccessibleStateSet(void)421 Reference< XAccessibleStateSet > SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleStateSet( void ) throw( RuntimeException )
422 {
423 	OGuard aGuard( Application::GetSolarMutex() );
424 
425 	utl::AccessibleStateSetHelper* pStateSetHelper = new utl::AccessibleStateSetHelper;
426 
427 	if ( rBHelper.bDisposed || mbDisposed )
428 	{
429 		pStateSetHelper->AddState( AccessibleStateType::DEFUNC );
430 	}
431 	else
432 	{
433 		// pStateSetHelper->AddState( AccessibleStateType::ENABLED );
434         // pStateSetHelper->AddState( AccessibleStateType::SENSITIVE );
435 		pStateSetHelper->AddState( AccessibleStateType::FOCUSABLE );
436 		if( mpControl->HasFocus() )
437 			pStateSetHelper->AddState( AccessibleStateType::FOCUSED );
438 		pStateSetHelper->AddState( AccessibleStateType::OPAQUE );
439 		pStateSetHelper->AddState( AccessibleStateType::SHOWING );
440 		pStateSetHelper->AddState( AccessibleStateType::VISIBLE );
441 	}
442 
443 	return pStateSetHelper;
444 }
445 
446 //-----------------------------------------------------------------------------
447 
getLocale(void)448 lang::Locale SAL_CALL SvxGraphCtrlAccessibleContext::getLocale( void ) throw( IllegalAccessibleComponentStateException, RuntimeException )
449 {
450 	OGuard aGuard( Application::GetSolarMutex() );
451 
452 	if( mxParent.is() )
453     {
454     	Reference< XAccessibleContext >	xParentContext( mxParent->getAccessibleContext() );
455         if( xParentContext.is() )
456 	    	return xParentContext->getLocale();
457     }
458 
459     //	No parent.  Therefore throw exception to indicate this cluelessness.
460     throw IllegalAccessibleComponentStateException();
461 }
462 
463 //=====  XAccessibleEventListener  ============================================
464 
addEventListener(const Reference<XAccessibleEventListener> & xListener)465 void SAL_CALL SvxGraphCtrlAccessibleContext::addEventListener( const Reference< XAccessibleEventListener >& xListener )
466     throw( RuntimeException )
467 {
468 	if (xListener.is())
469     {
470         OGuard aGuard( Application::GetSolarMutex() );
471 		if (!mnClientId)
472             mnClientId = comphelper::AccessibleEventNotifier::registerClient( );
473 		comphelper::AccessibleEventNotifier::addEventListener( mnClientId, xListener );
474     }
475 }
476 
477 //-----------------------------------------------------------------------------
478 
removeEventListener(const Reference<XAccessibleEventListener> & xListener)479 void SAL_CALL SvxGraphCtrlAccessibleContext::removeEventListener( const Reference< XAccessibleEventListener >& xListener )
480     throw( RuntimeException )
481 {
482 	if (xListener.is())
483 	{
484     	OGuard aGuard( Application::GetSolarMutex() );
485 
486         sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, xListener );
487 		if ( !nListenerCount )
488 		{
489 			// no listeners anymore
490 			// -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
491 			// and at least to us not firing any events anymore, in case somebody calls
492 			// NotifyAccessibleEvent, again
493 			comphelper::AccessibleEventNotifier::revokeClient( mnClientId );
494 			mnClientId = 0;
495 		}
496 	}
497 }
498 
499 //-----------------------------------------------------------------------------
500 
addFocusListener(const Reference<awt::XFocusListener> & xListener)501 void SAL_CALL SvxGraphCtrlAccessibleContext::addFocusListener( const Reference< awt::XFocusListener >& xListener )
502 	throw( RuntimeException )
503 {
504 	OGuard aGuard( Application::GetSolarMutex() );
505 
506 	if( xListener.is() )
507     {
508 		Reference< ::com::sun::star::awt::XWindow >	xWindow( VCLUnoHelper::GetInterface( mpControl ) );
509 		if( xWindow.is() )
510 			xWindow->addFocusListener( xListener );
511     }
512 }
513 
514 //-----------------------------------------------------------------------------
515 
removeFocusListener(const Reference<awt::XFocusListener> & xListener)516 void SAL_CALL SvxGraphCtrlAccessibleContext::removeFocusListener( const Reference< awt::XFocusListener >& xListener )
517 	throw (RuntimeException)
518 {
519 	OGuard aGuard( Application::GetSolarMutex() );
520 
521 	if( xListener.is() )
522     {
523 		Reference< ::com::sun::star::awt::XWindow >	xWindow = VCLUnoHelper::GetInterface( mpControl );
524 		if( xWindow.is() )
525 			xWindow->removeFocusListener( xListener );
526     }
527 }
528 
529 //-----------------------------------------------------------------------------
530 
grabFocus()531 void SAL_CALL SvxGraphCtrlAccessibleContext::grabFocus() throw( RuntimeException )
532 {
533 	OGuard aGuard( Application::GetSolarMutex() );
534 
535 	if( NULL == mpControl )
536 		throw DisposedException();
537 
538 	mpControl->GrabFocus();
539 }
540 
541 //-----------------------------------------------------------------------------
542 
getAccessibleKeyBinding()543 Any SAL_CALL SvxGraphCtrlAccessibleContext::getAccessibleKeyBinding() throw( RuntimeException )
544 {
545 	// here is no implementation, because here are no KeyBindings for every object
546 	return Any();
547 }
548 
549 
550 
551 
552 
getForeground(void)553 sal_Int32 SAL_CALL SvxGraphCtrlAccessibleContext::getForeground (void)
554     throw (::com::sun::star::uno::RuntimeException)
555 {
556 	svtools::ColorConfig aColorConfig;
557     sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
558     return static_cast<sal_Int32>(nColor);
559 }
560 
561 
562 
563 
getBackground(void)564 sal_Int32 SAL_CALL SvxGraphCtrlAccessibleContext::getBackground (void)
565     throw (::com::sun::star::uno::RuntimeException)
566 {
567     sal_uInt32 nColor = Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor();
568     return static_cast<sal_Int32>(nColor);
569 }
570 
571 
572 //=====  XServiceInfo  ========================================================
573 
getImplementationName(void)574 OUString SAL_CALL SvxGraphCtrlAccessibleContext::getImplementationName( void ) throw( RuntimeException )
575 {
576 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.ui.SvxGraphCtrlAccessibleContext" ) );
577 }
578 
579 //-----------------------------------------------------------------------------
580 
supportsService(const OUString & sServiceName)581 sal_Bool SAL_CALL SvxGraphCtrlAccessibleContext::supportsService( const OUString& sServiceName ) throw( RuntimeException )
582 {
583 	OGuard aGuard( Application::GetSolarMutex() );
584     //  Iterate over all supported service names and return true if on of them
585     //  matches the given name.
586     Sequence< OUString >	aSupportedServices( getSupportedServiceNames() );
587 	int						nLenght = aSupportedServices.getLength();
588 
589     for( int i = 0 ; i < nLenght ; ++i )
590 	{
591         if( sServiceName == aSupportedServices[ i ] )
592             return sal_True;
593 	}
594 
595     return sal_False;
596 }
597 
598 //-----------------------------------------------------------------------------
599 
getSupportedServiceNames(void)600 Sequence< OUString > SAL_CALL SvxGraphCtrlAccessibleContext::getSupportedServiceNames( void ) throw( RuntimeException )
601 {
602 	Sequence< OUString > aSNs( 3 );
603 
604 	aSNs[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.Accessible" ) );
605 	aSNs[1] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ) );
606 	aSNs[2] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.drawing.AccessibleGraphControl" ) );
607 
608 	return aSNs;
609 }
610 
611 //=====  XTypeProvider  =======================================================
612 
getImplementationId(void)613 Sequence<sal_Int8> SAL_CALL SvxGraphCtrlAccessibleContext::getImplementationId( void ) throw( RuntimeException )
614 {
615 	OGuard aGuard( Application::GetSolarMutex() );
616 	return getUniqueId();
617 }
618 
619 //=====  XServiceName  ========================================================
620 
getServiceName(void)621 OUString SvxGraphCtrlAccessibleContext::getServiceName( void ) throw( RuntimeException )
622 {
623 	return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.accessibility.AccessibleContext" ) );
624 }
625 
626 //=====  XAccessibleSelection =============================================
627 
selectAccessibleChild(sal_Int32 nIndex)628 void SAL_CALL SvxGraphCtrlAccessibleContext::selectAccessibleChild( sal_Int32 nIndex ) throw( lang::IndexOutOfBoundsException, RuntimeException )
629 {
630 	OGuard aGuard( Application::GetSolarMutex() );
631 
632 	if( NULL == mpView )
633 		throw DisposedException();
634 
635 	SdrObject* pObj = getSdrObject( nIndex );
636 
637 	if( pObj )
638 		mpView->MarkObj( pObj, mpView->GetSdrPageView());
639 }
640 
641 //-----------------------------------------------------------------------------
642 
isAccessibleChildSelected(sal_Int32 nIndex)643 sal_Bool SAL_CALL SvxGraphCtrlAccessibleContext::isAccessibleChildSelected( sal_Int32 nIndex ) throw( lang::IndexOutOfBoundsException, RuntimeException )
644 {
645 	OGuard aGuard( Application::GetSolarMutex() );
646 
647 	if( NULL == mpView )
648 		throw DisposedException();
649 
650 	return mpView->IsObjMarked( getSdrObject( nIndex ) );
651 }
652 
653 //-----------------------------------------------------------------------------
654 
clearAccessibleSelection()655 void SAL_CALL SvxGraphCtrlAccessibleContext::clearAccessibleSelection() throw( RuntimeException )
656 {
657 	OGuard aGuard( Application::GetSolarMutex() );
658 
659 	if( NULL == mpView )
660 		throw DisposedException();
661 
662 	mpView->UnmarkAllObj();
663 }
664 
665 //-----------------------------------------------------------------------------
666 
selectAllAccessibleChildren()667 void SAL_CALL SvxGraphCtrlAccessibleContext::selectAllAccessibleChildren() throw( RuntimeException )
668 {
669 	OGuard aGuard( Application::GetSolarMutex() );
670 
671 	if( NULL == mpView )
672 		throw DisposedException();
673 
674 	mpView->MarkAllObj();
675 }
676 
677 //-----------------------------------------------------------------------------
678 
getSelectedAccessibleChildCount()679 sal_Int32 SAL_CALL SvxGraphCtrlAccessibleContext::getSelectedAccessibleChildCount() throw( RuntimeException )
680 {
681 	OGuard aGuard( Application::GetSolarMutex() );
682 
683 	if( NULL == mpView )
684 		throw DisposedException();
685 
686 	const SdrMarkList& rList = mpView->GetMarkedObjectList();
687 	return rList.GetMarkCount();
688 }
689 
690 //-----------------------------------------------------------------------------
691 
getSelectedAccessibleChild(sal_Int32 nIndex)692 Reference< XAccessible > SAL_CALL SvxGraphCtrlAccessibleContext::getSelectedAccessibleChild( sal_Int32 nIndex )
693 	throw( lang::IndexOutOfBoundsException, RuntimeException )
694 {
695 	OGuard aGuard( Application::GetSolarMutex() );
696 
697 	checkChildIndexOnSelection( nIndex );
698 
699 	Reference< XAccessible > xAccessible;
700 
701 	const SdrMarkList& rList = mpView->GetMarkedObjectList();
702 	SdrObject* pObj = rList.GetMark(nIndex)->GetMarkedSdrObj();
703 	if( pObj )
704 		xAccessible = getAccessible( pObj );
705 
706 	return xAccessible;
707 }
708 
709 //-----------------------------------------------------------------------------
710 
deselectAccessibleChild(sal_Int32 nIndex)711 void SAL_CALL SvxGraphCtrlAccessibleContext::deselectAccessibleChild( sal_Int32 nIndex ) throw( lang::IndexOutOfBoundsException, RuntimeException )
712 {
713 	OGuard aGuard( Application::GetSolarMutex() );
714 
715 	checkChildIndexOnSelection( nIndex );
716 
717 	if( mpView )
718 	{
719 		const SdrMarkList& rList = mpView->GetMarkedObjectList();
720 
721         SdrObject* pObj = getSdrObject( nIndex );
722 		if( pObj )
723 		{
724 			SdrMarkList aRefList( rList );
725 
726 			SdrPageView* pPV = mpView->GetSdrPageView();
727 			mpView->UnmarkAllObj( pPV );
728 
729 			sal_uInt32 nCount = aRefList.GetMarkCount();
730 			sal_uInt32 nMark;
731 			for( nMark = 0; nMark < nCount; nMark++ )
732 			{
733 				if( aRefList.GetMark(nMark)->GetMarkedSdrObj() != pObj )
734 					mpView->MarkObj( aRefList.GetMark(nMark)->GetMarkedSdrObj(), pPV );
735 			}
736 		}
737 	}
738 }
739 
740 //=====  internals ========================================================
741 
checkChildIndex(long nIndex)742 void SvxGraphCtrlAccessibleContext::checkChildIndex( long nIndex ) throw( lang::IndexOutOfBoundsException )
743 {
744 	if( nIndex < 0 || nIndex >= getAccessibleChildCount() )
745 		throw lang::IndexOutOfBoundsException();
746 }
747 
748 //-----------------------------------------------------------------------------
749 
checkChildIndexOnSelection(long nIndex)750 void SvxGraphCtrlAccessibleContext::checkChildIndexOnSelection( long nIndex ) throw( lang::IndexOutOfBoundsException )
751 {
752 	if( nIndex < 0 || nIndex >= getSelectedAccessibleChildCount() )
753 		throw lang::IndexOutOfBoundsException();
754 }
755 
756 //-----------------------------------------------------------------------------
757 
setName(const OUString & rName)758 void SvxGraphCtrlAccessibleContext::setName( const OUString& rName )
759 {
760 	OGuard aGuard( Application::GetSolarMutex() );
761 
762 	msName = rName;
763 }
764 
765 //-----------------------------------------------------------------------------
766 
setDescription(const OUString & rDescr)767 void SvxGraphCtrlAccessibleContext::setDescription( const OUString& rDescr )
768 {
769 	OGuard aGuard( Application::GetSolarMutex() );
770 
771 	msDescription = rDescr;
772 }
773 
774 
775 
776 
777 /** Replace the model, page, and view pointers by the ones provided
778     (explicitly and implicitly).
779 */
setModelAndView(SdrModel * pModel,SdrView * pView)780 void SvxGraphCtrlAccessibleContext::setModelAndView (
781     SdrModel* pModel,
782     SdrView* pView)
783 {
784 	OGuard aGuard (Application::GetSolarMutex());
785 
786     mpModel = pModel;
787     if (mpModel != NULL)
788         mpPage = (SdrPage*)mpModel->GetPage( 0 );
789     mpView = pView;
790 
791     if (mpModel == NULL || mpPage == NULL || mpView == NULL)
792     {
793         mbDisposed = true;
794 
795         // Set all the pointers to NULL just in case they are used as
796         // a disposed flag.
797         mpModel = NULL;
798         mpPage = NULL;
799         mpView = NULL;
800     }
801 
802 	maTreeInfo.SetSdrView (mpView);
803 }
804 
805 
806 
807 //-----------------------------------------------------------------------------
808 
disposing()809 void SAL_CALL SvxGraphCtrlAccessibleContext::disposing()
810 {
811 	OGuard aGuard( Application::GetSolarMutex() );
812 
813 	if( mbDisposed )
814 		return;
815 
816 	mbDisposed = sal_True;
817 
818 	mpControl = NULL;		// object dies with representation
819 	mpView = NULL;
820 	mpPage = NULL;
821 
822 	{
823 		ShapesMapType::iterator I;
824 
825 		for (I=mxShapes.begin(); I!=mxShapes.end(); I++)
826 		{
827 			XAccessible* pAcc = (*I).second;
828 			Reference< XComponent > xComp( pAcc, UNO_QUERY );
829 			if( xComp.is() )
830 				xComp->dispose();
831 
832 			(*I).second->release();
833 		}
834 
835 		mxShapes.clear();
836 	}
837 
838     // Send a disposing to all listeners.
839 	if ( mnClientId )
840 	{
841         comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this );
842 		mnClientId =  0;
843 	}
844 }
845 
846 //-----------------------------------------------------------------------------
847 
GetBoundingBoxOnScreen(void)848 Rectangle SvxGraphCtrlAccessibleContext::GetBoundingBoxOnScreen( void ) throw( RuntimeException )
849 {
850 	OGuard aGuard( Application::GetSolarMutex() );
851 
852 	if( NULL == mpControl )
853 		throw DisposedException();
854 
855 	return Rectangle(
856         mpControl->GetAccessibleParentWindow()->OutputToAbsoluteScreenPixel(
857             mpControl->GetPosPixel() ),
858         mpControl->GetSizePixel() );
859 }
860 
861 //-----------------------------------------------------------------------------
862 
863 /** Calculate the relative coordinates of the bounding box as difference
864     between the absolute coordinates of the bounding boxes of this control
865     and its parent in the accessibility tree.
866 */
GetBoundingBox(void)867 Rectangle SvxGraphCtrlAccessibleContext::GetBoundingBox( void ) throw( RuntimeException )
868 {
869 	OGuard aGuard( Application::GetSolarMutex() );
870 
871 	Rectangle aBounds ( 0, 0, 0, 0 );
872 
873 	Window* pWindow = mpControl;
874 	if (pWindow != NULL)
875 	{
876 		aBounds = pWindow->GetWindowExtentsRelative (NULL);
877 		Window* pParent = pWindow->GetAccessibleParentWindow();
878 		if (pParent != NULL)
879 		{
880 			Rectangle aParentRect = pParent->GetWindowExtentsRelative (NULL);
881 			aBounds -= aParentRect.TopLeft();
882 		}
883 	}
884     else
885 		throw DisposedException();
886 
887 	return aBounds;
888 }
889 
890 //-----------------------------------------------------------------------------
891 
getUniqueId(void)892 Sequence< sal_Int8 > SvxGraphCtrlAccessibleContext::getUniqueId( void )
893 {
894 	// no guard because it's private -> has to guarded when using it!
895 	static OImplementationId*	pId = 0;
896 	if( !pId )
897 	{
898 		OGuard aGuard( Application::GetSolarMutex() );
899 		if( !pId)
900 		{
901 			static OImplementationId	aId;
902 			pId = &aId;
903 		}
904 	}
905 	return pId->getImplementationId();
906 }
907 
908 //-----------------------------------------------------------------------------
909 
Notify(SfxBroadcaster &,const SfxHint & rHint)910 void SvxGraphCtrlAccessibleContext::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
911 {
912 	const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
913 
914 	if( pSdrHint )
915 	{
916 		switch( pSdrHint->GetKind() )
917 		{
918 			case HINT_OBJCHG:
919 				{
920 					ShapesMapType::iterator iter = mxShapes.find( pSdrHint->GetObject() );
921 
922 					if( iter != mxShapes.end() )
923 					{
924 						// if we already have one, return it
925 						AccessibleShape* pShape = (*iter).second;
926 
927 						if( NULL != pShape )
928 							pShape->CommitChange( AccessibleEventId::VISIBLE_DATA_CHANGED, uno::Any(), uno::Any() );
929 					}
930 				}
931 				break;
932 
933 			case HINT_OBJINSERTED:
934 				CommitChange( AccessibleEventId::CHILD, makeAny( getAccessible( pSdrHint->GetObject() ) ) , uno::Any());
935 				break;
936 			case HINT_OBJREMOVED:
937 				CommitChange( AccessibleEventId::CHILD, uno::Any(), makeAny( getAccessible( pSdrHint->GetObject() ) )  );
938 				break;
939 			case HINT_MODELCLEARED:
940 				dispose();
941 				break;
942             default:
943                 break;
944 		}
945 	}
946 	else
947 	{
948 		const SfxSimpleHint* pSfxHint = PTR_CAST(SfxSimpleHint, &rHint );
949 
950 		// ist unser SdDrawDocument gerade gestorben?
951 		if(pSfxHint && pSfxHint->GetId() == SFX_HINT_DYING)
952 		{
953 			dispose();
954 		}
955 	}
956 }
957 
958 //=====  IAccessibleViewforwarder  ========================================
959 
IsValid(void) const960 sal_Bool SvxGraphCtrlAccessibleContext::IsValid (void) const
961 {
962     return sal_True;
963 }
964 
965 //-----------------------------------------------------------------------------
966 
GetVisibleArea(void) const967 Rectangle SvxGraphCtrlAccessibleContext::GetVisibleArea (void) const
968 {
969 	Rectangle aVisArea;
970 
971 	if( mpView && mpView->PaintWindowCount())
972 	{
973 		SdrPaintWindow* pPaintWindow = mpView->GetPaintWindow(0L);
974 		aVisArea = pPaintWindow->GetVisibleArea();
975 	}
976 
977 	return aVisArea;
978 }
979 
980 //-----------------------------------------------------------------------------
981 
LogicToPixel(const Point & rPoint) const982 Point SvxGraphCtrlAccessibleContext::LogicToPixel (const Point& rPoint) const
983 {
984 	if( mpControl )
985 	{
986 		Rectangle aBBox(mpControl->GetWindowExtentsRelative(NULL));
987 	    return mpControl->LogicToPixel (rPoint) + aBBox.TopLeft();
988 	}
989 	else
990 	{
991 		return rPoint;
992 	}
993 }
994 
995 //-----------------------------------------------------------------------------
996 
LogicToPixel(const Size & rSize) const997 Size SvxGraphCtrlAccessibleContext::LogicToPixel (const Size& rSize) const
998 {
999 	if( mpControl )
1000 		return mpControl->LogicToPixel (rSize);
1001 	else
1002 		return rSize;
1003 }
1004 
1005 //-----------------------------------------------------------------------------
1006 
PixelToLogic(const Point & rPoint) const1007 Point SvxGraphCtrlAccessibleContext::PixelToLogic (const Point& rPoint) const
1008 {
1009 	if( mpControl )
1010 		return mpControl->PixelToLogic (rPoint);
1011 	else
1012 		return rPoint;
1013 }
1014 
1015 //-----------------------------------------------------------------------------
1016 
PixelToLogic(const Size & rSize) const1017 Size SvxGraphCtrlAccessibleContext::PixelToLogic (const Size& rSize) const
1018 {
1019 	if( mpControl )
1020 		return mpControl->PixelToLogic (rSize);
1021 	else
1022 		return rSize;
1023 }
1024