fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / svx / source / accessibility / AccessibleShape.cxx
blob007bded67b08faed2cc6854f58e4be63f17ee75a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/AccessibleShape.hxx>
21 #include "svx/DescriptionGenerator.hxx"
22 #include <svx/AccessibleShapeInfo.hxx>
23 #include <com/sun/star/view/XSelectionSupplier.hpp>
24 #include <com/sun/star/accessibility/AccessibleRole.hpp>
25 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
26 #include <com/sun/star/beans/XPropertySet.hpp>
27 #include <com/sun/star/container/XChild.hpp>
28 #include <com/sun/star/drawing/XShapes.hpp>
29 #include <com/sun/star/drawing/XShapeDescriptor.hpp>
30 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
31 #include <com/sun/star/drawing/FillStyle.hpp>
32 #include <com/sun/star/text/XText.hpp>
33 #include <editeng/outlobj.hxx>
34 #include <rtl/ref.hxx>
35 #include <editeng/unoedsrc.hxx>
36 #include <svx/unoshtxt.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdmodel.hxx>
39 #include "svx/unoapi.hxx"
40 #include <com/sun/star/uno/Exception.hpp>
41 #include <svx/ShapeTypeHandler.hxx>
42 #include <svx/SvxShapeTypes.hxx>
44 #include "accessibility.hrc"
45 #include "svx/svdstr.hrc"
46 #include <svx/dialmgr.hxx>
47 #include <vcl/svapp.hxx>
48 #include <unotools/accessiblestatesethelper.hxx>
49 #include <svx/svdview.hxx>
50 #include <comphelper/servicehelper.hxx>
51 #include "AccessibleEmptyEditSource.hxx"
53 using namespace ::com::sun::star;
54 using namespace ::com::sun::star::accessibility;
55 using ::com::sun::star::uno::Reference;
57 namespace accessibility {
59 namespace {
61 OUString GetOptionalProperty (
62 const Reference<beans::XPropertySet>& rxSet,
63 const OUString& rsPropertyName)
65 OUString sValue;
67 if (rxSet.is())
69 const Reference<beans::XPropertySetInfo> xInfo (rxSet->getPropertySetInfo());
70 if ( ! xInfo.is() || xInfo->hasPropertyByName(rsPropertyName))
72 try
74 rxSet->getPropertyValue(rsPropertyName) >>= sValue;
76 catch (beans::UnknownPropertyException&)
78 // This exception should only be thrown when the property
79 // does not exits (of course) and the XPropertySetInfo is
80 // not available.
84 return sValue;
87 } // end of anonymous namespace
92 //===== internal ============================================================
94 AccessibleShape::AccessibleShape (
95 const AccessibleShapeInfo& rShapeInfo,
96 const AccessibleShapeTreeInfo& rShapeTreeInfo)
97 : AccessibleContextBase (rShapeInfo.mxParent,AccessibleRole::LIST_ITEM),
98 mpChildrenManager(NULL),
99 mxShape (rShapeInfo.mxShape),
100 maShapeTreeInfo (rShapeTreeInfo),
101 mnIndex (rShapeInfo.mnIndex),
102 m_nIndexInParent(-1),
103 mpText (NULL),
104 mpParent (rShapeInfo.mpChildrenManager)
106 m_pShape = GetSdrObjectFromXShape(mxShape);
107 UpdateNameAndDescription();
113 AccessibleShape::~AccessibleShape (void)
115 delete mpChildrenManager;
116 delete mpText;
117 OSL_TRACE ("~AccessibleShape");
119 // Unregistering from the various broadcasters should be unnecessary
120 // since this destructor would not have been called if one of the
121 // broadcasters would still hold a strong reference to this object.
127 void AccessibleShape::Init (void)
129 // Update the OPAQUE and SELECTED shape.
130 UpdateStates ();
132 // Create a children manager when this shape has children of its own.
133 Reference<drawing::XShapes> xShapes (mxShape, uno::UNO_QUERY);
134 if (xShapes.is() && xShapes->getCount() > 0)
135 mpChildrenManager = new ChildrenManager (
136 this, xShapes, maShapeTreeInfo, *this);
137 if (mpChildrenManager != NULL)
138 mpChildrenManager->Update();
140 // Register at model as document::XEventListener.
141 if (maShapeTreeInfo.GetModelBroadcaster().is())
142 maShapeTreeInfo.GetModelBroadcaster()->addEventListener (
143 static_cast<document::XEventListener*>(this));
145 // Beware! Here we leave the paths of the UNO API and descend into the
146 // depths of the core. Necessary for making the edit engine
147 // accessible.
148 Reference<text::XText> xText (mxShape, uno::UNO_QUERY);
149 if (xText.is())
151 SdrView* pView = maShapeTreeInfo.GetSdrView ();
152 const Window* pWindow = maShapeTreeInfo.GetWindow ();
153 if (pView != NULL && pWindow != NULL && mxShape.is())
155 // #107948# Determine whether shape text is empty
156 SdrObject* pSdrObject = GetSdrObjectFromXShape(mxShape);
157 if( pSdrObject )
159 SdrTextObj* pTextObj = PTR_CAST( SdrTextObj, pSdrObject );
160 OutlinerParaObject* pOutlinerParaObject = NULL;
162 if( pTextObj )
163 pOutlinerParaObject = pTextObj->GetEditOutlinerParaObject(); // Get the OutlinerParaObject if text edit is active
165 bool bOwnParaObj = pOutlinerParaObject != NULL;
167 if( !pOutlinerParaObject && pSdrObject )
168 pOutlinerParaObject = pSdrObject->GetOutlinerParaObject();
170 // create AccessibleTextHelper to handle this shape's text
171 if( !pOutlinerParaObject )
173 // empty text -> use proxy edit source to delay creation of EditEngine
174 SAL_WNODEPRECATED_DECLARATIONS_PUSH
175 ::std::auto_ptr<SvxEditSource> pEditSource( new AccessibleEmptyEditSource ( *pSdrObject, *pView, *pWindow) );
176 SAL_WNODEPRECATED_DECLARATIONS_POP
177 mpText = new AccessibleTextHelper( pEditSource );
179 else
181 // non-empty text -> use full-fledged edit source right away
182 SAL_WNODEPRECATED_DECLARATIONS_PUSH
183 ::std::auto_ptr<SvxEditSource> pEditSource( new SvxTextEditSource ( *pSdrObject, 0, *pView, *pWindow) );
184 SAL_WNODEPRECATED_DECLARATIONS_POP
185 mpText = new AccessibleTextHelper( pEditSource );
188 if( bOwnParaObj )
189 delete pOutlinerParaObject;
191 mpText->SetEventSource(this);
200 void AccessibleShape::UpdateStates (void)
202 ::utl::AccessibleStateSetHelper* pStateSet =
203 static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
204 if (pStateSet == NULL)
205 return;
207 // Set the opaque state for certain shape types when their fill style is
208 // solid.
209 bool bShapeIsOpaque = false;
210 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
212 case DRAWING_PAGE:
213 case DRAWING_RECTANGLE:
214 case DRAWING_TEXT:
216 uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
217 if (xSet.is())
221 drawing::FillStyle aFillStyle;
222 bShapeIsOpaque = ( xSet->getPropertyValue (OUString("FillStyle")) >>= aFillStyle)
223 && aFillStyle == drawing::FillStyle_SOLID;
225 catch (::com::sun::star::beans::UnknownPropertyException&)
227 // Ignore.
232 if (bShapeIsOpaque)
233 pStateSet->AddState (AccessibleStateType::OPAQUE);
234 else
235 pStateSet->RemoveState (AccessibleStateType::OPAQUE);
237 // Set the selected state.
238 bool bShapeIsSelected = false;
239 // XXX fix_me this has to be done with an extra interface later on
240 if ( m_pShape && maShapeTreeInfo.GetSdrView() )
242 bShapeIsSelected = maShapeTreeInfo.GetSdrView()->IsObjMarked(m_pShape) == sal_True;
245 if (bShapeIsSelected)
246 pStateSet->AddState (AccessibleStateType::SELECTED);
247 else
248 pStateSet->RemoveState (AccessibleStateType::SELECTED);
254 bool AccessibleShape::operator== (const AccessibleShape& rShape)
256 return this==&rShape;
262 sal_Bool AccessibleShape::SetState (sal_Int16 aState)
264 sal_Bool bStateHasChanged = sal_False;
266 if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
268 // Offer FOCUSED state to edit engine and detect whether the state
269 // changes.
270 sal_Bool bIsFocused = mpText->HaveFocus ();
271 mpText->SetFocus (sal_True);
272 bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
274 else
275 bStateHasChanged = AccessibleContextBase::SetState (aState);
277 return bStateHasChanged;
283 sal_Bool AccessibleShape::ResetState (sal_Int16 aState)
285 sal_Bool bStateHasChanged = sal_False;
287 if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
289 // Try to remove FOCUSED state from the edit engine and detect
290 // whether the state changes.
291 sal_Bool bIsFocused = mpText->HaveFocus ();
292 mpText->SetFocus (sal_False);
293 bStateHasChanged = (bIsFocused != mpText->HaveFocus ());
295 else
296 bStateHasChanged = AccessibleContextBase::ResetState (aState);
298 return bStateHasChanged;
304 sal_Bool AccessibleShape::GetState (sal_Int16 aState)
306 if (aState == AccessibleStateType::FOCUSED && mpText != NULL)
308 // Just delegate the call to the edit engine. The state is not
309 // merged into the state set.
310 return mpText->HaveFocus();
312 else
313 return AccessibleContextBase::GetState (aState);
319 //===== XAccessibleContext ==================================================
321 /** The children of this shape come from two sources: The children from
322 group or scene shapes and the paragraphs of text.
324 sal_Int32 SAL_CALL
325 AccessibleShape::getAccessibleChildCount ()
326 throw (::com::sun::star::uno::RuntimeException)
328 ThrowIfDisposed ();
329 sal_Int32 nChildCount = 0;
331 // Add the number of shapes that are children of this shape.
332 if (mpChildrenManager != NULL)
333 nChildCount += mpChildrenManager->GetChildCount ();
334 // Add the number text paragraphs.
335 if (mpText != NULL)
336 nChildCount += mpText->GetChildCount ();
338 return nChildCount;
344 /** Forward the request to the shape. Return the requested shape or throw
345 an exception for a wrong index.
347 uno::Reference<XAccessible> SAL_CALL
348 AccessibleShape::getAccessibleChild (sal_Int32 nIndex)
349 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
351 ThrowIfDisposed ();
353 uno::Reference<XAccessible> xChild;
355 // Depending on the index decide whether to delegate this call to the
356 // children manager or the edit engine.
357 if ((mpChildrenManager != NULL)
358 && (nIndex < mpChildrenManager->GetChildCount()))
360 xChild = mpChildrenManager->GetChild (nIndex);
362 else if (mpText != NULL)
364 sal_Int32 nI = nIndex;
365 if (mpChildrenManager != NULL)
366 nI -= mpChildrenManager->GetChildCount();
367 xChild = mpText->GetChild (nI);
369 else
370 throw lang::IndexOutOfBoundsException (
371 OUString("shape has no child with index ")
372 + OUString::valueOf(nIndex),
373 static_cast<uno::XWeak*>(this));
375 return xChild;
381 /** Return a copy of the state set.
382 Possible states are:
383 ENABLED
384 SHOWING
385 VISIBLE
387 uno::Reference<XAccessibleStateSet> SAL_CALL
388 AccessibleShape::getAccessibleStateSet (void)
389 throw (::com::sun::star::uno::RuntimeException)
391 ::osl::MutexGuard aGuard (maMutex);
392 Reference<XAccessibleStateSet> xStateSet;
394 if (rBHelper.bDisposed || mpText == NULL)
395 // Return a minimal state set that only contains the DEFUNC state.
396 xStateSet = AccessibleContextBase::getAccessibleStateSet ();
397 else
399 ::utl::AccessibleStateSetHelper* pStateSet =
400 static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
402 if (pStateSet != NULL)
404 // Merge current FOCUSED state from edit engine.
405 if (mpText != NULL)
407 if (mpText->HaveFocus())
408 pStateSet->AddState (AccessibleStateType::FOCUSED);
409 else
410 pStateSet->RemoveState (AccessibleStateType::FOCUSED);
413 // Create a copy of the state set that may be modified by the
414 // caller without affecting the current state set.
415 xStateSet = Reference<XAccessibleStateSet>(
416 new ::utl::AccessibleStateSetHelper (*pStateSet));
420 return xStateSet;
426 //===== XAccessibleComponent ================================================
428 /** The implementation below is at the moment straightforward. It iterates
429 over all children (and thereby instances all children which have not
430 been already instatiated) until a child covering the specifed point is
431 found.
432 This leaves room for improvement. For instance, first iterate only over
433 the already instantiated children and only if no match is found
434 instantiate the remaining ones.
436 uno::Reference<XAccessible > SAL_CALL
437 AccessibleShape::getAccessibleAtPoint (
438 const awt::Point& aPoint)
439 throw (uno::RuntimeException)
441 ::osl::MutexGuard aGuard (maMutex);
443 sal_Int32 nChildCount = getAccessibleChildCount ();
444 for (sal_Int32 i=0; i<nChildCount; ++i)
446 Reference<XAccessible> xChild (getAccessibleChild (i));
447 if (xChild.is())
449 Reference<XAccessibleComponent> xChildComponent (
450 xChild->getAccessibleContext(), uno::UNO_QUERY);
451 if (xChildComponent.is())
453 awt::Rectangle aBBox (xChildComponent->getBounds());
454 if ( (aPoint.X >= aBBox.X)
455 && (aPoint.Y >= aBBox.Y)
456 && (aPoint.X < aBBox.X+aBBox.Width)
457 && (aPoint.Y < aBBox.Y+aBBox.Height) )
458 return xChild;
463 // Have not found a child under the given point. Returning empty
464 // reference to indicate this.
465 return uno::Reference<XAccessible>();
471 awt::Rectangle SAL_CALL AccessibleShape::getBounds (void)
472 throw (::com::sun::star::uno::RuntimeException)
474 SolarMutexGuard aSolarGuard;
475 ::osl::MutexGuard aGuard (maMutex);
477 ThrowIfDisposed ();
478 awt::Rectangle aBoundingBox;
479 if ( mxShape.is() )
482 static const OUString sBoundRectName ("BoundRect");
483 static const OUString sAnchorPositionName ("AnchorPosition");
485 // Get the shape's bounding box in internal coordinates (in 100th of
486 // mm). Use the property BoundRect. Only if that is not supported ask
487 // the shape for its position and size directly.
488 Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
489 Reference<beans::XPropertySetInfo> xSetInfo;
490 bool bFoundBoundRect = false;
491 if (xSet.is())
493 xSetInfo = xSet->getPropertySetInfo ();
494 if (xSetInfo.is())
496 if (xSetInfo->hasPropertyByName (sBoundRectName))
500 uno::Any aValue = xSet->getPropertyValue (sBoundRectName);
501 aValue >>= aBoundingBox;
502 bFoundBoundRect = true;
504 catch (beans::UnknownPropertyException const&)
506 // Handled below (bFoundBoundRect stays false).
509 else
510 OSL_TRACE (" no property BoundRect");
514 // Fallback when there is no BoundRect Property.
515 if ( ! bFoundBoundRect )
517 awt::Point aPosition (mxShape->getPosition());
518 awt::Size aSize (mxShape->getSize());
519 aBoundingBox = awt::Rectangle (
520 aPosition.X, aPosition.Y,
521 aSize.Width, aSize.Height);
523 // While BoundRects have absolute positions, the position returned
524 // by XPosition::getPosition is relative. Get the anchor position
525 // (usually not (0,0) for Writer shapes).
526 if (xSetInfo.is())
528 if (xSetInfo->hasPropertyByName (sAnchorPositionName))
530 uno::Any aPos = xSet->getPropertyValue (sAnchorPositionName);
531 awt::Point aAnchorPosition;
532 aPos >>= aAnchorPosition;
533 aBoundingBox.X += aAnchorPosition.X;
534 aBoundingBox.Y += aAnchorPosition.Y;
539 // Transform coordinates from internal to pixel.
540 if (maShapeTreeInfo.GetViewForwarder() == NULL)
541 throw uno::RuntimeException (OUString (
542 "AccessibleShape has no valid view forwarder"),
543 static_cast<uno::XWeak*>(this));
544 ::Size aPixelSize = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
545 ::Size (aBoundingBox.Width, aBoundingBox.Height));
546 ::Point aPixelPosition = maShapeTreeInfo.GetViewForwarder()->LogicToPixel (
547 ::Point (aBoundingBox.X, aBoundingBox.Y));
549 // Clip the shape's bounding box with the bounding box of its parent.
550 Reference<XAccessibleComponent> xParentComponent (
551 getAccessibleParent(), uno::UNO_QUERY);
552 if (xParentComponent.is())
554 // Make the coordinates relative to the parent.
555 awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
556 int x = aPixelPosition.getX() - aParentLocation.X;
557 int y = aPixelPosition.getY() - aParentLocation.Y;
559 // Clip with parent (with coordinates relative to itself).
560 ::Rectangle aBBox (
561 x, y, x + aPixelSize.getWidth(), y + aPixelSize.getHeight());
562 awt::Size aParentSize (xParentComponent->getSize());
563 ::Rectangle aParentBBox (0,0, aParentSize.Width, aParentSize.Height);
564 aBBox = aBBox.GetIntersection (aParentBBox);
565 aBoundingBox = awt::Rectangle (
566 aBBox.getX(),
567 aBBox.getY(),
568 aBBox.getWidth(),
569 aBBox.getHeight());
571 else
573 OSL_TRACE ("parent does not support component");
574 aBoundingBox = awt::Rectangle (
575 aPixelPosition.getX(), aPixelPosition.getY(),
576 aPixelSize.getWidth(), aPixelSize.getHeight());
580 return aBoundingBox;
586 awt::Point SAL_CALL AccessibleShape::getLocation (void)
587 throw (::com::sun::star::uno::RuntimeException)
589 ThrowIfDisposed ();
590 awt::Rectangle aBoundingBox (getBounds());
591 return awt::Point (aBoundingBox.X, aBoundingBox.Y);
597 awt::Point SAL_CALL AccessibleShape::getLocationOnScreen (void)
598 throw (::com::sun::star::uno::RuntimeException)
600 ThrowIfDisposed ();
602 // Get relative position...
603 awt::Point aLocation (getLocation ());
605 // ... and add absolute position of the parent.
606 uno::Reference<XAccessibleComponent> xParentComponent (
607 getAccessibleParent(), uno::UNO_QUERY);
608 if (xParentComponent.is())
610 awt::Point aParentLocation (xParentComponent->getLocationOnScreen());
611 aLocation.X += aParentLocation.X;
612 aLocation.Y += aParentLocation.Y;
614 else
615 OSL_TRACE ("getLocation: parent does not support XAccessibleComponent");
616 return aLocation;
622 awt::Size SAL_CALL AccessibleShape::getSize (void)
623 throw (uno::RuntimeException)
625 ThrowIfDisposed ();
626 awt::Rectangle aBoundingBox (getBounds());
627 return awt::Size (aBoundingBox.Width, aBoundingBox.Height);
633 sal_Int32 SAL_CALL AccessibleShape::getForeground (void)
634 throw (::com::sun::star::uno::RuntimeException)
636 ThrowIfDisposed ();
637 sal_Int32 nColor (0x0ffffffL);
641 uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
642 if (aSet.is())
644 uno::Any aColor;
645 aColor = aSet->getPropertyValue (OUString("LineColor"));
646 aColor >>= nColor;
649 catch (const ::com::sun::star::beans::UnknownPropertyException &)
651 // Ignore exception and return default color.
653 return nColor;
659 sal_Int32 SAL_CALL AccessibleShape::getBackground (void)
660 throw (::com::sun::star::uno::RuntimeException)
662 ThrowIfDisposed ();
663 sal_Int32 nColor (0L);
667 uno::Reference<beans::XPropertySet> aSet (mxShape, uno::UNO_QUERY);
668 if (aSet.is())
670 uno::Any aColor;
671 aColor = aSet->getPropertyValue (OUString("FillColor"));
672 aColor >>= nColor;
675 catch (const ::com::sun::star::beans::UnknownPropertyException &)
677 // Ignore exception and return default color.
679 return nColor;
685 //===== XAccessibleEventBroadcaster =========================================
687 void SAL_CALL AccessibleShape::addAccessibleEventListener (
688 const Reference<XAccessibleEventListener >& rxListener)
689 throw (uno::RuntimeException)
691 if (rBHelper.bDisposed || rBHelper.bInDispose)
693 uno::Reference<uno::XInterface> xThis (
694 (lang::XComponent *)this, uno::UNO_QUERY);
695 rxListener->disposing (lang::EventObject (xThis));
697 else
699 AccessibleContextBase::addAccessibleEventListener (rxListener);
700 if (mpText != NULL)
701 mpText->AddEventListener (rxListener);
708 void SAL_CALL AccessibleShape::removeAccessibleEventListener (
709 const Reference<XAccessibleEventListener >& rxListener)
710 throw (uno::RuntimeException)
712 AccessibleContextBase::removeAccessibleEventListener (rxListener);
713 if (mpText != NULL)
714 mpText->RemoveEventListener (rxListener);
720 //===== XInterface ==========================================================
722 com::sun::star::uno::Any SAL_CALL
723 AccessibleShape::queryInterface (const com::sun::star::uno::Type & rType)
724 throw (::com::sun::star::uno::RuntimeException)
726 ::com::sun::star::uno::Any aReturn = AccessibleContextBase::queryInterface (rType);
727 if ( ! aReturn.hasValue())
728 aReturn = ::cppu::queryInterface (rType,
729 static_cast<XAccessibleComponent*>(this),
730 static_cast<XAccessibleExtendedComponent*>(this),
731 static_cast<lang::XEventListener*>(this),
732 static_cast<document::XEventListener*>(this),
733 static_cast<lang::XUnoTunnel*>(this)
735 return aReturn;
741 void SAL_CALL
742 AccessibleShape::acquire (void)
743 throw ()
745 AccessibleContextBase::acquire ();
751 void SAL_CALL
752 AccessibleShape::release (void)
753 throw ()
755 AccessibleContextBase::release ();
761 //===== XServiceInfo ========================================================
763 OUString SAL_CALL
764 AccessibleShape::getImplementationName (void)
765 throw (::com::sun::star::uno::RuntimeException)
767 return OUString("AccessibleShape");
773 uno::Sequence<OUString> SAL_CALL
774 AccessibleShape::getSupportedServiceNames (void)
775 throw (::com::sun::star::uno::RuntimeException)
777 ThrowIfDisposed ();
778 // Get list of supported service names from base class...
779 uno::Sequence<OUString> aServiceNames =
780 AccessibleContextBase::getSupportedServiceNames();
781 sal_Int32 nCount (aServiceNames.getLength());
783 // ...and add additional names.
784 aServiceNames.realloc (nCount + 1);
785 static const OUString sAdditionalServiceName ("com.sun.star.drawing.AccessibleShape");
786 aServiceNames[nCount] = sAdditionalServiceName;
788 return aServiceNames;
795 //===== XTypeProvider ===================================================
797 uno::Sequence<uno::Type> SAL_CALL
798 AccessibleShape::getTypes (void)
799 throw (uno::RuntimeException)
801 ThrowIfDisposed ();
802 // Get list of types from the context base implementation, ...
803 uno::Sequence<uno::Type> aTypeList (AccessibleContextBase::getTypes());
804 // ... get list of types from component base implementation, ...
805 uno::Sequence<uno::Type> aComponentTypeList (AccessibleComponentBase::getTypes());
806 // ... define local types, ...
807 const uno::Type aLangEventListenerType =
808 ::getCppuType((const uno::Reference<lang::XEventListener>*)0);
809 const uno::Type aDocumentEventListenerType =
810 ::getCppuType((const uno::Reference<document::XEventListener>*)0);
811 const uno::Type aUnoTunnelType =
812 ::getCppuType((const uno::Reference<lang::XUnoTunnel>*)0);
814 // ... and merge them all into one list.
815 sal_Int32 nTypeCount (aTypeList.getLength()),
816 nComponentTypeCount (aComponentTypeList.getLength());
817 int i;
819 aTypeList.realloc (nTypeCount + nComponentTypeCount + 3);
821 for (i=0; i<nComponentTypeCount; i++)
822 aTypeList[nTypeCount + i] = aComponentTypeList[i];
824 aTypeList[nTypeCount + i++ ] = aLangEventListenerType;
825 aTypeList[nTypeCount + i++ ] = aDocumentEventListenerType;
826 aTypeList[nTypeCount + i ] = aUnoTunnelType;
828 return aTypeList;
834 //===== lang::XEventListener ================================================
836 /** Disposing calls are accepted only from the model: Just reset the
837 reference to the model in the shape tree info. Otherwise this object
838 remains functional.
840 void SAL_CALL
841 AccessibleShape::disposing (const lang::EventObject& aEvent)
842 throw (uno::RuntimeException)
844 SolarMutexGuard aSolarGuard;
845 ::osl::MutexGuard aGuard (maMutex);
849 if (aEvent.Source == maShapeTreeInfo.GetModelBroadcaster())
851 // Remove reference to model broadcaster to allow it to pass
852 // away.
853 maShapeTreeInfo.SetModelBroadcaster(NULL);
857 catch (uno::RuntimeException const&)
859 OSL_TRACE ("caught exception while disposing");
866 //===== document::XEventListener ============================================
868 void SAL_CALL
869 AccessibleShape::notifyEvent (const document::EventObject& rEventObject)
870 throw (uno::RuntimeException)
872 static const OUString sShapeModified ("ShapeModified");
874 // First check if the event is for us.
875 uno::Reference<drawing::XShape> xShape (
876 rEventObject.Source, uno::UNO_QUERY);
877 if ( xShape.get() == mxShape.get() )
879 if (rEventObject.EventName.equals (sShapeModified))
881 // Some property of a shape has been modified. Send an event
882 // that indicates a change of the visible data to all listeners.
883 CommitChange (
884 AccessibleEventId::VISIBLE_DATA_CHANGED,
885 uno::Any(),
886 uno::Any());
888 // Name and Description may have changed. Update the local
889 // values accordingly.
890 UpdateNameAndDescription();
895 //===== lang::XUnoTunnel ================================================
897 namespace
899 class theAccessibleShapeImplementationId : public rtl::Static< UnoTunnelIdInit, theAccessibleShapeImplementationId > {};
902 const uno::Sequence< sal_Int8 >&
903 AccessibleShape::getUnoTunnelImplementationId()
904 throw()
906 return theAccessibleShapeImplementationId::get().getSeq();
909 //------------------------------------------------------------------------------
910 AccessibleShape*
911 AccessibleShape::getImplementation( const uno::Reference< uno::XInterface >& rxIFace )
912 throw()
914 uno::Reference< lang::XUnoTunnel > xTunnel( rxIFace, uno::UNO_QUERY );
915 AccessibleShape* pReturn = NULL;
917 if( xTunnel.is() )
918 pReturn = reinterpret_cast< AccessibleShape* >( xTunnel->getSomething( getUnoTunnelImplementationId() ) );
920 return( pReturn );
923 //------------------------------------------------------------------------------
924 sal_Int64 SAL_CALL
925 AccessibleShape::getSomething( const uno::Sequence< sal_Int8 >& rIdentifier )
926 throw(uno::RuntimeException)
928 sal_Int64 nReturn( 0 );
930 if( ( rIdentifier.getLength() == 16 ) && ( 0 == memcmp( getUnoTunnelImplementationId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) )
931 nReturn = reinterpret_cast< sal_Int64 >( this );
933 return( nReturn );
936 //===== IAccessibleViewForwarderListener ====================================
938 void AccessibleShape::ViewForwarderChanged (ChangeType aChangeType,
939 const IAccessibleViewForwarder* pViewForwarder)
941 // Inform all listeners that the graphical representation (i.e. size
942 // and/or position) of the shape has changed.
943 CommitChange (AccessibleEventId::VISIBLE_DATA_CHANGED,
944 uno::Any(),
945 uno::Any());
947 // Tell children manager of the modified view forwarder.
948 if (mpChildrenManager != NULL)
949 mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
951 // update our children that our screen position might have changed
952 if( mpText )
953 mpText->UpdateChildren();
959 //===== protected internal ==================================================
960 /// Set this object's name if is different to the current name.
961 OUString
962 AccessibleShape::CreateAccessibleBaseName (void)
963 throw (::com::sun::star::uno::RuntimeException)
965 return ShapeTypeHandler::CreateAccessibleBaseName( mxShape );
969 OUString
970 AccessibleShape::CreateAccessibleName (void)
971 throw (::com::sun::star::uno::RuntimeException)
973 OUString sName (CreateAccessibleBaseName());
975 // Append the shape's index to the name to disambiguate between shapes
976 // of the same type. If such an index where not given to the
977 // constructor then use the z-order instead. If even that does not exist
978 // we throw an exception.
979 long nIndex = mnIndex;
980 if (nIndex == -1)
984 uno::Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY);
985 if (xSet.is())
987 uno::Any aZOrder (xSet->getPropertyValue (OUString("ZOrder")));
988 aZOrder >>= nIndex;
990 // Add one to be not zero based.
991 nIndex += 1;
994 catch (const beans::UnknownPropertyException &)
996 // We throw our own exception that is a bit more informative.
997 throw uno::RuntimeException (OUString (
998 "AccessibleShape has invalid index and no ZOrder property"),
999 static_cast<uno::XWeak*>(this));
1004 // Put a space between name and index because of Gnopernicus othewise
1005 // spells the name.
1006 sName += " " + OUString::valueOf (nIndex);
1008 return sName;
1014 OUString
1015 AccessibleShape::CreateAccessibleDescription (void)
1016 throw (::com::sun::star::uno::RuntimeException)
1018 DescriptionGenerator aDG (mxShape);
1019 aDG.Initialize (CreateAccessibleBaseName());
1020 switch (ShapeTypeHandler::Instance().GetTypeId (mxShape))
1022 case DRAWING_3D_CUBE:
1023 case DRAWING_3D_EXTRUDE:
1024 case DRAWING_3D_LATHE:
1025 case DRAWING_3D_SPHERE:
1026 aDG.Add3DProperties ();
1027 break;
1029 case DRAWING_3D_SCENE:
1030 case DRAWING_GROUP:
1031 case DRAWING_PAGE:
1032 // No further information is appended.
1033 break;
1035 case DRAWING_CAPTION:
1036 case DRAWING_CLOSED_BEZIER:
1037 case DRAWING_CLOSED_FREEHAND:
1038 case DRAWING_ELLIPSE:
1039 case DRAWING_POLY_POLYGON:
1040 case DRAWING_POLY_POLYGON_PATH:
1041 case DRAWING_RECTANGLE:
1042 aDG.AddLineProperties ();
1043 aDG.AddFillProperties ();
1044 break;
1046 case DRAWING_CONNECTOR:
1047 case DRAWING_LINE:
1048 case DRAWING_MEASURE:
1049 case DRAWING_OPEN_BEZIER:
1050 case DRAWING_OPEN_FREEHAND:
1051 case DRAWING_POLY_LINE:
1052 case DRAWING_POLY_LINE_PATH:
1053 aDG.AddLineProperties ();
1054 break;
1056 case DRAWING_CONTROL:
1057 aDG.AddProperty ("ControlBackground", DescriptionGenerator::COLOR, "");
1058 aDG.AddProperty ("ControlBorder", DescriptionGenerator::INTEGER, "");
1059 break;
1061 case DRAWING_TEXT:
1062 aDG.AddTextProperties ();
1063 break;
1065 default:
1066 aDG.Initialize ("Unknown accessible shape");
1067 uno::Reference<drawing::XShapeDescriptor> xDescriptor (mxShape, uno::UNO_QUERY);
1068 if (xDescriptor.is())
1070 aDG.AppendString ("service name=");
1071 aDG.AppendString (xDescriptor->getShapeType());
1075 return aDG();
1081 uno::Reference< drawing::XShape > AccessibleShape::GetXShape()
1083 return( mxShape );
1088 // protected
1089 void AccessibleShape::disposing (void)
1091 SolarMutexGuard aSolarGuard;
1092 ::osl::MutexGuard aGuard (maMutex);
1094 // Make sure to send an event that this object looses the focus in the
1095 // case that it has the focus.
1096 ::utl::AccessibleStateSetHelper* pStateSet =
1097 static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
1098 if (pStateSet != NULL)
1099 pStateSet->RemoveState (AccessibleStateType::FOCUSED);
1101 // Unregister from broadcasters.
1102 Reference<lang::XComponent> xComponent (mxShape, uno::UNO_QUERY);
1103 if (xComponent.is())
1104 xComponent->removeEventListener (this);
1106 // Unregister from model.
1107 if (maShapeTreeInfo.GetModelBroadcaster().is())
1108 maShapeTreeInfo.GetModelBroadcaster()->removeEventListener (
1109 static_cast<document::XEventListener*>(this));
1111 // Release the child containers.
1112 if (mpChildrenManager != NULL)
1114 delete mpChildrenManager;
1115 mpChildrenManager = NULL;
1117 if (mpText != NULL)
1119 mpText->Dispose();
1120 delete mpText;
1121 mpText = NULL;
1124 // Cleanup. Remove references to objects to allow them to be
1125 // destroyed.
1126 mxShape = NULL;
1127 maShapeTreeInfo = AccessibleShapeTreeInfo();
1129 // Call base classes.
1130 AccessibleContextBase::dispose ();
1133 sal_Int32 SAL_CALL
1134 AccessibleShape::getAccessibleIndexInParent (void)
1135 throw (::com::sun::star::uno::RuntimeException)
1137 ThrowIfDisposed ();
1138 // Use a simple but slow solution for now. Optimize later.
1140 sal_Int32 nIndex = m_nIndexInParent;
1141 if ( -1 == nIndex )
1142 nIndex = AccessibleContextBase::getAccessibleIndexInParent();
1143 return nIndex;
1149 void AccessibleShape::UpdateNameAndDescription (void)
1151 // Ignore missing title, name, or description. There are fallbacks for
1152 // them.
1155 Reference<beans::XPropertySet> xSet (mxShape, uno::UNO_QUERY_THROW);
1156 OUString sString;
1158 // Get the accessible name.
1159 sString = GetOptionalProperty(xSet, "Title");
1160 if (!sString.isEmpty())
1162 SetAccessibleName(sString, AccessibleContextBase::FromShape);
1164 else
1166 sString = GetOptionalProperty(xSet, "Name");
1167 if (!sString.isEmpty())
1168 SetAccessibleName(sString, AccessibleContextBase::FromShape);
1171 // Get the accessible description.
1172 sString = GetOptionalProperty(xSet, "Description");
1173 if (!sString.isEmpty())
1174 SetAccessibleDescription(sString, AccessibleContextBase::FromShape);
1176 catch (uno::RuntimeException&)
1181 } // end of namespace accessibility
1183 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */