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