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