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