/************************************************************************* * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: AccessibleDocumentViewBase.cxx,v $ * * $Revision: 1.23 $ * * last change: $Author: rt $ $Date: 2005-09-09 03:25:51 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. * * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2005 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * ************************************************************************/ #ifndef _SD_ACCESSIBILITY_ACCESSIBLE_DOCUMENT_VIEW_BASE_HXX #include "AccessibleDocumentViewBase.hxx" #endif #ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGE_HPP_ #include #endif #ifndef _COM_SUN_STAR_DRAWING_XDRAWVIEW_HPP_ #include #endif #ifndef _COM_SUN_STAR_DRAWING_XSHAPES_HPP_ #include #endif #ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_ #include #endif #ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_ #include #endif #ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_ #include #endif #ifndef _COM_SUN_STAR_DOCUMENT_XDOCUMENTINFOSUPPLIER_HPP_ #include #endif #ifndef _COM_SUN_STAR_DOCUMENT_XEVENTBROADCASTER_HPP_ #include #endif #ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_ #include #endif #ifndef _COM_SUN_STAR_ACCESSIBLE_ACCESSIBLEEVENTID_HPP_ #include #endif #ifndef _COM_SUN_STAR_LANG_INDEXOUTOFBOUNDSEXCEPTION_HPP_ #include #endif #ifndef _COM_SUN_STAR_LANG_XMULSTISERVICEFACTORY_HPP_ #include #endif #ifndef _RTL_USTRING_H_ #include #endif #ifndef _SFXFRAME_HXX #include #endif #include #include #include #include #include #ifndef SD_WINDOW_HXX #include "Window.hxx" #endif #include #ifndef SD_VIEW_SHELL_HXX #include "ViewShell.hxx" #endif #ifndef SD_VIEW_HXX #include "View.hxx" #endif #include using namespace ::rtl; using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; using ::com::sun::star::uno::Reference; class SfxViewFrame; namespace accessibility { static SfxViewFrame* mpViewFrame = NULL; //===== internal ============================================================ AccessibleDocumentViewBase::AccessibleDocumentViewBase ( ::sd::Window* pSdWindow, ::sd::ViewShell* pViewShell, const uno::Reference& rxController, const uno::Reference& rxParent) : AccessibleContextBase (rxParent, AccessibleRole::DOCUMENT), mpWindow (pSdWindow), mxController (rxController), mxModel (NULL), maViewForwarder ( static_cast(pViewShell->GetView()), *static_cast(pSdWindow)) { if (mxController.is()) mxModel = mxController->getModel(); // Fill the shape tree info. maShapeTreeInfo.SetModelBroadcaster ( uno::Reference( mxModel, uno::UNO_QUERY)); maShapeTreeInfo.SetController (mxController); maShapeTreeInfo.SetSdrView (pViewShell->GetView()); maShapeTreeInfo.SetWindow (pSdWindow); maShapeTreeInfo.SetViewForwarder (&maViewForwarder); mxWindow = ::VCLUnoHelper::GetInterface (pSdWindow); mpViewFrame = pViewShell->GetViewFrame(); } AccessibleDocumentViewBase::~AccessibleDocumentViewBase (void) { // At this place we should be disposed. You may want to add a // corresponding assertion into the destructor of a derived class. } void AccessibleDocumentViewBase::Init (void) { // Finish the initialization of the shape tree info container. maShapeTreeInfo.SetDocumentWindow (this); // Register as window listener to stay up to date with its size and // position. mxWindow->addWindowListener (this); // Register as focus listener to mxWindow->addFocusListener (this); // Determine the list of shapes on the current page. uno::Reference xShapeList; uno::Reference xView (mxController, uno::UNO_QUERY); if (xView.is()) xShapeList = uno::Reference ( xView->getCurrentPage(), uno::UNO_QUERY); // Register this object as dispose event listener at the model. if (mxModel.is()) mxModel->addEventListener ( static_cast(this)); // Register as property change listener at the controller. uno::Reference xSet (mxController, uno::UNO_QUERY); if (xSet.is()) xSet->addPropertyChangeListener ( OUString (RTL_CONSTASCII_USTRINGPARAM("")), static_cast(this)); // Register at VCL Window to be informed of activated and deactivated // OLE objects. Window* pWindow = maShapeTreeInfo.GetWindow(); if (pWindow != NULL) { pWindow->AddChildEventListener (LINK( this, AccessibleDocumentViewBase, WindowChildEventListener)); USHORT nCount = pWindow->GetChildCount(); for (sal_uInt16 i=0; iGetChild (i); if (pChildWindow && (AccessibleRole::EMBEDDED_OBJECT ==pChildWindow->GetAccessibleRole())) { SetAccessibleOLEObject (pChildWindow->GetAccessible()); } } } } IMPL_LINK(AccessibleDocumentViewBase, WindowChildEventListener, VclSimpleEvent*, pEvent) { OSL_ASSERT(pEvent!=NULL && pEvent->ISA(VclWindowEvent)); if (pEvent!=NULL && pEvent->ISA(VclWindowEvent)) { VclWindowEvent* pWindowEvent = static_cast(pEvent); // DBG_ASSERT( pVclEvent->GetWindow(), "Window???" ); switch (pWindowEvent->GetId()) { case VCLEVENT_OBJECT_DYING: { // Window is dying. Unregister from VCL Window. // This is also attempted in the disposing() method. Window* pWindow = maShapeTreeInfo.GetWindow(); Window* pDyingWindow = static_cast( pWindowEvent->GetWindow()); if (pWindow==pDyingWindow && pWindow!=NULL) { pWindow->RemoveChildEventListener (LINK( this, AccessibleDocumentViewBase, WindowChildEventListener)); } } break; case VCLEVENT_WINDOW_SHOW: { // A new window has been created. Is it an OLE object? Window* pChildWindow = static_cast( pWindowEvent->GetData()); if (pChildWindow!=NULL && (pChildWindow->GetAccessibleRole() == AccessibleRole::EMBEDDED_OBJECT)) { SetAccessibleOLEObject (pChildWindow->GetAccessible()); } } break; case VCLEVENT_WINDOW_HIDE: { // A window has been destroyed. Has that been an OLE // object? Window* pChildWindow = static_cast( pWindowEvent->GetData()); if (pChildWindow!=NULL && (pChildWindow->GetAccessibleRole() == AccessibleRole::EMBEDDED_OBJECT)) { SetAccessibleOLEObject (NULL); } } break; } } return 0; } //===== IAccessibleViewForwarderListener ==================================== void AccessibleDocumentViewBase::ViewForwarderChanged (ChangeType aChangeType, const IAccessibleViewForwarder* pViewForwarder) { // Empty } //===== XAccessibleContext ================================================== Reference SAL_CALL AccessibleDocumentViewBase::getAccessibleParent (void) throw (uno::RuntimeException) { return AccessibleContextBase::getAccessibleParent(); } sal_Int32 SAL_CALL AccessibleDocumentViewBase::getAccessibleChildCount (void) throw (uno::RuntimeException) { if (mxAccessibleOLEObject.is()) return 1; else return 0; } Reference SAL_CALL AccessibleDocumentViewBase::getAccessibleChild (long nIndex) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard (maMutex); if (mxAccessibleOLEObject.is()) if (nIndex == 0) return mxAccessibleOLEObject; throw lang::IndexOutOfBoundsException ( ::rtl::OUString::createFromAscii ("no child with index ") + rtl::OUString::valueOf(nIndex), NULL); } //===== XAccessibleComponent ================================================ /** Iterate over all children and test whether the specified point lies within one of their bounding boxes. Return the first child for which this is true. */ uno::Reference SAL_CALL AccessibleDocumentViewBase::getAccessibleAtPoint ( const awt::Point& aPoint) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard (maMutex); uno::Reference xChildAtPosition; sal_Int32 nChildCount = getAccessibleChildCount (); for (sal_Int32 i=nChildCount-1; i>=0; --i) { Reference xChild (getAccessibleChild (i)); if (xChild.is()) { Reference xChildComponent ( xChild->getAccessibleContext(), uno::UNO_QUERY); if (xChildComponent.is()) { awt::Rectangle aBBox (xChildComponent->getBounds()); if ( (aPoint.X >= aBBox.X) && (aPoint.Y >= aBBox.Y) && (aPoint.X < aBBox.X+aBBox.Width) && (aPoint.Y < aBBox.Y+aBBox.Height) ) { xChildAtPosition = xChild; break; } } } } // Have not found a child under the given point. Returning empty // reference to indicate this. return xChildAtPosition; } awt::Rectangle SAL_CALL AccessibleDocumentViewBase::getBounds (void) throw (::com::sun::star::uno::RuntimeException) { // Transform visible area into screen coordinates. ::Rectangle aVisibleArea ( maShapeTreeInfo.GetViewForwarder()->GetVisibleArea()); ::Point aPixelTopLeft ( maShapeTreeInfo.GetViewForwarder()->LogicToPixel ( aVisibleArea.TopLeft())); ::Point aPixelSize ( maShapeTreeInfo.GetViewForwarder()->LogicToPixel ( aVisibleArea.BottomRight()) - aPixelTopLeft); // Prepare to subtract the parent position to transform into relative // coordinates. awt::Point aParentPosition; Reference xParent = getAccessibleParent (); if (xParent.is()) { Reference xParentComponent ( xParent->getAccessibleContext(), uno::UNO_QUERY); if (xParentComponent.is()) aParentPosition = xParentComponent->getLocationOnScreen(); } return awt::Rectangle ( aPixelTopLeft.X() - aParentPosition.X, aPixelTopLeft.Y() - aParentPosition.Y, aPixelSize.X(), aPixelSize.Y()); } awt::Point SAL_CALL AccessibleDocumentViewBase::getLocation (void) throw (uno::RuntimeException) { ThrowIfDisposed (); awt::Rectangle aBoundingBox (getBounds()); return awt::Point (aBoundingBox.X, aBoundingBox.Y); } awt::Point SAL_CALL AccessibleDocumentViewBase::getLocationOnScreen (void) throw (uno::RuntimeException) { ::Point aLogicalPoint (maShapeTreeInfo.GetViewForwarder()->GetVisibleArea().TopLeft()); ::Point aPixelPoint (maShapeTreeInfo.GetViewForwarder()->LogicToPixel (aLogicalPoint)); return awt::Point (aPixelPoint.X(), aPixelPoint.Y()); } awt::Size SAL_CALL AccessibleDocumentViewBase::getSize (void) throw (uno::RuntimeException) { // Transform visible area into screen coordinates. ::Rectangle aVisibleArea ( maShapeTreeInfo.GetViewForwarder()->GetVisibleArea()); ::Point aPixelTopLeft ( maShapeTreeInfo.GetViewForwarder()->LogicToPixel ( aVisibleArea.TopLeft())); ::Point aPixelSize ( maShapeTreeInfo.GetViewForwarder()->LogicToPixel ( aVisibleArea.BottomRight()) - aPixelTopLeft); return awt::Size (aPixelSize.X(), aPixelSize.Y()); } //===== XInterface ========================================================== uno::Any SAL_CALL AccessibleDocumentViewBase::queryInterface (const uno::Type & rType) throw (uno::RuntimeException) { uno::Any aReturn = AccessibleContextBase::queryInterface (rType); if ( ! aReturn.hasValue()) aReturn = ::cppu::queryInterface (rType, static_cast(this), static_cast(this), static_cast( static_cast(this)), static_cast(this), static_cast(this), static_cast(this) ); return aReturn; } void SAL_CALL AccessibleDocumentViewBase::acquire (void) throw () { AccessibleContextBase::acquire (); } void SAL_CALL AccessibleDocumentViewBase::release (void) throw () { AccessibleContextBase::release (); } //===== XServiceInfo ======================================================== ::rtl::OUString SAL_CALL AccessibleDocumentViewBase::getImplementationName (void) throw (::com::sun::star::uno::RuntimeException) { return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleDocumentViewBase")); } ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL AccessibleDocumentViewBase::getSupportedServiceNames (void) throw (::com::sun::star::uno::RuntimeException) { return AccessibleContextBase::getSupportedServiceNames (); } //===== XTypeProvider ======================================================= ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type> SAL_CALL AccessibleDocumentViewBase::getTypes (void) throw (::com::sun::star::uno::RuntimeException) { // Get list of types from the context base implementation, ... uno::Sequence aTypeList (AccessibleContextBase::getTypes()); // ... get list of types from component base implementation, ... uno::Sequence aComponentTypeList (AccessibleComponentBase::getTypes()); // ...and add the additional type for the component, ... const uno::Type aLangEventListenerType = ::getCppuType((const uno::Reference*)0); const uno::Type aPropertyChangeListenerType = ::getCppuType((const uno::Reference*)0); const uno::Type aWindowListenerType = ::getCppuType((const uno::Reference*)0); const uno::Type aFocusListenerType = ::getCppuType((const uno::Reference*)0); const uno::Type aEventBroadcaster = ::getCppuType((const uno::Reference*)0); // ... and merge them all into one list. sal_Int32 nTypeCount (aTypeList.getLength()), nComponentTypeCount (aComponentTypeList.getLength()), i; aTypeList.realloc (nTypeCount + nComponentTypeCount + 5); for (i=0; i aGuard (::osl::Mutex::getGlobalMutex()); mxModel->removeEventListener ( static_cast(this)); // Reset the model reference. mxModel = NULL; // Propagate change of controller down the shape tree. maShapeTreeInfo.SetControllerBroadcaster (NULL); } else if (rEventObject.Source == mxController) { ::osl::Guard< ::osl::Mutex> aGuard (::osl::Mutex::getGlobalMutex()); // Unregister as property change listener at the controller. uno::Reference xSet (mxController,uno::UNO_QUERY); if (xSet.is()) xSet->removePropertyChangeListener ( OUString (RTL_CONSTASCII_USTRINGPARAM("")), static_cast(this)); // Reset the model reference. mxController = NULL; } } //===== XPropertyChangeListener ============================================= void SAL_CALL AccessibleDocumentViewBase::propertyChange (const beans::PropertyChangeEvent& rEventObject) throw (::com::sun::star::uno::RuntimeException) {} //===== XWindowListener ===================================================== void SAL_CALL AccessibleDocumentViewBase::windowResized (const ::com::sun::star::awt::WindowEvent& e) throw (::com::sun::star::uno::RuntimeException) { if( IsDisposed() ) return; ViewForwarderChanged ( IAccessibleViewForwarderListener::VISIBLE_AREA, &maViewForwarder); } void SAL_CALL AccessibleDocumentViewBase::windowMoved (const ::com::sun::star::awt::WindowEvent& e) throw (::com::sun::star::uno::RuntimeException) { if( IsDisposed() ) return; ViewForwarderChanged ( IAccessibleViewForwarderListener::VISIBLE_AREA, &maViewForwarder); } void SAL_CALL AccessibleDocumentViewBase::windowShown (const ::com::sun::star::lang::EventObject& e) throw (::com::sun::star::uno::RuntimeException) { if( IsDisposed() ) return; ViewForwarderChanged ( IAccessibleViewForwarderListener::VISIBLE_AREA, &maViewForwarder); } void SAL_CALL AccessibleDocumentViewBase::windowHidden (const ::com::sun::star::lang::EventObject& e) throw (::com::sun::star::uno::RuntimeException) { if( IsDisposed() ) return; ViewForwarderChanged ( IAccessibleViewForwarderListener::VISIBLE_AREA, &maViewForwarder); } //===== XFocusListener ================================================== void AccessibleDocumentViewBase::focusGained (const ::com::sun::star::awt::FocusEvent& e) throw (::com::sun::star::uno::RuntimeException) { if (e.Source == mxWindow) Activated (); } void AccessibleDocumentViewBase::focusLost (const ::com::sun::star::awt::FocusEvent& e) throw (::com::sun::star::uno::RuntimeException) { if (e.Source == mxWindow) Deactivated (); } //===== protected internal ================================================== // This method is called from the component helper base class while disposing. void SAL_CALL AccessibleDocumentViewBase::disposing (void) { // Unregister from VCL Window. Window* pWindow = maShapeTreeInfo.GetWindow(); if (pWindow != NULL) { pWindow->RemoveChildEventListener (LINK( this, AccessibleDocumentViewBase, WindowChildEventListener)); } else DBG_ASSERT (pWindow, "AccessibleDocumentViewBase::disposing"); // Unregister from window. if (mxWindow.is()) { mxWindow->removeWindowListener (this); mxWindow->removeFocusListener (this); } // Unregister form the model. if (mxModel.is()) mxModel->removeEventListener ( static_cast(this)); // Unregister from the controller. uno::Reference xSet (mxController, uno::UNO_QUERY); if (xSet.is()) xSet->removePropertyChangeListener ( OUString (RTL_CONSTASCII_USTRINGPARAM("")), static_cast(this)); AccessibleContextBase::disposing (); } /// Create a name for this view. ::rtl::OUString AccessibleDocumentViewBase::CreateAccessibleName (void) throw (::com::sun::star::uno::RuntimeException) { return ::rtl::OUString ( RTL_CONSTASCII_USTRINGPARAM("AccessibleDocumentViewBase")); } /** Create a description for this view. Use the model's description or URL if a description is not available. */ ::rtl::OUString AccessibleDocumentViewBase::CreateAccessibleDescription (void) throw (::com::sun::star::uno::RuntimeException) { rtl::OUString sDescription; uno::Reference xInfo (mxController, uno::UNO_QUERY); if (xInfo.is()) { OUString sFirstService = xInfo->getSupportedServiceNames()[0]; if (sFirstService == OUString ( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.DrawingDocumentDrawView"))) { sDescription = OUString (RTL_CONSTASCII_USTRINGPARAM("Draw Document")); } else sDescription = sFirstService; } else sDescription = OUString ( RTL_CONSTASCII_USTRINGPARAM("Accessible Draw Document")); return sDescription; } void AccessibleDocumentViewBase::Activated (void) { // Empty. Overwrite to do something usefull. } void AccessibleDocumentViewBase::Deactivated (void) { // Empty. Overwrite to do something usefull. } void AccessibleDocumentViewBase::SetAccessibleOLEObject ( const Reference & xOLEObject) { // Send child event about removed accessible OLE object if necessary. if (mxAccessibleOLEObject != xOLEObject) if (mxAccessibleOLEObject.is()) CommitChange ( AccessibleEventId::CHILD, uno::Any(), uno::makeAny (mxAccessibleOLEObject)); // Assume that the accessible OLE Object disposes itself correctly. { ::osl::MutexGuard aGuard (maMutex); mxAccessibleOLEObject = xOLEObject; } // Send child event about new accessible OLE object if necessary. if (mxAccessibleOLEObject.is()) CommitChange ( AccessibleEventId::CHILD, uno::makeAny (mxAccessibleOLEObject), uno::Any()); } //===== methods from AccessibleSelectionBase ================================================== // return the member maMutex; ::osl::Mutex& AccessibleDocumentViewBase::implGetMutex() { return( maMutex ); } // return ourself as context in default case uno::Reference< XAccessibleContext > AccessibleDocumentViewBase::implGetAccessibleContext() throw (uno::RuntimeException) { return( this ); } // return sal_False in default case sal_Bool AccessibleDocumentViewBase::implIsSelected( sal_Int32 nAccessibleChildIndex ) throw (uno::RuntimeException) { return( sal_False ); } // return nothing in default case void AccessibleDocumentViewBase::implSelect( sal_Int32 nAccessibleChildIndex, sal_Bool bSelect ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) { } } // end of namespace accessibility