/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_editeng.hxx" //------------------------------------------------------------------------ // // Global header // //------------------------------------------------------------------------ #include #include #include #include #include //------------------------------------------------------------------------ // // Project-local header // //------------------------------------------------------------------------ #include #include #include #include "editeng/AccessibleParaManager.hxx" #include "editeng/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(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 && nEndPara >= nStartPara , "AccessibleParaManager::FireEvent: invalid index" ); if( maChildren.size() > nStartPara && maChildren.size() >= nEndPara && nEndPara >= nStartPara) { 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 ); } } //------------------------------------------------------------------------