xref: /trunk/main/svx/source/accessibility/AccessibleShape.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
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 <svx/AccessibleShape.hxx>
27 #include "svx/DescriptionGenerator.hxx"
28 #include <svx/AccessibleShapeInfo.hxx>
29 #include <com/sun/star/view/XSelectionSupplier.hpp>
30 #include <rtl/uuid.h>
31 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLE_ROLE_HPP_
32 #include <com/sun/star/accessibility/AccessibleRole.hpp>
33 #endif
34 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLETEXTTYPE_HPP_
35 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
36 #endif
37 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLE_STATE_TYPE_HPP_
38 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
39 #endif
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/drawing/XShapes.hpp>
43 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
44 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
45 #include <com/sun/star/drawing/FillStyle.hpp>
46 #include <com/sun/star/text/XText.hpp>
47 #include <editeng/outlobj.hxx>
48 #include <rtl/ref.hxx>
49 #include <editeng/unoedsrc.hxx>
50 #include <svx/unoshtxt.hxx>
51 #include <svx/svdobj.hxx>
52 #include <svx/svdmodel.hxx>
53 #include "svx/unoapi.hxx"
54 #include <com/sun/star/uno/Exception.hpp>
55 #include <svx/ShapeTypeHandler.hxx>
56 #include <svx/SvxShapeTypes.hxx>
57 
58 #ifndef _SVX_ACCESSIBILITY_HRC
59 #include "accessibility.hrc"
60 #endif
61 #include "svx/svdstr.hrc"
62 #include <svx/dialmgr.hxx>
63 #include <vcl/svapp.hxx>
64 #include <unotools/accessiblestatesethelper.hxx>
65 #include <svx/svdview.hxx>
66 #include "AccessibleEmptyEditSource.hxx"
67 #include <svx/svdpage.hxx>
68 #ifndef _COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLERELATIONTYPE_HPP_
69 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
70 #endif
71 #ifndef _UTL_ACCESSIBLERELATIONSETHELPER_HXX_
72 #include <unotools/accessiblerelationsethelper.hxx>
73 #endif
74 using namespace ::com::sun::star;
75 using namespace ::com::sun::star::accessibility;
76 using ::com::sun::star::lang::IndexOutOfBoundsException;
77 using ::com::sun::star::uno::RuntimeException;
78 using ::com::sun::star::uno::Reference;
79 using ::rtl::OUString;
80 #include <algorithm>
81 
82 // #include <Accessiblehyperlink.hxx>
83 namespace accessibility {
84 
85 namespace {
86 
GetOptionalProperty(const Reference<beans::XPropertySet> & rxSet,const OUString & rsPropertyName)87 OUString GetOptionalProperty (
88     const Reference<beans::XPropertySet>& rxSet,
89     const OUString& rsPropertyName)
90 {
91     OUString sValue;
92 
93     if (rxSet.is())
94     {
95         const Reference<beans::XPropertySetInfo> xInfo (rxSet->getPropertySetInfo());
96         if ( ! xInfo.is() || xInfo->hasPropertyByName(rsPropertyName))
97         {
98             try
99             {
100                 rxSet->getPropertyValue(rsPropertyName) >>= sValue;
101             }
102             catch (beans::UnknownPropertyException&)
103             {
104                 // This exception should only be thrown when the property
105                 // does not exits (of course) and the XPropertySetInfo is
106                 // not available.
107             }
108         }
109     }
110     return sValue;
111 }
112 
113 } // end of anonymous namespace
114 
115 
116 
117 
118 //=====  internal  ============================================================
119 
AccessibleShape(const AccessibleShapeInfo & rShapeInfo,const AccessibleShapeTreeInfo & rShapeTreeInfo)120 AccessibleShape::AccessibleShape (
121     const AccessibleShapeInfo& rShapeInfo,
122     const AccessibleShapeTreeInfo& rShapeTreeInfo)
123     : AccessibleContextBase (rShapeInfo.mxParent,AccessibleRole::SHAPE),
124       mpChildrenManager(NULL),
125       mxShape (rShapeInfo.mxShape),
126       maShapeTreeInfo (rShapeTreeInfo),
127       mnIndex (rShapeInfo.mnIndex),
128       m_nIndexInParent(-1),
129       mpText (NULL),
130       mpParent (rShapeInfo.mpChildrenManager)
131 {
132     m_pShape = GetSdrObjectFromXShape(mxShape);
133     UpdateNameAndDescription();
134 }
AccessibleShape(const::com::sun::star::uno::Reference<::com::sun::star::drawing::XShape> & rxShape,const::com::sun::star::uno::Reference<::com::sun::star::accessibility::XAccessible> & rxParent,const AccessibleShapeTreeInfo & rShapeTreeInfo,sal_Int32 nIndex)135 AccessibleShape::AccessibleShape (
136         const ::com::sun::star::uno::Reference<
137             ::com::sun::star::drawing::XShape>& rxShape,
138         const ::com::sun::star::uno::Reference<
139             ::com::sun::star::accessibility::XAccessible>& rxParent,
140         const AccessibleShapeTreeInfo& rShapeTreeInfo,
141         sal_Int32 nIndex)
142     : AccessibleContextBase (rxParent,AccessibleRole::SHAPE),
143       mpChildrenManager(NULL),
144       mxShape (rxShape),
145       maShapeTreeInfo (rShapeTreeInfo),
146       mnIndex (nIndex),
147       m_nIndexInParent(-1),
148       mpText (NULL),
149       mpParent (NULL)
150 {
151     m_pShape = GetSdrObjectFromXShape(mxShape);
152 }
~AccessibleShape(void)153 AccessibleShape::~AccessibleShape (void)
154 {
155     if (mpChildrenManager != NULL)
156         delete mpChildrenManager;
157     if (mpText != NULL)
158         delete mpText;
159     OSL_TRACE ("~AccessibleShape");
160 
161     // Unregistering from the various broadcasters should be unnecessary
162     // since this destructor would not have been called if one of the
163     // broadcasters would still hold a strong reference to this object.
164 }
165 
166 
167 
168 
Init(void)169 void AccessibleShape::Init (void)
170 {
171     // Update the OPAQUE and SELECTED shape.
172     UpdateStates ();
173 
174     // Create a children manager when this shape has children of its own.
175     Reference<drawing::XShapes> xShapes (mxShape, uno::UNO_QUERY);
176     if (xShapes.is() && xShapes->getCount() > 0)
177         mpChildrenManager = new ChildrenManager (
178             this, xShapes, maShapeTreeInfo, *this);
179     if (mpChildrenManager != NULL)
180         mpChildrenManager->Update();
181 
182     // Register at model as document::XEventListener.
183     if (maShapeTreeInfo.GetModelBroadcaster().is())
184         maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
185             static_cast<document::XEventListener*>(this));
186 
187     // Beware! Here we leave the paths of the UNO API and descend into the
188     // depths of the core.  Necessary for makeing the edit engine
189     // accessible.
190     Reference<text::XText> xText (mxShape, uno::UNO_QUERY);
191     if (xText.is())
192     {
193         SdrView* pView = maShapeTreeInfo.GetSdrView ();
194         const Window* pWindow = maShapeTreeInfo.GetWindow ();
195         if (pView != NULL && pWindow != NULL && mxShape.is())
196         {
197             // #107948# Determine whether shape text is empty
198             SdrObject* pSdrObject = GetSdrObjectFromXShape(mxShape);
199             if( pSdrObject )
200             {
201                 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, pSdrObject );
202                 OutlinerParaObject* pOutlinerParaObject = NULL;
203 
204                 if( pTextObj )
205                     pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
206 
207                 bool bOwnParaObj = pOutlinerParaObject != NULL;
208 
209                 if( !pOutlinerParaObject && pSdrObject )
210                     pOutlinerParaObject = pSdrObject->GetOutlinerParaObject();
211 
212                 // create AccessibleTextHelper to handle this shape's text
213                 if( !pOutlinerParaObject )
214                 {
215                     // empty text -> use proxy edit source to delay creation of EditEngine
216                     ::std::auto_ptr<SvxEditSource> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject, *pView, *pWindow) );
217                     mpText = new AccessibleTextHelper( pEditSource );
218                 }
219                 else
220                 {
221                     // non-empty text -> use full-fledged edit source right away
222                     ::std::auto_ptr<SvxEditSource> pEditSource( new SvxTextEditSource ( *pSdrObject, 0, *pView, *pWindow) );
223                     mpText = new AccessibleTextHelper( pEditSource );
224                 }
225 
226                 if( bOwnParaObj )
227                     delete pOutlinerParaObject;
228 
229                 mpText->SetEventSource(this);
230             }
231         }
232     }
233 }
234 
235 
236 
237 
UpdateStates(void)238 void AccessibleShape::UpdateStates (void)
239 {
240     ::utl::AccessibleStateSetHelper* pStateSet =
241         static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
242     if (pStateSet == NULL)
243         return;
244 
245     // Set the opaque state for certain shape types when their fill style is
246     // solid.
247     bool bShapeIsOpaque = false;
248     switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
249     {
250         case DRAWING_PAGE:
251         case DRAWING_RECTANGLE:
252         case DRAWING_TEXT:
253         {
254             uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
255             if (xSet.is())
256             {
257                 try
258                 {
259                     drawing::FillStyle aFillStyle;
260                     bShapeIsOpaque =  ( xSet->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"))) >>= aFillStyle)
261                                         && aFillStyle == drawing::FillStyle_SOLID;
262                 }
263                 catch (::com::sun::star::beans::UnknownPropertyException&)
264                 {
265                     // Ignore.
266                 }
267             }
268         }
269     }
270     if (bShapeIsOpaque)
271         pStateSet->AddState (AccessibleStateType::OPAQUE);
272     else
273         pStateSet->RemoveState (AccessibleStateType::OPAQUE);
274 
275     // Set the selected state.
276     bool bShapeIsSelected = false;
277     // XXX fix_me this has to be done with an extra interface later on
278     if ( m_pShape && maShapeTreeInfo.GetSdrView() )
279     {
280         bShapeIsSelected = maShapeTreeInfo.GetSdrView()->IsObjMarked(m_pShape) == sal_True;
281     }
282 
283     if (bShapeIsSelected)
284         pStateSet->AddState (AccessibleStateType::SELECTED);
285     else
286         pStateSet->RemoveState (AccessibleStateType::SELECTED);
287 }
GetStyle()288     ::rtl::OUString AccessibleShape::GetStyle()
289     {
290         return ShapeTypeHandler::CreateAccessibleBaseName( mxShape );
291     }
292 
operator ==(const AccessibleShape & rShape)293 bool AccessibleShape::operator== (const AccessibleShape& rShape)
294 {
295     return this==&rShape;
296 }
297 
298 
299 
300 
SetState(sal_Int16 aState)301 sal_Bool AccessibleShape::SetState (sal_Int16 aState)
302 {
303     sal_Bool bStateHasChanged = sal_False;
304 
305     if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
306     {
307         // Offer FOCUSED state to edit engine and detect whether the state
308         // changes.
309         sal_Bool bIsFocused = mpText->HaveFocus ();
310         mpText->SetFocus (sal_True);
311         bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
312     }
313     else
314         bStateHasChanged = AccessibleContextBase::SetState (aState);
315 
316     return bStateHasChanged;
317 }
318 
319 
320 
321 
ResetState(sal_Int16 aState)322 sal_Bool AccessibleShape::ResetState (sal_Int16 aState)
323 {
324     sal_Bool bStateHasChanged = sal_False;
325 
326     if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
327     {
328         // Try to remove FOCUSED state from the edit engine and detect
329         // whether the state changes.
330         sal_Bool bIsFocused = mpText->HaveFocus ();
331         mpText->SetFocus (sal_False);
332         bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
333     }
334     else
335         bStateHasChanged = AccessibleContextBase::ResetState (aState);
336 
337     return bStateHasChanged;
338 }
339 
340 
341 
342 
GetState(sal_Int16 aState)343 sal_Bool AccessibleShape::GetState (sal_Int16 aState)
344 {
345     if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
346     {
347         // Just delegate the call to the edit engine.  The state is not
348         // merged into the state set.
349         return mpText->HaveFocus();
350     }
351     else
352         return AccessibleContextBase::GetState (aState);
353 }
354 // Solution: OverWrite the parent's getAccessibleName method
getAccessibleName(void)355 ::rtl::OUString SAL_CALL AccessibleShape::getAccessibleName (void)
356 {
357         ThrowIfDisposed ();
358     if( m_pShape && m_pShape->GetTitle().Len() > 0)
359         return CreateAccessibleName() + ::rtl::OUString(' ') + m_pShape->GetTitle();
360     else
361         return CreateAccessibleName();
362 }
363 
getAccessibleDescription(void)364 ::rtl::OUString SAL_CALL AccessibleShape::getAccessibleDescription (void)
365 {
366         ThrowIfDisposed ();
367     if( m_pShape && m_pShape->GetDescription().Len() > 0)
368         return  m_pShape->GetDescription() ;
369     else
370         return OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
371 }
372 //=====  XAccessibleContext  ==================================================
373 
374 /** The children of this shape come from two sources: The children from
375     group or scene shapes and the paragraphs of text.
376 */
377 sal_Int32 SAL_CALL
getAccessibleChildCount()378     AccessibleShape::getAccessibleChildCount ()
379 {
380     ThrowIfDisposed ();
381     sal_Int32 nChildCount = 0;
382 
383     // Add the number of shapes that are children of this shape.
384     if (mpChildrenManager != NULL)
385         nChildCount += mpChildrenManager->GetChildCount ();
386     // Add the number text paragraphs.
387     if (mpText != NULL)
388         nChildCount += mpText->GetChildCount ();
389 
390     return nChildCount;
391 }
392 
393 
394 
395 
396 /** Forward the request to the shape.  Return the requested shape or throw
397     an exception for a wrong index.
398 */
399 uno::Reference<XAccessible> SAL_CALL
getAccessibleChild(sal_Int32 nIndex)400     AccessibleShape::getAccessibleChild (sal_Int32 nIndex)
401 {
402     ThrowIfDisposed ();
403 
404     uno::Reference<XAccessible> xChild;
405 
406     // Depending on the index decide whether to delegate this call to the
407     // children manager or the edit engine.
408     if ((mpChildrenManager != NULL)
409         && (nIndex < mpChildrenManager->GetChildCount()))
410     {
411         xChild = mpChildrenManager->GetChild (nIndex);
412     }
413     else if (mpText != NULL)
414     {
415         sal_Int32 nI = nIndex;
416         if (mpChildrenManager != NULL)
417             nI -= mpChildrenManager->GetChildCount();
418         xChild = mpText->GetChild (nI);
419     }
420     else
421         throw lang::IndexOutOfBoundsException (
422             ::rtl::OUString::createFromAscii ("shape has no child with index ")
423             + rtl::OUString::valueOf(nIndex),
424             static_cast<uno::XWeak*>(this));
425 
426     return xChild;
427 }
428 
429 uno::Reference<XAccessibleRelationSet> SAL_CALL
getAccessibleRelationSet(void)430     AccessibleShape::getAccessibleRelationSet (void)
431 {
432     ::osl::MutexGuard aGuard (maMutex);
433     ::utl::AccessibleRelationSetHelper* pRelationSet = new utl::AccessibleRelationSetHelper;
434 
435     //this mxshape is the captioned shape, only for sw
436     if (pRelationSet != NULL)
437     {
438         uno::Sequence< uno::Reference< uno::XInterface > > aSequence(1);
439         aSequence[0] = mpParent->GetAccessibleCaption(mxShape);
440         if(aSequence[0].get())
441         {
442             pRelationSet->AddRelation(
443                 AccessibleRelation( AccessibleRelationType::DESCRIBED_BY, aSequence ) );
444         }
445         return uno::Reference<XAccessibleRelationSet> (
446             new ::utl::AccessibleRelationSetHelper (*pRelationSet));
447     }
448     else
449     {
450         return uno::Reference<XAccessibleRelationSet>(NULL);
451     }
452 }
453 
454 /** Return a copy of the state set.
455     Possible states are:
456         ENABLED
457         SHOWING
458         VISIBLE
459 */
460 uno::Reference<XAccessibleStateSet> SAL_CALL
getAccessibleStateSet(void)461     AccessibleShape::getAccessibleStateSet (void)
462 {
463     ::osl::MutexGuard aGuard (maMutex);
464     Reference<XAccessibleStateSet> xStateSet;
465 
466     if (rBHelper.bDisposed || mpText == NULL)
467         // Return a minimal state set that only contains the DEFUNC state.
468     {
469         xStateSet = AccessibleContextBase::getAccessibleStateSet ();
470         ::utl::AccessibleStateSetHelper* pStateSet =
471               static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
472             ::com::sun::star::uno::Reference<XAccessible> xTempAcc = getAccessibleParent();
473             if( xTempAcc.is() )
474             {
475                 ::com::sun::star::uno::Reference<XAccessibleContext>
476                                         xTempAccContext = xTempAcc->getAccessibleContext();
477                 if( xTempAccContext.is() )
478                 {
479                     ::com::sun::star::uno::Reference<XAccessibleStateSet> rState =
480                         xTempAccContext->getAccessibleStateSet();
481                     if( rState.is() )           {
482                         com::sun::star::uno::Sequence<short> pStates = rState->getStates();
483                         int count = pStates.getLength();
484                         for( int iIndex = 0;iIndex < count;iIndex++ )
485                         {
486                             if( pStates[iIndex] == AccessibleStateType::EDITABLE )
487                             {
488                                 pStateSet->AddState (AccessibleStateType::EDITABLE);
489                                 pStateSet->AddState (AccessibleStateType::RESIZABLE);
490                                 pStateSet->AddState (AccessibleStateType::MOVEABLE);
491                                 break;
492                             }
493                         }
494                     }
495                 }
496             }
497             xStateSet = Reference<XAccessibleStateSet>(
498                 new ::utl::AccessibleStateSetHelper (*pStateSet));
499     }else
500     {
501         ::utl::AccessibleStateSetHelper* pStateSet =
502               static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
503 
504         if (pStateSet != NULL)
505         {
506             // Merge current FOCUSED state from edit engine.
507             if (mpText != NULL)
508             {
509                 if (mpText->HaveFocus())
510                     pStateSet->AddState (AccessibleStateType::FOCUSED);
511                 else
512                     pStateSet->RemoveState (AccessibleStateType::FOCUSED);
513             }
514             //Solution:Just when the document is not read-only,set states EDITABLE,RESIZABLE,MOVEABLE
515             ::com::sun::star::uno::Reference<XAccessible> xTempAcc = getAccessibleParent();
516             if( xTempAcc.is() )
517             {
518                 ::com::sun::star::uno::Reference<XAccessibleContext>
519                                         xTempAccContext = xTempAcc->getAccessibleContext();
520                 if( xTempAccContext.is() )
521                 {
522                     ::com::sun::star::uno::Reference<XAccessibleStateSet> rState =
523                         xTempAccContext->getAccessibleStateSet();
524                     if( rState.is() )           {
525                         com::sun::star::uno::Sequence<short> pStates = rState->getStates();
526                         int count = pStates.getLength();
527                         for( int iIndex = 0;iIndex < count;iIndex++ )
528                         {
529                             if( pStates[iIndex] == AccessibleStateType::EDITABLE )
530                             {
531                                 pStateSet->AddState (AccessibleStateType::EDITABLE);
532                                 pStateSet->AddState (AccessibleStateType::RESIZABLE);
533                                 pStateSet->AddState (AccessibleStateType::MOVEABLE);
534                                 break;
535                             }
536                         }
537                     }
538                 }
539             }
540             // Create a copy of the state set that may be modified by the
541             // caller without affecting the current state set.
542             xStateSet = Reference<XAccessibleStateSet>(
543                 new ::utl::AccessibleStateSetHelper (*pStateSet));
544         }
545     }
546     UpdateDocumentAllSelState(xStateSet);
547     return xStateSet;
548 }
549 
550 
551 
552 
553 //=====  XAccessibleComponent  ================================================
554 
555 /** The implementation below is at the moment straightforward.  It iterates
556     over all children (and thereby instances all children which have not
557     been already instantiated) until a child covering the specified point is
558     found.
559     This leaves room for improvement.  For instance, first iterate only over
560     the already instantiated children and only if no match is found
561     instantiate the remaining ones.
562 */
563 uno::Reference<XAccessible > SAL_CALL
getAccessibleAtPoint(const awt::Point & aPoint)564     AccessibleShape::getAccessibleAtPoint (
565         const awt::Point& aPoint)
566 {
567     ::osl::MutexGuard aGuard (maMutex);
568 
569     sal_Int32 nChildCount = getAccessibleChildCount ();
570     for (sal_Int32 i=0; i<nChildCount; ++i)
571     {
572         Reference<XAccessible> xChild (getAccessibleChild (i));
573         if (xChild.is())
574         {
575             Reference<XAccessibleComponent> xChildComponent (
576                 xChild->getAccessibleContext(), uno::UNO_QUERY);
577             if (xChildComponent.is())
578             {
579                 awt::Rectangle aBBox (xChildComponent->getBounds());
580                 if ( (aPoint.X >= aBBox.X)
581                     && (aPoint.Y >= aBBox.Y)
582                     && (aPoint.X < aBBox.X+aBBox.Width)
583                     && (aPoint.Y < aBBox.Y+aBBox.Height) )
584                     return xChild;
585             }
586         }
587     }
588 
589     // Have not found a child under the given point.  Returning empty
590     // reference to indicate this.
591     return uno::Reference<XAccessible>();
592 }
593 
594 
595 
596 
getBounds(void)597 awt::Rectangle SAL_CALL AccessibleShape::getBounds (void)
598 {
599     ::vos::OGuard aSolarGuard (::Application::GetSolarMutex());
600     ::osl::MutexGuard aGuard (maMutex);
601 
602     ThrowIfDisposed ();
603     awt::Rectangle aBoundingBox;
604     if ( mxShape.is() )
605     {
606 
607         static const OUString sBoundRectName (
608             RTL_CONSTASCII_USTRINGPARAM("BoundRect"));
609         static const OUString sAnchorPositionName (
610             RTL_CONSTASCII_USTRINGPARAM("AnchorPosition"));
611 
612         // Get the shape's bounding box in internal coordinates (in 100th of
613         // mm).  Use the property BoundRect.  Only if that is not supported ask
614         // the shape for its position and size directly.
615         Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
616         Reference<beans::XPropertySetInfo> xSetInfo;
617         bool bFoundBoundRect = false;
618         if (xSet.is())
619         {
620             xSetInfo = xSet->getPropertySetInfo ();
621             if (xSetInfo.is())
622             {
623                 if (xSetInfo->hasPropertyByName (sBoundRectName))
624                 {
625                     try
626                     {
627                         uno::Any aValue = xSet->getPropertyValue (sBoundRectName);
628                         aValue >>= aBoundingBox;
629                         bFoundBoundRect = true;
630                     }
631                     catch (beans::UnknownPropertyException e)
632                     {
633                         // Handled below (bFoundBoundRect stays false).
634                     }
635                 }
636                 else
637                     OSL_TRACE (" no property BoundRect");
638             }
639         }
640 
641         // Fallback when there is no BoundRect Property.
642         if ( ! bFoundBoundRect )
643         {
644             awt::Point aPosition (mxShape->getPosition());
645             awt::Size aSize (mxShape->getSize());
646             aBoundingBox = awt::Rectangle (
647                 aPosition.X, aPosition.Y,
648                 aSize.Width, aSize.Height);
649 
650             // While BoundRects have absolute positions, the position returned
651             // by XPosition::getPosition is relative.  Get the anchor position
652             // (usually not (0,0) for Writer shapes).
653             if (xSetInfo.is())
654             {
655                 if (xSetInfo->hasPropertyByName (sAnchorPositionName))
656                 {
657                     uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
658                     awt::Point aAnchorPosition;
659                     aPos >>= aAnchorPosition;
660                     aBoundingBox.X += aAnchorPosition.X;
661                     aBoundingBox.Y += aAnchorPosition.Y;
662                 }
663             }
664         }
665 
666         // Transform coordinates from internal to pixel.
667         if (maShapeTreeInfo.GetViewForwarder() == NULL)
668             throw uno::RuntimeException (::rtl::OUString (
669                 RTL_CONSTASCII_USTRINGPARAM(
670                     "AccessibleShape has no valid view forwarder")),
671                 static_cast<uno::XWeak*>(this));
672         ::Size aPixelSize = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
673             ::Size (aBoundingBox.Width, aBoundingBox.Height));
674         ::Point aPixelPosition = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
675             ::Point (aBoundingBox.X, aBoundingBox.Y));
676 
677         // Clip the shape's bounding box with the bounding box of its parent.
678         Reference<XAccessibleComponent> xParentComponent (
679             getAccessibleParent(), uno::UNO_QUERY);
680         if (xParentComponent.is())
681         {
682             // Make the coordinates relative to the parent.
683             awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
684             int x = aPixelPosition.getX() - aParentLocation.X;
685             int y = aPixelPosition.getY() - aParentLocation.Y;
686 
687             /*        //  The following block is a workaround for bug #99889# (property
688             //  BoundRect returns coordinates relative to document window
689             //  instead of absolute coordinates for shapes in Writer).  Has to
690             //  be removed as soon as bug is fixed.
691 
692             // Use a non-null anchor position as flag that the shape is in a
693             // Writer document.
694             if (xSetInfo.is())
695                 if (xSetInfo->hasPropertyByName (sAnchorPositionName))
696                 {
697                     uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
698                     awt::Point aAnchorPosition;
699                     aPos >>= aAnchorPosition;
700                     if (aAnchorPosition.X > 0)
701                     {
702                         x = aPixelPosition.getX();
703                         y = aPixelPosition.getY();
704                     }
705                 }
706             //  End of workaround.
707             */
708             // Clip with parent (with coordinates relative to itself).
709             ::Rectangle aBBox (
710                 x, y, x + aPixelSize.getWidth(), y + aPixelSize.getHeight());
711             awt::Size aParentSize (xParentComponent->getSize());
712             ::Rectangle aParentBBox (0,0, aParentSize.Width, aParentSize.Height);
713             aBBox = aBBox.GetIntersection (aParentBBox);
714             aBoundingBox = awt::Rectangle (
715                 aBBox.getX(),
716                 aBBox.getY(),
717                 aBBox.getWidth(),
718                 aBBox.getHeight());
719         }
720         else
721         {
722             OSL_TRACE ("parent does not support component");
723             aBoundingBox = awt::Rectangle (
724                 aPixelPosition.getX(), aPixelPosition.getY(),
725                 aPixelSize.getWidth(), aPixelSize.getHeight());
726         }
727     }
728 
729     return aBoundingBox;
730 }
731 
732 
733 
734 
getLocation(void)735 awt::Point SAL_CALL AccessibleShape::getLocation (void)
736 {
737     ThrowIfDisposed ();
738     awt::Rectangle aBoundingBox (getBounds());
739     return awt::Point (aBoundingBox.X, aBoundingBox.Y);
740 }
741 
742 
743 
744 
getLocationOnScreen(void)745 awt::Point SAL_CALL AccessibleShape::getLocationOnScreen (void)
746 {
747     ThrowIfDisposed ();
748 
749     // Get relative position...
750     awt::Point aLocation (getLocation ());
751 
752     // ... and add absolute position of the parent.
753     uno::Reference<XAccessibleComponent> xParentComponent (
754         getAccessibleParent(), uno::UNO_QUERY);
755     if (xParentComponent.is())
756     {
757         awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
758         aLocation.X += aParentLocation.X;
759         aLocation.Y += aParentLocation.Y;
760     }
761     else
762         OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
763     return aLocation;
764 }
765 
766 
767 
768 
getSize(void)769 awt::Size SAL_CALL AccessibleShape::getSize (void)
770 {
771     ThrowIfDisposed ();
772     awt::Rectangle aBoundingBox (getBounds());
773     return awt::Size (aBoundingBox.Width, aBoundingBox.Height);
774 }
775 
776 
777 
778 
getForeground(void)779 sal_Int32 SAL_CALL AccessibleShape::getForeground (void)
780 {
781     ThrowIfDisposed ();
782     sal_Int32 nColor (0x0ffffffL);
783 
784     try
785     {
786         uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
787         if (aSet.is())
788         {
789             uno::Any aColor;
790             aColor = aSet->getPropertyValue (OUString::createFromAscii ("LineColor"));
791             aColor >>= nColor;
792         }
793     }
794     catch (::com::sun::star::beans::UnknownPropertyException)
795     {
796         // Ignore exception and return default color.
797     }
798     return nColor;
799 }
800 
801 
802 
803 
getBackground(void)804 sal_Int32 SAL_CALL AccessibleShape::getBackground (void)
805 {
806     ThrowIfDisposed ();
807     sal_Int32 nColor (0L);
808 
809     try
810     {
811         uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
812         if (aSet.is())
813         {
814             uno::Any aColor;
815             aColor = aSet->getPropertyValue (OUString::createFromAscii ("FillColor"));
816             aColor >>= nColor;
817             aColor = aSet->getPropertyValue (OUString::createFromAscii ("FillTransparence"));
818             short nTrans=0;
819             aColor >>= nTrans;
820             Color crBk(nColor);
821             if (nTrans == 0 )
822             {
823                 crBk.SetTransparency(0xff);
824             }
825             else
826             {
827                 nTrans = short(256 - nTrans / 100. * 256);
828                 crBk.SetTransparency(sal_uInt8(nTrans));
829             }
830             nColor = crBk.GetColor();
831         }
832     }
833     catch (::com::sun::star::beans::UnknownPropertyException)
834     {
835         // Ignore exception and return default color.
836     }
837     return nColor;
838 }
839 
840 
841 
842 
843 //=====  XAccessibleEventBroadcaster  =========================================
844 
addEventListener(const Reference<XAccessibleEventListener> & rxListener)845 void SAL_CALL AccessibleShape::addEventListener (
846     const Reference<XAccessibleEventListener >& rxListener)
847 {
848     if (rBHelper.bDisposed || rBHelper.bInDispose)
849     {
850         uno::Reference<uno::XInterface> xThis (
851             (lang::XComponent *)this, uno::UNO_QUERY);
852         rxListener->disposing (lang::EventObject (xThis));
853     }
854     else
855     {
856         AccessibleContextBase::addEventListener (rxListener);
857         if (mpText != NULL)
858             mpText->AddEventListener (rxListener);
859     }
860 }
861 
862 
863 
864 
removeEventListener(const Reference<XAccessibleEventListener> & rxListener)865 void SAL_CALL AccessibleShape::removeEventListener (
866     const Reference<XAccessibleEventListener >& rxListener)
867 {
868     AccessibleContextBase::removeEventListener (rxListener);
869     if (mpText != NULL)
870         mpText->RemoveEventListener (rxListener);
871 }
872 
873 
874 
875 
876 //=====  XInterface  ==========================================================
877 
878 com::sun::star::uno::Any SAL_CALL
queryInterface(const com::sun::star::uno::Type & rType)879     AccessibleShape::queryInterface (const com::sun::star::uno::Type & rType)
880 {
881     ::com::sun::star::uno::Any aReturn = AccessibleContextBase::queryInterface (rType);
882     if ( ! aReturn.hasValue())
883         aReturn = ::cppu::queryInterface (rType,
884             static_cast<XAccessibleComponent*>(this),
885             static_cast<XAccessibleExtendedComponent*>(this),
886             static_cast< ::com::sun::star::accessibility::XAccessibleSelection* >(this),
887 
888          static_cast< ::com::sun::star::accessibility::XAccessibleExtendedAttributes* >(this),
889             static_cast<lang::XEventListener*>(this),
890             static_cast<document::XEventListener*>(this),
891             static_cast<lang::XUnoTunnel*>(this),
892             static_cast<XAccessibleGroupPosition*>(this),
893             static_cast<XAccessibleHypertext*>(this)
894             );
895     return aReturn;
896 }
897 
898 
899 
900 
901 void SAL_CALL
acquire(void)902     AccessibleShape::acquire (void)
903     throw ()
904 {
905     AccessibleContextBase::acquire ();
906 }
907 
908 
909 
910 
911 void SAL_CALL
release(void)912     AccessibleShape::release (void)
913     throw ()
914 {
915     AccessibleContextBase::release ();
916 }
917 //
918 //=====  XAccessibleSelection  ============================================
919 //
920 
921 //--------------------------------------------------------------------------------
selectAccessibleChild(sal_Int32)922 void SAL_CALL AccessibleShape::selectAccessibleChild( sal_Int32 )
923 {
924 }
925 
926 //----------------------------------------------------------------------------------
isAccessibleChildSelected(sal_Int32 nChildIndex)927 sal_Bool SAL_CALL AccessibleShape::isAccessibleChildSelected( sal_Int32 nChildIndex )
928 {
929     uno::Reference<XAccessible> xAcc = getAccessibleChild( nChildIndex );
930     uno::Reference<XAccessibleContext> xContext;
931     if( xAcc.is() )
932     {
933         xContext = xAcc->getAccessibleContext();
934     }
935 
936     if( xContext.is() )
937     {
938         if( xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH )
939         {
940             uno::Reference< ::com::sun::star::accessibility::XAccessibleText >
941                 xText(xAcc, uno::UNO_QUERY);
942             if( xText.is() )
943             {
944                 if( xText->getSelectionStart() >= 0 ) return sal_True;
945             }
946         }
947         else if( xContext->getAccessibleRole() == AccessibleRole::SHAPE )
948         {
949             Reference< XAccessibleStateSet > pRState = xContext->getAccessibleStateSet();
950             if( !pRState.is() )
951                 return sal_False;
952 
953             uno::Sequence<short> pStates = pRState->getStates();
954             int nCount = pStates.getLength();
955             for( int i = 0; i < nCount; i++ )
956             {
957                 if(pStates[i] == AccessibleStateType::SELECTED)
958                     return sal_True;
959             }
960             return sal_False;
961         }
962     }
963 
964     return sal_False;
965 }
966 
967 //---------------------------------------------------------------------
clearAccessibleSelection()968 void SAL_CALL AccessibleShape::clearAccessibleSelection(  )
969 {
970 }
971 
972 //-------------------------------------------------------------------------
selectAllAccessibleChildren()973 void SAL_CALL AccessibleShape::selectAllAccessibleChildren(  )
974 {
975 }
976 
977 //----------------------------------------------------------------------------
getSelectedAccessibleChildCount()978 sal_Int32 SAL_CALL AccessibleShape::getSelectedAccessibleChildCount()
979 {
980     sal_Int32 nCount = 0;
981     sal_Int32 TotalCount = getAccessibleChildCount();
982     for( sal_Int32 i = 0; i < TotalCount; i++ )
983         if( isAccessibleChildSelected(i) ) nCount++;
984 
985     return nCount;
986 }
987 
988 //--------------------------------------------------------------------------------------
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)989 Reference<XAccessible> SAL_CALL AccessibleShape::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex )
990 {
991     if ( nSelectedChildIndex > getSelectedAccessibleChildCount() )
992         throw IndexOutOfBoundsException();
993     sal_Int32 i1, i2;
994     for( i1 = 0, i2 = 0; i1 < getAccessibleChildCount(); i1++ )
995         if( isAccessibleChildSelected(i1) )
996         {
997             if( i2 == nSelectedChildIndex )
998                 return getAccessibleChild( i1 );
999             i2++;
1000         }
1001     return Reference<XAccessible>();
1002 }
1003 
1004 //----------------------------------------------------------------------------------
deselectAccessibleChild(sal_Int32)1005 void SAL_CALL AccessibleShape::deselectAccessibleChild( sal_Int32 )
1006 {
1007 
1008 }
1009 
1010 //=====  XAccessibleExtendedAttributes  ========================================================
getExtendedAttributes()1011 uno::Any SAL_CALL AccessibleShape::getExtendedAttributes()
1012 {
1013     uno::Any strRet;
1014     ::rtl::OUString style;
1015     if( getAccessibleRole() != AccessibleRole::SHAPE ) return strRet;
1016     if( m_pShape )
1017     {
1018         //style = ::rtl::OUString::createFromAscii("style=");
1019         style = ::rtl::OUString::createFromAscii("style:");
1020         style += GetStyle();
1021     }
1022     style += ::rtl::OUString::createFromAscii(";");
1023     strRet <<= style;
1024     return strRet;
1025 }
1026 //=====  XServiceInfo  ========================================================
1027 
1028 ::rtl::OUString SAL_CALL
getImplementationName(void)1029     AccessibleShape::getImplementationName (void)
1030 {
1031     return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleShape"));
1032 }
1033 
1034 
1035 
1036 
1037 uno::Sequence<OUString> SAL_CALL
getSupportedServiceNames(void)1038     AccessibleShape::getSupportedServiceNames (void)
1039 {
1040     ThrowIfDisposed ();
1041     // Get list of supported service names from base class...
1042     uno::Sequence<OUString> aServiceNames =
1043         AccessibleContextBase::getSupportedServiceNames();
1044     sal_Int32 nCount (aServiceNames.getLength());
1045 
1046     // ...and add additional names.
1047     aServiceNames.realloc (nCount + 1);
1048     static const OUString sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
1049         "com.sun.star.drawing.AccessibleShape"));
1050     aServiceNames[nCount] = sAdditionalServiceName;
1051 
1052     return aServiceNames;
1053 }
1054 
1055 
1056 
1057 
1058 
1059 //=====  XTypeProvider  ===================================================
1060 
1061 uno::Sequence<uno::Type> SAL_CALL
getTypes(void)1062     AccessibleShape::getTypes (void)
1063 {
1064     ThrowIfDisposed ();
1065     // Get list of types from the context base implementation, ...
1066     uno::Sequence<uno::Type> aTypeList (AccessibleContextBase::getTypes());
1067     // ... get list of types from component base implementation, ...
1068     uno::Sequence<uno::Type> aComponentTypeList (AccessibleComponentBase::getTypes());
1069     // ... define local types, ...
1070     const uno::Type aLangEventListenerType =
1071         ::getCppuType((const uno::Reference<lang::XEventListener>*)0);
1072     const uno::Type aDocumentEventListenerType =
1073         ::getCppuType((const uno::Reference<document::XEventListener>*)0);
1074     const uno::Type aUnoTunnelType =
1075         ::getCppuType((const uno::Reference<lang::XUnoTunnel>*)0);
1076     //    const uno::Type aStateSetType =
1077     //      ::getCppuType((const uno::Reference<XAccessibleStateSet>*)0);
1078 
1079     // ... and merge them all into one list.
1080     sal_Int32   nTypeCount (aTypeList.getLength()),
1081         nComponentTypeCount (aComponentTypeList.getLength());
1082     int         i;
1083 
1084     aTypeList.realloc (nTypeCount + nComponentTypeCount + 3);
1085 
1086     for (i=0; i<nComponentTypeCount; i++)
1087         aTypeList[nTypeCount + i] = aComponentTypeList[i];
1088 
1089     aTypeList[nTypeCount + i++ ] = aLangEventListenerType;
1090     aTypeList[nTypeCount + i++ ] = aDocumentEventListenerType;
1091     aTypeList[nTypeCount + i ] = aUnoTunnelType;
1092 
1093     return aTypeList;
1094 }
1095 
1096 
1097 
1098 
1099 //=====  lang::XEventListener  ================================================
1100 
1101 /** Disposing calls are accepted only from the model: Just reset the
1102     reference to the model in the shape tree info.  Otherwise this object
1103     remains functional.
1104 */
1105 void SAL_CALL
disposing(const lang::EventObject & aEvent)1106     AccessibleShape::disposing (const lang::EventObject& aEvent)
1107 {
1108     ::vos::OGuard aSolarGuard (::Application::GetSolarMutex());
1109     ::osl::MutexGuard aGuard (maMutex);
1110 
1111     try
1112     {
1113         if (aEvent.Source ==  maShapeTreeInfo.GetModelBroadcaster())
1114         {
1115             // Remove reference to model broadcaster to allow it to pass
1116             // away.
1117             maShapeTreeInfo.SetModelBroadcaster(NULL);
1118         }
1119 
1120     }
1121     catch (uno::RuntimeException e)
1122     {
1123         OSL_TRACE ("caught exception while disposing");
1124     }
1125 }
1126 
1127 
1128 
1129 
1130 //=====  document::XEventListener  ============================================
1131 
1132 void SAL_CALL
notifyEvent(const document::EventObject & rEventObject)1133     AccessibleShape::notifyEvent (const document::EventObject& rEventObject)
1134 {
1135     static const OUString sShapeModified (
1136         RTL_CONSTASCII_USTRINGPARAM("ShapeModified"));
1137 
1138     // First check if the event is for us.
1139     uno::Reference<drawing::XShape> xShape (
1140         rEventObject.Source, uno::UNO_QUERY);
1141     if ( xShape.get() == mxShape.get() )
1142     {
1143         if (rEventObject.EventName.equals (sShapeModified))
1144         {
1145             //Need to update text children when receiving ShapeModified hint when exiting edit mode for text box
1146             if (mpText)
1147                 mpText->UpdateChildren();
1148 
1149 
1150             // Some property of a shape has been modified.  Send an event
1151             // that indicates a change of the visible data to all listeners.
1152             CommitChange (
1153                 AccessibleEventId::VISIBLE_DATA_CHANGED,
1154                 uno::Any(),
1155                 uno::Any());
1156 
1157             // Name and Description may have changed.  Update the local
1158             // values accordingly.
1159             UpdateNameAndDescription();
1160         }
1161     }
1162 }
1163 
1164 
1165 
1166 
1167 //=====  lang::XUnoTunnel  ================================================
1168 
1169 const uno::Sequence< sal_Int8 >&
getUnoTunnelImplementationId()1170     AccessibleShape::getUnoTunnelImplementationId()
1171     throw()
1172 {
1173     static uno::Sequence< sal_Int8 >* pSeq = 0;
1174 
1175     if( !pSeq )
1176     {
1177         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
1178 
1179         if( !pSeq )
1180         {
1181             static uno::Sequence< sal_Int8 > aSeq( 16 );
1182             rtl_createUuid( (sal_uInt8*) aSeq.getArray(), 0, sal_True );
1183             pSeq = &aSeq;
1184         }
1185     }
1186 
1187     return( *pSeq );
1188 }
1189 
1190 //------------------------------------------------------------------------------
1191 AccessibleShape*
getImplementation(const uno::Reference<uno::XInterface> & rxIFace)1192     AccessibleShape::getImplementation( const uno::Reference< uno::XInterface >& rxIFace )
1193     throw()
1194 {
1195     uno::Reference< lang::XUnoTunnel >  xTunnel( rxIFace, uno::UNO_QUERY );
1196     AccessibleShape*                    pReturn = NULL;
1197 
1198     if( xTunnel.is() )
1199         pReturn = reinterpret_cast< AccessibleShape* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
1200 
1201     return( pReturn );
1202 }
1203 
1204 //------------------------------------------------------------------------------
1205 sal_Int64 SAL_CALL
getSomething(const uno::Sequence<sal_Int8> & rIdentifier)1206     AccessibleShape::getSomething( const uno::Sequence< sal_Int8 >& rIdentifier )
1207 {
1208     sal_Int64 nReturn( 0 );
1209 
1210     if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) )
1211         nReturn = reinterpret_cast< sal_Int64 >( this );
1212 
1213     return( nReturn );
1214 }
1215 
1216 //=====  IAccessibleViewForwarderListener  ====================================
1217 
ViewForwarderChanged(ChangeType aChangeType,const IAccessibleViewForwarder * pViewForwarder)1218 void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType,
1219         const IAccessibleViewForwarder* pViewForwarder)
1220 {
1221     // Inform all listeners that the graphical representation (i.e. size
1222     // and/or position) of the shape has changed.
1223     CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED,
1224         uno::Any(),
1225         uno::Any());
1226 
1227     // Tell children manager of the modified view forwarder.
1228     if (mpChildrenManager != NULL)
1229         mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
1230 
1231     // update our children that our screen position might have changed
1232     if( mpText )
1233         mpText->UpdateChildren();
1234 }
1235 
1236 
1237 
1238 
1239 //=====  protected internal  ==================================================
1240 /// Set this object's name if is different to the current name.
1241 ::rtl::OUString
CreateAccessibleBaseName(void)1242     AccessibleShape::CreateAccessibleBaseName (void)
1243 {
1244     return ShapeTypeHandler::CreateAccessibleBaseName( mxShape );
1245 }
1246 
1247 
1248 ::rtl::OUString
CreateAccessibleName(void)1249     AccessibleShape::CreateAccessibleName (void)
1250 {
1251     //OUString sName (CreateAccessibleBaseName());
1252     OUString sName;
1253     sName = GetFullAccessibleName(this);
1254     return sName;
1255 }
1256 
1257 ::rtl::OUString
GetFullAccessibleName(AccessibleShape * shape)1258     AccessibleShape::GetFullAccessibleName (AccessibleShape *shape)
1259 {
1260     OUString sName (shape->CreateAccessibleBaseName());
1261     // Append the shape's index to the name to disambiguate between shapes
1262     // of the same type.  If such an index where not given to the
1263     // constructor then use the z-order instead.  If even that does not exist
1264     // we throw an exception.
1265     //long nIndex = mnIndex;
1266     //if (nIndex == -1)
1267     //{
1268     //    try
1269     //    {
1270     //        uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
1271     //        if (xSet.is())
1272     //        {
1273     //            uno::Any aZOrder (xSet->getPropertyValue (::rtl::OUString::createFromAscii ("ZOrder")));
1274     //            aZOrder >>= nIndex;
1275 
1276     //            // Add one to be not zero based.
1277     //            nIndex += 1;
1278     //        }
1279     //    }
1280     //    catch (beans::UnknownPropertyException)
1281     //    {
1282     //        // We throw our own exception that is a bit more informative.
1283     //        throw uno::RuntimeException (::rtl::OUString (
1284     //            RTL_CONSTASCII_USTRINGPARAM("AccessibleShape has invalid index and no ZOrder property")),
1285     //            static_cast<uno::XWeak*>(this));
1286     //    }
1287 
1288     //}
1289 
1290     //// Put a space between name and index because of Gnopernicus otherwise
1291     //// spells the name.
1292     //sName += OUString (RTL_CONSTASCII_USTRINGPARAM(" ")) + OUString::valueOf (nIndex);
1293 
1294     //return sName;
1295 
1296     XubString nameStr;
1297     if(shape->m_pShape)
1298         nameStr = shape->m_pShape->GetName();
1299     if(nameStr.Len() == 0)
1300     {
1301         sName +=  OUString( RTL_CONSTASCII_USTRINGPARAM( " " ));
1302     }
1303     else
1304     {
1305         sName = nameStr;
1306     }
1307     /*
1308     sal_Int32 nChildCount = shape->getAccessibleChildCount();
1309     if(nChildCount > 0)
1310       {
1311         for (sal_Int32 i=0; i<nChildCount; ++i)
1312         {
1313             Reference<XAccessible> xChild (shape->getAccessibleChild (i));
1314             if (xChild.is())
1315             {
1316             uno::Reference <XAccessibleContext> xChildContext(xChild->getAccessibleContext());
1317             if (xChildContext->getAccessibleRole() == AccessibleRole::PARAGRAPH)
1318             {
1319                 uno::Reference<XAccessibleText> xText = uno::Reference<XAccessibleText> ( xChild, uno::UNO_QUERY );
1320                 sName += OUString( RTL_CONSTASCII_USTRINGPARAM( " " )) + xText->getText();
1321             }
1322             else if (xChildContext->getAccessibleRole() == AccessibleRole::SHAPE)
1323             {
1324                 sName += OUString( RTL_CONSTASCII_USTRINGPARAM( " " )) + GetFullAccessibleName(static_cast< AccessibleShape*>( xChild.get()));
1325             }
1326             }
1327         }
1328       }
1329      */
1330     //Solution:If the new produced name if not the same with last,notify name changed
1331     //         Event
1332     if( aAccName != sName && aAccName.getLength() != 0 )
1333     {
1334         uno::Any aOldValue, aNewValue;
1335         aOldValue <<= aAccName;
1336         aNewValue <<= sName;
1337         CommitChange(
1338             AccessibleEventId::NAME_CHANGED,
1339             aNewValue,
1340             aOldValue);
1341     }
1342     aAccName = sName;
1343     return sName;
1344 }
1345 ::rtl::OUString
CreateAccessibleDescription(void)1346     AccessibleShape::CreateAccessibleDescription (void)
1347 {
1348     DescriptionGenerator aDG (mxShape);
1349     aDG.Initialize (CreateAccessibleBaseName());
1350     switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
1351     {
1352         case DRAWING_3D_CUBE:
1353         case DRAWING_3D_EXTRUDE:
1354         case DRAWING_3D_LATHE:
1355         case DRAWING_3D_SPHERE:
1356             aDG.Add3DProperties ();
1357             break;
1358 
1359         case DRAWING_3D_SCENE:
1360         case DRAWING_GROUP:
1361         case DRAWING_PAGE:
1362             // No further information is appended.
1363             break;
1364 
1365         case DRAWING_CAPTION:
1366         case DRAWING_CLOSED_BEZIER:
1367         case DRAWING_CLOSED_FREEHAND:
1368         case DRAWING_ELLIPSE:
1369         case DRAWING_POLY_POLYGON:
1370         case DRAWING_POLY_POLYGON_PATH:
1371         case DRAWING_RECTANGLE:
1372             aDG.AddLineProperties ();
1373             aDG.AddFillProperties ();
1374             break;
1375 
1376         case DRAWING_CONNECTOR:
1377         case DRAWING_LINE:
1378         case DRAWING_MEASURE:
1379         case DRAWING_OPEN_BEZIER:
1380         case DRAWING_OPEN_FREEHAND:
1381         case DRAWING_POLY_LINE:
1382         case DRAWING_POLY_LINE_PATH:
1383             aDG.AddLineProperties ();
1384             break;
1385 
1386         case DRAWING_CONTROL:
1387             aDG.AddProperty (OUString::createFromAscii ("ControlBackground"),
1388                 DescriptionGenerator::COLOR,
1389                 OUString());
1390             aDG.AddProperty (OUString::createFromAscii ("ControlBorder"),
1391                 DescriptionGenerator::INTEGER,
1392                 OUString());
1393             break;
1394 
1395         case DRAWING_TEXT:
1396             aDG.AddTextProperties ();
1397             break;
1398 
1399         default:
1400             aDG.Initialize (::rtl::OUString (
1401                                 RTL_CONSTASCII_USTRINGPARAM("Unknown accessible shape")));
1402             uno::Reference<drawing::XShapeDescriptor> xDescriptor (mxShape, uno::UNO_QUERY);
1403             if (xDescriptor.is())
1404             {
1405                 aDG.AppendString (::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("service name=")));
1406                 aDG.AppendString (xDescriptor->getShapeType());
1407             }
1408     }
1409 
1410     return aDG();
1411 }
1412 
1413 
1414 
1415 
GetXShape()1416 uno::Reference< drawing::XShape > AccessibleShape::GetXShape()
1417 {
1418     return( mxShape );
1419 }
1420 
1421 
1422 
1423 // protected
disposing(void)1424 void AccessibleShape::disposing (void)
1425 {
1426     ::vos::OGuard aSolarGuard (::Application::GetSolarMutex());
1427     ::osl::MutexGuard aGuard (maMutex);
1428 
1429     // Make sure to send an event that this object looses the focus in the
1430     // case that it has the focus.
1431     ::utl::AccessibleStateSetHelper* pStateSet =
1432           static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
1433     if (pStateSet != NULL)
1434         pStateSet->RemoveState (AccessibleStateType::FOCUSED);
1435 
1436     // Unregister from broadcasters.
1437     Reference<lang::XComponent> xComponent (mxShape, uno::UNO_QUERY);
1438     if (xComponent.is())
1439         xComponent->removeEventListener (this);
1440 
1441     // Unregister from model.
1442     if (maShapeTreeInfo.GetModelBroadcaster().is())
1443         maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
1444             static_cast<document::XEventListener*>(this));
1445 
1446     // Release the child containers.
1447     if (mpChildrenManager != NULL)
1448     {
1449         delete mpChildrenManager;
1450         mpChildrenManager = NULL;
1451     }
1452     if (mpText != NULL)
1453     {
1454         mpText->Dispose();
1455         delete mpText;
1456         mpText = NULL;
1457     }
1458 
1459     // Cleanup.  Remove references to objects to allow them to be
1460     // destroyed.
1461     mxShape = NULL;
1462     maShapeTreeInfo = AccessibleShapeTreeInfo();
1463 
1464     // Call base classes.
1465     AccessibleContextBase::dispose ();
1466 }
1467 
1468 sal_Int32 SAL_CALL
getAccessibleIndexInParent(void)1469     AccessibleShape::getAccessibleIndexInParent (void)
1470 {
1471     ThrowIfDisposed ();
1472     //  Use a simple but slow solution for now.  Optimize later.
1473 
1474     sal_Int32 nIndex = m_nIndexInParent;
1475     if ( -1 == nIndex )
1476         nIndex = AccessibleContextBase::getAccessibleIndexInParent();
1477     return nIndex;
1478 }
1479 
1480 
1481 
1482 
UpdateNameAndDescription(void)1483 void AccessibleShape::UpdateNameAndDescription (void)
1484 {
1485     // Ignore missing title, name, or description.  There are fallbacks for
1486     // them.
1487     try
1488     {
1489         Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY_THROW);
1490         OUString sString;
1491 
1492         // Get the accessible name.
1493         sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Title")));
1494         if (sString.getLength() > 0)
1495         {
1496             SetAccessibleName(sString, AccessibleContextBase::FromShape);
1497         }
1498         else
1499         {
1500             sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Name")));
1501             if (sString.getLength() > 0)
1502                 SetAccessibleName(sString, AccessibleContextBase::FromShape);
1503         }
1504 
1505         // Get the accessible description.
1506         sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Description")));
1507         if (sString.getLength() > 0)
1508             SetAccessibleDescription(sString, AccessibleContextBase::FromShape);
1509     }
1510     catch (uno::RuntimeException&)
1511     {
1512     }
1513 }
1514 //  Return this object's role.
getAccessibleRole(void)1515 sal_Int16 SAL_CALL AccessibleShape::getAccessibleRole (void)
1516 {
1517     sal_Int16 nAccessibleRole =  AccessibleRole::SHAPE ;
1518     switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
1519     {
1520         case     DRAWING_GRAPHIC_OBJECT:
1521                  nAccessibleRole =  AccessibleRole::GRAPHIC ;               break;
1522         case     DRAWING_OLE:
1523                  nAccessibleRole =  AccessibleRole::EMBEDDED_OBJECT ;       break;
1524 
1525         default:
1526             nAccessibleRole = AccessibleContextBase::getAccessibleRole();
1527             break;
1528     }
1529 
1530     return nAccessibleRole;
1531 }
1532 
1533 
UpdateDocumentAllSelState(Reference<XAccessibleStateSet> & xStateSet)1534 void AccessibleShape::UpdateDocumentAllSelState(Reference<XAccessibleStateSet> &xStateSet)
1535 {
1536     if (mpParent && mpParent->IsDocumentSelAll())
1537     {
1538         ::utl::AccessibleStateSetHelper* pStateSet =
1539             static_cast< ::utl::AccessibleStateSetHelper*>(xStateSet.get());
1540         pStateSet->AddState (AccessibleStateType::SELECTED);
1541 
1542         //uno::Any NewValue;
1543         //NewValue <<= AccessibleStateType::SELECTED;
1544 
1545         //CommitChange(AccessibleEventId::STATE_CHANGED,NewValue,uno::Any());
1546     }
1547 }
1548 
1549 //sort the drawing objects from up to down, from left to right
1550 struct XShapePosCompareHelper
1551 {
operator ()accessibility::XShapePosCompareHelper1552     bool operator() ( const uno::Reference<drawing::XShape>& xshape1,
1553         const uno::Reference<drawing::XShape>& xshape2 ) const
1554     {
1555         SdrObject* pObj1 = GetSdrObjectFromXShape(xshape1);
1556         SdrObject* pObj2 = GetSdrObjectFromXShape(xshape2);
1557         if(pObj1 && pObj2)
1558             return pObj1->GetOrdNum() < pObj2->GetOrdNum();
1559         else
1560             return 0;
1561     }
1562 };
1563 //end of group position
1564 
1565 //=====  XAccessibleGroupPosition  =========================================
1566 uno::Sequence< sal_Int32 > SAL_CALL
getGroupPosition(const uno::Any &)1567 AccessibleShape::getGroupPosition( const uno::Any& )
1568 {
1569     // we will return the:
1570     // [0] group level
1571     // [1] similar items counts in the group
1572     // [2] the position of the object in the group
1573     uno::Sequence< sal_Int32 > aRet( 3 );
1574     aRet[0] = 0;
1575     aRet[1] = 0;
1576     aRet[2] = 0;
1577 
1578     ::com::sun::star::uno::Reference<XAccessible> xParent = getAccessibleParent();
1579     if (!xParent.is())
1580     {
1581         return aRet;
1582     }
1583     SdrObject *pObj = GetSdrObjectFromXShape(mxShape);
1584 
1585 
1586     if(pObj == NULL )
1587     {
1588         return aRet;
1589     }
1590 
1591     // Compute object's group level.
1592     sal_Int32 nGroupLevel = 0;
1593     SdrObject * pUper = pObj->GetUpGroup();
1594     while( pUper )
1595     {
1596         ++nGroupLevel;
1597         pUper = pUper->GetUpGroup();
1598     }
1599 
1600     ::com::sun::star::uno::Reference<XAccessibleContext> xParentContext = xParent->getAccessibleContext();
1601     if( xParentContext->getAccessibleRole()  == AccessibleRole::DOCUMENT)//Document
1602     {
1603         Reference< XAccessibleGroupPosition > xGroupPosition( xParent,uno::UNO_QUERY );
1604         if ( xGroupPosition.is() )
1605         {
1606             aRet = xGroupPosition->getGroupPosition( uno::makeAny( getAccessibleContext() ) );
1607         }
1608         return aRet;
1609     }
1610     if (xParentContext->getAccessibleRole() != AccessibleRole::SHAPE)
1611     {
1612         return aRet;
1613     }
1614 
1615     SdrObjList *pGrpList = NULL;
1616     if( pObj->GetUpGroup() )
1617         pGrpList = pObj->GetUpGroup()->GetSubList();
1618     else
1619         return aRet;
1620 
1621     std::vector< uno::Reference<drawing::XShape> > vXShapes;
1622     if (pGrpList)
1623     {
1624         const sal_Int32 nObj = pGrpList->GetObjCount();
1625         for(sal_Int32 i = 0 ; i < nObj ; ++i)
1626         {
1627             SdrObject *pSubObj = pGrpList->GetObj(i);
1628             if (pSubObj &&
1629                 xParentContext->getAccessibleChild(i)->getAccessibleContext()->getAccessibleRole() != AccessibleRole::GROUP_BOX)
1630             {
1631                 vXShapes.push_back( GetXShapeForSdrObject(pSubObj) );
1632             }
1633         }
1634     }
1635 
1636     std::sort( vXShapes.begin(), vXShapes.end(), XShapePosCompareHelper() );
1637 
1638     //get the index of the selected object in the group
1639     std::vector< uno::Reference<drawing::XShape> >::iterator aIter;
1640     //we start counting position from 1
1641     sal_Int32 nPos = 1;
1642     for ( aIter = vXShapes.begin(); aIter != vXShapes.end(); aIter++, nPos++ )
1643     {
1644         if ( (*aIter).get() == mxShape.get() )
1645         {
1646             sal_Int32* pArray = aRet.getArray();
1647             pArray[0] = nGroupLevel;
1648             pArray[1] = vXShapes.size();
1649             pArray[2] = nPos;
1650             break;
1651         }
1652     }
1653 
1654     return aRet;
1655 }
1656 
getObjectLink(const uno::Any &)1657 ::rtl::OUString AccessibleShape::getObjectLink( const uno::Any& )
1658 {
1659     ::rtl::OUString aRet;
1660 
1661     SdrObject *pObj = GetSdrObjectFromXShape(mxShape);
1662     if(pObj == NULL )
1663     {
1664         return aRet;
1665     }
1666     if (maShapeTreeInfo.GetDocumentWindow().is())
1667     {
1668         Reference< XAccessibleGroupPosition > xGroupPosition( maShapeTreeInfo.GetDocumentWindow(), uno::UNO_QUERY );
1669         if (xGroupPosition.is())
1670         {
1671             aRet = xGroupPosition->getObjectLink( uno::makeAny( getAccessibleContext() ) );
1672         }
1673     }
1674     return aRet;
1675 }
1676 
1677 //=====  XAccessibleHypertext  ==================================================
getHyperLinkCount()1678 sal_Int32 SAL_CALL AccessibleShape::getHyperLinkCount()
1679 {
1680     // MT: Introduced with IA2 CWS, but SvxAccessibleHyperlink was redundant to svx::AccessibleHyperlink which we introduced meanwhile.
1681     // Code need to be adapted....
1682     return 0;
1683 
1684     /*
1685     SvxAccessibleHyperlink* pLink = new SvxAccessibleHyperlink(m_pShape,this);
1686     if (pLink->IsValidHyperlink())
1687         return 1;
1688     else
1689         return 0;
1690     */
1691 }
1692 uno::Reference< XAccessibleHyperlink > SAL_CALL
getHyperLink(sal_Int32)1693     AccessibleShape::getHyperLink( sal_Int32 )
1694 {
1695     uno::Reference< XAccessibleHyperlink > xRet;
1696     // MT: Introduced with IA2 CWS, but SvxAccessibleHyperlink was redundant to svx::AccessibleHyperlink which we introduced meanwhile.
1697     // Code need to be adapted....
1698     /*
1699     SvxAccessibleHyperlink* pLink = new SvxAccessibleHyperlink(m_pShape,this);
1700     if (pLink->IsValidHyperlink())
1701         xRet = pLink;
1702     if( !xRet.is() )
1703         throw ::com::sun::star::lang::IndexOutOfBoundsException();
1704     */
1705     return xRet;
1706 }
getHyperLinkIndex(sal_Int32)1707 sal_Int32 SAL_CALL AccessibleShape::getHyperLinkIndex( sal_Int32 )
1708 {
1709     sal_Int32 nRet = 0;
1710     return nRet;
1711 }
1712 //=====  XAccessibleText  ==================================================
getCaretPosition()1713 sal_Int32 SAL_CALL AccessibleShape::getCaretPosition(  ){return 0;}
setCaretPosition(sal_Int32)1714 sal_Bool SAL_CALL AccessibleShape::setCaretPosition( sal_Int32 ){return 0;}
getCharacter(sal_Int32)1715 sal_Unicode SAL_CALL AccessibleShape::getCharacter( sal_Int32 ){return 0;}
getCharacterAttributes(sal_Int32,const::com::sun::star::uno::Sequence<::rtl::OUString> &)1716 ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL AccessibleShape::getCharacterAttributes( sal_Int32, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& )
1717 {
1718     uno::Sequence< ::com::sun::star::beans::PropertyValue > aValues(0);
1719     return aValues;
1720 }
getCharacterBounds(sal_Int32)1721 ::com::sun::star::awt::Rectangle SAL_CALL AccessibleShape::getCharacterBounds( sal_Int32 )
1722 {
1723     return com::sun::star::awt::Rectangle(0, 0, 0, 0 );
1724 }
getCharacterCount()1725 sal_Int32 SAL_CALL AccessibleShape::getCharacterCount(  ){return 0;}
getIndexAtPoint(const::com::sun::star::awt::Point &)1726 sal_Int32 SAL_CALL AccessibleShape::getIndexAtPoint( const ::com::sun::star::awt::Point& ){return 0;}
getSelectedText()1727 ::rtl::OUString SAL_CALL AccessibleShape::getSelectedText(  ){return OUString();}
getSelectionStart()1728 sal_Int32 SAL_CALL AccessibleShape::getSelectionStart(  ){return 0;}
getSelectionEnd()1729 sal_Int32 SAL_CALL AccessibleShape::getSelectionEnd(  ){return 0;}
setSelection(sal_Int32,sal_Int32)1730 sal_Bool SAL_CALL AccessibleShape::setSelection( sal_Int32, sal_Int32 ){return sal_True;}
getText()1731 ::rtl::OUString SAL_CALL AccessibleShape::getText(  ){return OUString();}
getTextRange(sal_Int32,sal_Int32)1732 ::rtl::OUString SAL_CALL AccessibleShape::getTextRange( sal_Int32, sal_Int32 ){return OUString();}
getTextAtIndex(sal_Int32,sal_Int16)1733 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleShape::getTextAtIndex( sal_Int32, sal_Int16 )
1734 {
1735     ::com::sun::star::accessibility::TextSegment aResult;
1736     return aResult;
1737 }
getTextBeforeIndex(sal_Int32,sal_Int16)1738 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleShape::getTextBeforeIndex( sal_Int32, sal_Int16 )
1739 {
1740     ::com::sun::star::accessibility::TextSegment aResult;
1741     return aResult;
1742 }
getTextBehindIndex(sal_Int32,sal_Int16)1743 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleShape::getTextBehindIndex( sal_Int32, sal_Int16 )
1744 {
1745     ::com::sun::star::accessibility::TextSegment aResult;
1746     return aResult;
1747 }
copyText(sal_Int32,sal_Int32)1748 sal_Bool SAL_CALL AccessibleShape::copyText( sal_Int32, sal_Int32 ){return sal_True;}
1749 
1750 } // end of namespace accessibility
1751