merge the formfield patch from ooo-build
[ooovba.git] / sd / source / ui / accessibility / AccessibleDrawDocumentView.cxx
blob13e7dfd4fc8eb8968245f7172ec4cad6dce69a15
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: AccessibleDrawDocumentView.cxx,v $
10 * $Revision: 1.30 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sd.hxx"
33 #include "AccessibleDrawDocumentView.hxx"
34 #include <com/sun/star/drawing/XDrawPage.hpp>
35 #include <com/sun/star/drawing/XDrawView.hpp>
36 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
37 #include <com/sun/star/drawing/XShapes.hpp>
38 #include <com/sun/star/container/XChild.hpp>
39 #include <com/sun/star/frame/XController.hpp>
40 #include <com/sun/star/frame/XFrame.hpp>
41 #include <com/sun/star/document/XEventBroadcaster.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #ifndef _COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_
44 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
45 #endif
46 #ifndef _COM_SUN_STAR_ACCESSIBLE_ACCESSIBLESTATETYPE_HPP_
47 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
48 #endif
49 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
50 #ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #endif
53 #include <rtl/ustring.h>
54 #ifndef _SFXFRAME_HXX
55 #include<sfx2/viewfrm.hxx>
56 #endif
58 #include <svx/AccessibleShape.hxx>
60 #include <svx/svdobj.hxx>
61 #include <svx/svdmodel.hxx>
62 #include <svx/unoapi.hxx>
63 #include <svx/unoshcol.hxx>
64 #include <toolkit/helper/vclunohelper.hxx>
65 #include "Window.hxx"
66 #include <vcl/svapp.hxx>
69 #include "ViewShell.hxx"
70 #include "View.hxx"
71 #include <memory>
73 #include "accessibility.hrc"
74 #include "sdresid.hxx"
75 #include <vos/mutex.hxx>
77 using ::rtl::OUString;
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::uno;
80 using namespace ::com::sun::star::accessibility;
82 class SfxViewFrame;
84 #define A2S(pString) (::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(pString)))
86 namespace accessibility {
89 //===== internal ============================================================
91 AccessibleDrawDocumentView::AccessibleDrawDocumentView (
92 ::sd::Window* pSdWindow,
93 ::sd::ViewShell* pViewShell,
94 const uno::Reference<frame::XController>& rxController,
95 const uno::Reference<XAccessible>& rxParent)
96 : AccessibleDocumentViewBase (pSdWindow, pViewShell, rxController, rxParent),
97 mpChildrenManager (NULL)
99 OSL_TRACE ("AccessibleDrawDocumentView");
100 UpdateAccessibleName();
106 AccessibleDrawDocumentView::~AccessibleDrawDocumentView (void)
108 OSL_TRACE ("~AccessibleDrawDocumentView");
109 DBG_ASSERT (rBHelper.bDisposed || rBHelper.bInDispose,
110 "~AccessibleDrawDocumentView: object has not been disposed");
116 void AccessibleDrawDocumentView::Init (void)
118 AccessibleDocumentViewBase::Init ();
120 // Determine the list of shapes on the current page.
121 uno::Reference<drawing::XShapes> xShapeList;
122 uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
123 if (xView.is())
124 xShapeList = uno::Reference<drawing::XShapes> (
125 xView->getCurrentPage(), uno::UNO_QUERY);
127 // Create the children manager.
128 mpChildrenManager = new ChildrenManager(this, xShapeList, maShapeTreeInfo, *this);
129 if (mpChildrenManager != NULL)
131 // Create the page shape and initialize it. The shape is acquired
132 // before initialization and released after transferring ownership
133 // to the children manager to prevent premature disposing of the
134 // shape.
135 AccessiblePageShape* pPage = CreateDrawPageShape();
136 if (pPage != NULL)
138 pPage->acquire();
139 pPage->Init();
140 mpChildrenManager->AddAccessibleShape (
141 std::auto_ptr<AccessibleShape>(pPage));
142 pPage->release();
143 mpChildrenManager->Update ();
145 mpChildrenManager->UpdateSelection ();
152 void AccessibleDrawDocumentView::ViewForwarderChanged (ChangeType aChangeType,
153 const IAccessibleViewForwarder* pViewForwarder)
155 AccessibleDocumentViewBase::ViewForwarderChanged (aChangeType, pViewForwarder);
156 if (mpChildrenManager != NULL)
157 mpChildrenManager->ViewForwarderChanged (aChangeType, pViewForwarder);
163 /** The page shape is created on every call at the moment (provided that
164 every thing goes well).
166 AccessiblePageShape* AccessibleDrawDocumentView::CreateDrawPageShape (void)
168 AccessiblePageShape* pShape = NULL;
170 // Create a shape that represents the actual draw page.
171 uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
172 if (xView.is())
174 uno::Reference<beans::XPropertySet> xSet (
175 uno::Reference<beans::XPropertySet> (xView->getCurrentPage(), uno::UNO_QUERY));
176 if (xSet.is())
178 // Create a rectangle shape that will represent the draw page.
179 uno::Reference<lang::XMultiServiceFactory> xFactory (mxModel, uno::UNO_QUERY);
180 uno::Reference<drawing::XShape> xRectangle;
181 if (xFactory.is())
182 xRectangle = uno::Reference<drawing::XShape>(xFactory->createInstance (
183 OUString (RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.RectangleShape"))),
184 uno::UNO_QUERY);
186 // Set the shape's size and position.
187 if (xRectangle.is())
189 uno::Any aValue;
190 awt::Point aPosition;
191 awt::Size aSize;
193 // Set size and position of the shape to those of the draw
194 // page.
195 aValue = xSet->getPropertyValue (
196 OUString (RTL_CONSTASCII_USTRINGPARAM("BorderLeft")));
197 aValue >>= aPosition.X;
198 aValue = xSet->getPropertyValue (
199 OUString (RTL_CONSTASCII_USTRINGPARAM("BorderTop")));
200 aValue >>= aPosition.Y;
201 xRectangle->setPosition (aPosition);
203 aValue = xSet->getPropertyValue (
204 OUString (RTL_CONSTASCII_USTRINGPARAM("Width")));
205 aValue >>= aSize.Width;
206 aValue = xSet->getPropertyValue (
207 OUString (RTL_CONSTASCII_USTRINGPARAM("Height")));
208 aValue >>= aSize.Height;
209 xRectangle->setSize (aSize);
211 // Create the accessible object for the shape and
212 // initialize it.
213 pShape = new AccessiblePageShape (
214 xView->getCurrentPage(), this, maShapeTreeInfo);
218 return pShape;
224 //===== XAccessibleContext ==================================================
226 sal_Int32 SAL_CALL
227 AccessibleDrawDocumentView::getAccessibleChildCount (void)
228 throw (uno::RuntimeException)
230 ThrowIfDisposed ();
232 long mpChildCount = AccessibleDocumentViewBase::getAccessibleChildCount();
234 // Forward request to children manager.
235 if (mpChildrenManager != NULL)
236 mpChildCount += mpChildrenManager->GetChildCount ();
238 return mpChildCount;
244 uno::Reference<XAccessible> SAL_CALL
245 AccessibleDrawDocumentView::getAccessibleChild (sal_Int32 nIndex)
246 throw (::com::sun::star::uno::RuntimeException)
248 ThrowIfDisposed ();
250 ::osl::ClearableMutexGuard aGuard (maMutex);
252 // Take care of children of the base class.
253 sal_Int32 nCount = AccessibleDocumentViewBase::getAccessibleChildCount();
254 if (nCount > 0)
256 if (nIndex < nCount)
257 return AccessibleDocumentViewBase::getAccessibleChild(nIndex);
258 else
259 nIndex -= nCount;
262 // Create a copy of the pointer to the children manager and release the
263 // mutex before calling any of its methods.
264 ChildrenManager* pChildrenManager = mpChildrenManager;
265 aGuard.clear();
267 // Forward request to children manager.
268 if (pChildrenManager != NULL)
270 return pChildrenManager->GetChild (nIndex);
272 else
273 throw lang::IndexOutOfBoundsException (
274 ::rtl::OUString::createFromAscii ("no accessible child with index ")
275 + rtl::OUString::valueOf(nIndex),
276 static_cast<uno::XWeak*>(this));
282 //===== XEventListener ======================================================
284 void SAL_CALL
285 AccessibleDrawDocumentView::disposing (const lang::EventObject& rEventObject)
286 throw (::com::sun::star::uno::RuntimeException)
288 ThrowIfDisposed ();
290 AccessibleDocumentViewBase::disposing (rEventObject);
291 if (rEventObject.Source == mxModel)
293 ::osl::Guard< ::osl::Mutex> aGuard (::osl::Mutex::getGlobalMutex());
294 // maShapeTreeInfo has been modified in base class.
295 if (mpChildrenManager != NULL)
296 mpChildrenManager->SetInfo (maShapeTreeInfo);
303 //===== XPropertyChangeListener =============================================
305 void SAL_CALL
306 AccessibleDrawDocumentView::propertyChange (const beans::PropertyChangeEvent& rEventObject)
307 throw (::com::sun::star::uno::RuntimeException)
309 ThrowIfDisposed ();
311 AccessibleDocumentViewBase::propertyChange (rEventObject);
313 OSL_TRACE ("AccessibleDrawDocumentView::propertyChange");
314 if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("CurrentPage")))
316 OSL_TRACE (" current page changed");
318 // Update the accessible name to reflect the current slide.
319 UpdateAccessibleName();
321 // The current page changed. Update the children manager accordingly.
322 uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
323 if (xView.is() && mpChildrenManager!=NULL)
325 // Inform the children manager to forget all children and give
326 // him the new ones.
327 mpChildrenManager->ClearAccessibleShapeList ();
328 mpChildrenManager->SetShapeList (uno::Reference<drawing::XShapes> (
329 xView->getCurrentPage(), uno::UNO_QUERY));
331 // Create the page shape and initialize it. The shape is
332 // acquired before initialization and released after
333 // transferring ownership to the children manager to prevent
334 // premature disposing of the shape.
335 AccessiblePageShape* pPage = CreateDrawPageShape ();
336 if (pPage != NULL)
338 pPage->acquire();
339 pPage->Init();
340 mpChildrenManager->AddAccessibleShape (
341 std::auto_ptr<AccessibleShape>(pPage));
342 mpChildrenManager->Update (false);
343 pPage->release();
346 else
347 OSL_TRACE ("View invalid");
349 else if (rEventObject.PropertyName == OUString (RTL_CONSTASCII_USTRINGPARAM("VisibleArea")))
351 OSL_TRACE (" visible area changed");
352 if (mpChildrenManager != NULL)
353 mpChildrenManager->ViewForwarderChanged (
354 IAccessibleViewForwarderListener::VISIBLE_AREA,
355 &maViewForwarder);
357 else
359 OSL_TRACE (" unhandled");
361 OSL_TRACE (" done");
366 //===== XServiceInfo ========================================================
368 ::rtl::OUString SAL_CALL
369 AccessibleDrawDocumentView::getImplementationName (void)
370 throw (::com::sun::star::uno::RuntimeException)
372 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
373 "AccessibleDrawDocumentView"));
379 ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL
380 AccessibleDrawDocumentView::getSupportedServiceNames (void)
381 throw (::com::sun::star::uno::RuntimeException)
383 ThrowIfDisposed();
384 // Get list of supported service names from base class...
385 uno::Sequence<OUString> aServiceNames =
386 AccessibleDocumentViewBase::getSupportedServiceNames();
387 sal_Int32 nCount (aServiceNames.getLength());
389 // ...and add additional names.
390 aServiceNames.realloc (nCount + 1);
391 static const OUString sAdditionalServiceName (RTL_CONSTASCII_USTRINGPARAM(
392 "com.sun.star.drawing.AccessibleDrawDocumentView"));
393 aServiceNames[nCount] = sAdditionalServiceName;
395 return aServiceNames;
401 /// Create a name for this view.
402 ::rtl::OUString
403 AccessibleDrawDocumentView::CreateAccessibleName (void)
404 throw (::com::sun::star::uno::RuntimeException)
406 rtl::OUString sName;
408 uno::Reference<lang::XServiceInfo> xInfo (mxController, uno::UNO_QUERY);
409 if (xInfo.is())
411 uno::Sequence< ::rtl::OUString > aServices( xInfo->getSupportedServiceNames() );
412 OUString sFirstService = aServices[0];
413 if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
415 if( aServices.getLength() >= 2 &&
416 aServices[1] == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationView")))
418 ::vos::OGuard aGuard( Application::GetSolarMutex() );
420 sName = String( SdResId(SID_SD_A11Y_I_DRAWVIEW_N) );
422 else
424 ::vos::OGuard aGuard( Application::GetSolarMutex() );
426 sName = String( SdResId(SID_SD_A11Y_D_DRAWVIEW_N) );
429 else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesView")))
431 ::vos::OGuard aGuard( Application::GetSolarMutex() );
433 sName = String( SdResId(SID_SD_A11Y_I_NOTESVIEW_N) );
435 else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.HandoutView")))
437 ::vos::OGuard aGuard( Application::GetSolarMutex() );
439 sName = String( SdResId(SID_SD_A11Y_I_HANDOUTVIEW_N) );
441 else
443 sName = sFirstService;
446 else
448 sName = OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleDrawDocumentView"));
450 return sName;
456 /** Create a description for this view. Use the model's description or URL
457 if a description is not available.
459 ::rtl::OUString
460 AccessibleDrawDocumentView::CreateAccessibleDescription (void)
461 throw (::com::sun::star::uno::RuntimeException)
463 rtl::OUString sDescription;
465 uno::Reference<lang::XServiceInfo> xInfo (mxController, uno::UNO_QUERY);
466 if (xInfo.is())
468 uno::Sequence< ::rtl::OUString > aServices( xInfo->getSupportedServiceNames() );
469 OUString sFirstService = aServices[0];
470 if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView")))
472 if( aServices.getLength() >= 2 &&
473 aServices[1] == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.PresentationView")))
475 ::vos::OGuard aGuard( Application::GetSolarMutex() );
477 sDescription = String( SdResId(SID_SD_A11Y_I_DRAWVIEW_D) );
479 else
481 ::vos::OGuard aGuard( Application::GetSolarMutex() );
483 sDescription = String( SdResId(SID_SD_A11Y_D_DRAWVIEW_D) );
486 else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.NotesView")))
488 ::vos::OGuard aGuard( Application::GetSolarMutex() );
490 sDescription = String( SdResId(SID_SD_A11Y_I_NOTESVIEW_D) );
492 else if (sFirstService == OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.presentation.HandoutView")))
494 ::vos::OGuard aGuard( Application::GetSolarMutex() );
496 sDescription = String( SdResId(SID_SD_A11Y_I_HANDOUTVIEW_D) );
498 else
500 sDescription = sFirstService;
503 else
505 sDescription = OUString(RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document"));
507 return sDescription;
513 /** Return selection state of specified child
515 sal_Bool
516 AccessibleDrawDocumentView::implIsSelected( sal_Int32 nAccessibleChildIndex )
517 throw (uno::RuntimeException)
519 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
520 uno::Reference< view::XSelectionSupplier > xSel( mxController, uno::UNO_QUERY );
521 sal_Bool bRet = sal_False;
523 OSL_ENSURE( 0 <= nAccessibleChildIndex, "AccessibleDrawDocumentView::implIsSelected: invalid index!" );
525 if( xSel.is() && ( 0 <= nAccessibleChildIndex ) )
527 uno::Any aAny( xSel->getSelection() );
528 uno::Reference< drawing::XShapes > xShapes;
530 aAny >>= xShapes;
532 if( xShapes.is() )
534 AccessibleShape* pAcc = AccessibleShape::getImplementation( getAccessibleChild( nAccessibleChildIndex ) );
536 if( pAcc )
538 uno::Reference< drawing::XShape > xShape( pAcc->GetXShape() );
540 if( xShape.is() )
542 for( sal_Int32 i = 0, nCount = xShapes->getCount(); ( i < nCount ) && !bRet; ++i )
543 if( xShapes->getByIndex( i ) == xShape )
544 bRet = sal_True;
550 return( bRet );
556 /** Select or delselect the specified shapes. The corresponding accessible
557 shapes are notified over the selection change listeners registered with
558 the XSelectionSupplier of the controller.
560 void
561 AccessibleDrawDocumentView::implSelect( sal_Int32 nAccessibleChildIndex, sal_Bool bSelect )
562 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
564 const vos::OGuard aSolarGuard( Application::GetSolarMutex() );
565 uno::Reference< view::XSelectionSupplier > xSel( mxController, uno::UNO_QUERY );
566 AccessibleShape* pAccessibleChild;
568 if( xSel.is() )
570 uno::Any aAny;
572 if( ACCESSIBLE_SELECTION_CHILD_ALL == nAccessibleChildIndex )
574 // Select or deselect all children.
576 if( !bSelect )
577 xSel->select( aAny );
578 else
580 uno::Reference< drawing::XShapes > xShapes( new SvxShapeCollection() );
582 for(sal_Int32 i = 0, nCount = getAccessibleChildCount(); i < nCount; ++i )
584 AccessibleShape* pAcc = AccessibleShape::getImplementation( getAccessibleChild( i ) );
586 if( pAcc && pAcc->GetXShape().is() )
588 xShapes->add( pAcc->GetXShape() );
589 pAccessibleChild = pAcc;
593 if( xShapes->getCount() )
595 aAny <<= xShapes;
596 xSel->select( aAny );
600 else if( nAccessibleChildIndex >= 0 )
602 // Select or deselect only the child with index
603 // nAccessibleChildIndex.
605 AccessibleShape* pAcc = AccessibleShape::getImplementation(
606 getAccessibleChild( nAccessibleChildIndex ));
607 pAccessibleChild = pAcc;
609 // Add or remove the shape that is made accessible from the
610 // selection of the controller.
611 if( pAcc )
613 uno::Reference< drawing::XShape > xShape( pAcc->GetXShape() );
615 if( xShape.is() )
617 uno::Reference< drawing::XShapes > xShapes;
618 sal_Bool bFound = sal_False;
620 aAny = xSel->getSelection();
621 aAny >>= xShapes;
623 // Search shape to be selected in current selection.
624 if (xShapes.is())
626 sal_Int32 nCount = xShapes->getCount();
627 for (sal_Int32 i=0; ( i < nCount ) && !bFound; ++i )
628 if( xShapes->getByIndex( i ) == xShape )
629 bFound = sal_True;
631 else
632 // Create an empty selection to add the shape to.
633 xShapes = new SvxShapeCollection();
635 // Update the selection.
636 if( !bFound && bSelect )
637 xShapes->add( xShape );
638 else if( bFound && !bSelect )
639 xShapes->remove( xShape );
641 aAny <<= xShapes;
642 xSel->select( aAny );
652 void AccessibleDrawDocumentView::Activated (void)
654 if (mpChildrenManager != NULL)
656 mpChildrenManager->UpdateSelection();
657 // When none of the children has the focus then claim it for the
658 // view.
659 if ( ! mpChildrenManager->HasFocus())
660 SetState (AccessibleStateType::FOCUSED);
661 else
662 ResetState (AccessibleStateType::FOCUSED);
669 void AccessibleDrawDocumentView::Deactivated (void)
671 if (mpChildrenManager != NULL)
672 mpChildrenManager->RemoveFocus();
673 ResetState (AccessibleStateType::FOCUSED);
679 void AccessibleDrawDocumentView::impl_dispose (void)
681 if (mpChildrenManager != NULL)
683 delete mpChildrenManager;
684 mpChildrenManager = NULL;
687 AccessibleDocumentViewBase::impl_dispose();
692 /** This method is called from the component helper base class while
693 disposing.
695 void SAL_CALL AccessibleDrawDocumentView::disposing (void)
698 // Release resources.
699 if (mpChildrenManager != NULL)
701 delete mpChildrenManager;
702 mpChildrenManager = NULL;
705 // Forward call to base classes.
706 AccessibleDocumentViewBase::disposing ();
712 void AccessibleDrawDocumentView::UpdateAccessibleName (void)
714 OUString sNewName (CreateAccessibleName());
715 sNewName += A2S(": ");
717 // Add the number of the current slide.
718 uno::Reference<drawing::XDrawView> xView (mxController, uno::UNO_QUERY);
719 if (xView.is())
721 uno::Reference<beans::XPropertySet> xProperties (xView->getCurrentPage(), UNO_QUERY);
722 if (xProperties.is())
725 sal_Int16 nPageNumber (0);
726 if (xProperties->getPropertyValue(A2S("Number")) >>= nPageNumber)
728 sNewName += OUString::valueOf(sal_Int32(nPageNumber));
731 catch (beans::UnknownPropertyException&)
736 // Add the number of pages/slides.
737 Reference<drawing::XDrawPagesSupplier> xPagesSupplier (mxModel, UNO_QUERY);
738 if (xPagesSupplier.is())
740 Reference<container::XIndexAccess> xPages (xPagesSupplier->getDrawPages(), UNO_QUERY);
741 if (xPages.is())
743 sNewName += A2S(" / ");
744 sNewName += OUString::valueOf(xPages->getCount());
748 SetAccessibleName (sNewName, AutomaticallyCreated);
754 } // end of namespace accessibility