Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / svx / source / accessibility / AccessibleShape.cxx
blob7ef5c90e1a43a9166a02bfd98de2dda8766638fb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <svx/AccessibleShape.hxx>
30 #include "svx/DescriptionGenerator.hxx"
31 #include <svx/AccessibleShapeInfo.hxx>
32 #include <com/sun/star/view/XSelectionSupplier.hpp>
33 #include <com/sun/star/accessibility/AccessibleRole.hpp>
34 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
35 #include <com/sun/star/beans/XPropertySet.hpp>
36 #include <com/sun/star/container/XChild.hpp>
37 #include <com/sun/star/drawing/XShapes.hpp>
38 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
39 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 #include <com/sun/star/drawing/FillStyle.hpp>
41 #include <com/sun/star/text/XText.hpp>
42 #include <editeng/outlobj.hxx>
43 #include <rtl/ref.hxx>
44 #include <editeng/unoedsrc.hxx>
45 #include <svx/unoshtxt.hxx>
46 #include <svx/svdobj.hxx>
47 #include <svx/svdmodel.hxx>
48 #include "svx/unoapi.hxx"
49 #include <com/sun/star/uno/Exception.hpp>
50 #include <svx/ShapeTypeHandler.hxx>
51 #include <svx/SvxShapeTypes.hxx>
53 #include "accessibility.hrc"
54 #include "svx/svdstr.hrc"
55 #include <svx/dialmgr.hxx>
56 #include <vcl/svapp.hxx>
57 #include <unotools/accessiblestatesethelper.hxx>
58 #include <svx/svdview.hxx>
59 #include <comphelper/servicehelper.hxx>
60 #include "AccessibleEmptyEditSource.hxx"
62 using namespace ::com::sun::star;
63 using namespace ::com::sun::star::accessibility;
64 using ::com::sun::star::uno::Reference;
65 using ::rtl::OUString;
67 namespace accessibility {
69 namespace {
71 OUString GetOptionalProperty (
72 const Reference<beans::XPropertySet>& rxSet,
73 const OUString& rsPropertyName)
75 OUString sValue;
77 if (rxSet.is())
79 const Reference<beans::XPropertySetInfo> xInfo (rxSet->getPropertySetInfo());
80 if ( ! xInfo.is() || xInfo->hasPropertyByName(rsPropertyName))
82 try
84 rxSet->getPropertyValue(rsPropertyName) >>= sValue;
86 catch (beans::UnknownPropertyException&)
88 // This exception should only be thrown when the property
89 // does not exits (of course) and the XPropertySetInfo is
90 // not available.
94 return sValue;
97 } // end of anonymous namespace
102 //===== internal ============================================================
104 AccessibleShape::AccessibleShape (
105 const AccessibleShapeInfo& rShapeInfo,
106 const AccessibleShapeTreeInfo& rShapeTreeInfo)
107 : AccessibleContextBase (rShapeInfo.mxParent,AccessibleRole::LIST_ITEM),
108 mpChildrenManager(NULL),
109 mxShape (rShapeInfo.mxShape),
110 maShapeTreeInfo (rShapeTreeInfo),
111 mnIndex (rShapeInfo.mnIndex),
112 m_nIndexInParent(-1),
113 mpText (NULL),
114 mpParent (rShapeInfo.mpChildrenManager)
116 m_pShape = GetSdrObjectFromXShape(mxShape);
117 UpdateNameAndDescription();
123 AccessibleShape::~AccessibleShape (void)
125 if (mpChildrenManager != NULL)
126 delete mpChildrenManager;
127 if (mpText != NULL)
128 delete mpText;
129 OSL_TRACE ("~AccessibleShape");
131 // Unregistering from the various broadcasters should be unnecessary
132 // since this destructor would not have been called if one of the
133 // broadcasters would still hold a strong reference to this object.
139 void AccessibleShape::Init (void)
141 // Update the OPAQUE and SELECTED shape.
142 UpdateStates ();
144 // Create a children manager when this shape has children of its own.
145 Reference<drawing::XShapes> xShapes (mxShape, uno::UNO_QUERY);
146 if (xShapes.is() && xShapes->getCount() > 0)
147 mpChildrenManager = new ChildrenManager (
148 this, xShapes, maShapeTreeInfo, *this);
149 if (mpChildrenManager != NULL)
150 mpChildrenManager->Update();
152 // Register at model as document::XEventListener.
153 if (maShapeTreeInfo.GetModelBroadcaster().is())
154 maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
155 static_cast<document::XEventListener*>(this));
157 // Beware! Here we leave the paths of the UNO API and descend into the
158 // depths of the core. Necessary for makeing the edit engine
159 // accessible.
160 Reference<text::XText> xText (mxShape, uno::UNO_QUERY);
161 if (xText.is())
163 SdrView* pView = maShapeTreeInfo.GetSdrView ();
164 const Window* pWindow = maShapeTreeInfo.GetWindow ();
165 if (pView != NULL && pWindow != NULL && mxShape.is())
167 // #107948# Determine whether shape text is empty
168 SdrObject* pSdrObject = GetSdrObjectFromXShape(mxShape);
169 if( pSdrObject )
171 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, pSdrObject );
172 OutlinerParaObject* pOutlinerParaObject = NULL;
174 if( pTextObj )
175 pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
177 bool bOwnParaObj = pOutlinerParaObject != NULL;
179 if( !pOutlinerParaObject && pSdrObject )
180 pOutlinerParaObject = pSdrObject->GetOutlinerParaObject();
182 // create AccessibleTextHelper to handle this shape's text
183 if( !pOutlinerParaObject )
185 // empty text -> use proxy edit source to delay creation of EditEngine
186 SAL_WNODEPRECATED_DECLARATIONS_PUSH
187 ::std::auto_ptr<SvxEditSource> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject, *pView, *pWindow) );
188 SAL_WNODEPRECATED_DECLARATIONS_POP
189 mpText = new AccessibleTextHelper( pEditSource );
191 else
193 // non-empty text -> use full-fledged edit source right away
194 SAL_WNODEPRECATED_DECLARATIONS_PUSH
195 ::std::auto_ptr<SvxEditSource> pEditSource( new SvxTextEditSource ( *pSdrObject, 0, *pView, *pWindow) );
196 SAL_WNODEPRECATED_DECLARATIONS_POP
197 mpText = new AccessibleTextHelper( pEditSource );
200 if( bOwnParaObj )
201 delete pOutlinerParaObject;
203 mpText->SetEventSource(this);
212 void AccessibleShape::UpdateStates (void)
214 ::utl::AccessibleStateSetHelper* pStateSet =
215 static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
216 if (pStateSet == NULL)
217 return;
219 // Set the opaque state for certain shape types when their fill style is
220 // solid.
221 bool bShapeIsOpaque = false;
222 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
224 case DRAWING_PAGE:
225 case DRAWING_RECTANGLE:
226 case DRAWING_TEXT:
228 uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
229 if (xSet.is())
233 drawing::FillStyle aFillStyle;
234 bShapeIsOpaque = ( xSet->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FillStyle"))) >>= aFillStyle)
235 && aFillStyle == drawing::FillStyle_SOLID;
237 catch (::com::sun::star::beans::UnknownPropertyException&)
239 // Ignore.
244 if (bShapeIsOpaque)
245 pStateSet->AddState (AccessibleStateType::OPAQUE);
246 else
247 pStateSet->RemoveState (AccessibleStateType::OPAQUE);
249 // Set the selected state.
250 bool bShapeIsSelected = false;
251 // XXX fix_me this has to be done with an extra interface later on
252 if ( m_pShape && maShapeTreeInfo.GetSdrView() )
254 bShapeIsSelected = maShapeTreeInfo.GetSdrView()->IsObjMarked(m_pShape) == sal_True;
257 if (bShapeIsSelected)
258 pStateSet->AddState (AccessibleStateType::SELECTED);
259 else
260 pStateSet->RemoveState (AccessibleStateType::SELECTED);
266 bool AccessibleShape::operator== (const AccessibleShape& rShape)
268 return this==&rShape;
274 sal_Bool AccessibleShape::SetState (sal_Int16 aState)
276 sal_Bool bStateHasChanged = sal_False;
278 if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
280 // Offer FOCUSED state to edit engine and detect whether the state
281 // changes.
282 sal_Bool bIsFocused = mpText->HaveFocus ();
283 mpText->SetFocus (sal_True);
284 bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
286 else
287 bStateHasChanged = AccessibleContextBase::SetState (aState);
289 return bStateHasChanged;
295 sal_Bool AccessibleShape::ResetState (sal_Int16 aState)
297 sal_Bool bStateHasChanged = sal_False;
299 if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
301 // Try to remove FOCUSED state from the edit engine and detect
302 // whether the state changes.
303 sal_Bool bIsFocused = mpText->HaveFocus ();
304 mpText->SetFocus (sal_False);
305 bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
307 else
308 bStateHasChanged = AccessibleContextBase::ResetState (aState);
310 return bStateHasChanged;
316 sal_Bool AccessibleShape::GetState (sal_Int16 aState)
318 if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
320 // Just delegate the call to the edit engine. The state is not
321 // merged into the state set.
322 return mpText->HaveFocus();
324 else
325 return AccessibleContextBase::GetState (aState);
331 //===== XAccessibleContext ==================================================
333 /** The children of this shape come from two sources: The children from
334 group or scene shapes and the paragraphs of text.
336 sal_Int32 SAL_CALL
337 AccessibleShape::getAccessibleChildCount ()
338 throw (::com::sun::star::uno::RuntimeException)
340 ThrowIfDisposed ();
341 sal_Int32 nChildCount = 0;
343 // Add the number of shapes that are children of this shape.
344 if (mpChildrenManager != NULL)
345 nChildCount += mpChildrenManager->GetChildCount ();
346 // Add the number text paragraphs.
347 if (mpText != NULL)
348 nChildCount += mpText->GetChildCount ();
350 return nChildCount;
356 /** Forward the request to the shape. Return the requested shape or throw
357 an exception for a wrong index.
359 uno::Reference<XAccessible> SAL_CALL
360 AccessibleShape::getAccessibleChild (sal_Int32 nIndex)
361 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
363 ThrowIfDisposed ();
365 uno::Reference<XAccessible> xChild;
367 // Depending on the index decide whether to delegate this call to the
368 // children manager or the edit engine.
369 if ((mpChildrenManager != NULL)
370 && (nIndex < mpChildrenManager->GetChildCount()))
372 xChild = mpChildrenManager->GetChild (nIndex);
374 else if (mpText != NULL)
376 sal_Int32 nI = nIndex;
377 if (mpChildrenManager != NULL)
378 nI -= mpChildrenManager->GetChildCount();
379 xChild = mpText->GetChild (nI);
381 else
382 throw lang::IndexOutOfBoundsException (
383 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("shape has no child with index "))
384 + rtl::OUString::valueOf(nIndex),
385 static_cast<uno::XWeak*>(this));
387 return xChild;
393 /** Return a copy of the state set.
394 Possible states are:
395 ENABLED
396 SHOWING
397 VISIBLE
399 uno::Reference<XAccessibleStateSet> SAL_CALL
400 AccessibleShape::getAccessibleStateSet (void)
401 throw (::com::sun::star::uno::RuntimeException)
403 ::osl::MutexGuard aGuard (maMutex);
404 Reference<XAccessibleStateSet> xStateSet;
406 if (rBHelper.bDisposed || mpText == NULL)
407 // Return a minimal state set that only contains the DEFUNC state.
408 xStateSet = AccessibleContextBase::getAccessibleStateSet ();
409 else
411 ::utl::AccessibleStateSetHelper* pStateSet =
412 static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
414 if (pStateSet != NULL)
416 // Merge current FOCUSED state from edit engine.
417 if (mpText != NULL)
419 if (mpText->HaveFocus())
420 pStateSet->AddState (AccessibleStateType::FOCUSED);
421 else
422 pStateSet->RemoveState (AccessibleStateType::FOCUSED);
425 // Create a copy of the state set that may be modified by the
426 // caller without affecting the current state set.
427 xStateSet = Reference<XAccessibleStateSet>(
428 new ::utl::AccessibleStateSetHelper (*pStateSet));
432 return xStateSet;
438 //===== XAccessibleComponent ================================================
440 /** The implementation below is at the moment straightforward. It iterates
441 over all children (and thereby instances all children which have not
442 been already instatiated) until a child covering the specifed point is
443 found.
444 This leaves room for improvement. For instance, first iterate only over
445 the already instantiated children and only if no match is found
446 instantiate the remaining ones.
448 uno::Reference<XAccessible > SAL_CALL
449 AccessibleShape::getAccessibleAtPoint (
450 const awt::Point& aPoint)
451 throw (uno::RuntimeException)
453 ::osl::MutexGuard aGuard (maMutex);
455 sal_Int32 nChildCount = getAccessibleChildCount ();
456 for (sal_Int32 i=0; i<nChildCount; ++i)
458 Reference<XAccessible> xChild (getAccessibleChild (i));
459 if (xChild.is())
461 Reference<XAccessibleComponent> xChildComponent (
462 xChild->getAccessibleContext(), uno::UNO_QUERY);
463 if (xChildComponent.is())
465 awt::Rectangle aBBox (xChildComponent->getBounds());
466 if ( (aPoint.X >= aBBox.X)
467 && (aPoint.Y >= aBBox.Y)
468 && (aPoint.X < aBBox.X+aBBox.Width)
469 && (aPoint.Y < aBBox.Y+aBBox.Height) )
470 return xChild;
475 // Have not found a child under the given point. Returning empty
476 // reference to indicate this.
477 return uno::Reference<XAccessible>();
483 awt::Rectangle SAL_CALL AccessibleShape::getBounds (void)
484 throw (::com::sun::star::uno::RuntimeException)
486 SolarMutexGuard aSolarGuard;
487 ::osl::MutexGuard aGuard (maMutex);
489 ThrowIfDisposed ();
490 awt::Rectangle aBoundingBox;
491 if ( mxShape.is() )
494 static const OUString sBoundRectName (
495 RTL_CONSTASCII_USTRINGPARAM("BoundRect"));
496 static const OUString sAnchorPositionName (
497 RTL_CONSTASCII_USTRINGPARAM("AnchorPosition"));
499 // Get the shape's bounding box in internal coordinates (in 100th of
500 // mm). Use the property BoundRect. Only if that is not supported ask
501 // the shape for its position and size directly.
502 Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
503 Reference<beans::XPropertySetInfo> xSetInfo;
504 bool bFoundBoundRect = false;
505 if (xSet.is())
507 xSetInfo = xSet->getPropertySetInfo ();
508 if (xSetInfo.is())
510 if (xSetInfo->hasPropertyByName (sBoundRectName))
514 uno::Any aValue = xSet->getPropertyValue (sBoundRectName);
515 aValue >>= aBoundingBox;
516 bFoundBoundRect = true;
518 catch (beans::UnknownPropertyException const&)
520 // Handled below (bFoundBoundRect stays false).
523 else
524 OSL_TRACE (" no property BoundRect");
528 // Fallback when there is no BoundRect Property.
529 if ( ! bFoundBoundRect )
531 awt::Point aPosition (mxShape->getPosition());
532 awt::Size aSize (mxShape->getSize());
533 aBoundingBox = awt::Rectangle (
534 aPosition.X, aPosition.Y,
535 aSize.Width, aSize.Height);
537 // While BoundRects have absolute positions, the position returned
538 // by XPosition::getPosition is relative. Get the anchor position
539 // (usually not (0,0) for Writer shapes).
540 if (xSetInfo.is())
542 if (xSetInfo->hasPropertyByName (sAnchorPositionName))
544 uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
545 awt::Point aAnchorPosition;
546 aPos >>= aAnchorPosition;
547 aBoundingBox.X += aAnchorPosition.X;
548 aBoundingBox.Y += aAnchorPosition.Y;
553 // Transform coordinates from internal to pixel.
554 if (maShapeTreeInfo.GetViewForwarder() == NULL)
555 throw uno::RuntimeException (::rtl::OUString (
556 RTL_CONSTASCII_USTRINGPARAM(
557 "AccessibleShape has no valid view forwarder")),
558 static_cast<uno::XWeak*>(this));
559 ::Size aPixelSize = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
560 ::Size (aBoundingBox.Width, aBoundingBox.Height));
561 ::Point aPixelPosition = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
562 ::Point (aBoundingBox.X, aBoundingBox.Y));
564 // Clip the shape's bounding box with the bounding box of its parent.
565 Reference<XAccessibleComponent> xParentComponent (
566 getAccessibleParent(), uno::UNO_QUERY);
567 if (xParentComponent.is())
569 // Make the coordinates relative to the parent.
570 awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
571 int x = aPixelPosition.getX() - aParentLocation.X;
572 int y = aPixelPosition.getY() - aParentLocation.Y;
574 // Clip with parent (with coordinates relative to itself).
575 ::Rectangle aBBox (
576 x, y, x + aPixelSize.getWidth(), y + aPixelSize.getHeight());
577 awt::Size aParentSize (xParentComponent->getSize());
578 ::Rectangle aParentBBox (0,0, aParentSize.Width, aParentSize.Height);
579 aBBox = aBBox.GetIntersection (aParentBBox);
580 aBoundingBox = awt::Rectangle (
581 aBBox.getX(),
582 aBBox.getY(),
583 aBBox.getWidth(),
584 aBBox.getHeight());
586 else
588 OSL_TRACE ("parent does not support component");
589 aBoundingBox = awt::Rectangle (
590 aPixelPosition.getX(), aPixelPosition.getY(),
591 aPixelSize.getWidth(), aPixelSize.getHeight());
595 return aBoundingBox;
601 awt::Point SAL_CALL AccessibleShape::getLocation (void)
602 throw (::com::sun::star::uno::RuntimeException)
604 ThrowIfDisposed ();
605 awt::Rectangle aBoundingBox (getBounds());
606 return awt::Point (aBoundingBox.X, aBoundingBox.Y);
612 awt::Point SAL_CALL AccessibleShape::getLocationOnScreen (void)
613 throw (::com::sun::star::uno::RuntimeException)
615 ThrowIfDisposed ();
617 // Get relative position...
618 awt::Point aLocation (getLocation ());
620 // ... and add absolute position of the parent.
621 uno::Reference<XAccessibleComponent> xParentComponent (
622 getAccessibleParent(), uno::UNO_QUERY);
623 if (xParentComponent.is())
625 awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
626 aLocation.X += aParentLocation.X;
627 aLocation.Y += aParentLocation.Y;
629 else
630 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
631 return aLocation;
637 awt::Size SAL_CALL AccessibleShape::getSize (void)
638 throw (uno::RuntimeException)
640 ThrowIfDisposed ();
641 awt::Rectangle aBoundingBox (getBounds());
642 return awt::Size (aBoundingBox.Width, aBoundingBox.Height);
648 sal_Int32 SAL_CALL AccessibleShape::getForeground (void)
649 throw (::com::sun::star::uno::RuntimeException)
651 ThrowIfDisposed ();
652 sal_Int32 nColor (0x0ffffffL);
656 uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
657 if (aSet.is())
659 uno::Any aColor;
660 aColor = aSet->getPropertyValue (OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")) );
661 aColor >>= nColor;
664 catch (const ::com::sun::star::beans::UnknownPropertyException &)
666 // Ignore exception and return default color.
668 return nColor;
674 sal_Int32 SAL_CALL AccessibleShape::getBackground (void)
675 throw (::com::sun::star::uno::RuntimeException)
677 ThrowIfDisposed ();
678 sal_Int32 nColor (0L);
682 uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
683 if (aSet.is())
685 uno::Any aColor;
686 aColor = aSet->getPropertyValue (OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")) );
687 aColor >>= nColor;
690 catch (const ::com::sun::star::beans::UnknownPropertyException &)
692 // Ignore exception and return default color.
694 return nColor;
700 //===== XAccessibleEventBroadcaster =========================================
702 void SAL_CALL AccessibleShape::addEventListener (
703 const Reference<XAccessibleEventListener >& rxListener)
704 throw (uno::RuntimeException)
706 if (rBHelper.bDisposed || rBHelper.bInDispose)
708 uno::Reference<uno::XInterface> xThis (
709 (lang::XComponent *)this, uno::UNO_QUERY);
710 rxListener->disposing (lang::EventObject (xThis));
712 else
714 AccessibleContextBase::addEventListener (rxListener);
715 if (mpText != NULL)
716 mpText->AddEventListener (rxListener);
723 void SAL_CALL AccessibleShape::removeEventListener (
724 const Reference<XAccessibleEventListener >& rxListener)
725 throw (uno::RuntimeException)
727 AccessibleContextBase::removeEventListener (rxListener);
728 if (mpText != NULL)
729 mpText->RemoveEventListener (rxListener);
735 //===== XInterface ==========================================================
737 com::sun::star::uno::Any SAL_CALL
738 AccessibleShape::queryInterface (const com::sun::star::uno::Type & rType)
739 throw (::com::sun::star::uno::RuntimeException)
741 ::com::sun::star::uno::Any aReturn = AccessibleContextBase::queryInterface (rType);
742 if ( ! aReturn.hasValue())
743 aReturn = ::cppu::queryInterface (rType,
744 static_cast<XAccessibleComponent*>(this),
745 static_cast<XAccessibleExtendedComponent*>(this),
746 static_cast<lang::XEventListener*>(this),
747 static_cast<document::XEventListener*>(this),
748 static_cast<lang::XUnoTunnel*>(this)
750 return aReturn;
756 void SAL_CALL
757 AccessibleShape::acquire (void)
758 throw ()
760 AccessibleContextBase::acquire ();
766 void SAL_CALL
767 AccessibleShape::release (void)
768 throw ()
770 AccessibleContextBase::release ();
776 //===== XServiceInfo ========================================================
778 ::rtl::OUString SAL_CALL
779 AccessibleShape::getImplementationName (void)
780 throw (::com::sun::star::uno::RuntimeException)
782 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleShape"));
788 uno::Sequence<OUString> SAL_CALL
789 AccessibleShape::getSupportedServiceNames (void)
790 throw (::com::sun::star::uno::RuntimeException)
792 ThrowIfDisposed ();
793 // Get list of supported service names from base class...
794 uno::Sequence<OUString> aServiceNames =
795 AccessibleContextBase::getSupportedServiceNames();
796 sal_Int32 nCount (aServiceNames.getLength());
798 // ...and add additional names.
799 aServiceNames.realloc (nCount + 1);
800 static const OUString sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
801 "com.sun.star.drawing.AccessibleShape"));
802 aServiceNames[nCount] = sAdditionalServiceName;
804 return aServiceNames;
811 //===== XTypeProvider ===================================================
813 uno::Sequence<uno::Type> SAL_CALL
814 AccessibleShape::getTypes (void)
815 throw (uno::RuntimeException)
817 ThrowIfDisposed ();
818 // Get list of types from the context base implementation, ...
819 uno::Sequence<uno::Type> aTypeList (AccessibleContextBase::getTypes());
820 // ... get list of types from component base implementation, ...
821 uno::Sequence<uno::Type> aComponentTypeList (AccessibleComponentBase::getTypes());
822 // ... define local types, ...
823 const uno::Type aLangEventListenerType =
824 ::getCppuType((const uno::Reference<lang::XEventListener>*)0);
825 const uno::Type aDocumentEventListenerType =
826 ::getCppuType((const uno::Reference<document::XEventListener>*)0);
827 const uno::Type aUnoTunnelType =
828 ::getCppuType((const uno::Reference<lang::XUnoTunnel>*)0);
830 // ... and merge them all into one list.
831 sal_Int32 nTypeCount (aTypeList.getLength()),
832 nComponentTypeCount (aComponentTypeList.getLength());
833 int i;
835 aTypeList.realloc (nTypeCount + nComponentTypeCount + 3);
837 for (i=0; i<nComponentTypeCount; i++)
838 aTypeList[nTypeCount + i] = aComponentTypeList[i];
840 aTypeList[nTypeCount + i++ ] = aLangEventListenerType;
841 aTypeList[nTypeCount + i++ ] = aDocumentEventListenerType;
842 aTypeList[nTypeCount + i ] = aUnoTunnelType;
844 return aTypeList;
850 //===== lang::XEventListener ================================================
852 /** Disposing calls are accepted only from the model: Just reset the
853 reference to the model in the shape tree info. Otherwise this object
854 remains functional.
856 void SAL_CALL
857 AccessibleShape::disposing (const lang::EventObject& aEvent)
858 throw (uno::RuntimeException)
860 SolarMutexGuard aSolarGuard;
861 ::osl::MutexGuard aGuard (maMutex);
865 if (aEvent.Source == maShapeTreeInfo.GetModelBroadcaster())
867 // Remove reference to model broadcaster to allow it to pass
868 // away.
869 maShapeTreeInfo.SetModelBroadcaster(NULL);
873 catch (uno::RuntimeException const&)
875 OSL_TRACE ("caught exception while disposing");
882 //===== document::XEventListener ============================================
884 void SAL_CALL
885 AccessibleShape::notifyEvent (const document::EventObject& rEventObject)
886 throw (uno::RuntimeException)
888 static const OUString sShapeModified (
889 RTL_CONSTASCII_USTRINGPARAM("ShapeModified"));
891 // First check if the event is for us.
892 uno::Reference<drawing::XShape> xShape (
893 rEventObject.Source, uno::UNO_QUERY);
894 if ( xShape.get() == mxShape.get() )
896 if (rEventObject.EventName.equals (sShapeModified))
898 // Some property of a shape has been modified. Send an event
899 // that indicates a change of the visible data to all listeners.
900 CommitChange (
901 AccessibleEventId::VISIBLE_DATA_CHANGED,
902 uno::Any(),
903 uno::Any());
905 // Name and Description may have changed. Update the local
906 // values accordingly.
907 UpdateNameAndDescription();
912 //===== lang::XUnoTunnel ================================================
914 namespace
916 class theAccessibleShapeImplementationId : public rtl::Static< UnoTunnelIdInit, theAccessibleShapeImplementationId > {};
919 const uno::Sequence< sal_Int8 >&
920 AccessibleShape::getUnoTunnelImplementationId()
921 throw()
923 return theAccessibleShapeImplementationId::get().getSeq();
926 //------------------------------------------------------------------------------
927 AccessibleShape*
928 AccessibleShape::getImplementation( const uno::Reference< uno::XInterface >& rxIFace )
929 throw()
931 uno::Reference< lang::XUnoTunnel > xTunnel( rxIFace, uno::UNO_QUERY );
932 AccessibleShape* pReturn = NULL;
934 if( xTunnel.is() )
935 pReturn = reinterpret_cast< AccessibleShape* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
937 return( pReturn );
940 //------------------------------------------------------------------------------
941 sal_Int64 SAL_CALL
942 AccessibleShape::getSomething( const uno::Sequence< sal_Int8 >& rIdentifier )
943 throw(uno::RuntimeException)
945 sal_Int64 nReturn( 0 );
947 if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) )
948 nReturn = reinterpret_cast< sal_Int64 >( this );
950 return( nReturn );
953 //===== IAccessibleViewForwarderListener ====================================
955 void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType,
956 const IAccessibleViewForwarder* pViewForwarder)
958 // Inform all listeners that the graphical representation (i.e. size
959 // and/or position) of the shape has changed.
960 CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED,
961 uno::Any(),
962 uno::Any());
964 // Tell children manager of the modified view forwarder.
965 if (mpChildrenManager != NULL)
966 mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
968 // update our children that our screen position might have changed
969 if( mpText )
970 mpText->UpdateChildren();
976 //===== protected internal ==================================================
977 /// Set this object's name if is different to the current name.
978 ::rtl::OUString
979 AccessibleShape::CreateAccessibleBaseName (void)
980 throw (::com::sun::star::uno::RuntimeException)
982 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape );
986 ::rtl::OUString
987 AccessibleShape::CreateAccessibleName (void)
988 throw (::com::sun::star::uno::RuntimeException)
990 OUString sName (CreateAccessibleBaseName());
992 // Append the shape's index to the name to disambiguate between shapes
993 // of the same type. If such an index where not given to the
994 // constructor then use the z-order instead. If even that does not exist
995 // we throw an exception.
996 long nIndex = mnIndex;
997 if (nIndex == -1)
1001 uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
1002 if (xSet.is())
1004 uno::Any aZOrder (xSet->getPropertyValue (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ZOrder")) ));
1005 aZOrder >>= nIndex;
1007 // Add one to be not zero based.
1008 nIndex += 1;
1011 catch (const beans::UnknownPropertyException &)
1013 // We throw our own exception that is a bit more informative.
1014 throw uno::RuntimeException (::rtl::OUString (
1015 RTL_CONSTASCII_USTRINGPARAM("AccessibleShape has invalid index and no ZOrder property")),
1016 static_cast<uno::XWeak*>(this));
1021 // Put a space between name and index because of Gnopernicus othewise
1022 // spells the name.
1023 sName += OUString (RTL_CONSTASCII_USTRINGPARAM(" ")) + OUString::valueOf (nIndex);
1025 return sName;
1031 ::rtl::OUString
1032 AccessibleShape::CreateAccessibleDescription (void)
1033 throw (::com::sun::star::uno::RuntimeException)
1035 DescriptionGenerator aDG (mxShape);
1036 aDG.Initialize (CreateAccessibleBaseName());
1037 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
1039 case DRAWING_3D_CUBE:
1040 case DRAWING_3D_EXTRUDE:
1041 case DRAWING_3D_LATHE:
1042 case DRAWING_3D_SPHERE:
1043 aDG.Add3DProperties ();
1044 break;
1046 case DRAWING_3D_SCENE:
1047 case DRAWING_GROUP:
1048 case DRAWING_PAGE:
1049 // No further information is appended.
1050 break;
1052 case DRAWING_CAPTION:
1053 case DRAWING_CLOSED_BEZIER:
1054 case DRAWING_CLOSED_FREEHAND:
1055 case DRAWING_ELLIPSE:
1056 case DRAWING_POLY_POLYGON:
1057 case DRAWING_POLY_POLYGON_PATH:
1058 case DRAWING_RECTANGLE:
1059 aDG.AddLineProperties ();
1060 aDG.AddFillProperties ();
1061 break;
1063 case DRAWING_CONNECTOR:
1064 case DRAWING_LINE:
1065 case DRAWING_MEASURE:
1066 case DRAWING_OPEN_BEZIER:
1067 case DRAWING_OPEN_FREEHAND:
1068 case DRAWING_POLY_LINE:
1069 case DRAWING_POLY_LINE_PATH:
1070 aDG.AddLineProperties ();
1071 break;
1073 case DRAWING_CONTROL:
1074 aDG.AddProperty (OUString(RTL_CONSTASCII_USTRINGPARAM("ControlBackground")),
1075 DescriptionGenerator::COLOR,
1076 OUString());
1077 aDG.AddProperty (OUString(RTL_CONSTASCII_USTRINGPARAM("ControlBorder")),
1078 DescriptionGenerator::INTEGER,
1079 OUString());
1080 break;
1082 case DRAWING_TEXT:
1083 aDG.AddTextProperties ();
1084 break;
1086 default:
1087 aDG.Initialize (::rtl::OUString (
1088 RTL_CONSTASCII_USTRINGPARAM("Unknown accessible shape")));
1089 uno::Reference<drawing::XShapeDescriptor> xDescriptor (mxShape, uno::UNO_QUERY);
1090 if (xDescriptor.is())
1092 aDG.AppendString (::rtl::OUString (RTL_CONSTASCII_USTRINGPARAM("service name=")));
1093 aDG.AppendString (xDescriptor->getShapeType());
1097 return aDG();
1103 uno::Reference< drawing::XShape > AccessibleShape::GetXShape()
1105 return( mxShape );
1110 // protected
1111 void AccessibleShape::disposing (void)
1113 SolarMutexGuard aSolarGuard;
1114 ::osl::MutexGuard aGuard (maMutex);
1116 // Make sure to send an event that this object looses the focus in the
1117 // case that it has the focus.
1118 ::utl::AccessibleStateSetHelper* pStateSet =
1119 static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
1120 if (pStateSet != NULL)
1121 pStateSet->RemoveState (AccessibleStateType::FOCUSED);
1123 // Unregister from broadcasters.
1124 Reference<lang::XComponent> xComponent (mxShape, uno::UNO_QUERY);
1125 if (xComponent.is())
1126 xComponent->removeEventListener (this);
1128 // Unregister from model.
1129 if (maShapeTreeInfo.GetModelBroadcaster().is())
1130 maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
1131 static_cast<document::XEventListener*>(this));
1133 // Release the child containers.
1134 if (mpChildrenManager != NULL)
1136 delete mpChildrenManager;
1137 mpChildrenManager = NULL;
1139 if (mpText != NULL)
1141 mpText->Dispose();
1142 delete mpText;
1143 mpText = NULL;
1146 // Cleanup. Remove references to objects to allow them to be
1147 // destroyed.
1148 mxShape = NULL;
1149 maShapeTreeInfo = AccessibleShapeTreeInfo();
1151 // Call base classes.
1152 AccessibleContextBase::dispose ();
1155 sal_Int32 SAL_CALL
1156 AccessibleShape::getAccessibleIndexInParent (void)
1157 throw (::com::sun::star::uno::RuntimeException)
1159 ThrowIfDisposed ();
1160 // Use a simple but slow solution for now. Optimize later.
1162 sal_Int32 nIndex = m_nIndexInParent;
1163 if ( -1 == nIndex )
1164 nIndex = AccessibleContextBase::getAccessibleIndexInParent();
1165 return nIndex;
1171 void AccessibleShape::UpdateNameAndDescription (void)
1173 // Ignore missing title, name, or description. There are fallbacks for
1174 // them.
1177 Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY_THROW);
1178 OUString sString;
1180 // Get the accessible name.
1181 sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Title")));
1182 if (!sString.isEmpty())
1184 SetAccessibleName(sString, AccessibleContextBase::FromShape);
1186 else
1188 sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Name")));
1189 if (!sString.isEmpty())
1190 SetAccessibleName(sString, AccessibleContextBase::FromShape);
1193 // Get the accessible description.
1194 sString = GetOptionalProperty(xSet, OUString(RTL_CONSTASCII_USTRINGPARAM("Description")));
1195 if (!sString.isEmpty())
1196 SetAccessibleDescription(sString, AccessibleContextBase::FromShape);
1198 catch (uno::RuntimeException&)
1206 } // end of namespace accessibility
1208 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */