diff options
Diffstat (limited to 'editeng/source/accessibility')
-rw-r--r-- | editeng/source/accessibility/AccessibleComponentBase.cxx | 240 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleContextBase.cxx | 718 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleEditableTextPara.cxx | 2204 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleEditableTextPara.hxx | 414 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleImageBullet.cxx | 654 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleImageBullet.hxx | 240 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleParaManager.cxx | 423 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleParaManager.hxx | 349 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleSelectionBase.cxx | 111 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleStaticTextBase.cxx | 1050 | ||||
-rw-r--r-- | editeng/source/accessibility/AccessibleStringWrap.cxx | 103 | ||||
-rw-r--r-- | editeng/source/accessibility/accessibility.src | 43 | ||||
-rwxr-xr-x | editeng/source/accessibility/makefile.mk | 58 |
13 files changed, 6607 insertions, 0 deletions
diff --git a/editeng/source/accessibility/AccessibleComponentBase.cxx b/editeng/source/accessibility/AccessibleComponentBase.cxx new file mode 100644 index 0000000000..7d6d5205e0 --- /dev/null +++ b/editeng/source/accessibility/AccessibleComponentBase.cxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleComponentBase.cxx,v $ + * $Revision: 1.17 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + + +#include <editeng/AccessibleComponentBase.hxx> + +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/XAccessibleSelection.hpp> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/drawing/XShapes.hpp> +#include <com/sun/star/drawing/XShapeDescriptor.hpp> +#include <com/sun/star/lang/IndexOutOfBoundsException.hpp> + +#include <tools/color.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +namespace accessibility { + +//===== internal ============================================================ + +AccessibleComponentBase::AccessibleComponentBase (void) +{ +} + + + + +AccessibleComponentBase::~AccessibleComponentBase (void) +{ +} + + + + +//===== XAccessibleComponent ================================================ + +sal_Bool SAL_CALL AccessibleComponentBase::containsPoint ( + const ::com::sun::star::awt::Point& aPoint) + throw (::com::sun::star::uno::RuntimeException) +{ + awt::Size aSize (getSize()); + return (aPoint.X >= 0) + && (aPoint.X < aSize.Width) + && (aPoint.Y >= 0) + && (aPoint.Y < aSize.Height); +} + + + + +uno::Reference<XAccessible > SAL_CALL + AccessibleComponentBase::getAccessibleAtPoint ( + const awt::Point& /*aPoint*/) + throw (uno::RuntimeException) +{ + return uno::Reference<XAccessible>(); +} + + + + +awt::Rectangle SAL_CALL AccessibleComponentBase::getBounds (void) + throw (uno::RuntimeException) +{ + return awt::Rectangle(); +} + + + + +awt::Point SAL_CALL AccessibleComponentBase::getLocation (void) + throw (::com::sun::star::uno::RuntimeException) +{ + awt::Rectangle aBBox (getBounds()); + return awt::Point (aBBox.X, aBBox.Y); +} + + + + +awt::Point SAL_CALL AccessibleComponentBase::getLocationOnScreen (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return awt::Point(); +} + + + + +::com::sun::star::awt::Size SAL_CALL AccessibleComponentBase::getSize (void) + throw (::com::sun::star::uno::RuntimeException) +{ + awt::Rectangle aBBox (getBounds()); + return awt::Size (aBBox.Width, aBBox.Height); +} + + + + +void SAL_CALL AccessibleComponentBase::addFocusListener ( + const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XFocusListener >& /*xListener*/) + throw (::com::sun::star::uno::RuntimeException) +{ + // Ignored +} + + + + +void SAL_CALL AccessibleComponentBase::removeFocusListener (const ::com::sun::star::uno::Reference< + ::com::sun::star::awt::XFocusListener >& /*xListener*/ ) + throw (::com::sun::star::uno::RuntimeException) +{ + // Ignored +} + + + + +void SAL_CALL AccessibleComponentBase::grabFocus (void) + throw (::com::sun::star::uno::RuntimeException) +{ + uno::Reference<XAccessibleContext> xContext (this, uno::UNO_QUERY); + uno::Reference<XAccessibleSelection> xSelection ( + xContext->getAccessibleParent(), uno::UNO_QUERY); + if (xSelection.is()) + { + // Do a single selection on this object. + xSelection->clearAccessibleSelection(); + xSelection->selectAccessibleChild (xContext->getAccessibleIndexInParent()); + } +} + + + + +sal_Int32 SAL_CALL AccessibleComponentBase::getForeground (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return Color(COL_BLACK).GetColor(); +} + + + + +sal_Int32 SAL_CALL AccessibleComponentBase::getBackground (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return Color(COL_WHITE).GetColor(); +} + + + + +//===== XAccessibleExtendedComponent ======================================== + +::com::sun::star::uno::Reference< ::com::sun::star::awt::XFont > SAL_CALL + AccessibleComponentBase::getFont (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return uno::Reference<awt::XFont>(); +} + + + + +::rtl::OUString SAL_CALL AccessibleComponentBase::getTitledBorderText (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii (""); +} + + + + +::rtl::OUString SAL_CALL AccessibleComponentBase::getToolTipText (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii (""); +} + + + + +//===== XTypeProvider =================================================== + +uno::Sequence<uno::Type> SAL_CALL + AccessibleComponentBase::getTypes (void) + throw (uno::RuntimeException) +{ + // Get list of types from the context base implementation... + uno::Sequence<uno::Type> aTypeList (2); + // ...and add the additional type for the component. + const uno::Type aComponentType = + ::getCppuType((const uno::Reference<XAccessibleComponent>*)0); + const uno::Type aExtendedComponentType = + ::getCppuType((const uno::Reference<XAccessibleExtendedComponent>*)0); + aTypeList[0] = aComponentType; + aTypeList[1] = aExtendedComponentType; + + return aTypeList; +} + + +} // end of namespace accessibility diff --git a/editeng/source/accessibility/AccessibleContextBase.cxx b/editeng/source/accessibility/AccessibleContextBase.cxx new file mode 100644 index 0000000000..d3671624f4 --- /dev/null +++ b/editeng/source/accessibility/AccessibleContextBase.cxx @@ -0,0 +1,718 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleContextBase.cxx,v $ + * $Revision: 1.28.144.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + + +#include <editeng/AccessibleContextBase.hxx> + +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/beans/PropertyChangeEvent.hpp> +#include <com/sun/star/accessibility/XAccessibleEventListener.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> + +#include <unotools/accessiblestatesethelper.hxx> +#include <unotools/accessiblerelationsethelper.hxx> +#include <comphelper/accessibleeventnotifier.hxx> +#include <rtl/uuid.h> +#include <vos/mutex.hxx> +//#include <vcl/svapp.hxx> + +#include <utility> + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; +using ::com::sun::star::uno::Reference; + +namespace accessibility { + +//===== internal ============================================================ + +// Define a shortcut for the somewhot longish base class name. +typedef ::cppu::WeakComponentImplHelper4< + ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::lang::XServiceInfo> BaseClass; + +AccessibleContextBase::AccessibleContextBase ( + const uno::Reference<XAccessible>& rxParent, + const sal_Int16 aRole) + : BaseClass (MutexOwner::maMutex), + mxStateSet (NULL), + mxRelationSet (NULL), + mxParent(rxParent), + msDescription(), + meDescriptionOrigin(NotSet), + msName(), + meNameOrigin(NotSet), + mnClientId(0), + maRole(aRole) +{ + // Create the state set. + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper (); + mxStateSet = pStateSet; + + // Set some states. Don't use the SetState method because no events + // shall be broadcastet (that is not yet initialized anyway). + if (pStateSet != NULL) + { + pStateSet->AddState (AccessibleStateType::ENABLED); + pStateSet->AddState (AccessibleStateType::SENSITIVE); + pStateSet->AddState (AccessibleStateType::SHOWING); + pStateSet->AddState (AccessibleStateType::VISIBLE); + pStateSet->AddState (AccessibleStateType::FOCUSABLE); + pStateSet->AddState (AccessibleStateType::SELECTABLE); + } + + // Create the relation set. + ::utl::AccessibleRelationSetHelper* pRelationSet = new ::utl::AccessibleRelationSetHelper (); + mxRelationSet = pRelationSet; +} + + + + +AccessibleContextBase::~AccessibleContextBase(void) +{ +} + + + + +sal_Bool AccessibleContextBase::SetState (sal_Int16 aState) +{ + ::osl::ClearableMutexGuard aGuard (maMutex); + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if ((pStateSet != NULL) && !pStateSet->contains(aState)) + { + pStateSet->AddState (aState); + // Clear the mutex guard so that it is not locked during calls to + // listeners. + aGuard.clear(); + + // Send event for all states except the DEFUNC state. + if (aState != AccessibleStateType::DEFUNC) + { + uno::Any aNewValue; + aNewValue <<= aState; + CommitChange( + AccessibleEventId::STATE_CHANGED, + aNewValue, + uno::Any()); + } + return sal_True; + } + else + return sal_False; +} + + + + +sal_Bool AccessibleContextBase::ResetState (sal_Int16 aState) +{ + ::osl::ClearableMutexGuard aGuard (maMutex); + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if ((pStateSet != NULL) && pStateSet->contains(aState)) + { + pStateSet->RemoveState (aState); + // Clear the mutex guard so that it is not locked during calls to listeners. + aGuard.clear(); + + uno::Any aOldValue; + aOldValue <<= aState; + CommitChange( + AccessibleEventId::STATE_CHANGED, + uno::Any(), + aOldValue); + return sal_True; + } + else + return sal_False; +} + + + + +sal_Bool AccessibleContextBase::GetState (sal_Int16 aState) +{ + ::osl::MutexGuard aGuard (maMutex); + ::utl::AccessibleStateSetHelper* pStateSet = + static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if (pStateSet != NULL) + return pStateSet->contains(aState); + else + // If there is no state set then return false as a default value. + return sal_False; +} + + + + +void AccessibleContextBase::SetRelationSet ( + const uno::Reference<XAccessibleRelationSet>& rxNewRelationSet) + throw (::com::sun::star::uno::RuntimeException) +{ + OSL_TRACE ("setting relation set"); + + // Try to emit some meaningfull events indicating differing relations in + // both sets. + typedef std::pair<short int,short int> RD; + const RD aRelationDescriptors[] = { + RD(AccessibleRelationType::CONTROLLED_BY, AccessibleEventId::CONTROLLED_BY_RELATION_CHANGED), + RD(AccessibleRelationType::CONTROLLER_FOR, AccessibleEventId::CONTROLLER_FOR_RELATION_CHANGED), + RD(AccessibleRelationType::LABELED_BY, AccessibleEventId::LABELED_BY_RELATION_CHANGED), + RD(AccessibleRelationType::LABEL_FOR, AccessibleEventId::LABEL_FOR_RELATION_CHANGED), + RD(AccessibleRelationType::MEMBER_OF, AccessibleEventId::MEMBER_OF_RELATION_CHANGED), + RD(AccessibleRelationType::INVALID, -1), + }; + for (int i=0; aRelationDescriptors[i].first!=AccessibleRelationType::INVALID; i++) + if (mxRelationSet->containsRelation(aRelationDescriptors[i].first) + != rxNewRelationSet->containsRelation(aRelationDescriptors[i].first)) + CommitChange (aRelationDescriptors[i].second, uno::Any(), uno::Any()); + + mxRelationSet = rxNewRelationSet; +} + + + + +//===== XAccessible ========================================================= + +uno::Reference< XAccessibleContext> SAL_CALL + AccessibleContextBase::getAccessibleContext (void) + throw (uno::RuntimeException) +{ + ThrowIfDisposed (); + return this; +} + + + + +//===== XAccessibleContext ================================================== + +/** No children. +*/ +sal_Int32 SAL_CALL + AccessibleContextBase::getAccessibleChildCount (void) + throw (uno::RuntimeException) +{ + ThrowIfDisposed (); + return 0; +} + + + + +/** Forward the request to the shape. Return the requested shape or throw + an exception for a wrong index. +*/ +uno::Reference<XAccessible> SAL_CALL + AccessibleContextBase::getAccessibleChild (sal_Int32 nIndex) + throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + throw lang::IndexOutOfBoundsException ( + ::rtl::OUString::createFromAscii ("no child with index " + nIndex), + NULL); +} + + + + +uno::Reference<XAccessible> SAL_CALL + AccessibleContextBase::getAccessibleParent (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + return mxParent; +} + + + + +sal_Int32 SAL_CALL + AccessibleContextBase::getAccessibleIndexInParent (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + // Use a simple but slow solution for now. Optimize later. + + // Iterate over all the parent's children and search for this object. + if (mxParent.is()) + { + uno::Reference<XAccessibleContext> xParentContext ( + mxParent->getAccessibleContext()); + if (xParentContext.is()) + { + sal_Int32 nChildCount = xParentContext->getAccessibleChildCount(); + for (sal_Int32 i=0; i<nChildCount; i++) + { + uno::Reference<XAccessible> xChild (xParentContext->getAccessibleChild (i)); + if (xChild.is()) + { + uno::Reference<XAccessibleContext> xChildContext = xChild->getAccessibleContext(); + if (xChildContext == (XAccessibleContext*)this) + return i; + } + } + } + } + + // Return -1 to indicate that this object's parent does not know about the + // object. + return -1; +} + + + + +sal_Int16 SAL_CALL + AccessibleContextBase::getAccessibleRole (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + return maRole; +} + + + + +::rtl::OUString SAL_CALL + AccessibleContextBase::getAccessibleDescription (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + return msDescription; +} + + + + +OUString SAL_CALL + AccessibleContextBase::getAccessibleName (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + if (meNameOrigin == NotSet) + { + // Do not send an event because this is the first time it has been + // requested. + msName = CreateAccessibleName(); + meNameOrigin = AutomaticallyCreated; + } + + return msName; +} + + + + +/** Return a copy of the relation set. +*/ +uno::Reference<XAccessibleRelationSet> SAL_CALL + AccessibleContextBase::getAccessibleRelationSet (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + // Create a copy of the relation set and return it. + ::utl::AccessibleRelationSetHelper* pRelationSet = + static_cast< ::utl::AccessibleRelationSetHelper*>(mxRelationSet.get()); + if (pRelationSet != NULL) + { + return uno::Reference<XAccessibleRelationSet> ( + new ::utl::AccessibleRelationSetHelper (*pRelationSet)); + } + else + return uno::Reference<XAccessibleRelationSet>(NULL); +} + + + + +/** Return a copy of the state set. + Possible states are: + ENABLED + SHOWING + VISIBLE +*/ +uno::Reference<XAccessibleStateSet> SAL_CALL + AccessibleContextBase::getAccessibleStateSet (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ::utl::AccessibleStateSetHelper* pStateSet = NULL; + + if (rBHelper.bDisposed) + { + // We are already disposed! + // Create a new state set that has only set the DEFUNC state. + pStateSet = new ::utl::AccessibleStateSetHelper (); + if (pStateSet != NULL) + pStateSet->AddState (AccessibleStateType::DEFUNC); + } + else + { + // Create a copy of the state set and return it. + pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + // Merge current focused state from edit engine. +#if 0 + if (aState == AccessibleStateType::FOCUSED + && pStateSet != NULL + && mpText != NULL) + { + if (mpText->GetFocusedState ()) + pStateSet->AddState (aState); + else + pStateSet->RemoveState (aState); + } +#endif + if (pStateSet != NULL) + pStateSet = new ::utl::AccessibleStateSetHelper (*pStateSet); + } + + return uno::Reference<XAccessibleStateSet>(pStateSet); +} + + + + +lang::Locale SAL_CALL + AccessibleContextBase::getLocale (void) + throw (IllegalAccessibleComponentStateException, + ::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + // Delegate request to parent. + if (mxParent.is()) + { + uno::Reference<XAccessibleContext> xParentContext ( + mxParent->getAccessibleContext()); + if (xParentContext.is()) + return xParentContext->getLocale (); + } + + // No locale and no parent. Therefore throw exception to indicate this + // cluelessness. + throw IllegalAccessibleComponentStateException (); +} + + + + +//===== XAccessibleEventListener ============================================ + +void SAL_CALL + AccessibleContextBase::addEventListener ( + const uno::Reference<XAccessibleEventListener >& rxListener) + throw (uno::RuntimeException) +{ + if (rxListener.is()) + { + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + uno::Reference<uno::XInterface> x ((lang::XComponent *)this, uno::UNO_QUERY); + rxListener->disposing (lang::EventObject (x)); + } + else + { + if (!mnClientId) + mnClientId = comphelper::AccessibleEventNotifier::registerClient( ); + comphelper::AccessibleEventNotifier::addEventListener( mnClientId, rxListener ); + } + } +} + + + + +void SAL_CALL + AccessibleContextBase::removeEventListener ( + const uno::Reference<XAccessibleEventListener >& rxListener ) + throw (uno::RuntimeException) +{ + ThrowIfDisposed (); + if (rxListener.is()) + { + sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( mnClientId, rxListener ); + if ( !nListenerCount ) + { + // no listeners anymore + // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client), + // and at least to us not firing any events anymore, in case somebody calls + // NotifyAccessibleEvent, again + comphelper::AccessibleEventNotifier::revokeClient( mnClientId ); + mnClientId = 0; + } + } +} + + + + +//===== XServiceInfo ======================================================== + +::rtl::OUString SAL_CALL + AccessibleContextBase::getImplementationName (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + return OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleContextBase")); +} + + + + +sal_Bool SAL_CALL + AccessibleContextBase::supportsService (const OUString& sServiceName) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + // Iterate over all supported service names and return true if on of them + // matches the given name. + uno::Sequence< ::rtl::OUString> aSupportedServices ( + getSupportedServiceNames ()); + for (int i=0; i<aSupportedServices.getLength(); i++) + if (sServiceName == aSupportedServices[i]) + return sal_True; + return sal_False; +} + + + + +uno::Sequence< ::rtl::OUString> SAL_CALL + AccessibleContextBase::getSupportedServiceNames (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + static const OUString sServiceNames[2] = { + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.accessibility.Accessible")), + OUString(RTL_CONSTASCII_USTRINGPARAM( + "com.sun.star.accessibility.AccessibleContext")) + }; + return uno::Sequence<OUString> (sServiceNames, 2); +} + + + + +//===== XTypeProvider ======================================================= + +uno::Sequence< ::com::sun::star::uno::Type> + AccessibleContextBase::getTypes (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + + // This class supports no interfaces on its own. Just return those + // supported by the base class. + return BaseClass::getTypes(); +} + + + + +uno::Sequence<sal_Int8> SAL_CALL + AccessibleContextBase::getImplementationId (void) + throw (::com::sun::star::uno::RuntimeException) +{ + ThrowIfDisposed (); + static uno::Sequence<sal_Int8> aId; + if (aId.getLength() == 0) + { + ::osl::MutexGuard aGuard (maMutex); + aId.realloc (16); + rtl_createUuid ((sal_uInt8 *)aId.getArray(), 0, sal_True); + } + return aId; +} + + + + +//===== internal ============================================================ + +void SAL_CALL AccessibleContextBase::disposing (void) +{ + SetState (AccessibleStateType::DEFUNC); + + ::osl::MutexGuard aGuard (maMutex); + + // Send a disposing to all listeners. + if ( mnClientId ) + { + comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( mnClientId, *this ); + mnClientId = 0; + } +} + + + + +void AccessibleContextBase::SetAccessibleDescription ( + const ::rtl::OUString& rDescription, + StringOrigin eDescriptionOrigin) + throw (uno::RuntimeException) +{ + if (eDescriptionOrigin < meDescriptionOrigin + || (eDescriptionOrigin == meDescriptionOrigin && msDescription != rDescription)) + { + uno::Any aOldValue, aNewValue; + aOldValue <<= msDescription; + aNewValue <<= rDescription; + + msDescription = rDescription; + meDescriptionOrigin = eDescriptionOrigin; + + CommitChange( + AccessibleEventId::DESCRIPTION_CHANGED, + aNewValue, + aOldValue); + } +} + + + + +void AccessibleContextBase::SetAccessibleName ( + const ::rtl::OUString& rName, + StringOrigin eNameOrigin) + throw (uno::RuntimeException) +{ + if (eNameOrigin < meNameOrigin + || (eNameOrigin == meNameOrigin && msName != rName)) + { + uno::Any aOldValue, aNewValue; + aOldValue <<= msName; + aNewValue <<= rName; + + msName = rName; + meNameOrigin = eNameOrigin; + + CommitChange( + AccessibleEventId::NAME_CHANGED, + aNewValue, + aOldValue); + } +} + + + + +::rtl::OUString AccessibleContextBase::CreateAccessibleDescription (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii ("Empty Description"); +} + + + + +::rtl::OUString AccessibleContextBase::CreateAccessibleName (void) + throw (::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii ("Empty Name"); +} + + + + +void AccessibleContextBase::CommitChange ( + sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue) +{ + // Do not call FireEvent and do not even create the event object when no + // listener has been registered yet. Creating the event object can + // otherwise lead to a crash. See issue 93419 for details. + if (mnClientId != 0) + { + AccessibleEventObject aEvent ( + static_cast<XAccessibleContext*>(this), + nEventId, + rNewValue, + rOldValue); + + FireEvent (aEvent); + } +} + + + + +void AccessibleContextBase::FireEvent (const AccessibleEventObject& aEvent) +{ + if (mnClientId) + comphelper::AccessibleEventNotifier::addEvent( mnClientId, aEvent ); +} + + + + +void AccessibleContextBase::ThrowIfDisposed (void) + throw (::com::sun::star::lang::DisposedException) +{ + if (rBHelper.bDisposed || rBHelper.bInDispose) + { + OSL_TRACE ("Calling disposed object. Throwing exception:"); + throw lang::DisposedException ( + OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), + static_cast<uno::XWeak*>(this)); + } +} + + + +sal_Bool AccessibleContextBase::IsDisposed (void) +{ + return (rBHelper.bDisposed || rBHelper.bInDispose); +} + + + +void AccessibleContextBase::SetAccessibleRole( sal_Int16 _nRole ) +{ + maRole = _nRole; +} + + +} // end of namespace accessibility diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.cxx b/editeng/source/accessibility/AccessibleEditableTextPara.cxx new file mode 100644 index 0000000000..7b32e6fe58 --- /dev/null +++ b/editeng/source/accessibility/AccessibleEditableTextPara.cxx @@ -0,0 +1,2204 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleEditableTextPara.cxx,v $ + * $Revision: 1.53 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//------------------------------------------------------------------------ +// +// Global header +// +//------------------------------------------------------------------------ + +#include <limits.h> +#include <vector> +#include <algorithm> +#include <vos/mutex.hxx> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <comphelper/accessibleeventnotifier.hxx> +#include <comphelper/sequenceashashmap.hxx> +#include <unotools/accessiblestatesethelper.hxx> + +// --> OD 2006-01-11 #i27138# +#include <unotools/accessiblerelationsethelper.hxx> +#include <com/sun/star/accessibility/AccessibleRelationType.hpp> +// <-- +#include <vcl/unohelp.hxx> +#include <editeng/editeng.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/unoipset.hxx> +#include <editeng/outliner.hxx> + +//------------------------------------------------------------------------ +// +// Project-local header +// +//------------------------------------------------------------------------ + +#include <com/sun/star/beans/PropertyState.hpp> +#include <editeng/unolingu.hxx> +#include <editeng/unopracc.hxx> +#include "AccessibleEditableTextPara.hxx" +#include <svtools/colorcfg.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::accessibility; + + +//------------------------------------------------------------------------ +// +// AccessibleEditableTextPara implementation +// +//------------------------------------------------------------------------ + +namespace accessibility +{ + + const SvxItemPropertySet* ImplGetSvxCharAndParaPropertiesSet() + { + // PropertyMap for character and paragraph properties + static const SfxItemPropertyMapEntry aPropMap[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + SVX_UNOEDIT_NUMBERING_PROPERTIE, + {MAP_CHAR_LEN("TextUserDefinedAttributes"), EE_CHAR_XMLATTRIBS, &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >*)0) , 0, 0}, + {MAP_CHAR_LEN("ParaUserDefinedAttributes"), EE_PARA_XMLATTRIBS, &::getCppuType((const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >*)0) , 0, 0}, + {0,0,0,0,0,0} + }; + static SvxItemPropertySet aPropSet( aPropMap, EditEngine::GetGlobalItemPool() ); + return &aPropSet; + } + + + DBG_NAME( AccessibleEditableTextPara ) + + // --> OD 2006-01-11 #i27138# - add parameter <_pParaManager> + AccessibleEditableTextPara::AccessibleEditableTextPara( + const uno::Reference< XAccessible >& rParent, + const AccessibleParaManager* _pParaManager ) + : AccessibleTextParaInterfaceBase( m_aMutex ), + mnParagraphIndex( 0 ), + mnIndexInParent( 0 ), + mpEditSource( NULL ), + maEEOffset( 0, 0 ), + mxParent( rParent ), + // well, that's strictly (UNO) exception safe, though not + // really robust. We rely on the fact that this member is + // constructed last, and that the constructor body catches + // exceptions, thus no chance for exceptions once the Id is + // fetched. Nevertheless, normally should employ RAII here... + mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient()), + // --> OD 2006-01-11 #i27138# + mpParaManager( _pParaManager ) + // <-- + { +#ifdef DBG_UTIL + DBG_CTOR( AccessibleEditableTextPara, NULL ); + OSL_TRACE( "AccessibleEditableTextPara received ID: %d\n", mnNotifierClientId ); +#endif + + try + { + // Create the state set. + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper (); + mxStateSet = pStateSet; + + // these are always on + pStateSet->AddState( AccessibleStateType::MULTI_LINE ); + pStateSet->AddState( AccessibleStateType::FOCUSABLE ); + pStateSet->AddState( AccessibleStateType::VISIBLE ); + pStateSet->AddState( AccessibleStateType::SHOWING ); + pStateSet->AddState( AccessibleStateType::ENABLED ); + pStateSet->AddState( AccessibleStateType::SENSITIVE ); + } + catch( const uno::Exception& ) {} + } + + AccessibleEditableTextPara::~AccessibleEditableTextPara() + { + DBG_DTOR( AccessibleEditableTextPara, NULL ); + + // sign off from event notifier + if( getNotifierClientId() != -1 ) + { + try + { + ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() ); +#ifdef DBG_UTIL + OSL_TRACE( "AccessibleEditableTextPara revoked ID: %d\n", mnNotifierClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + ::rtl::OUString AccessibleEditableTextPara::implGetText() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextRange( 0, GetTextLen() ); + } + + ::com::sun::star::lang::Locale AccessibleEditableTextPara::implGetLocale() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + lang::Locale aLocale; + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getLocale: paragraph index value overflow"); + + // return locale of first character in the paragraph + return SvxLanguageToLocale(aLocale, GetTextForwarder().GetLanguage( static_cast< USHORT >( GetParagraphIndex() ), 0 )); + } + + void AccessibleEditableTextPara::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + USHORT nStart, nEnd; + + if( GetSelection( nStart, nEnd ) ) + { + nStartIndex = nStart; + nEndIndex = nEnd; + } + else + { + // #102234# No exception, just set to 'invalid' + nStartIndex = -1; + nEndIndex = -1; + } + } + + void AccessibleEditableTextPara::implGetParagraphBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 /*nIndex*/ ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + DBG_WARNING( "AccessibleEditableTextPara::implGetParagraphBoundary: only a base implementation, ignoring the index" ); + + rBoundary.startPos = 0; + rBoundary.endPos = GetTextLen(); + } + + void AccessibleEditableTextPara::implGetLineBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + const sal_Int32 nParaIndex = GetParagraphIndex(); + + DBG_ASSERT(nParaIndex >= 0 && nParaIndex <= USHRT_MAX, + "AccessibleEditableTextPara::implGetLineBoundary: paragraph index value overflow"); + + const sal_Int32 nTextLen = rCacheTF.GetTextLen( static_cast< USHORT >( nParaIndex ) ); + + CheckPosition(nIndex); + + rBoundary.startPos = rBoundary.endPos = -1; + + const USHORT nLineCount=rCacheTF.GetLineCount( static_cast< USHORT >( nParaIndex ) ); + + if( nIndex == nTextLen ) + { + // #i17014# Special-casing one-behind-the-end character + if( nLineCount <= 1 ) + rBoundary.startPos = 0; + else + rBoundary.startPos = nTextLen - rCacheTF.GetLineLen( static_cast< USHORT >( nParaIndex ), + nLineCount-1 ); + + rBoundary.endPos = nTextLen; + } + else + { + // normal line search + USHORT nLine; + sal_Int32 nCurIndex; + for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine ) + { + nCurIndex += rCacheTF.GetLineLen( static_cast< USHORT >( nParaIndex ), nLine); + + if( nCurIndex > nIndex ) + { + rBoundary.startPos = nCurIndex - rCacheTF.GetLineLen(static_cast< USHORT >( nParaIndex ), nLine); + rBoundary.endPos = nCurIndex; + break; + } + } + } + } + + int AccessibleEditableTextPara::getNotifierClientId() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnNotifierClientId; + } + + void AccessibleEditableTextPara::SetIndexInParent( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + mnIndexInParent = nIndex; + } + + sal_Int32 AccessibleEditableTextPara::GetIndexInParent() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnIndexInParent; + } + + void AccessibleEditableTextPara::SetParagraphIndex( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + sal_Int32 nOldIndex = mnParagraphIndex; + + mnParagraphIndex = nIndex; + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + if( aChild.is() ) + aChild->SetParagraphIndex(mnParagraphIndex); + + try + { + if( nOldIndex != nIndex ) + { + uno::Any aOldDesc; + uno::Any aOldName; + + try + { + aOldDesc <<= getAccessibleDescription(); + aOldName <<= getAccessibleName(); + } + catch( const uno::Exception& ) {} // optional behaviour + // index and therefore description changed + FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc ); + FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName ); + } + } + catch( const uno::Exception& ) {} // optional behaviour + } + + sal_Int32 AccessibleEditableTextPara::GetParagraphIndex() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnParagraphIndex; + } + + void AccessibleEditableTextPara::Dispose() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + int nClientId( getNotifierClientId() ); + + // #108212# drop all references before notifying dispose + mxParent = NULL; + mnNotifierClientId = -1; + mpEditSource = NULL; + + // notify listeners + if( nClientId != -1 ) + { + try + { + uno::Reference < XAccessibleContext > xThis = getAccessibleContext(); + + // #106234# Delegate to EventNotifier + ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, xThis ); +#ifdef DBG_UTIL + OSL_TRACE( "Disposed ID: %d\n", nClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + void AccessibleEditableTextPara::SetEditSource( SvxEditSourceAdapter* pEditSource ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + mpEditSource = pEditSource; + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + if( aChild.is() ) + aChild->SetEditSource(pEditSource); + + if( !mpEditSource ) + { + // going defunc + UnSetState( AccessibleStateType::SHOWING ); + UnSetState( AccessibleStateType::VISIBLE ); + SetState( AccessibleStateType::INVALID ); + SetState( AccessibleStateType::DEFUNC ); + + Dispose(); + } + + // #108900# Init last text content + try + { + TextChanged(); + } + catch( const uno::RuntimeException& ) {} + } + + ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // check overflow + DBG_ASSERT(nStartEEIndex >= 0 && nStartEEIndex <= USHRT_MAX && + nEndEEIndex >= 0 && nEndEEIndex <= USHRT_MAX && + GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::MakeSelection: index value overflow"); + + USHORT nParaIndex = static_cast< USHORT >( GetParagraphIndex() ); + return ESelection( nParaIndex, static_cast< USHORT >( nStartEEIndex ), + nParaIndex, static_cast< USHORT >( nEndEEIndex ) ); + } + + ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nEEIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return MakeSelection( nEEIndex, nEEIndex+1 ); + } + + ESelection AccessibleEditableTextPara::MakeCursor( sal_Int32 nEEIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return MakeSelection( nEEIndex, nEEIndex ); + } + + void AccessibleEditableTextPara::CheckIndex( sal_Int32 nIndex ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( nIndex < 0 || nIndex >= getCharacterCount() ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleEditableTextPara: character index out of bounds")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy + } + + void AccessibleEditableTextPara::CheckPosition( sal_Int32 nIndex ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( nIndex < 0 || nIndex > getCharacterCount() ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleEditableTextPara: character position out of bounds")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy + } + + void AccessibleEditableTextPara::CheckRange( sal_Int32 nStart, sal_Int32 nEnd ) SAL_THROW((lang::IndexOutOfBoundsException, uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + CheckPosition( nStart ); + CheckPosition( nEnd ); + } + + sal_Bool AccessibleEditableTextPara::GetSelection( USHORT& nStartPos, USHORT& nEndPos ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ESelection aSelection; + USHORT nPara = static_cast< USHORT > ( GetParagraphIndex() ); + if( !GetEditViewForwarder().GetSelection( aSelection ) ) + return sal_False; + + if( aSelection.nStartPara < aSelection.nEndPara ) + { + if( aSelection.nStartPara > nPara || + aSelection.nEndPara < nPara ) + return sal_False; + + if( nPara == aSelection.nStartPara ) + nStartPos = aSelection.nStartPos; + else + nStartPos = 0; + + if( nPara == aSelection.nEndPara ) + nEndPos = aSelection.nEndPos; + else + nEndPos = GetTextLen(); + } + else + { + if( aSelection.nStartPara < nPara || + aSelection.nEndPara > nPara ) + return sal_False; + + if( nPara == aSelection.nStartPara ) + nStartPos = aSelection.nStartPos; + else + nStartPos = GetTextLen(); + + if( nPara == aSelection.nEndPara ) + nEndPos = aSelection.nEndPos; + else + nEndPos = 0; + } + + return sal_True; + } + + String AccessibleEditableTextPara::GetText( sal_Int32 nIndex ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextForwarder().GetText( MakeSelection(nIndex) ); + } + + String AccessibleEditableTextPara::GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextForwarder().GetText( MakeSelection(nStartIndex, nEndIndex) ); + } + + USHORT AccessibleEditableTextPara::GetTextLen() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return GetTextForwarder().GetTextLen( static_cast< USHORT >( GetParagraphIndex() ) ); + } + + sal_Bool AccessibleEditableTextPara::IsVisible() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mpEditSource ? sal_True : sal_False ; + } + + uno::Reference< XAccessibleText > AccessibleEditableTextPara::GetParaInterface( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + uno::Reference< XAccessible > xParent = getAccessibleParent(); + if( xParent.is() ) + { + uno::Reference< XAccessibleContext > xParentContext = xParent->getAccessibleContext(); + if( xParentContext.is() ) + { + uno::Reference< XAccessible > xPara = xParentContext->getAccessibleChild( nIndex ); + if( xPara.is() ) + return uno::Reference< XAccessibleText > ( xPara, uno::UNO_QUERY ); + } + } + + return uno::Reference< XAccessibleText >(); + } + + SvxEditSourceAdapter& AccessibleEditableTextPara::GetEditSource() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( mpEditSource ) + return *mpEditSource; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No edit source, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + SvxAccessibleTextAdapter& AccessibleEditableTextPara::GetTextForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSourceAdapter& rEditSource = GetEditSource(); + SvxAccessibleTextAdapter* pTextForwarder = rEditSource.GetTextForwarderAdapter(); + + if( !pTextForwarder ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch text forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + + if( pTextForwarder->IsValid() ) + return *pTextForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + SvxViewForwarder& AccessibleEditableTextPara::GetViewForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder(); + + if( !pViewForwarder ) + { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + if( pViewForwarder->IsValid() ) + return *pViewForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + SvxAccessibleTextEditViewAdapter& AccessibleEditableTextPara::GetEditViewForwarder( sal_Bool bCreate ) const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSourceAdapter& rEditSource = GetEditSource(); + SvxAccessibleTextEditViewAdapter* pTextEditViewForwarder = rEditSource.GetEditViewForwarderAdapter( bCreate ); + + if( !pTextEditViewForwarder ) + { + if( bCreate ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No view forwarder, object not in edit mode")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + + if( pTextEditViewForwarder->IsValid() ) + return *pTextEditViewForwarder; + else + { + if( bCreate ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object not in edit mode")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy + } + } + + sal_Bool AccessibleEditableTextPara::HaveEditView() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder(); + + if( !pViewForwarder ) + return sal_False; + + if( !pViewForwarder->IsValid() ) + return sal_False; + + return sal_True; + } + + sal_Bool AccessibleEditableTextPara::HaveChildren() + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::HaveChildren: paragraph index value overflow"); + + return GetTextForwarder().HaveImageBullet( static_cast< USHORT >(GetParagraphIndex()) ); + } + + sal_Bool AccessibleEditableTextPara::IsActive() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder(); + + if( !pViewForwarder ) + return sal_False; + + if( pViewForwarder->IsValid() ) + return sal_False; + else + return sal_True; + } + + Rectangle AccessibleEditableTextPara::LogicToPixel( const Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder& rForwarder ) + { + // convert to screen coordinates + return Rectangle( rForwarder.LogicToPixel( rRect.TopLeft(), rMapMode ), + rForwarder.LogicToPixel( rRect.BottomRight(), rMapMode ) ); + } + + const Point& AccessibleEditableTextPara::GetEEOffset() const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return maEEOffset; + } + + void AccessibleEditableTextPara::SetEEOffset( const Point& rOffset ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + if( aChild.is() ) + aChild->SetEEOffset(rOffset); + + maEEOffset = rOffset; + } + + void AccessibleEditableTextPara::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue) const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleEditableTextPara* > (this)->getAccessibleContext() ); + + AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue); + + // #102261# Call global queue for focus events + if( nEventId == AccessibleEventId::STATE_CHANGED ) + vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent ); + + // #106234# Delegate to EventNotifier + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(), + aEvent ); + } + + void AccessibleEditableTextPara::GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + FireEvent( nEventId, rNewValue ); + } + + void AccessibleEditableTextPara::LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + FireEvent( nEventId, uno::Any(), rOldValue ); + } + + bool AccessibleEditableTextPara::HasState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL ) + return pStateSet->contains(nStateId) ? true : false; + + return false; + } + + void AccessibleEditableTextPara::SetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + !pStateSet->contains(nStateId) ) + { + pStateSet->AddState( nStateId ); + GotPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + void AccessibleEditableTextPara::UnSetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + pStateSet->contains(nStateId) ) + { + pStateSet->RemoveState( nStateId ); + LostPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + void AccessibleEditableTextPara::TextChanged() + { + ::rtl::OUString aCurrentString( OCommonAccessibleText::getText() ); + uno::Any aDeleted; + uno::Any aInserted; + if( OCommonAccessibleText::implInitTextChangedEvent( maLastTextString, aCurrentString, + aDeleted, aInserted) ) + { + FireEvent( AccessibleEventId::TEXT_CHANGED, aInserted, aDeleted ); + maLastTextString = aCurrentString; + } + } + + sal_Bool AccessibleEditableTextPara::GetAttributeRun( USHORT& nStartIndex, USHORT& nEndIndex, sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + DBG_ASSERT(nIndex >= 0 && nIndex <= USHRT_MAX, + "AccessibleEditableTextPara::GetAttributeRun: index value overflow"); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getLocale: paragraph index value overflow"); + + return GetTextForwarder().GetAttributeRun( nStartIndex, + nEndIndex, + static_cast< USHORT >(GetParagraphIndex()), + static_cast< USHORT >(nIndex) ); + } + + uno::Any SAL_CALL AccessibleEditableTextPara::queryInterface (const uno::Type & rType) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + uno::Any aRet; + + // must provide XAccesibleText by hand, since it comes publicly inherited by XAccessibleEditableText + if ( rType == ::getCppuType((uno::Reference< XAccessibleText > *)0) ) + { + uno::Reference< XAccessibleText > aAccText = static_cast< XAccessibleEditableText * >(this); + aRet <<= aAccText; + } + else if ( rType == ::getCppuType((uno::Reference< XAccessibleEditableText > *)0) ) + { + uno::Reference< XAccessibleEditableText > aAccEditText = this; + aRet <<= aAccEditText; + } + else + { + aRet = AccessibleTextParaInterfaceBase::queryInterface(rType); + } + + return aRet; + } + + // XAccessible + uno::Reference< XAccessibleContext > SAL_CALL AccessibleEditableTextPara::getAccessibleContext() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // We implement the XAccessibleContext interface in the same object + return uno::Reference< XAccessibleContext > ( this ); + } + + // XAccessibleContext + sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return HaveChildren() ? 1 : 0; + } + + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( !HaveChildren() ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No childs available")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + + if( i != 0 ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Invalid child index")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + + WeakBullet::HardRefType aChild( maImageBullet.get() ); + + if( !aChild.is() ) + { + // there is no hard reference available, create object then + AccessibleImageBullet* pChild = new AccessibleImageBullet( uno::Reference< XAccessible >( this ) ); + uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY ); + + if( !xChild.is() ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Child creation failed")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); + + aChild = WeakBullet::HardRefType( xChild, pChild ); + + aChild->SetEditSource( &GetEditSource() ); + aChild->SetParagraphIndex( GetParagraphIndex() ); + aChild->SetIndexInParent( i ); + + maImageBullet = aChild; + } + + return aChild.getRef(); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + +#ifdef DBG_UTIL + if( !mxParent.is() ) + DBG_TRACE( "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?"); +#endif + + return mxParent; + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return mnIndexInParent; + } + + sal_Int16 SAL_CALL AccessibleEditableTextPara::getAccessibleRole() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return AccessibleRole::PARAGRAPH; + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getAccessibleDescription() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + +// ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return ::rtl::OUString(); + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getAccessibleName() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + +// ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return ::rtl::OUString(); + } + + uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleEditableTextPara::getAccessibleRelationSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // --> OD 2006-01-11 #i27138# - provide relations CONTENT_FLOWS_FROM + // and CONTENT_FLOWS_TO + if ( mpParaManager ) + { + utl::AccessibleRelationSetHelper* pAccRelSetHelper = + new utl::AccessibleRelationSetHelper(); + sal_Int32 nMyParaIndex( GetParagraphIndex() ); + // relation CONTENT_FLOWS_FROM + if ( nMyParaIndex > 0 && + mpParaManager->IsReferencable( nMyParaIndex - 1 ) ) + { + uno::Sequence<uno::Reference<XInterface> > aSequence(1); + aSequence[0] = + mpParaManager->GetChild( nMyParaIndex - 1 ).first.get().getRef(); + AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM, + aSequence ); + pAccRelSetHelper->AddRelation( aAccRel ); + } + + // relation CONTENT_FLOWS_TO + if ( (nMyParaIndex + 1) < (sal_Int32)mpParaManager->GetNum() && + mpParaManager->IsReferencable( nMyParaIndex + 1 ) ) + { + uno::Sequence<uno::Reference<XInterface> > aSequence(1); + aSequence[0] = + mpParaManager->GetChild( nMyParaIndex + 1 ).first.get().getRef(); + AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO, + aSequence ); + pAccRelSetHelper->AddRelation( aAccRel ); + } + + return pAccRelSetHelper; + } + else + { + // no relations, therefore empty + return uno::Reference< XAccessibleRelationSet >(); + } + // <-- + } + + uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Create a copy of the state set and return it. + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + if( !pStateSet ) + return uno::Reference<XAccessibleStateSet>(); + + return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) ); + } + + lang::Locale SAL_CALL AccessibleEditableTextPara::getLocale() throw (IllegalAccessibleComponentStateException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return implGetLocale(); + } + + void SAL_CALL AccessibleEditableTextPara::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener ); + } + + void SAL_CALL AccessibleEditableTextPara::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener ); + } + + // XAccessibleComponent + sal_Bool SAL_CALL AccessibleEditableTextPara::containsPoint( const awt::Point& aTmpPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::contains: index value overflow"); + + awt::Rectangle aTmpRect = getBounds(); + Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) ); + Point aPoint( aTmpPoint.X, aTmpPoint.Y ); + + return aRect.IsInside( aPoint ); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( HaveChildren() ) + { + // #103862# No longer need to make given position relative + Point aPoint( _aPoint.X, _aPoint.Y ); + + // respect EditEngine offset to surrounding shape/cell + aPoint -= GetEEOffset(); + + // convert to EditEngine coordinate system + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) ); + + EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( static_cast< USHORT > (GetParagraphIndex()) ); + + if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && + aBulletInfo.bVisible && + aBulletInfo.nType == SVX_NUM_BITMAP ) + { + Rectangle aRect = aBulletInfo.aBounds; + + if( aRect.IsInside( aLogPoint ) ) + return getAccessibleChild(0); + } + } + + // no children at all, or none at given position + return uno::Reference< XAccessible >(); + } + + awt::Rectangle SAL_CALL AccessibleEditableTextPara::getBounds() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getBounds: index value overflow"); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Rectangle aRect = rCacheTF.GetParaBounds( static_cast< USHORT >( GetParagraphIndex() ) ); + + // convert to screen coordinates + Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, + rCacheTF.GetMapMode(), + GetViewForwarder() ); + + // offset from shape/cell + Point aOffset = GetEEOffset(); + + return awt::Rectangle( aScreenRect.Left() + aOffset.X(), + aScreenRect.Top() + aOffset.Y(), + aScreenRect.GetSize().Width(), + aScreenRect.GetSize().Height() ); + } + + awt::Point SAL_CALL AccessibleEditableTextPara::getLocation( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Point( aRect.X, aRect.Y ); + } + + awt::Point SAL_CALL AccessibleEditableTextPara::getLocationOnScreen( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // relate us to parent + uno::Reference< XAccessible > xParent = getAccessibleParent(); + if( xParent.is() ) + { + uno::Reference< XAccessibleComponent > xParentComponent( xParent, uno::UNO_QUERY ); + if( xParentComponent.is() ) + { + awt::Point aRefPoint = xParentComponent->getLocationOnScreen(); + awt::Point aPoint = getLocation(); + aPoint.X += aRefPoint.X; + aPoint.Y += aRefPoint.Y; + + return aPoint; + } + } + + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot access parent")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + } + + awt::Size SAL_CALL AccessibleEditableTextPara::getSize( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Size( aRect.Width, aRect.Height ); + } + + void SAL_CALL AccessibleEditableTextPara::grabFocus( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // set cursor to this paragraph + setSelection(0,0); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getForeground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // #104444# Added to XAccessibleComponent interface + svtools::ColorConfig aColorConfig; + UINT32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; + return static_cast<sal_Int32>(nColor); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getBackground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // #104444# Added to XAccessibleComponent interface + Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor() ); + + // the background is transparent + aColor.SetTransparency( 0xFF); + + return static_cast<sal_Int32>( aColor.GetColor() ); + } + + // XAccessibleText + sal_Int32 SAL_CALL AccessibleEditableTextPara::getCaretPosition() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( !HaveEditView() ) + return -1; + + ESelection aSelection; + if( GetEditViewForwarder().GetSelection( aSelection ) && + GetParagraphIndex() == aSelection.nEndPara ) + { + // caret is always nEndPara,nEndPos + return aSelection.nEndPos; + } + + // not within this paragraph + return -1; + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return setSelection(nIndex, nIndex); + } + + sal_Unicode SAL_CALL AccessibleEditableTextPara::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacter: index value overflow"); + + return OCommonAccessibleText::getCharacter( nIndex ); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& rRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + CheckIndex(nIndex); // may throw IndexOutOfBoundsException + + // get default attribues... + ::comphelper::SequenceAsHashMap aPropHashMap( getDefaultAttributes( rRequestedAttributes ) ); + + // ... and override them with the direct attributes from the specific position + uno::Sequence< beans::PropertyValue > aRunAttribs( getRunAttributes( nIndex, rRequestedAttributes ) ); + sal_Int32 nRunAttribs = aRunAttribs.getLength(); + const beans::PropertyValue *pRunAttrib = aRunAttribs.getConstArray(); + for (sal_Int32 k = 0; k < nRunAttribs; ++k) + { + const beans::PropertyValue &rRunAttrib = pRunAttrib[k]; + aPropHashMap[ rRunAttrib.Name ] = rRunAttrib.Value; //!! should not only be the value !! + } +#ifdef TL_DEBUG + { + uno::Sequence< rtl::OUString > aNames(1); + aNames.getArray()[0] = rtl::OUString::createFromAscii("CharHeight"); + const rtl::OUString *pNames = aNames.getConstArray(); + const uno::Sequence< beans::PropertyValue > aAttribs( getRunAttributes( nIndex, aNames ) ); + const beans::PropertyValue *pAttribs = aAttribs.getConstArray(); + double d1 = -1.0; + float f1 = -1.0; + if (aAttribs.getLength()) + { + uno::Any aAny( pAttribs[0].Value ); + aAny >>= d1; + aAny >>= f1; + } + int i = 3; + } +#endif + + // get resulting sequence + uno::Sequence< beans::PropertyValue > aRes; + aPropHashMap >> aRes; + + // since SequenceAsHashMap ignores property handles and property state + // we have to restore the property state here (property handles are + // of no use to the accessibility API). + sal_Int32 nRes = aRes.getLength(); + beans::PropertyValue *pRes = aRes.getArray(); + for (sal_Int32 i = 0; i < nRes; ++i) + { + beans::PropertyValue &rRes = pRes[i]; + sal_Bool bIsDirectVal = sal_False; + for (sal_Int32 k = 0; k < nRunAttribs && !bIsDirectVal; ++k) + { + if (rRes.Name == pRunAttrib[k].Name) + bIsDirectVal = sal_True; + } + rRes.Handle = -1; + rRes.State = bIsDirectVal ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; + } + + return aRes; + } + + awt::Rectangle SAL_CALL AccessibleEditableTextPara::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterBounds: index value overflow"); + + // #108900# Have position semantics now for nIndex, as + // one-past-the-end values are legal, too. + CheckPosition( nIndex ); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Rectangle aRect = rCacheTF.GetCharBounds( static_cast< USHORT >( GetParagraphIndex() ), static_cast< USHORT >( nIndex ) ); + + // convert to screen + Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, + rCacheTF.GetMapMode(), + GetViewForwarder() ); + // #109864# offset from parent (paragraph), but in screen + // coordinates. This makes sure the internal text offset in + // the outline view forwarder gets cancelled out here + awt::Rectangle aParaRect( getBounds() ); + aScreenRect.Move( -aParaRect.X, -aParaRect.Y ); + + // offset from shape/cell + Point aOffset = GetEEOffset(); + + return awt::Rectangle( aScreenRect.Left() + aOffset.X(), + aScreenRect.Top() + aOffset.Y(), + aScreenRect.GetSize().Width(), + aScreenRect.GetSize().Height() ); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getCharacterCount() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterCount: index value overflow"); + + return OCommonAccessibleText::getCharacterCount(); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + USHORT nPara, nIndex; + + // offset from surrounding cell/shape + Point aOffset( GetEEOffset() ); + Point aPoint( rPoint.X - aOffset.X(), rPoint.Y - aOffset.Y() ); + + // convert to logical coordinates + SvxTextForwarder& rCacheTF = GetTextForwarder(); + Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) ); + + // re-offset to parent (paragraph) + Rectangle aParaRect = rCacheTF.GetParaBounds( static_cast< USHORT >( GetParagraphIndex() ) ); + aLogPoint.Move( aParaRect.Left(), aParaRect.Top() ); + + if( rCacheTF.GetIndexAtPoint( aLogPoint, nPara, nIndex ) && + GetParagraphIndex() == nPara ) + { + // #102259# Double-check if we're _really_ on the given character + try + { + awt::Rectangle aRect1( getCharacterBounds(nIndex) ); + Rectangle aRect2( aRect1.X, aRect1.Y, + aRect1.Width + aRect1.X, aRect1.Height + aRect1.Y ); + if( aRect2.IsInside( Point( rPoint.X, rPoint.Y ) ) ) + return nIndex; + else + return -1; + } + catch( const lang::IndexOutOfBoundsException& ) + { + // #103927# Don't throw for invalid nIndex values + return -1; + } + } + else + { + // not within our paragraph + return -1; + } + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getSelectedText() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getSelectedText: index value overflow"); + + if( !HaveEditView() ) + return ::rtl::OUString(); + + return OCommonAccessibleText::getSelectedText(); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionStart() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getSelectionStart: index value overflow"); + + if( !HaveEditView() ) + return -1; + + return OCommonAccessibleText::getSelectionStart(); + } + + sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionEnd() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getSelectionEnd: index value overflow"); + + if( !HaveEditView() ) + return -1; + + return OCommonAccessibleText::getSelectionEnd(); + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::setSelection: paragraph index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + return rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getText() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getText: paragraph index value overflow"); + + return OCommonAccessibleText::getText(); + } + + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextRange: paragraph index value overflow"); + + return OCommonAccessibleText::getTextRange(nStartIndex, nEndIndex); + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextAtIndex: paragraph index value overflow"); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch( aTextType ) + { + // Not yet handled by OCommonAccessibleText. Missing + // implGetAttributeRunBoundary() method there + case AccessibleTextType::ATTRIBUTE_RUN: + { + const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( static_cast< USHORT >( GetParagraphIndex() ) ); + + if( nIndex == nTextLen ) + { + // #i17014# Special-casing one-behind-the-end character + aResult.SegmentStart = aResult.SegmentEnd = nTextLen; + } + else + { + USHORT nStartIndex, nEndIndex; + + if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + break; + } + + default: + aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); + break; + } /* end of switch( aTextType ) */ + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextBeforeIndex: paragraph index value overflow"); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch( aTextType ) + { + // Not yet handled by OCommonAccessibleText. Missing + // implGetAttributeRunBoundary() method there + case AccessibleTextType::ATTRIBUTE_RUN: + { + const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( static_cast< USHORT >( GetParagraphIndex() ) ); + USHORT nStartIndex, nEndIndex; + + if( nIndex == nTextLen ) + { + // #i17014# Special-casing one-behind-the-end character + if( nIndex > 0 && + GetAttributeRun(nStartIndex, nEndIndex, nIndex-1) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + else + { + if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) + { + // already at the left border? If not, query + // one index further left + if( nStartIndex > 0 && + GetAttributeRun(nStartIndex, nEndIndex, nStartIndex-1) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + } + break; + } + + default: + aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); + break; + } /* end of switch( aTextType ) */ + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getTextBehindIndex: paragraph index value overflow"); + + ::com::sun::star::accessibility::TextSegment aResult; + aResult.SegmentStart = -1; + aResult.SegmentEnd = -1; + + switch( aTextType ) + { + case AccessibleTextType::ATTRIBUTE_RUN: + { + USHORT nStartIndex, nEndIndex; + + if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) + { + // already at the right border? + if( nEndIndex < GetTextLen() ) + { + if( GetAttributeRun(nStartIndex, nEndIndex, nEndIndex) ) + { + aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); + aResult.SegmentStart = nStartIndex; + aResult.SegmentEnd = nEndIndex; + } + } + } + break; + } + + default: + aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); + break; + } /* end of switch( aTextType ) */ + + return aResult; + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + #if OSL_DEBUG_LEVEL > 0 + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + (void)rCacheTF; + #else + GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + #endif + + sal_Bool aRetVal; + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::copyText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + // save current selection + ESelection aOldSelection; + + rCacheVF.GetSelection( aOldSelection ); + rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + aRetVal = rCacheVF.Copy(); + rCacheVF.SetSelection( aOldSelection ); // restore + + return aRetVal; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + // XAccessibleEditableText + sal_Bool SAL_CALL AccessibleEditableTextPara::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::cutText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + // don't save selection, might become invalid after cut! + rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + + return rCacheVF.Cut(); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::pasteText( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::pasteText: index value overflow"); + + CheckPosition(nIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nIndex) ) ) + return sal_False; // non-editable area selected + + // #104400# set empty selection (=> cursor) to given index + rCacheVF.SetSelection( MakeCursor(nIndex) ); + + return rCacheVF.Paste(); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::deleteText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + sal_Bool bRet = rCacheTF.Delete( MakeSelection(nStartIndex, nEndIndex) ); + + GetEditSource().UpdateData(); + + return bRet; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::insertText: index value overflow"); + + CheckPosition(nIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nIndex) ) ) + return sal_False; // non-editable area selected + + // #104400# insert given text at empty selection (=> cursor) + sal_Bool bRet = rCacheTF.InsertText( sText, MakeCursor(nIndex) ); + + rCacheTF.QuickFormatDoc(); + GetEditSource().UpdateData(); + + return bRet; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::rtl::OUString& sReplacement ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::replaceText: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + // insert given text into given range => replace + sal_Bool bRet = rCacheTF.InsertText( sReplacement, MakeSelection(nStartIndex, nEndIndex) ); + + rCacheTF.QuickFormatDoc(); + GetEditSource().UpdateData(); + + return bRet; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const uno::Sequence< beans::PropertyValue >& aAttributeSet ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + try + { + // #102710# Request edit view when doing changes + // AccessibleEmptyEditSource relies on this behaviour + GetEditViewForwarder( sal_True ); + SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + USHORT nPara = static_cast< USHORT >( GetParagraphIndex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::setAttributes: index value overflow"); + + CheckRange(nStartIndex, nEndIndex); + + if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) + return sal_False; // non-editable area selected + + // do the indices span the whole paragraph? Then use the outliner map + // TODO: hold it as a member? + SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), + 0 == nStartIndex && + rCacheTF.GetTextLen(nPara) == nEndIndex ? + ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() : + ImplGetSvxTextPortionSvxPropertySet() ); + + aPropSet.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); + + // convert from PropertyValue to Any + sal_Int32 i, nLength( aAttributeSet.getLength() ); + const beans::PropertyValue* pPropArray = aAttributeSet.getConstArray(); + for(i=0; i<nLength; ++i) + { + try + { + aPropSet.setPropertyValue(pPropArray->Name, pPropArray->Value); + } + catch( const uno::Exception& ) + { + DBG_ERROR("AccessibleEditableTextPara::setAttributes exception in setPropertyValue"); + } + + ++pPropArray; + } + + rCacheTF.QuickFormatDoc(); + GetEditSource().UpdateData(); + + return sal_True; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::setText( const ::rtl::OUString& sText ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + return replaceText(0, getCharacterCount(), sText); + } + + // XAccessibleTextAttributes + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getDefaultAttributes( + const uno::Sequence< ::rtl::OUString >& rRequestedAttributes ) + throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + #if OSL_DEBUG_LEVEL > 0 + SvxAccessibleTextAdapter& rCacheTF = + #endif + GetTextForwarder(); + + #if OSL_DEBUG_LEVEL > 0 + (void)rCacheTF; + #endif + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterAttributes: index value overflow"); + + // get XPropertySetInfo for paragraph attributes and + // character attributes that span all the paragraphs text. + SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), + ImplGetSvxCharAndParaPropertiesSet() ); + aPropSet.SetSelection( MakeSelection( 0, GetTextLen() ) ); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = aPropSet.getPropertySetInfo(); + if (!xPropSetInfo.is()) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot query XPropertySetInfo")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + + // build sequence of available properties to check + sal_Int32 nLenReqAttr = rRequestedAttributes.getLength(); + uno::Sequence< beans::Property > aProperties; + if (nLenReqAttr) + { + const rtl::OUString *pRequestedAttributes = rRequestedAttributes.getConstArray(); + + aProperties.realloc( nLenReqAttr ); + beans::Property *pProperties = aProperties.getArray(); + sal_Int32 nCurLen = 0; + for (sal_Int32 i = 0; i < nLenReqAttr; ++i) + { + beans::Property aProp; + try + { + aProp = xPropSetInfo->getPropertyByName( pRequestedAttributes[i] ); + } + catch (beans::UnknownPropertyException &) + { + continue; + } + pProperties[ nCurLen++ ] = aProp; + } + aProperties.realloc( nCurLen ); + } + else + aProperties = xPropSetInfo->getProperties(); + + sal_Int32 nLength = aProperties.getLength(); + const beans::Property *pProperties = aProperties.getConstArray(); + + // build resulting sequence + uno::Sequence< beans::PropertyValue > aOutSequence( nLength ); + beans::PropertyValue* pOutSequence = aOutSequence.getArray(); + sal_Int32 nOutLen = 0; + for (sal_Int32 i = 0; i < nLength; ++i) + { + // calling implementation functions: + // _getPropertyState and _getPropertyValue (see below) to provide + // the proper paragraph number when retrieving paragraph attributes + PropertyState eState = aPropSet._getPropertyState( pProperties->Name, mnParagraphIndex ); + if ( eState == PropertyState_AMBIGUOUS_VALUE ) + { + OSL_ENSURE( false, "ambiguous property value encountered" ); + } + + //if (eState == PropertyState_DIRECT_VALUE) + // per definition all paragraph properties and all character + // properties spanning the whole paragraph should be returned + // and declared as default value + { + pOutSequence->Name = pProperties->Name; + pOutSequence->Handle = pProperties->Handle; + pOutSequence->Value = aPropSet._getPropertyValue( pProperties->Name, mnParagraphIndex ); + pOutSequence->State = PropertyState_DEFAULT_VALUE; + + ++pOutSequence; + ++nOutLen; + } + ++pProperties; + } + aOutSequence.realloc( nOutLen ); + + return aOutSequence; + } + + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getRunAttributes( + sal_Int32 nIndex, + const uno::Sequence< ::rtl::OUString >& rRequestedAttributes ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + #if OSL_DEBUG_LEVEL > 0 + SvxAccessibleTextAdapter& rCacheTF = + #endif + GetTextForwarder(); + + #if OSL_DEBUG_LEVEL > 0 + (void)rCacheTF; + #endif + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getCharacterAttributes: index value overflow"); + + CheckIndex(nIndex); + + SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), + ImplGetSvxCharAndParaPropertiesSet() ); + aPropSet.SetSelection( MakeSelection( nIndex ) ); + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = aPropSet.getPropertySetInfo(); + if (!xPropSetInfo.is()) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot query XPropertySetInfo")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + + // build sequence of available properties to check + sal_Int32 nLenReqAttr = rRequestedAttributes.getLength(); + uno::Sequence< beans::Property > aProperties; + if (nLenReqAttr) + { + const rtl::OUString *pRequestedAttributes = rRequestedAttributes.getConstArray(); + + aProperties.realloc( nLenReqAttr ); + beans::Property *pProperties = aProperties.getArray(); + sal_Int32 nCurLen = 0; + for (sal_Int32 i = 0; i < nLenReqAttr; ++i) + { + beans::Property aProp; + try + { + aProp = xPropSetInfo->getPropertyByName( pRequestedAttributes[i] ); + } + catch (beans::UnknownPropertyException &) + { + continue; + } + pProperties[ nCurLen++ ] = aProp; + } + aProperties.realloc( nCurLen ); + } + else + aProperties = xPropSetInfo->getProperties(); + + sal_Int32 nLength = aProperties.getLength(); + const beans::Property *pProperties = aProperties.getConstArray(); + + // build resulting sequence + uno::Sequence< beans::PropertyValue > aOutSequence( nLength ); + beans::PropertyValue* pOutSequence = aOutSequence.getArray(); + sal_Int32 nOutLen = 0; + for (sal_Int32 i = 0; i < nLength; ++i) + { + // calling 'regular' functions that will operate on the selection + PropertyState eState = aPropSet.getPropertyState( pProperties->Name ); + if (eState == PropertyState_DIRECT_VALUE) + { + pOutSequence->Name = pProperties->Name; + pOutSequence->Handle = pProperties->Handle; + pOutSequence->Value = aPropSet.getPropertyValue( pProperties->Name ); + pOutSequence->State = eState; + + ++pOutSequence; + ++nOutLen; + } + ++pProperties; + } + aOutSequence.realloc( nOutLen ); + + return aOutSequence; + } + + // XAccessibleMultiLineText + sal_Int32 SAL_CALL AccessibleEditableTextPara::getLineNumberAtIndex( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + sal_Int32 nRes = -1; + sal_Int32 nPara = GetParagraphIndex(); + + SvxTextForwarder &rCacheTF = GetTextForwarder(); + const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount(); + DBG_ASSERT( bValidPara, "getLineNumberAtIndex: current paragraph index out of range" ); + if (bValidPara) + { + // we explicitly allow for the index to point at the character right behind the text + if (0 <= nIndex && nIndex <= rCacheTF.GetTextLen( static_cast< USHORT >(nPara) )) + nRes = rCacheTF.GetLineNumberAtIndex( static_cast< USHORT >(nPara), static_cast< USHORT >(nIndex) ); + else + throw lang::IndexOutOfBoundsException(); + } + return nRes; + } + + // XAccessibleMultiLineText + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineNumber( sal_Int32 nLineNo ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::com::sun::star::accessibility::TextSegment aResult; + sal_Int32 nPara = GetParagraphIndex(); + SvxTextForwarder &rCacheTF = GetTextForwarder(); + const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount(); + DBG_ASSERT( bValidPara, "getTextAtLineNumber: current paragraph index out of range" ); + if (bValidPara) + { + if (0 <= nLineNo && nLineNo < rCacheTF.GetLineCount( static_cast< USHORT >(nPara) )) + { + USHORT nStart = 0, nEnd = 0; + rCacheTF.GetLineBoundaries( nStart, nEnd, static_cast< USHORT >(nPara), static_cast< USHORT >(nLineNo) ); + if (nStart != 0xFFFF && nEnd != 0xFFFF) + { + try + { + aResult.SegmentText = getTextRange( nStart, nEnd ); + aResult.SegmentStart = nStart; + aResult.SegmentEnd = nEnd; + } + catch (lang::IndexOutOfBoundsException) + { + // this is not the exception that should be raised in this function ... + DBG_ASSERT( 0, "unexpected exception" ); + } + } + } + else + throw lang::IndexOutOfBoundsException(); + } + return aResult; + } + + // XAccessibleMultiLineText + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineWithCaret( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + ::com::sun::star::accessibility::TextSegment aResult; + try + { + aResult = getTextAtLineNumber( getNumberOfLineWithCaret() ); + } + catch (lang::IndexOutOfBoundsException &) + { + // this one needs to be catched since this interface does not allow for it. + } + return aResult; + } + + // XAccessibleMultiLineText + sal_Int32 SAL_CALL AccessibleEditableTextPara::getNumberOfLineWithCaret( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + sal_Int32 nRes = -1; + try + { + nRes = getLineNumberAtIndex( getCaretPosition() ); + } + catch (lang::IndexOutOfBoundsException &) + { + // this one needs to be catched since this interface does not allow for it. + } + return nRes; + } + + + // XServiceInfo + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getImplementationName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("AccessibleEditableTextPara")); + } + + sal_Bool SAL_CALL AccessibleEditableTextPara::supportsService (const ::rtl::OUString& sServiceName) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // Iterate over all supported service names and return true if on of them + // matches the given name. + uno::Sequence< ::rtl::OUString> aSupportedServices ( + getSupportedServiceNames ()); + for (int i=0; i<aSupportedServices.getLength(); i++) + if (sServiceName == aSupportedServices[i]) + return sal_True; + return sal_False; + } + + uno::Sequence< ::rtl::OUString> SAL_CALL AccessibleEditableTextPara::getSupportedServiceNames (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + const ::rtl::OUString sServiceName( getServiceName() ); + return uno::Sequence< ::rtl::OUString > (&sServiceName, 1); + } + + // XServiceName + ::rtl::OUString SAL_CALL AccessibleEditableTextPara::getServiceName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleEditableTextPara, NULL ); + + // #105185# Using correct service now + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.AccessibleParagraphView")); + } + +} // end of namespace accessibility + +//------------------------------------------------------------------------ diff --git a/editeng/source/accessibility/AccessibleEditableTextPara.hxx b/editeng/source/accessibility/AccessibleEditableTextPara.hxx new file mode 100644 index 0000000000..f78cbd4ad4 --- /dev/null +++ b/editeng/source/accessibility/AccessibleEditableTextPara.hxx @@ -0,0 +1,414 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleEditableTextPara.hxx,v $ + * $Revision: 1.22 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVX_ACCESSIBLE_EDITABLE_TEXT_PARA_HXX +#define _SVX_ACCESSIBLE_EDITABLE_TEXT_PARA_HXX + +#include <tools/gen.hxx> +#include <tools/string.hxx> +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/compbase8.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/interfacecontainer.hxx> + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleEditableText.hpp> +#include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp> +#include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp> + +#include <comphelper/accessibletexthelper.hxx> +#include <comphelper/broadcasthelper.hxx> +#include "AccessibleParaManager.hxx" +#include "AccessibleImageBullet.hxx" +#include "unoedprx.hxx" + +namespace accessibility +{ + typedef ::cppu::WeakComponentImplHelper8< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleEditableText, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::accessibility::XAccessibleTextAttributes, + ::com::sun::star::accessibility::XAccessibleMultiLineText, + ::com::sun::star::lang::XServiceInfo > AccessibleTextParaInterfaceBase; + + /** This class implements the actual text paragraphs for the EditEngine/Outliner UAA + */ + class AccessibleEditableTextPara : public ::comphelper::OBaseMutex, public AccessibleTextParaInterfaceBase, public ::comphelper::OCommonAccessibleText + { + + protected: + // override OCommonAccessibleText methods + virtual ::rtl::OUString implGetText(); + virtual ::com::sun::star::lang::Locale implGetLocale(); + virtual void implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ); + virtual void implGetParagraphBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex ); + virtual void implGetLineBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex ); + + public: + /// Create accessible object for given parent + // --> OD 2006-01-11 #i27138# + // - add parameter <_pParaManager> (default value NULL) + // This has to be the the instance of <AccessibleParaManager>, which + // created and manages this accessible paragraph. + AccessibleEditableTextPara ( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rParent, + const AccessibleParaManager* _pParaManager = NULL ); + // <-- + + virtual ~AccessibleEditableTextPara (); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface (const ::com::sun::star::uno::Type & rType) throw (::com::sun::star::uno::RuntimeException); + + // XComponent + + using WeakComponentImplHelperBase::addEventListener; + using WeakComponentImplHelperBase::removeEventListener; + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole() throw (::com::sun::star::uno::RuntimeException); + /// Maximal length of text returned by getAccessibleDescription() + enum { MaxDescriptionLen = 40 }; + virtual ::rtl::OUString SAL_CALL getAccessibleDescription() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale() throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleText (this comes implicitely inherited by XAccessibleEditableText AND by XAccessibleMultiLineText) + virtual sal_Int32 SAL_CALL getCaretPosition() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setCaretPosition( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getCharacterCount() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getIndexAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getSelectedText() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectionStart() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getSelectionEnd() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getText() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine) + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine) + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine) + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEditableText + virtual sal_Bool SAL_CALL cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL pasteText( sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL insertText( const ::rtl::OUString& sText, sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::rtl::OUString& sReplacement ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aAttributeSet ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL setText( const ::rtl::OUString& sText ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleTextAttributes + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getDefaultAttributes( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > SAL_CALL getRunAttributes( ::sal_Int32 Index, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleMultiLineText + virtual ::sal_Int32 SAL_CALL getLineNumberAtIndex( ::sal_Int32 nIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtLineNumber( ::sal_Int32 nLineNo ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::accessibility::TextSegment SAL_CALL getTextAtLineWithCaret( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::sal_Int32 SAL_CALL getNumberOfLineWithCaret( ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName (void) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService (const ::rtl::OUString& sServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL getSupportedServiceNames (void) throw (::com::sun::star::uno::RuntimeException); + + // XServiceName + virtual ::rtl::OUString SAL_CALL getServiceName (void) throw (::com::sun::star::uno::RuntimeException); + + /** Set the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetIndexInParent( sal_Int32 nIndex ); + + /** Get the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetIndexInParent() const; + + /** Set the current paragraph number + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetParagraphIndex( sal_Int32 nIndex ); + + /** Query the current paragraph number (0 - nParas-1) + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetParagraphIndex() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Set the edit engine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEEOffset( const Point& rOffset ); + + /** Set the EditEngine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEditSource( SvxEditSourceAdapter* pEditSource ); + + /** Dispose this object + + Notifies and deregisters the listeners, drops all references. + */ + void Dispose(); + + /// Calls all Listener objects to tell them the change. Don't hold locks when calling this! + virtual void FireEvent(const sal_Int16 nEventId, const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + /// Queries the given state on the internal state set + bool HasState( const sal_Int16 nStateId ); + /// Sets the given state on the internal state set and fires STATE_CHANGE event. Don't hold locks when calling this! + void SetState( const sal_Int16 nStateId ); + /// Unsets the given state on the internal state set and fires STATE_CHANGE event. Don't hold locks when calling this! + void UnSetState( const sal_Int16 nStateId ); + + static Rectangle LogicToPixel( const Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder& rForwarder ); + + SvxEditSourceAdapter& GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query the SvxTextForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxAccessibleTextAdapter& GetTextForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query the SvxViewForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxViewForwarder& GetViewForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query whether a GetEditViewForwarder( sal_False ) will return a forwarder + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Bool HaveEditView() const; + + /** Query the SvxEditViewForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxAccessibleTextEditViewAdapter& GetEditViewForwarder( sal_Bool bCreate = sal_False ) const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Send a TEXT_CHANGED event for this paragraph + + This method internally caters for calculating text + differences, and sends the appropriate Anys in the + Accessibility::TEXT_CHANGED event + */ + void TextChanged(); + + private: + + // declared, but not defined + AccessibleEditableTextPara( const AccessibleEditableTextPara& ); + AccessibleEditableTextPara& operator= ( const AccessibleEditableTextPara& ); + + /** Calculate character range of similar attributes + + @param nStartIndex + Therein, the start of the character range with the same attributes is returned + + @param nEndIndex + Therein, the end (exclusively) of the character range with the same attributes is returned + + @param nIndex + The character index at where to look for similar character attributes + + @return sal_False, if the method was not able to determine the range + */ + sal_Bool GetAttributeRun( USHORT& nStartIndex, USHORT& nEndIndex, sal_Int32 nIndex ); + + // syntactic sugar for FireEvent + void GotPropertyEvent( const ::com::sun::star::uno::Any& rNewValue, const sal_Int16 nEventId ) const; + void LostPropertyEvent( const ::com::sun::star::uno::Any& rOldValue, const sal_Int16 nEventId ) const; + + /** Query the visibility state + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + + @return the visibility state. Per definition, a defunc object is no longer visible + */ + sal_Bool IsVisible() const; + + int getNotifierClientId() const; + + // retrieve text interface for given paragraph index + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleText > GetParaInterface( sal_Int32 nIndex ); + + /// Do we have children? This is the case for image bullets + sal_Bool HaveChildren(); + + /// Is the underlying object in edit mode + sal_Bool IsActive() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + const Point& GetEEOffset() const; + + // Get text from forwarder + String GetText( sal_Int32 nIndex ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + String GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + USHORT GetTextLen() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Get the current selection of this paragraph + + @return sal_False, if nothing in this paragraph is selected + */ + sal_Bool GetSelection( USHORT& nStartPos, USHORT& nEndPos ) SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** create selection from Accessible selection. + + */ + ESelection MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex ); + ESelection MakeSelection( sal_Int32 nEEIndex ); + ESelection MakeCursor( sal_Int32 nEEIndex ); + + // check whether index value is within permitted range + + /// Check whether 0<=nIndex<=n-1 + void CheckIndex( sal_Int32 nIndex ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); + /// Check whether 0<=nIndex<=n + void CheckPosition( sal_Int32 nIndex ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); + /// Check whether 0<=nStart<=n and 0<=nEnd<=n + void CheckRange( sal_Int32 nStart, sal_Int32 nEnd ) SAL_THROW((::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)); + + // the paragraph index in the edit engine (guarded by solar mutex) + sal_Int32 mnParagraphIndex; + + // our current index in the parent (guarded by solar mutex) + sal_Int32 mnIndexInParent; + + // the current edit source (guarded by solar mutex) + SvxEditSourceAdapter* mpEditSource; + + // the possible child (for image bullets, guarded by solar mutex) + typedef WeakCppRef < ::com::sun::star::accessibility::XAccessible, AccessibleImageBullet > WeakBullet; + WeakBullet maImageBullet; + + // the last string used for an Accessibility::TEXT_CHANGED event (guarded by solar mutex) + ::rtl::OUString maLastTextString; + + // the offset of the underlying EditEngine from the shape/cell (guarded by solar mutex) + Point maEEOffset; + + // the current state set (updated from SetState/UnSetState and guarded by solar mutex) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > mxStateSet; + + /// The shape we're the accessible for (unguarded) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxParent; + + /// Our listeners (guarded by maMutex) + int mnNotifierClientId; + + // --> OD 2006-01-11 #i27138# + // the paragraph manager, which created this instance - is NULL, if + // instance isn't created by AccessibleParaManager. + // Needed for method <getAccessibleRelationSet()> to retrieve predecessor + // paragraph and the successor paragraph. + const AccessibleParaManager* mpParaManager; + }; + +} // end of namespace accessibility + +#endif + diff --git a/editeng/source/accessibility/AccessibleImageBullet.cxx b/editeng/source/accessibility/AccessibleImageBullet.cxx new file mode 100644 index 0000000000..064f196049 --- /dev/null +++ b/editeng/source/accessibility/AccessibleImageBullet.cxx @@ -0,0 +1,654 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleImageBullet.cxx,v $ + * $Revision: 1.22 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" +#include <tools/gen.hxx> +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> +#include <rtl/ustring.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/accessibility/AccessibleRole.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> +#include <com/sun/star/accessibility/AccessibleEventId.hpp> +#include <comphelper/accessibleeventnotifier.hxx> +#include <unotools/accessiblestatesethelper.hxx> +#include <editeng/unolingu.hxx> +#include "AccessibleEditableTextPara.hxx" +#include "AccessibleImageBullet.hxx" +#include <editeng/eerdll.hxx> + +#include <editeng/editdata.hxx> +#include <editeng/editeng.hxx> +#include <editeng/outliner.hxx> +#include "editeng.hrc" +#include <svtools/colorcfg.hxx> + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +namespace accessibility +{ + DBG_NAME( AccessibleImageBullet ) + + AccessibleImageBullet::AccessibleImageBullet ( const uno::Reference< XAccessible >& rParent ) : + mnParagraphIndex( 0 ), + mnIndexInParent( 0 ), + mpEditSource( NULL ), + maEEOffset( 0, 0 ), + mxParent( rParent ), + // well, that's strictly (UNO) exception safe, though not + // really robust. We rely on the fact that this member is + // constructed last, and that the constructor body catches + // exceptions, thus no chance for exceptions once the Id is + // fetched. Nevertheless, normally should employ RAII here... + mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient()) + { +#ifdef DBG_UTIL + DBG_CTOR( AccessibleImageBullet, NULL ); + OSL_TRACE( "Received ID: %d", mnNotifierClientId ); +#endif + + try + { + // Create the state set. + ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper (); + mxStateSet = pStateSet; + + // these are always on + pStateSet->AddState( AccessibleStateType::VISIBLE ); + pStateSet->AddState( AccessibleStateType::SHOWING ); + pStateSet->AddState( AccessibleStateType::ENABLED ); + pStateSet->AddState( AccessibleStateType::SENSITIVE ); + } + catch( const uno::Exception& ) {} + } + + AccessibleImageBullet::~AccessibleImageBullet() + { + DBG_DTOR( AccessibleImageBullet, NULL ); + + // sign off from event notifier + if( getNotifierClientId() != -1 ) + { + try + { + ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() ); +#ifdef DBG_UTIL + OSL_TRACE( "AccessibleImageBullet revoked ID: %d\n", mnNotifierClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + uno::Any SAL_CALL AccessibleImageBullet::queryInterface (const uno::Type & rType) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return AccessibleImageBulletInterfaceBase::queryInterface(rType); + } + + uno::Reference< XAccessibleContext > SAL_CALL AccessibleImageBullet::getAccessibleContext( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // We implement the XAccessibleContext interface in the same object + return uno::Reference< XAccessibleContext > ( this ); + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getAccessibleChildCount() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return 0; + } + + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + (void)i; + + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No childs available")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy + } + + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mxParent; + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getAccessibleIndexInParent() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnIndexInParent; + } + + sal_Int16 SAL_CALL AccessibleImageBullet::getAccessibleRole() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return AccessibleRole::GRAPHIC; + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getAccessibleDescription() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Get the string from the resource for the specified id. + return ::rtl::OUString( String( EditResId (RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION) ) ); + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getAccessibleName() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Get the string from the resource for the specified id. + return ::rtl::OUString( String ( EditResId (RID_SVXSTR_A11Y_IMAGEBULLET_NAME) ) ); + } + + uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleImageBullet::getAccessibleRelationSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // no relations, therefore empty + return uno::Reference< XAccessibleRelationSet >(); + } + + uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleImageBullet::getAccessibleStateSet() throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // Create a copy of the state set and return it. + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + + if( !pStateSet ) + return uno::Reference<XAccessibleStateSet>(); + + return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) ); + } + + lang::Locale SAL_CALL AccessibleImageBullet::getLocale() throw (IllegalAccessibleComponentStateException, uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + lang::Locale aLocale; + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleImageBullet::getLocale: paragraph index value overflow"); + + // return locale of first character in the paragraph + return SvxLanguageToLocale(aLocale, GetTextForwarder().GetLanguage( static_cast< USHORT >( GetParagraphIndex() ), 0 )); + } + + void SAL_CALL AccessibleImageBullet::addEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener ); + } + + void SAL_CALL AccessibleImageBullet::removeEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + if( getNotifierClientId() != -1 ) + ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener ); + } + + sal_Bool SAL_CALL AccessibleImageBullet::containsPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::contains: index value overflow"); + + awt::Rectangle aTmpRect = getBounds(); + Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) ); + Point aPoint( rPoint.X, rPoint.Y ); + + return aRect.IsInside( aPoint ); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleImageBullet::getAccessibleAtPoint( const awt::Point& /*aPoint*/ ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // as we have no children, empty reference + return uno::Reference< XAccessible >(); + } + + awt::Rectangle SAL_CALL AccessibleImageBullet::getBounds( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX, + "AccessibleEditableTextPara::getBounds: index value overflow"); + + SvxTextForwarder& rCacheTF = GetTextForwarder(); + EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( static_cast< USHORT > (GetParagraphIndex()) ); + Rectangle aParentRect = rCacheTF.GetParaBounds( static_cast< USHORT >( GetParagraphIndex() ) ); + + if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && + aBulletInfo.bVisible && + aBulletInfo.nType == SVX_NUM_BITMAP ) + { + Rectangle aRect = aBulletInfo.aBounds; + + // subtract paragraph position (bullet pos is absolute in EditEngine/Outliner) + aRect.Move( -aParentRect.Left(), -aParentRect.Top() ); + + // convert to screen coordinates + Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, + rCacheTF.GetMapMode(), + GetViewForwarder() ); + + // offset from shape/cell + Point aOffset = GetEEOffset(); + + return awt::Rectangle( aScreenRect.Left() + aOffset.X(), + aScreenRect.Top() + aOffset.Y(), + aScreenRect.GetSize().Width(), + aScreenRect.GetSize().Height() ); + } + + return awt::Rectangle(); + } + + awt::Point SAL_CALL AccessibleImageBullet::getLocation( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Point( aRect.X, aRect.Y ); + } + + awt::Point SAL_CALL AccessibleImageBullet::getLocationOnScreen( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // relate us to parent + uno::Reference< XAccessible > xParent = getAccessibleParent(); + if( xParent.is() ) + { + uno::Reference< XAccessibleComponent > xParentComponent( xParent, uno::UNO_QUERY ); + if( xParentComponent.is() ) + { + awt::Point aRefPoint = xParentComponent->getLocationOnScreen(); + awt::Point aPoint = getLocation(); + aPoint.X += aRefPoint.X; + aPoint.Y += aRefPoint.Y; + + return aPoint; + } + } + + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Cannot access parent")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + } + + awt::Size SAL_CALL AccessibleImageBullet::getSize( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + awt::Rectangle aRect = getBounds(); + + return awt::Size( aRect.Width, aRect.Height ); + } + + void SAL_CALL AccessibleImageBullet::grabFocus( ) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Not focusable")), + uno::Reference< uno::XInterface > + ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getForeground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // #104444# Added to XAccessibleComponent interface + svtools::ColorConfig aColorConfig; + UINT32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; + return static_cast<sal_Int32>(nColor); + } + + sal_Int32 SAL_CALL AccessibleImageBullet::getBackground( ) throw (::com::sun::star::uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // #104444# Added to XAccessibleComponent interface + Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor() ); + + // the background is transparent + aColor.SetTransparency( 0xFF); + + return static_cast<sal_Int32>( aColor.GetColor() ); + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getImplementationName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM ("AccessibleImageBullet")); + } + + sal_Bool SAL_CALL AccessibleImageBullet::supportsService (const ::rtl::OUString& sServiceName) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + // Iterate over all supported service names and return true if on of them + // matches the given name. + uno::Sequence< ::rtl::OUString> aSupportedServices ( + getSupportedServiceNames ()); + for (int i=0; i<aSupportedServices.getLength(); i++) + if (sServiceName == aSupportedServices[i]) + return sal_True; + return sal_False; + } + + uno::Sequence< ::rtl::OUString> SAL_CALL AccessibleImageBullet::getSupportedServiceNames (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + const ::rtl::OUString sServiceName (RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.accessibility.AccessibleContext")); + return uno::Sequence< ::rtl::OUString > (&sServiceName, 1); + } + + ::rtl::OUString SAL_CALL AccessibleImageBullet::getServiceName (void) throw (uno::RuntimeException) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.accessibility.AccessibleContext")); + } + + void AccessibleImageBullet::SetIndexInParent( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + mnIndexInParent = nIndex; + } + + sal_Int32 AccessibleImageBullet::GetIndexInParent() const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnIndexInParent; + } + + void AccessibleImageBullet::SetEEOffset( const Point& rOffset ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + maEEOffset = rOffset; + } + + void AccessibleImageBullet::Dispose() + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + int nClientId( getNotifierClientId() ); + + // #108212# drop all references before notifying dispose + mxParent = NULL; + mnNotifierClientId = -1; + mpEditSource = NULL; + + // notify listeners + if( nClientId != -1 ) + { + try + { + uno::Reference < XAccessibleContext > xThis = getAccessibleContext(); + + // #106234# Delegate to EventNotifier + ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, xThis ); +#ifdef DBG_UTIL + OSL_TRACE( "AccessibleImageBullet disposed ID: %d", nClientId ); +#endif + } + catch( const uno::Exception& ) {} + } + } + + void AccessibleImageBullet::SetEditSource( SvxEditSource* pEditSource ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + mpEditSource = pEditSource; + + if( !mpEditSource ) + { + // going defunc + UnSetState( AccessibleStateType::SHOWING ); + UnSetState( AccessibleStateType::VISIBLE ); + SetState( AccessibleStateType::INVALID ); + SetState( AccessibleStateType::DEFUNC ); + + Dispose(); + } + } + + void AccessibleImageBullet::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue ) const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleImageBullet* > (this)->getAccessibleContext() ); + + AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue); + + // #106234# Delegate to EventNotifier + ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(), + aEvent ); + } + + void AccessibleImageBullet::GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + FireEvent( nEventId, rNewValue ); + } + + void AccessibleImageBullet::LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + FireEvent( nEventId, uno::Any(), rOldValue ); + } + + void AccessibleImageBullet::SetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + !pStateSet->contains(nStateId) ) + { + pStateSet->AddState( nStateId ); + GotPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + void AccessibleImageBullet::UnSetState( const sal_Int16 nStateId ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get()); + if( pStateSet != NULL && + pStateSet->contains(nStateId) ) + { + pStateSet->RemoveState( nStateId ); + LostPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED ); + } + } + + int AccessibleImageBullet::getNotifierClientId() const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnNotifierClientId; + } + + void AccessibleImageBullet::SetParagraphIndex( sal_Int32 nIndex ) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + uno::Any aOldDesc; + uno::Any aOldName; + + try + { + aOldDesc <<= getAccessibleDescription(); + aOldName <<= getAccessibleName(); + } + catch( const uno::Exception& ) {} // optional behaviour + + sal_Int32 nOldIndex = mnParagraphIndex; + + mnParagraphIndex = nIndex; + + try + { + if( nOldIndex != nIndex ) + { + // index and therefore description changed + FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc ); + FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName ); + } + } + catch( const uno::Exception& ) {} // optional behaviour + } + + sal_Int32 AccessibleImageBullet::GetParagraphIndex() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return mnParagraphIndex; + } + + SvxEditSource& AccessibleImageBullet::GetEditSource() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + if( mpEditSource ) + return *mpEditSource; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("No edit source, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + SvxTextForwarder& AccessibleImageBullet::GetTextForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxTextForwarder* pTextForwarder = rEditSource.GetTextForwarder(); + + if( !pTextForwarder ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch text forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + + if( pTextForwarder->IsValid() ) + return *pTextForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + SvxViewForwarder& AccessibleImageBullet::GetViewForwarder() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + SvxEditSource& rEditSource = GetEditSource(); + SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder(); + + if( !pViewForwarder ) + { + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Unable to fetch view forwarder, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + if( pViewForwarder->IsValid() ) + return *pViewForwarder; + else + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("View forwarder is invalid, object is defunct")), + uno::Reference< uno::XInterface > + ( static_cast< ::cppu::OWeakObject* > + ( const_cast< AccessibleImageBullet* > (this) ) ) ); // disambiguate hierarchy + } + + const Point& AccessibleImageBullet::GetEEOffset() const + { + DBG_CHKTHIS( AccessibleImageBullet, NULL ); + + return maEEOffset; + } + +} // end of namespace accessibility + diff --git a/editeng/source/accessibility/AccessibleImageBullet.hxx b/editeng/source/accessibility/AccessibleImageBullet.hxx new file mode 100644 index 0000000000..b1dc462021 --- /dev/null +++ b/editeng/source/accessibility/AccessibleImageBullet.hxx @@ -0,0 +1,240 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleImageBullet.hxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVX_ACCESSIBLE_IMAGE_BULLET_HXX +#define _SVX_ACCESSIBLE_IMAGE_BULLET_HXX + +#include <tools/gen.hxx> +#include <cppuhelper/weakref.hxx> +#include <cppuhelper/implbase5.hxx> + +#ifndef _CPPUHELPER_INTERFACECONTAINER_H_ +#include <cppuhelper/interfacecontainer.hxx> +#endif +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> +#include <com/sun/star/accessibility/XAccessibleComponent.hpp> +#include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp> +#include "AccessibleParaManager.hxx" +#include <editeng/unoedsrc.hxx> + +namespace accessibility +{ + typedef ::cppu::WeakImplHelper5< ::com::sun::star::accessibility::XAccessible, + ::com::sun::star::accessibility::XAccessibleContext, + ::com::sun::star::accessibility::XAccessibleComponent, + ::com::sun::star::accessibility::XAccessibleEventBroadcaster, + ::com::sun::star::lang::XServiceInfo > AccessibleImageBulletInterfaceBase; + + /** This class implements the image bullets for the EditEngine/Outliner UAA + */ + class AccessibleImageBullet : public AccessibleImageBulletInterfaceBase + { + + public: + /// Create accessible object for given parent + AccessibleImageBullet ( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& rParent ); + + virtual ~AccessibleImageBullet (); + + // XInterface + virtual ::com::sun::star::uno::Any SAL_CALL queryInterface (const ::com::sun::star::uno::Type & rType) throw (::com::sun::star::uno::RuntimeException); + + // XAccessible + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext( ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleContext + virtual sal_Int32 SAL_CALL getAccessibleChildCount() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int16 SAL_CALL getAccessibleRole() throw (::com::sun::star::uno::RuntimeException); + /// Maximal length of text returned by getAccessibleDescription() + enum { MaxDescriptionLen = 40 }; + virtual ::rtl::OUString SAL_CALL getAccessibleDescription() throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getAccessibleName() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::lang::Locale SAL_CALL getLocale() throw (::com::sun::star::accessibility::IllegalAccessibleComponentStateException, ::com::sun::star::uno::RuntimeException); + + // XAccessibleEventBroadcaster + virtual void SAL_CALL addEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeEventListener( const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleEventListener >& xListener ) throw (::com::sun::star::uno::RuntimeException); + + // XAccessibleComponent + virtual sal_Bool SAL_CALL containsPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const ::com::sun::star::awt::Point& aPoint ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Rectangle SAL_CALL getBounds( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocation( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Point SAL_CALL getLocationOnScreen( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::awt::Size SAL_CALL getSize( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL grabFocus( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getForeground( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Int32 SAL_CALL getBackground( ) throw (::com::sun::star::uno::RuntimeException); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName (void) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService (const ::rtl::OUString& sServiceName) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString> SAL_CALL getSupportedServiceNames (void) throw (::com::sun::star::uno::RuntimeException); + + // XServiceName + virtual ::rtl::OUString SAL_CALL getServiceName (void) throw (::com::sun::star::uno::RuntimeException); + + /** Set the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetIndexInParent( sal_Int32 nIndex ); + + /** Get the current index in the accessibility parent + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetIndexInParent() const; + + /** Set the edit engine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEEOffset( const Point& rOffset ); + + /** Set the EditEngine offset + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetEditSource( SvxEditSource* pEditSource ); + + /** Dispose this object + + Notifies and deregisters the listeners, drops all references. + */ + void Dispose(); + + /** Set the current paragraph number + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + void SetParagraphIndex( sal_Int32 nIndex ); + + /** Query the current paragraph number (0 - nParas-1) + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + sal_Int32 GetParagraphIndex() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /// Calls all Listener objects to tell them the change. Don't hold locks when calling this! + virtual void FireEvent(const sal_Int16 nEventId, const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + private: + + // declared, but not defined + AccessibleImageBullet( const AccessibleImageBullet& ); + AccessibleImageBullet& operator= ( const AccessibleImageBullet& ); + + // syntactic sugar for FireEvent + void GotPropertyEvent( const ::com::sun::star::uno::Any& rNewValue, const sal_Int16 nEventId ) const; + void LostPropertyEvent( const ::com::sun::star::uno::Any& rOldValue, const sal_Int16 nEventId ) const; + + // maintain state set and send STATE_CHANGE events + void SetState( const sal_Int16 nStateId ); + void UnSetState( const sal_Int16 nStateId ); + + SvxEditSource& GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + int getNotifierClientId() const; + + /** Query the SvxTextForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxTextForwarder& GetTextForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + /** Query the SvxViewForwarder for EditEngine access. + + @attention This method does not lock the SolarMutex, + leaving that to the calling code. This is because only + there potential deadlock situations can be resolved. Thus, + make sure SolarMutex is locked when calling this. + */ + SvxViewForwarder& GetViewForwarder() const SAL_THROW((::com::sun::star::uno::RuntimeException)); + + const Point& GetEEOffset() const; + + // the paragraph index in the edit engine (guarded by solar mutex) + sal_Int32 mnParagraphIndex; + + // our current index in the parent (guarded by solar mutex) + sal_Int32 mnIndexInParent; + + // the current edit source (guarded by solar mutex) + SvxEditSource* mpEditSource; + + // the offset of the underlying EditEngine from the shape/cell (guarded by solar mutex) + Point maEEOffset; + + // the current state set (updated from SetState/UnSetState and guarded by solar mutex) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleStateSet > mxStateSet; + + mutable osl::Mutex maMutex; + + /// The shape we're the accessible for (unguarded) + ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > mxParent; + + /// Our listeners (guarded by maMutex) + int mnNotifierClientId; + }; + +} // end of namespace accessibility + +#endif + diff --git a/editeng/source/accessibility/AccessibleParaManager.cxx b/editeng/source/accessibility/AccessibleParaManager.cxx new file mode 100644 index 0000000000..0d8e75020c --- /dev/null +++ b/editeng/source/accessibility/AccessibleParaManager.cxx @@ -0,0 +1,423 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleParaManager.cxx,v $ + * $Revision: 1.16 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//------------------------------------------------------------------------ +// +// Global header +// +//------------------------------------------------------------------------ +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/weakref.hxx> +#include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/AccessibleStateType.hpp> + +//------------------------------------------------------------------------ +// +// Project-local header +// +//------------------------------------------------------------------------ + +#include <editeng/unoedhlp.hxx> +#include <editeng/unopracc.hxx> +#include <editeng/unoedsrc.hxx> +#include "AccessibleParaManager.hxx" +#include "AccessibleEditableTextPara.hxx" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + + + +namespace accessibility +{ + AccessibleParaManager::AccessibleParaManager() : + maChildren(1), + maEEOffset( 0, 0 ), + mnFocusedChild( -1 ), + mbActive( sal_False ) + { + } + + AccessibleParaManager::~AccessibleParaManager() + { + // owner is responsible for possible child defuncs + } + + void AccessibleParaManager::SetAdditionalChildStates( const VectorOfStates& rChildStates ) + { + maChildStates = rChildStates; + } + + const AccessibleParaManager::VectorOfStates& AccessibleParaManager::GetAdditionalChildStates() const + { + return maChildStates; + } + + void AccessibleParaManager::SetNum( sal_Int32 nNumParas ) + { + if( (size_t)nNumParas < maChildren.size() ) + Release( nNumParas, maChildren.size() ); + + maChildren.resize( nNumParas ); + + if( mnFocusedChild >= nNumParas ) + mnFocusedChild = -1; + } + + sal_uInt32 AccessibleParaManager::GetNum() const + { + return maChildren.size(); + } + + AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::begin() + { + return maChildren.begin(); + } + + AccessibleParaManager::VectorOfChildren::iterator AccessibleParaManager::end() + { + return maChildren.end(); + } + + AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::begin() const + { + return maChildren.begin(); + } + + AccessibleParaManager::VectorOfChildren::const_iterator AccessibleParaManager::end() const + { + return maChildren.end(); + } + + void AccessibleParaManager::Release( sal_uInt32 nPara ) + { + DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::Release: invalid index" ); + + if( maChildren.size() > nPara ) + { + ShutdownPara( GetChild( nPara ) ); + + // clear reference and rect + maChildren[ nPara ] = WeakChild(); + } + } + + void AccessibleParaManager::FireEvent( sal_uInt32 nPara, + const sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue ) const + { + DBG_ASSERT( maChildren.size() > nPara, "AccessibleParaManager::FireEvent: invalid index" ); + + if( maChildren.size() > nPara ) + { + WeakPara::HardRefType maChild( GetChild( nPara ).first.get() ); + if( maChild.is() ) + maChild->FireEvent( nEventId, rNewValue, rOldValue ); + } + } + + sal_Bool AccessibleParaManager::IsReferencable( WeakPara::HardRefType aChild ) + { + return aChild.is(); + } + + sal_Bool AccessibleParaManager::IsReferencable( sal_uInt32 nChild ) const + { + DBG_ASSERT( maChildren.size() > nChild, "AccessibleParaManager::IsReferencable: invalid index" ); + + if( maChildren.size() > nChild ) + { + // retrieve hard reference from weak one + return IsReferencable( GetChild( nChild ).first.get() ); + } + else + { + return sal_False; + } + } + + AccessibleParaManager::WeakChild AccessibleParaManager::GetChild( sal_uInt32 nParagraphIndex ) const + { + DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::GetChild: invalid index" ); + + if( maChildren.size() > nParagraphIndex ) + { + return maChildren[ nParagraphIndex ]; + } + else + { + return WeakChild(); + } + } + + AccessibleParaManager::Child AccessibleParaManager::CreateChild( sal_Int32 nChild, + const uno::Reference< XAccessible >& xFrontEnd, + SvxEditSourceAdapter& rEditSource, + sal_uInt32 nParagraphIndex ) + { + DBG_ASSERT( maChildren.size() > nParagraphIndex, "AccessibleParaManager::CreateChild: invalid index" ); + + if( maChildren.size() > nParagraphIndex ) + { + // retrieve hard reference from weak one + WeakPara::HardRefType aChild( GetChild( nParagraphIndex ).first.get() ); + + if( !IsReferencable( nParagraphIndex ) ) + { + // there is no hard reference available, create object then + // --> OD 2006-01-11 #i27138# + AccessibleEditableTextPara* pChild = new AccessibleEditableTextPara( xFrontEnd, this ); + // <-- + uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY ); + + if( !xChild.is() ) + throw uno::RuntimeException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Child creation failed")), xFrontEnd); + + aChild = WeakPara::HardRefType( xChild, pChild ); + + InitChild( *aChild, rEditSource, nChild, nParagraphIndex ); + + maChildren[ nParagraphIndex ] = WeakChild( aChild, pChild->getBounds() ); + } + + return Child( aChild.getRef(), GetChild( nParagraphIndex ).second ); + } + else + { + return Child(); + } + } + + void AccessibleParaManager::SetEEOffset( const Point& rOffset ) + { + maEEOffset = rOffset; + + MemFunAdapter< const Point& > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEEOffset, rOffset ); + ::std::for_each( begin(), end(), aAdapter ); + } + + void AccessibleParaManager::SetActive( sal_Bool bActive ) + { + mbActive = bActive; + + if( bActive ) + { + SetState( AccessibleStateType::ACTIVE ); + SetState( AccessibleStateType::EDITABLE ); + } + else + { + UnSetState( AccessibleStateType::ACTIVE ); + UnSetState( AccessibleStateType::EDITABLE ); + } + } + + void AccessibleParaManager::SetFocus( sal_Int32 nChild ) + { + if( mnFocusedChild != -1 ) + UnSetState( mnFocusedChild, AccessibleStateType::FOCUSED ); + + mnFocusedChild = nChild; + + if( mnFocusedChild != -1 ) + SetState( mnFocusedChild, AccessibleStateType::FOCUSED ); + } + + void AccessibleParaManager::InitChild( AccessibleEditableTextPara& rChild, + SvxEditSourceAdapter& rEditSource, + sal_Int32 nChild, + sal_uInt32 nParagraphIndex ) const + { + rChild.SetEditSource( &rEditSource ); + rChild.SetIndexInParent( nChild ); + rChild.SetParagraphIndex( nParagraphIndex ); + + rChild.SetEEOffset( maEEOffset ); + + if( mbActive ) + { + rChild.SetState( AccessibleStateType::ACTIVE ); + rChild.SetState( AccessibleStateType::EDITABLE ); + } + + if( mnFocusedChild == static_cast<sal_Int32>(nParagraphIndex) ) + rChild.SetState( AccessibleStateType::FOCUSED ); + + // add states passed from outside + for( VectorOfStates::const_iterator aIt = maChildStates.begin(), aEnd = maChildStates.end(); aIt != aEnd; ++aIt ) + rChild.SetState( *aIt ); + } + + void AccessibleParaManager::SetState( sal_Int32 nChild, const sal_Int16 nStateId ) + { + MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::SetState, + nStateId ); + aFunc( GetChild(nChild) ); + } + + void AccessibleParaManager::SetState( const sal_Int16 nStateId ) + { + ::std::for_each( begin(), end(), + MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::SetState, + nStateId ) ); + } + + void AccessibleParaManager::UnSetState( sal_Int32 nChild, const sal_Int16 nStateId ) + { + MemFunAdapter< const sal_Int16 > aFunc( &AccessibleEditableTextPara::UnSetState, + nStateId ); + aFunc( GetChild(nChild) ); + } + + void AccessibleParaManager::UnSetState( const sal_Int16 nStateId ) + { + ::std::for_each( begin(), end(), + MemFunAdapter< const sal_Int16 >( &AccessibleEditableTextPara::UnSetState, + nStateId ) ); + } + + void AccessibleParaManager::SetEditSource( SvxEditSourceAdapter* pEditSource ) + { + MemFunAdapter< SvxEditSourceAdapter* > aAdapter( &::accessibility::AccessibleEditableTextPara::SetEditSource, pEditSource ); + ::std::for_each( begin(), end(), aAdapter ); + } + + // not generic yet, no arguments... + class AccessibleParaManager_DisposeChildren : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void > + { + public: + AccessibleParaManager_DisposeChildren() {} + void operator()( ::accessibility::AccessibleEditableTextPara& rPara ) + { + rPara.Dispose(); + } + }; + + void AccessibleParaManager::Dispose() + { + AccessibleParaManager_DisposeChildren aFunctor; + + ::std::for_each( begin(), end(), + WeakChildAdapter< AccessibleParaManager_DisposeChildren > (aFunctor) ); + } + + // not generic yet, too many method arguments... + class StateChangeEvent : public ::std::unary_function< ::accessibility::AccessibleEditableTextPara&, void > + { + public: + typedef void return_type; + StateChangeEvent( const sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue ) : + mnEventId( nEventId ), + mrNewValue( rNewValue ), + mrOldValue( rOldValue ) {} + void operator()( ::accessibility::AccessibleEditableTextPara& rPara ) + { + rPara.FireEvent( mnEventId, mrNewValue, mrOldValue ); + } + + private: + const sal_Int16 mnEventId; + const uno::Any& mrNewValue; + const uno::Any& mrOldValue; + }; + + void AccessibleParaManager::FireEvent( sal_uInt32 nStartPara, + sal_uInt32 nEndPara, + const sal_Int16 nEventId, + const uno::Any& rNewValue, + const uno::Any& rOldValue ) const + { + DBG_ASSERT( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara , "AccessibleParaManager::FireEvent: invalid index" ); + + if( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara ) + { + VectorOfChildren::const_iterator front = maChildren.begin(); + VectorOfChildren::const_iterator back = front; + + ::std::advance( front, nStartPara ); + ::std::advance( back, nEndPara ); + + StateChangeEvent aFunctor( nEventId, rNewValue, rOldValue ); + + ::std::for_each( front, back, AccessibleParaManager::WeakChildAdapter< StateChangeEvent >( aFunctor ) ); + } + } + + class ReleaseChild : public ::std::unary_function< const AccessibleParaManager::WeakChild&, AccessibleParaManager::WeakChild > + { + public: + AccessibleParaManager::WeakChild operator()( const AccessibleParaManager::WeakChild& rPara ) + { + AccessibleParaManager::ShutdownPara( rPara ); + + // clear reference + return AccessibleParaManager::WeakChild(); + } + }; + + void AccessibleParaManager::Release( sal_uInt32 nStartPara, sal_uInt32 nEndPara ) + { + DBG_ASSERT( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara, "AccessibleParaManager::Release: invalid index" ); + + if( maChildren.size() > nStartPara && + maChildren.size() >= nEndPara ) + { + VectorOfChildren::iterator front = maChildren.begin(); + VectorOfChildren::iterator back = front; + + ::std::advance( front, nStartPara ); + ::std::advance( back, nEndPara ); + + ::std::transform( front, back, front, ReleaseChild() ); + } + } + + void AccessibleParaManager::ShutdownPara( const WeakChild& rChild ) + { + WeakPara::HardRefType aChild( rChild.first.get() ); + + if( IsReferencable( aChild ) ) + aChild->SetEditSource( NULL ); + } + +} + +//------------------------------------------------------------------------ diff --git a/editeng/source/accessibility/AccessibleParaManager.hxx b/editeng/source/accessibility/AccessibleParaManager.hxx new file mode 100644 index 0000000000..17644c2b7a --- /dev/null +++ b/editeng/source/accessibility/AccessibleParaManager.hxx @@ -0,0 +1,349 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleParaManager.hxx,v $ + * $Revision: 1.12 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SVX_ACCESSIBLE_PARA_MANAGER_HXX +#define _SVX_ACCESSIBLE_PARA_MANAGER_HXX + +#include <vector> +#include <algorithm> +#include <functional> +#include <utility> +#include <tools/gen.hxx> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/uno/Reference.hxx> +#include <cppuhelper/weakref.hxx> +#include <com/sun/star/accessibility/XAccessibleContext.hpp> + +class SvxEditSourceAdapter; + +namespace accessibility +{ + class AccessibleEditableTextPara; + + /** Helper class for WeakCppRef + + This class is returned by WeakChild::get() and contains a hard + reference and a reference to the c++ object. This combination + prevents the c++ object from destruction during usage. Hold + this object only as long as absolutely necessary, prevents + referenced object from vanishing otherwise + */ + template < class UnoType, class CppType > class HardCppRef + { + public: + + typedef UnoType UnoInterfaceType; + typedef CppType InterfaceType; + + HardCppRef( const ::com::sun::star::uno::WeakReference< UnoInterfaceType >& xRef, InterfaceType* rImpl ) : + mxRef( xRef ), + mpImpl( rImpl ) + { + } + + /** Query whether the reference is still valid. + + Hands off also from the implementation pointer if this + returns sal_False! + */ + sal_Bool is() const { return mxRef.is(); } + InterfaceType* operator->() const { return mpImpl; } + InterfaceType& operator*() const { return *mpImpl; } + ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() { return mxRef; } + const ::com::sun::star::uno::Reference< UnoInterfaceType >& getRef() const { return mxRef; } + + // default copy constructor and assignment will do + // HardCppRef( const HardCppRef& ); + // HardCppRef& operator= ( const HardCppRef& ); + + private: + + // the interface, hard reference to prevent object from vanishing + ::com::sun::star::uno::Reference< UnoInterfaceType > mxRef; + + // the c++ object, for our internal stuff + InterfaceType* mpImpl; + + }; + + /** Helper class for weak object references plus implementation + + This class combines a weak reference (to facilitate automatic + object disposal if user drops last reference) and hard + reference to the c++ class (for fast access and bypassing of + the UNO interface) + */ + template < class UnoType, class CppType > class WeakCppRef + { + public: + + typedef UnoType UnoInterfaceType; + typedef CppType InterfaceType; + typedef HardCppRef< UnoInterfaceType, InterfaceType > HardRefType; + + WeakCppRef() : maWeakRef(), maUnsafeRef( NULL ) {} + WeakCppRef( InterfaceType& rImpl ) : + maWeakRef( ::com::sun::star::uno::Reference< UnoInterfaceType >( rImpl, ::com::sun::star::uno::UNO_QUERY ) ), + maUnsafeRef( &rImpl ) + { + } + + WeakCppRef( HardRefType& rImpl ) : + maWeakRef( rImpl.getRef() ), + maUnsafeRef( rImpl.operator->() ) + { + } + + // get object with c++ object and hard reference (which + // prevents the c++ object from destruction during use) + HardRefType get() const { return HardRefType( maWeakRef, maUnsafeRef ); } + + // default copy constructor and assignment will do + // WeakCppRef( const WeakCppRef& ); + // WeakCppRef& operator= ( const WeakCppRef& ); + + private: + + // the interface, hold weakly + ::com::sun::star::uno::WeakReference< UnoInterfaceType > maWeakRef; + + // hard ref to c++ class, _only_ valid if maWeakRef.is() is true + InterfaceType* maUnsafeRef; + }; + + + /** This class manages the paragraphs of an AccessibleTextHelper + + To facilitate automatic deletion of paragraphs no longer used, + this class uses the WeakCppRef helper to hold the objects weakly. + */ + class AccessibleParaManager + { + public: + typedef WeakCppRef < ::com::sun::star::accessibility::XAccessible, AccessibleEditableTextPara > WeakPara; + typedef ::std::pair< WeakPara, ::com::sun::star::awt::Rectangle > WeakChild; + typedef ::std::pair< ::com::sun::star::uno::Reference< + ::com::sun::star::accessibility::XAccessible > , ::com::sun::star::awt::Rectangle > Child; + typedef ::std::vector< WeakChild > VectorOfChildren; + typedef ::std::vector< sal_Int16 > VectorOfStates; + + AccessibleParaManager(); + ~AccessibleParaManager(); + + /** Sets a vector of additional accessible states. + + The states are passed to every created child object + (text paragraph). The state values are defined in + com::sun::star::accessibility::AccessibleStateType. + */ + void SetAdditionalChildStates( const VectorOfStates& rChildStates ); + + /** Returns the additional accessible states for children. + */ + const VectorOfStates& GetAdditionalChildStates() const; + + /** Set the number of paragraphs + + @param nNumPara + The total number of paragraphs the EditEngine currently + has (_not_ the number of currently visible children) + */ + void SetNum( sal_Int32 nNumParas ); + + /** Get the number of paragraphs currently possible */ + sal_uInt32 GetNum() const; + + // iterators + VectorOfChildren::iterator begin(); + VectorOfChildren::iterator end(); + VectorOfChildren::const_iterator begin() const; + VectorOfChildren::const_iterator end() const; + + // dealing with single paragraphs (release reference, return reference etc) + void Release( sal_uInt32 nPara ); + /// Set focus to given child + void SetFocus( sal_Int32 nChild ); + + void FireEvent( sal_uInt32 nPara, + const sal_Int16 nEventId, + const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), + const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + static sal_Bool IsReferencable( WeakPara::HardRefType aChild ); + sal_Bool IsReferencable( sal_uInt32 nChild ) const; + static void ShutdownPara( const WeakChild& rChild ); + + Child CreateChild( sal_Int32 nChild, + const ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible >& xFrontEnd, + SvxEditSourceAdapter& rEditSource, + sal_uInt32 nParagraphIndex ); + + WeakChild GetChild( sal_uInt32 nParagraphIndex ) const; + + // forwarder to all paragraphs + /// Make all children active and editable (or off) + void SetActive( sal_Bool bActive = sal_True ); + /// Set state of all children + void SetState( const sal_Int16 nStateId ); + /// Unset state of all children + void UnSetState( const sal_Int16 nStateId ); + /// Set offset to edit engine for all children + void SetEEOffset ( const Point& rOffset ); + /// Change edit source on all living children + void SetEditSource ( SvxEditSourceAdapter* pEditSource ); + /// Dispose all living children + void Dispose (); + + // forwarder to given paragraphs + //------------------------------------------------------------------------ + /** Release the given range of paragraphs + + All ranges have the meaning [start,end), similar to STL + + @param nStartPara + Index of paragraph to start with releasing + + @param nEndPara + Index of first paragraph to stop with releasing + */ + void Release( sal_uInt32 nStartPara, sal_uInt32 nEndPara ); + + /** Fire event for the given range of paragraphs + + All ranges have the meaning [start,end), similar to STL + + @param nStartPara + Index of paragraph to start with event firing + + @param nEndPara + Index of first paragraph to stop with event firing + */ + void FireEvent( sal_uInt32 nStartPara, + sal_uInt32 nEndPara, + const sal_Int16 nEventId, + const ::com::sun::star::uno::Any& rNewValue = ::com::sun::star::uno::Any(), + const ::com::sun::star::uno::Any& rOldValue = ::com::sun::star::uno::Any() ) const; + + /** Functor adapter for ForEach template + + Adapts giving functor such that only the paragraph objects + are accessed and the fact that our children are held + weakly is hidden + + The functor must provide the following method: + void operator() ( AccessibleEditablePara& ) + + */ + template < typename Functor > class WeakChildAdapter : public ::std::unary_function< const WeakChild&, void > + { + public: + WeakChildAdapter( Functor& rFunctor ) : mrFunctor(rFunctor) {} + void operator()( const WeakChild& rPara ) + { + // retrieve hard reference from weak one + WeakPara::HardRefType aHardRef( rPara.first.get() ); + + if( aHardRef.is() ) + mrFunctor( *aHardRef ); + } + + private: + Functor& mrFunctor; + }; + + /** Adapter for unary member functions + + Since STL's binder don't work with const& arguments (and + BOOST's neither, at least on MSVC), have to provide our + own adapter for unary member functions. + + Create with pointer to member function of + AccessibleEditableTextPara and the corresponding argument. + */ + template < typename Argument > class MemFunAdapter : public ::std::unary_function< const WeakChild&, void > + { + public: + typedef void (::accessibility::AccessibleEditableTextPara::*FunctionPointer)( Argument ); + + MemFunAdapter( FunctionPointer aFunPtr, Argument aArg ) : maFunPtr(aFunPtr), maArg(aArg) {} + void operator()( const WeakChild& rPara ) + { + // retrieve hard reference from weak one + WeakPara::HardRefType aHardRef( rPara.first.get() ); + + if( aHardRef.is() ) + (*aHardRef.*maFunPtr)( maArg ); + } + + private: + FunctionPointer maFunPtr; + Argument maArg; + }; + + /** Generic algorithm on given paragraphs + + Convenience method, that already adapts the given functor with WeakChildAdapter + */ + template < typename Functor > void ForEach( Functor& rFunctor ) + { + ::std::for_each( begin(), end(), WeakChildAdapter< Functor >(rFunctor) ); + } + + private: + /// Set state on given child + void SetState( sal_Int32 nChild, const sal_Int16 nStateId ); + /// Unset state on given child + void UnSetState( sal_Int32 nChild, const sal_Int16 nStateId ); + /// Init child with default state (as stored in previous SetFocus and SetActive calls) + void InitChild( AccessibleEditableTextPara& rChild, + SvxEditSourceAdapter& rEditSource, + sal_Int32 nChild, + sal_uInt32 nParagraphIndex ) const; + + // vector the size of the paragraph number of the underlying EditEngine + VectorOfChildren maChildren; + + /// Additional states that will be set at every created child object. + VectorOfStates maChildStates; + + // cache EE offset for child creation + Point maEEOffset; + + // which child currently has the focus (-1 for none) + sal_Int32 mnFocusedChild; + + // whether children are active and editable + sal_Bool mbActive; + }; + +} // end of namespace accessibility + +#endif + diff --git a/editeng/source/accessibility/AccessibleSelectionBase.cxx b/editeng/source/accessibility/AccessibleSelectionBase.cxx new file mode 100644 index 0000000000..56054da0a8 --- /dev/null +++ b/editeng/source/accessibility/AccessibleSelectionBase.cxx @@ -0,0 +1,111 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleSelectionBase.cxx,v $ + * $Revision: 1.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <editeng/AccessibleSelectionBase.hxx> + +using namespace ::rtl; +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +namespace accessibility +{ + // --------------------------- + // - AccessibleSelectionBase - + // --------------------------- + + AccessibleSelectionBase::AccessibleSelectionBase() + { + } + + //-------------------------------------------------------------------- + + AccessibleSelectionBase::~AccessibleSelectionBase() + { + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::selectAccessibleChild( sal_Int32 nChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::selectAccessibleChild( nChildIndex ); + } + + //-------------------------------------------------------------------- + + sal_Bool SAL_CALL AccessibleSelectionBase::isAccessibleChildSelected( sal_Int32 nChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + return( OCommonAccessibleSelection::isAccessibleChildSelected( nChildIndex ) ); + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::clearAccessibleSelection( ) throw (uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::clearAccessibleSelection(); + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::selectAllAccessibleChildren( ) throw (uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::selectAllAccessibleChildren(); + } + + //-------------------------------------------------------------------- + + sal_Int32 SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChildCount( ) throw (uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + return( OCommonAccessibleSelection::getSelectedAccessibleChildCount() ); + } + + //-------------------------------------------------------------------- + + uno::Reference< XAccessible > SAL_CALL AccessibleSelectionBase::getSelectedAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + return( OCommonAccessibleSelection::getSelectedAccessibleChild( nSelectedChildIndex ) ); + } + + //-------------------------------------------------------------------- + + void SAL_CALL AccessibleSelectionBase::deselectAccessibleChild( sal_Int32 nSelectedChildIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::osl::MutexGuard aGuard( implGetMutex() ); + OCommonAccessibleSelection::deselectAccessibleChild( nSelectedChildIndex ); + } +} diff --git a/editeng/source/accessibility/AccessibleStaticTextBase.cxx b/editeng/source/accessibility/AccessibleStaticTextBase.cxx new file mode 100644 index 0000000000..1caa0e7392 --- /dev/null +++ b/editeng/source/accessibility/AccessibleStaticTextBase.cxx @@ -0,0 +1,1050 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleStaticTextBase.cxx,v $ + * $Revision: 1.27 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +//------------------------------------------------------------------------ +// +// Global header +// +//------------------------------------------------------------------------ + +#include <limits.h> +#include <vector> +#include <algorithm> +#include <boost/bind.hpp> +#include <vos/mutex.hxx> +#include <vcl/window.hxx> +#include <vcl/svapp.hxx> +#include <comphelper/sequenceasvector.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/awt/Point.hpp> +#include <com/sun/star/awt/Rectangle.hpp> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> + +//------------------------------------------------------------------------ +// +// Project-local header +// +//------------------------------------------------------------------------ + +#include <editeng/editdata.hxx> +#include <editeng/unopracc.hxx> +#include "unoedprx.hxx" +#include <editeng/AccessibleStaticTextBase.hxx> +#include "AccessibleEditableTextPara.hxx" + + +using namespace ::com::sun::star; +using namespace ::com::sun::star::accessibility; + +/* TODO: + ===== + + - separate adapter functionality from AccessibleStaticText class + + - refactor common loops into templates, using mem_fun + + */ + +namespace accessibility +{ + typedef ::comphelper::SequenceAsVector< beans::PropertyValue > PropertyValueVector; + + class PropertyValueEqualFunctor : public ::std::binary_function< beans::PropertyValue, beans::PropertyValue, bool > + { + public: + PropertyValueEqualFunctor() + {} + bool operator() ( const beans::PropertyValue& lhs, const beans::PropertyValue& rhs ) const + { + return ( lhs.Name == rhs.Name && lhs.Value == rhs.Value ); + } + }; + + //------------------------------------------------------------------------ + // + // Static Helper + // + //------------------------------------------------------------------------ + ESelection MakeSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ) + { + DBG_ASSERT(nStartPara >= 0 && nStartPara <= USHRT_MAX && + nStartIndex >= 0 && nStartIndex <= USHRT_MAX && + nEndPara >= 0 && nEndPara <= USHRT_MAX && + nEndIndex >= 0 && nEndIndex <= USHRT_MAX , + "AccessibleStaticTextBase_Impl::MakeSelection: index value overflow"); + + return ESelection( static_cast< USHORT >(nStartPara), static_cast< USHORT >(nStartIndex), + static_cast< USHORT >(nEndPara), static_cast< USHORT >(nEndIndex) ); + } + + //------------------------------------------------------------------------ + // + // AccessibleStaticTextBase_Impl declaration + // + //------------------------------------------------------------------------ + + DBG_NAME( AccessibleStaticTextBase_Impl ); + + /** AccessibleStaticTextBase_Impl + + This class implements the AccessibleStaticTextBase + functionality, mainly by forwarding the calls to an aggregated + AccessibleEditableTextPara. As this is a therefore non-trivial + adapter, factoring out the common functionality from + AccessibleEditableTextPara might be a profitable future task. + */ + class AccessibleStaticTextBase_Impl + { + + public: + + // receive pointer to our frontend class and view window + AccessibleStaticTextBase_Impl(); + ~AccessibleStaticTextBase_Impl(); + + SvxEditSourceAdapter& GetEditSource() const SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return maEditSource; + } + void SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException)); + + void SetEventSource( const uno::Reference< XAccessible >& rInterface ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + mxThis = rInterface; + } + uno::Reference< XAccessible > GetEventSource() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return mxThis; + } + + void SetOffset( const Point& ); + Point GetOffset() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + ::osl::MutexGuard aGuard( maMutex ); Point aPoint( maOffset ); + return aPoint; + } + + void UpdateChildren(); + void Dispose(); + +#ifdef DBG_UTIL + void CheckInvariants() const; +#endif + + AccessibleEditableTextPara& GetParagraph( sal_Int32 nPara ) const; + sal_Int32 GetParagraphCount() const; + sal_Int32 GetParagraphIndex() const; + sal_Int32 GetLineCount( sal_Int32 nParagraph ) const; + + EPosition Index2Internal( sal_Int32 nFlatIndex ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return ImpCalcInternal( nFlatIndex, false ); + } + + EPosition Range2Internal( sal_Int32 nFlatIndex ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + return ImpCalcInternal( nFlatIndex, true ); + } + + sal_Int32 Internal2Index( EPosition nEEIndex ) const; + + void CorrectTextSegment( TextSegment& aTextSegment, + int nPara ) const; + + sal_Bool SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ); + sal_Bool CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ); + + Rectangle GetParagraphBoundingBox() const; + + private: + + EPosition ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const; + + // our frontend class (the one implementing the actual + // interface). That's not necessarily the one containing the impl + // pointer + uno::Reference< XAccessible > mxThis; + + // implements our functionality, we're just an adapter (guarded by solar mutex) + mutable AccessibleEditableTextPara* mpTextParagraph; + + uno::Reference< XAccessible > mxParagraph; + + // a wrapper for the text forwarders (guarded by solar mutex) + mutable SvxEditSourceAdapter maEditSource; + + // guard for maOffset + mutable ::osl::Mutex maMutex; + + /// our current offset to the containing shape/cell (guarded by maMutex) + Point maOffset; + + }; + + //------------------------------------------------------------------------ + // + // AccessibleStaticTextBase_Impl implementation + // + //------------------------------------------------------------------------ + + AccessibleStaticTextBase_Impl::AccessibleStaticTextBase_Impl() : + mxThis( NULL ), + mpTextParagraph( new AccessibleEditableTextPara(NULL) ), + mxParagraph( mpTextParagraph ), + maEditSource(), + maMutex(), + maOffset(0,0) + { + DBG_CTOR( AccessibleStaticTextBase_Impl, NULL ); + + // TODO: this is still somewhat of a hack, all the more since + // now the maTextParagraph has an empty parent reference set + } + + AccessibleStaticTextBase_Impl::~AccessibleStaticTextBase_Impl() + { + DBG_DTOR( AccessibleStaticTextBase_Impl, NULL ); + } + + void AccessibleStaticTextBase_Impl::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((uno::RuntimeException)) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + maEditSource.SetEditSource( pEditSource ); + if( mpTextParagraph ) + mpTextParagraph->SetEditSource( &maEditSource ); + } + + void AccessibleStaticTextBase_Impl::SetOffset( const Point& rPoint ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + // guard against non-atomic access to maOffset data structure + { + ::osl::MutexGuard aGuard( maMutex ); + maOffset = rPoint; + } + + if( mpTextParagraph ) + mpTextParagraph->SetEEOffset( rPoint ); + + // in all cases, check visibility afterwards. + UpdateChildren(); + } + + void AccessibleStaticTextBase_Impl::UpdateChildren() + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + // currently no children + } + + void AccessibleStaticTextBase_Impl::Dispose() + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + // we're the owner of the paragraph, so destroy it, too + if( mpTextParagraph ) + mpTextParagraph->Dispose(); + + // drop references + mxParagraph = NULL; + mxThis = NULL; + mpTextParagraph = NULL; + } + +#ifdef DBG_UTIL + void AccessibleStaticTextBase_Impl::CheckInvariants() const + { + // TODO + } +#endif + + AccessibleEditableTextPara& AccessibleStaticTextBase_Impl::GetParagraph( sal_Int32 nPara ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + throw lang::DisposedException ( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("object has been already disposed")), mxThis ); + + // TODO: Have a differnt method on AccessibleEditableTextPara + // that does not care about state changes + mpTextParagraph->SetParagraphIndex( nPara ); + + return *mpTextParagraph; + } + + sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphCount() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + return 0; + else + return mpTextParagraph->GetTextForwarder().GetParagraphCount(); + } + + sal_Int32 AccessibleStaticTextBase_Impl::GetParagraphIndex() const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + sal_Int32 nIndex = -1; + if( mpTextParagraph ) + nIndex = mpTextParagraph->GetParagraphIndex(); + return nIndex; + } + + sal_Int32 AccessibleStaticTextBase_Impl::GetLineCount( sal_Int32 nParagraph ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + sal_Int32 nIndex = 0; + if( mpTextParagraph ) + nIndex = mpTextParagraph->GetTextForwarder().GetLineCount( static_cast< USHORT >(nParagraph) ); + return nIndex; + } + + sal_Int32 AccessibleStaticTextBase_Impl::Internal2Index( EPosition nEEIndex ) const + { + sal_Int32 aRes(0); + int i; + for(i=0; i<nEEIndex.nPara; ++i) + aRes += GetParagraph(i).getCharacterCount(); + + return aRes + nEEIndex.nIndex; + } + + void AccessibleStaticTextBase_Impl::CorrectTextSegment( TextSegment& aTextSegment, + int nPara ) const + { + // Keep 'invalid' values at the TextSegment + if( aTextSegment.SegmentStart != -1 && + aTextSegment.SegmentStart != -1 ) + { + // #112814# Correct TextSegment by paragraph offset + sal_Int32 nOffset(0); + int i; + for(i=0; i<nPara; ++i) + nOffset += GetParagraph(i).getCharacterCount(); + + aTextSegment.SegmentStart += nOffset; + aTextSegment.SegmentEnd += nOffset; + } + } + + EPosition AccessibleStaticTextBase_Impl::ImpCalcInternal( sal_Int32 nFlatIndex, bool bExclusive ) const + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( nFlatIndex < 0 ) + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")), + mxThis); + // gratuitously accepting larger indices here, AccessibleEditableTextPara will throw eventually + + sal_Int32 nCurrPara, nCurrIndex, nParas, nCurrCount; + for( nCurrPara=0, nParas=GetParagraphCount(), nCurrCount=0, nCurrIndex=0; nCurrPara<nParas; ++nCurrPara ) + { + nCurrCount = GetParagraph( nCurrPara ).getCharacterCount(); + nCurrIndex += nCurrCount; + + if( nCurrIndex > nFlatIndex ) + { + // check overflow + DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX && + nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX , + "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow"); + + return EPosition( static_cast< USHORT >(nCurrPara), static_cast< USHORT >(nFlatIndex - nCurrIndex + nCurrCount) ); + } + } + + // #102170# Allow one-past the end for ranges + if( bExclusive && nCurrIndex == nFlatIndex ) + { + // check overflow + DBG_ASSERT(nCurrPara >= 0 && nCurrPara <= USHRT_MAX && + nFlatIndex - nCurrIndex + nCurrCount >= 0 && nFlatIndex - nCurrIndex + nCurrCount <= USHRT_MAX , + "AccessibleStaticTextBase_Impl::Index2Internal: index value overflow"); + + return EPosition( static_cast< USHORT >(nCurrPara-1), static_cast< USHORT >(nFlatIndex - nCurrIndex + nCurrCount) ); + } + + // not found? Out of bounds + throw lang::IndexOutOfBoundsException(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("AccessibleStaticTextBase_Impl::Index2Internal: character index out of bounds")), + mxThis); + } + + sal_Bool AccessibleStaticTextBase_Impl::SetSelection( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + return sal_False; + + try + { + SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True ); + return rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) ); + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + sal_Bool AccessibleStaticTextBase_Impl::CopyText( sal_Int32 nStartPara, sal_Int32 nStartIndex, + sal_Int32 nEndPara, sal_Int32 nEndIndex ) + { + DBG_CHKTHIS( AccessibleStaticTextBase_Impl, NULL ); + + if( !mpTextParagraph ) + return sal_False; + + try + { + SvxEditViewForwarder& rCacheVF = mpTextParagraph->GetEditViewForwarder( sal_True ); + mpTextParagraph->GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs + sal_Bool aRetVal; + + // save current selection + ESelection aOldSelection; + + rCacheVF.GetSelection( aOldSelection ); + rCacheVF.SetSelection( MakeSelection(nStartPara, nStartIndex, nEndPara, nEndIndex) ); + aRetVal = rCacheVF.Copy(); + rCacheVF.SetSelection( aOldSelection ); // restore + + return aRetVal; + } + catch( const uno::RuntimeException& ) + { + return sal_False; + } + } + + Rectangle AccessibleStaticTextBase_Impl::GetParagraphBoundingBox() const + { + Rectangle aRect; + if( mpTextParagraph ) + { + awt::Rectangle aAwtRect = mpTextParagraph->getBounds(); + aRect = Rectangle( Point( aAwtRect.X, aAwtRect.Y ), Size( aAwtRect.Width, aAwtRect.Height ) ); + } + else + { + aRect.SetEmpty(); + } + return aRect; + } + + //------------------------------------------------------------------------ + // + // AccessibleStaticTextBase implementation + // + //------------------------------------------------------------------------ + + AccessibleStaticTextBase::AccessibleStaticTextBase( ::std::auto_ptr< SvxEditSource > pEditSource ) : + mpImpl( new AccessibleStaticTextBase_Impl() ) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + SetEditSource( pEditSource ); + } + + AccessibleStaticTextBase::~AccessibleStaticTextBase() + { + } + + const SvxEditSource& AccessibleStaticTextBase::GetEditSource() const SAL_THROW((::com::sun::star::uno::RuntimeException)) + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); + + const SvxEditSource& aEditSource = mpImpl->GetEditSource(); + + mpImpl->CheckInvariants(); + + return aEditSource; +#else + return mpImpl->GetEditSource(); +#endif + } + + void AccessibleStaticTextBase::SetEditSource( ::std::auto_ptr< SvxEditSource > pEditSource ) SAL_THROW((::com::sun::star::uno::RuntimeException)) + { +#ifdef DBG_UTIL + // precondition: solar mutex locked + DBG_TESTSOLARMUTEX(); + + mpImpl->CheckInvariants(); + + mpImpl->SetEditSource( pEditSource ); + + mpImpl->CheckInvariants(); +#else + mpImpl->SetEditSource( pEditSource ); +#endif + } + + void AccessibleStaticTextBase::SetEventSource( const uno::Reference< XAccessible >& rInterface ) + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + + mpImpl->SetEventSource( rInterface ); + +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + } + + uno::Reference< XAccessible > AccessibleStaticTextBase::GetEventSource() const + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); + + uno::Reference< XAccessible > xRet( mpImpl->GetEventSource() ); + + mpImpl->CheckInvariants(); + + return xRet; +#else + return mpImpl->GetEventSource(); +#endif + } + + void AccessibleStaticTextBase::SetOffset( const Point& rPoint ) + { +#ifdef DBG_UTIL + // precondition: solar mutex locked + DBG_TESTSOLARMUTEX(); + + mpImpl->CheckInvariants(); + + mpImpl->SetOffset( rPoint ); + + mpImpl->CheckInvariants(); +#else + mpImpl->SetOffset( rPoint ); +#endif + } + + Point AccessibleStaticTextBase::GetOffset() const + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); + + Point aPoint( mpImpl->GetOffset() ); + + mpImpl->CheckInvariants(); + + return aPoint; +#else + return mpImpl->GetOffset(); +#endif + } + + void AccessibleStaticTextBase::UpdateChildren() SAL_THROW((::com::sun::star::uno::RuntimeException)) + { +#ifdef DBG_UTIL + // precondition: solar mutex locked + DBG_TESTSOLARMUTEX(); + + mpImpl->CheckInvariants(); + + mpImpl->UpdateChildren(); + + mpImpl->CheckInvariants(); +#else + mpImpl->UpdateChildren(); +#endif + } + + void AccessibleStaticTextBase::Dispose() + { +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + + mpImpl->Dispose(); + +#ifdef DBG_UTIL + mpImpl->CheckInvariants(); +#endif + } + + // XAccessibleContext + sal_Int32 SAL_CALL AccessibleStaticTextBase::getAccessibleChildCount() throw (uno::RuntimeException) + { + // no children at all + return 0; + } + + uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleChild( sal_Int32 /*i*/ ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + // no children at all + return uno::Reference< XAccessible >(); + } + + uno::Reference< XAccessible > SAL_CALL AccessibleStaticTextBase::getAccessibleAtPoint( const awt::Point& /*_aPoint*/ ) throw (uno::RuntimeException) + { + // no children at all + return uno::Reference< XAccessible >(); + } + + // XAccessibleText + sal_Int32 SAL_CALL AccessibleStaticTextBase::getCaretPosition() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nPos, nParas; + for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + { + if( (nPos=mpImpl->GetParagraph(i).getCaretPosition()) != -1 ) + return nPos; + } + + return nPos; + } + + sal_Bool SAL_CALL AccessibleStaticTextBase::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + return setSelection(nIndex, nIndex); + } + + sal_Unicode SAL_CALL AccessibleStaticTextBase::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Index2Internal(nIndex) ); + + return mpImpl->GetParagraph( aPos.nPara ).getCharacter( aPos.nIndex ); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Index2Internal(nIndex) ); + + return mpImpl->GetParagraph( aPos.nPara ).getCharacterAttributes( aPos.nIndex, aRequestedAttributes ); + } + + awt::Rectangle SAL_CALL AccessibleStaticTextBase::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + // #108900# Allow ranges for nIndex, as one-past-the-end + // values are now legal, too. + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + // #i70916# Text in spread sheet cells return the wrong extents + AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara ); + awt::Rectangle aParaBounds( rPara.getBounds() ); + awt::Rectangle aBounds( rPara.getCharacterBounds( aPos.nIndex ) ); + aBounds.X += aParaBounds.X; + aBounds.Y += aParaBounds.Y; + + return aBounds; + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getCharacterCount() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nCount, nParas; + for( i=0, nCount=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + nCount += mpImpl->GetParagraph(i).getCharacterCount(); + + return nCount; + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + const sal_Int32 nParas( mpImpl->GetParagraphCount() ); + sal_Int32 nIndex; + int i; + for( i=0; i<nParas; ++i ) + { + // TODO: maybe exploit the fact that paragraphs are + // ordered vertically for early exit + + // #i70916# Text in spread sheet cells return the wrong extents + AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( i ); + awt::Rectangle aParaBounds( rPara.getBounds() ); + awt::Point aPoint( rPoint ); + aPoint.X -= aParaBounds.X; + aPoint.Y -= aParaBounds.Y; + + // #112814# Use correct index offset + if ( ( nIndex = rPara.getIndexAtPoint( aPoint ) ) != -1 ) + return mpImpl->Internal2Index( EPosition(sal::static_int_cast<USHORT>(i), + sal::static_int_cast<USHORT>(nIndex)) ); + } + + return -1; + } + + ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getSelectedText() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 nStart( getSelectionStart() ); + sal_Int32 nEnd( getSelectionEnd() ); + + // #104481# Return the empty string for 'no selection' + if( nStart < 0 || nEnd < 0 ) + return ::rtl::OUString(); + + return getTextRange( nStart, nEnd ); + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionStart() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nPos, nParas; + for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + { + if( (nPos=mpImpl->GetParagraph(i).getSelectionStart()) != -1 ) + return nPos; + } + + return nPos; + } + + sal_Int32 SAL_CALL AccessibleStaticTextBase::getSelectionEnd() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nPos, nParas; + for( i=0, nPos=-1, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + { + if( (nPos=mpImpl->GetParagraph(i).getSelectionEnd()) != -1 ) + return nPos; + } + + return nPos; + } + + sal_Bool SAL_CALL AccessibleStaticTextBase::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); + EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); + + return mpImpl->SetSelection( aStartIndex.nPara, aStartIndex.nIndex, + aEndIndex.nPara, aEndIndex.nIndex ); + } + + ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getText() throw (uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + sal_Int32 i, nParas; + ::rtl::OUString aRes; + for( i=0, nParas=mpImpl->GetParagraphCount(); i<nParas; ++i ) + aRes += mpImpl->GetParagraph(i).getText(); + + return aRes; + } + + ::rtl::OUString SAL_CALL AccessibleStaticTextBase::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( nStartIndex > nEndIndex ) + ::std::swap(nStartIndex, nEndIndex); + + EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); + EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); + + // #102170# Special case: start and end paragraph are identical + if( aStartIndex.nPara == aEndIndex.nPara ) + { + return mpImpl->GetParagraph( aStartIndex.nPara ).getTextRange( aStartIndex.nIndex, aEndIndex.nIndex ); + } + else + { + sal_Int32 i( aStartIndex.nPara ); + ::rtl::OUString aRes( mpImpl->GetParagraph(i).getTextRange( aStartIndex.nIndex, + mpImpl->GetParagraph(i).getCharacterCount()-1) ); + ++i; + + // paragraphs inbetween are fully included + for( ; i<aEndIndex.nPara; ++i ) + aRes += mpImpl->GetParagraph(i).getText(); + + if( i<=aEndIndex.nPara ) + aRes += mpImpl->GetParagraph(i).getTextRange( 0, aEndIndex.nIndex ); + + return aRes; + } + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + ::com::sun::star::accessibility::TextSegment aResult; + + if( AccessibleTextType::PARAGRAPH == aTextType ) + { + // #106393# Special casing one behind last paragraph is + // not necessary, since then, we return the content and + // boundary of that last paragraph. Range2Internal is + // tolerant against that, and returns the last paragraph + // in aPos.nPara. + + // retrieve full text of the paragraph + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) ); + aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); + } + else + { + // No special handling required, forward to wrapped class + aResult = mpImpl->GetParagraph( aPos.nPara ).getTextAtIndex( aPos.nIndex, aTextType ); + + // #112814# Adapt the start index with the paragraph offset + mpImpl->CorrectTextSegment( aResult, aPos.nPara ); + } + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + ::com::sun::star::accessibility::TextSegment aResult; + + if( AccessibleTextType::PARAGRAPH == aTextType ) + { + if( aPos.nIndex == mpImpl->GetParagraph( aPos.nPara ).getCharacterCount() ) + { + // #103589# Special casing one behind the last paragraph + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara, 0 ) ); + } + else if( aPos.nPara > 0 ) + { + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara - 1 ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara - 1, 0 ) ); + } + + aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); + } + else + { + // No special handling required, forward to wrapped class + aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBeforeIndex( aPos.nIndex, aTextType ); + + // #112814# Adapt the start index with the paragraph offset + mpImpl->CorrectTextSegment( aResult, aPos.nPara ); + } + + return aResult; + } + + ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleStaticTextBase::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Range2Internal(nIndex) ); + + ::com::sun::star::accessibility::TextSegment aResult; + + if( AccessibleTextType::PARAGRAPH == aTextType ) + { + // Special casing one behind the last paragraph is not + // necessary, this case is invalid here for + // getTextBehindIndex + if( aPos.nPara + 1 < mpImpl->GetParagraphCount() ) + { + aResult.SegmentText = mpImpl->GetParagraph( aPos.nPara + 1 ).getText(); + + // #112814# Adapt the start index with the paragraph offset + aResult.SegmentStart = mpImpl->Internal2Index( EPosition( aPos.nPara + 1, 0 ) ); + aResult.SegmentEnd = aResult.SegmentStart + aResult.SegmentText.getLength(); + } + } + else + { + // No special handling required, forward to wrapped class + aResult = mpImpl->GetParagraph( aPos.nPara ).getTextBehindIndex( aPos.nIndex, aTextType ); + + // #112814# Adapt the start index with the paragraph offset + mpImpl->CorrectTextSegment( aResult, aPos.nPara ); + } + + return aResult; + } + + sal_Bool SAL_CALL AccessibleStaticTextBase::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + if( nStartIndex > nEndIndex ) + ::std::swap(nStartIndex, nEndIndex); + + EPosition aStartIndex( mpImpl->Range2Internal(nStartIndex) ); + EPosition aEndIndex( mpImpl->Range2Internal(nEndIndex) ); + + return mpImpl->CopyText( aStartIndex.nPara, aStartIndex.nIndex, + aEndIndex.nPara, aEndIndex.nIndex ); + } + + // XAccessibleTextAttributes + uno::Sequence< beans::PropertyValue > AccessibleStaticTextBase::getDefaultAttributes( const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (uno::RuntimeException) + { + // get the intersection of the default attributes of all paragraphs + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + PropertyValueVector aDefAttrVec( mpImpl->GetParagraph( 0 ).getDefaultAttributes( RequestedAttributes ) ); + + const sal_Int32 nParaCount = mpImpl->GetParagraphCount(); + for ( sal_Int32 nPara = 1; nPara < nParaCount; ++nPara ) + { + uno::Sequence< beans::PropertyValue > aSeq = mpImpl->GetParagraph( nPara ).getDefaultAttributes( RequestedAttributes ); + PropertyValueVector aIntersectionVec; + + PropertyValueVector::const_iterator aEnd = aDefAttrVec.end(); + for ( PropertyValueVector::const_iterator aItr = aDefAttrVec.begin(); aItr != aEnd; ++aItr ) + { + const beans::PropertyValue* pItr = aSeq.getConstArray(); + const beans::PropertyValue* pEnd = pItr + aSeq.getLength(); + const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( *aItr ) ) ); + if ( pFind != pEnd ) + { + aIntersectionVec.push_back( *pFind ); + } + } + + aDefAttrVec.swap( aIntersectionVec ); + + if ( aDefAttrVec.empty() ) + { + break; + } + } + + return aDefAttrVec.getAsConstList(); + } + + uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleStaticTextBase::getRunAttributes( sal_Int32 nIndex, const uno::Sequence< ::rtl::OUString >& RequestedAttributes ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException) + { + // get those default attributes of the paragraph, which are not part + // of the intersection of all paragraphs and add them to the run attributes + + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + + EPosition aPos( mpImpl->Index2Internal( nIndex ) ); + AccessibleEditableTextPara& rPara = mpImpl->GetParagraph( aPos.nPara ); + uno::Sequence< beans::PropertyValue > aDefAttrSeq = rPara.getDefaultAttributes( RequestedAttributes ); + uno::Sequence< beans::PropertyValue > aRunAttrSeq = rPara.getRunAttributes( aPos.nIndex, RequestedAttributes ); + uno::Sequence< beans::PropertyValue > aIntersectionSeq = getDefaultAttributes( RequestedAttributes ); + PropertyValueVector aDiffVec; + + const beans::PropertyValue* pDefAttr = aDefAttrSeq.getConstArray(); + const sal_Int32 nLength = aDefAttrSeq.getLength(); + for ( sal_Int32 i = 0; i < nLength; ++i ) + { + const beans::PropertyValue* pItr = aIntersectionSeq.getConstArray(); + const beans::PropertyValue* pEnd = pItr + aIntersectionSeq.getLength(); + const beans::PropertyValue* pFind = ::std::find_if( pItr, pEnd, ::std::bind2nd( PropertyValueEqualFunctor(), boost::cref( pDefAttr[i] ) ) ); + if ( pFind == pEnd && pDefAttr[i].Handle != 0) + { + aDiffVec.push_back( pDefAttr[i] ); + } + } + + return ::comphelper::concatSequences( aRunAttrSeq, aDiffVec.getAsConstList() ); + } + + Rectangle AccessibleStaticTextBase::GetParagraphBoundingBox() const + { + return mpImpl->GetParagraphBoundingBox(); + } + + sal_Int32 AccessibleStaticTextBase::GetParagraphIndex() const + { + return mpImpl->GetParagraphIndex(); + } + + sal_Int32 AccessibleStaticTextBase::GetParagraphCount() const + { + return mpImpl->GetParagraphCount(); + } + + sal_Int32 AccessibleStaticTextBase::GetLineCount( sal_Int32 nParagraph ) const + { + return mpImpl->GetLineCount( nParagraph ); + } + +} // end of namespace accessibility + +//------------------------------------------------------------------------ diff --git a/editeng/source/accessibility/AccessibleStringWrap.cxx b/editeng/source/accessibility/AccessibleStringWrap.cxx new file mode 100644 index 0000000000..22cd0e1cf4 --- /dev/null +++ b/editeng/source/accessibility/AccessibleStringWrap.cxx @@ -0,0 +1,103 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: AccessibleStringWrap.cxx,v $ + * $Revision: 1.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_editeng.hxx" + +#include <algorithm> +#include <tools/debug.hxx> +#include <vcl/outdev.hxx> + +#include <editeng/svxfont.hxx> +#include <editeng/AccessibleStringWrap.hxx> + +//------------------------------------------------------------------------ +// +// AccessibleStringWrap implementation +// +//------------------------------------------------------------------------ + +AccessibleStringWrap::AccessibleStringWrap( OutputDevice& rDev, SvxFont& rFont, const String& rText ) : + mrDev( rDev ), + mrFont( rFont ), + maText( rText ) +{ +} + +sal_Bool AccessibleStringWrap::GetCharacterBounds( sal_Int32 nIndex, Rectangle& rRect ) +{ + DBG_ASSERT(nIndex >= 0 && nIndex <= USHRT_MAX, + "SvxAccessibleStringWrap::GetCharacterBounds: index value overflow"); + + mrFont.SetPhysFont( &mrDev ); + + // #108900# Handle virtual position one-past-the end of the string + if( nIndex >= maText.Len() ) + { + // create a caret bounding rect that has the height of the + // current font and is one pixel wide. + rRect.Left() = mrDev.GetTextWidth(maText); + rRect.Top() = 0; + rRect.SetSize( Size(mrDev.GetTextHeight(), 1) ); + } + else + { + sal_Int32 aXArray[2]; + mrDev.GetCaretPositions( maText, aXArray, static_cast< USHORT >(nIndex), 1 ); + rRect.Left() = 0; + rRect.Top() = 0; + rRect.SetSize( Size(mrDev.GetTextHeight(), labs(aXArray[0] - aXArray[1])) ); + rRect.Move( ::std::min(aXArray[0], aXArray[1]), 0 ); + } + + if( mrFont.IsVertical() ) + { + // #101701# Rotate to vertical + rRect = Rectangle( Point(-rRect.Top(), rRect.Left()), + Point(-rRect.Bottom(), rRect.Right())); + } + + return sal_True; +} + +sal_Int32 AccessibleStringWrap::GetIndexAtPoint( const Point& rPoint ) +{ + // search for character bounding box containing given point + Rectangle aRect; + sal_Int32 i, nLen = maText.Len(); + for( i=0; i<nLen; ++i ) + { + GetCharacterBounds(i, aRect); + if( aRect.IsInside(rPoint) ) + return i; + } + + return -1; +} diff --git a/editeng/source/accessibility/accessibility.src b/editeng/source/accessibility/accessibility.src new file mode 100644 index 0000000000..51d2a49e6e --- /dev/null +++ b/editeng/source/accessibility/accessibility.src @@ -0,0 +1,43 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: accessibility.src,v $ + * $Revision: 1.34 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "editeng.hrc" + +String RID_SVXSTR_A11Y_IMAGEBULLET_DESCRIPTION +{ + Text [ en-US ] = "Image bullet in paragraph" ; +}; + +String RID_SVXSTR_A11Y_IMAGEBULLET_NAME +{ + Text [ en-US ] = "Image bullet" ; +}; + + diff --git a/editeng/source/accessibility/makefile.mk b/editeng/source/accessibility/makefile.mk new file mode 100755 index 0000000000..e29b6477f6 --- /dev/null +++ b/editeng/source/accessibility/makefile.mk @@ -0,0 +1,58 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2008 by Sun Microsystems, Inc. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.25 $ +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org 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 version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=editeng +TARGET=accessibility +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : settings.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- + +SLOFILES = \ + $(SLO)$/AccessibleStringWrap.obj \ + $(SLO)$/AccessibleContextBase.obj \ + $(SLO)$/AccessibleComponentBase.obj \ + $(SLO)$/AccessibleSelectionBase.obj \ + $(SLO)$/AccessibleStaticTextBase.obj \ + $(SLO)$/AccessibleParaManager.obj \ + $(SLO)$/AccessibleEditableTextPara.obj \ + $(SLO)$/AccessibleImageBullet.obj + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + |