xref: /trunk/main/svx/source/accessibility/GraphCtlAccessibleContext.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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