/************************************************************** * * 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_sw.hxx" #include <vos/ref.hxx> #include <cppuhelper/weakref.hxx> #include <vcl/window.hxx> #include <svx/svdmodel.hxx> #include <svx/unomod.hxx> #include <tools/debug.hxx> #include <map> #include <list> #include <vector> #include <accmap.hxx> #include <acccontext.hxx> #include <accdoc.hxx> #include <accpreview.hxx> #include <accpage.hxx> #include <accpara.hxx> #include <accheaderfooter.hxx> #include <accfootnote.hxx> #include <acctextframe.hxx> #include <accgraphic.hxx> #include <accembedded.hxx> #include <acccell.hxx> #include <acctable.hxx> #include <fesh.hxx> #include <rootfrm.hxx> #include <txtfrm.hxx> #include <hffrm.hxx> #include <ftnfrm.hxx> #include <cellfrm.hxx> #include <tabfrm.hxx> #include <pagefrm.hxx> #include <flyfrm.hxx> #include <ndtyp.hxx> #include <IDocumentDrawModelAccess.hxx> #include <svx/ShapeTypeHandler.hxx> #include <vcl/svapp.hxx> //IAccessibility2 Implementation 2009----- #ifndef _SVX_ACCESSIBILITY_SHAPE_TYPE_HANDLER_HXX #include <svx/ShapeTypeHandler.hxx> #endif #ifndef _SVX_ACCESSIBILITY_SVX_SHAPE_TYPES_HXX #include <svx/SvxShapeTypes.hxx> #endif #ifndef _SVDPAGE_HXX #include <svx/svdpage.hxx> #endif #include <com/sun/star/accessibility/AccessibleRelationType.hpp> #include <com/sun/star/accessibility/AccessibleEventId.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <com/sun/star/accessibility/AccessibleRole.hpp> #include <cppuhelper/implbase1.hxx> #include <pagepreviewlayout.hxx> #include <dcontact.hxx> #include <svx/unoapi.hxx> #include <svx/svdmark.hxx> #include <doc.hxx> #include <pam.hxx> #include <ndtxt.hxx> #include <dflyobj.hxx> #include <prevwpage.hxx> #include <switerator.hxx> using namespace ::com::sun::star; using namespace ::com::sun::star::accessibility; using ::rtl::OUString; using namespace ::sw::access; struct SwFrmFunc { sal_Bool operator()( const SwFrm * p1, const SwFrm * p2) const { return p1 < p2; } }; typedef ::std::map < const SwFrm *, uno::WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl; class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl { public: #ifdef DBG_UTIL sal_Bool mbLocked; #endif SwAccessibleContextMap_Impl() #ifdef DBG_UTIL : mbLocked( sal_False ) #endif {} }; //------------------------------------------------------------------------------ class SwDrawModellListener_Impl : public SfxListener, public ::cppu::WeakImplHelper1< document::XEventBroadcaster > { mutable ::osl::Mutex maListenerMutex; ::cppu::OInterfaceContainerHelper maEventListeners; SdrModel *mpDrawModel; protected: virtual ~SwDrawModellListener_Impl(); public: SwDrawModellListener_Impl( SdrModel *pDrawModel ); virtual void SAL_CALL addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException); virtual void SAL_CALL removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException); virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ); void Dispose(); }; SwDrawModellListener_Impl::SwDrawModellListener_Impl( SdrModel *pDrawModel ) : maEventListeners( maListenerMutex ), mpDrawModel( pDrawModel ) { StartListening( *mpDrawModel ); } SwDrawModellListener_Impl::~SwDrawModellListener_Impl() { EndListening( *mpDrawModel ); } void SAL_CALL SwDrawModellListener_Impl::addEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException) { maEventListeners.addInterface( xListener ); } void SAL_CALL SwDrawModellListener_Impl::removeEventListener( const uno::Reference< document::XEventListener >& xListener ) throw (uno::RuntimeException) { maEventListeners.removeInterface( xListener ); } void SwDrawModellListener_Impl::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) { // do not broadcast notifications for writer fly frames, because there // are no shapes that need to know about them. // OD 01.07.2003 #110554# - correct condition in order not to broadcast // notifications for writer fly frames. // OD 01.07.2003 #110554# - do not broadcast notifications for plane // <SdrObject>objects const SdrHint *pSdrHint = PTR_CAST( SdrHint, &rHint ); if ( !pSdrHint || ( pSdrHint->GetObject() && ( pSdrHint->GetObject()->ISA(SwFlyDrawObj) || pSdrHint->GetObject()->ISA(SwVirtFlyDrawObj) || IS_TYPE(SdrObject,pSdrHint->GetObject()) ) ) ) { return; } ASSERT( mpDrawModel, "draw model listener is disposed" ); if( !mpDrawModel ) return; document::EventObject aEvent; if( !SvxUnoDrawMSFactory::createEvent( mpDrawModel, pSdrHint, aEvent ) ) return; ::cppu::OInterfaceIteratorHelper aIter( maEventListeners ); while( aIter.hasMoreElements() ) { uno::Reference < document::XEventListener > xListener( aIter.next(), uno::UNO_QUERY ); try { xListener->notifyEvent( aEvent ); } catch( uno::RuntimeException const & r ) { (void)r; #if OSL_DEBUG_LEVEL > 1 ByteString aError( "Runtime exception caught while notifying shape.:\n" ); aError += ByteString( String( r.Message), RTL_TEXTENCODING_ASCII_US ); DBG_ERROR( aError.GetBuffer() ); #endif } } } void SwDrawModellListener_Impl::Dispose() { mpDrawModel = 0; } //------------------------------------------------------------------------------ struct SwShapeFunc { sal_Bool operator()( const SdrObject * p1, const SdrObject * p2) const { return p1 < p2; } }; typedef ::std::map < const SdrObject *, uno::WeakReference < XAccessible >, SwShapeFunc > _SwAccessibleShapeMap_Impl; typedef ::std::pair < const SdrObject *, ::vos::ORef < ::accessibility::AccessibleShape > > SwAccessibleObjShape_Impl; class SwAccessibleShapeMap_Impl: public _SwAccessibleShapeMap_Impl { ::accessibility::AccessibleShapeTreeInfo maInfo; public: #ifdef DBG_UTIL sal_Bool mbLocked; #endif SwAccessibleShapeMap_Impl( SwAccessibleMap *pMap ) #ifdef DBG_UTIL : mbLocked( sal_False ) #endif { maInfo.SetSdrView( pMap->GetShell()->GetDrawView() ); maInfo.SetWindow( pMap->GetShell()->GetWin() ); maInfo.SetViewForwarder( pMap ); // --> OD 2005-08-08 #i52858# - method name changed uno::Reference < document::XEventBroadcaster > xModelBroadcaster = new SwDrawModellListener_Impl( pMap->GetShell()->getIDocumentDrawModelAccess()->GetOrCreateDrawModel() ); // <-- maInfo.SetControllerBroadcaster( xModelBroadcaster ); } ~SwAccessibleShapeMap_Impl(); const ::accessibility::AccessibleShapeTreeInfo& GetInfo() const { return maInfo; } SwAccessibleObjShape_Impl *Copy( size_t& rSize, const SwFEShell *pFESh = 0, SwAccessibleObjShape_Impl **pSelShape = 0 ) const; }; SwAccessibleShapeMap_Impl::~SwAccessibleShapeMap_Impl() { uno::Reference < document::XEventBroadcaster > xBrd( maInfo.GetControllerBroadcaster() ); if( xBrd.is() ) static_cast < SwDrawModellListener_Impl * >( xBrd.get() )->Dispose(); } SwAccessibleObjShape_Impl *SwAccessibleShapeMap_Impl::Copy( size_t& rSize, const SwFEShell *pFESh, SwAccessibleObjShape_Impl **pSelStart ) const { SwAccessibleObjShape_Impl *pShapes = 0; SwAccessibleObjShape_Impl *pSelShape = 0; sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; rSize = size(); if( rSize > 0 ) { pShapes = new SwAccessibleObjShape_Impl[rSize]; const_iterator aIter = begin(); const_iterator aEndIter = end(); SwAccessibleObjShape_Impl *pShape = pShapes; pSelShape = &(pShapes[rSize]); while( aIter != aEndIter ) { const SdrObject *pObj = (*aIter).first; uno::Reference < XAccessible > xAcc( (*aIter).second ); //IAccessibility2 Implementation 2009----- if( nSelShapes && pFESh &&pFESh->IsObjSelected( *pObj ) ) //-----IAccessibility2 Implementation 2009 { // selected objects are inserted from the back --pSelShape; pSelShape->first = pObj; pSelShape->second = static_cast < ::accessibility::AccessibleShape* >( xAcc.get() ); --nSelShapes; } else { pShape->first = pObj; pShape->second = static_cast < ::accessibility::AccessibleShape* >( xAcc.get() ); ++pShape; } ++aIter; } ASSERT( pSelShape == pShape, "copying shapes went wrong!" ); } if( pSelStart ) *pSelStart = pSelShape; return pShapes; } //------------------------------------------------------------------------------ struct SwAccessibleEvent_Impl { public: enum EventType { CARET_OR_STATES, INVALID_CONTENT, POS_CHANGED, CHILD_POS_CHANGED, SHAPE_SELECTION, DISPOSE, INVALID_ATTR }; private: SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED // and POS_CHANGED uno::WeakReference < XAccessible > mxAcc; // The object that fires the event SwAccessibleChild maFrmOrObj; // the child for CHILD_POS_CHANGED and // the same as xAcc for any other // event type EventType meType; // The event type // --> OD 2005-12-12 #i27301# - use new type definition for <mnStates> tAccessibleStates mnStates; // check states or update caret pos // <-- SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& ); public: //IAccessibility2 Implementation 2009----- const SwFrm* mpParentFrm; // The object that fires the event sal_Bool IsNoXaccParentFrm() const { return CHILD_POS_CHANGED == meType && mpParentFrm != 0; } uno::WeakReference < XAccessible > GetxAcc() const { return mxAcc;} //-----IAccessibility2 Implementation 2009 public: SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA, const SwAccessibleChild& rFrmOrObj ) : mxAcc( pA ), maFrmOrObj( rFrmOrObj ), meType( eT ), mnStates( 0 ), mpParentFrm( 0 ) {} SwAccessibleEvent_Impl( EventType eT, const SwAccessibleChild& rFrmOrObj ) : maFrmOrObj( rFrmOrObj ), meType( eT ), mnStates( 0 ), mpParentFrm( 0 ) { ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType, "wrong event constructor, DISPOSE only" ); } SwAccessibleEvent_Impl( EventType eT ) : meType( eT ), mnStates( 0 ), mpParentFrm( 0 ) { ASSERT( SwAccessibleEvent_Impl::SHAPE_SELECTION == meType, "wrong event constructor, SHAPE_SELECTION only" ); } SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA, const SwAccessibleChild& rFrmOrObj, const SwRect& rR ) : maOldBox( rR ), mxAcc( pA ), maFrmOrObj( rFrmOrObj ), meType( eT ), mnStates( 0 ), mpParentFrm( 0 ) { ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType || SwAccessibleEvent_Impl::POS_CHANGED == meType, "wrong event constructor, (CHILD_)POS_CHANGED only" ); } // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates> SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA, const SwAccessibleChild& rFrmOrObj, const tAccessibleStates _nStates ) : mxAcc( pA ), maFrmOrObj( rFrmOrObj ), meType( eT ), mnStates( _nStates ), mpParentFrm( 0 ) { ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType, "wrong event constructor, CARET_OR_STATES only" ); } //IAccessibility2 Implementation 2009----- SwAccessibleEvent_Impl( EventType eT, const SwFrm *pParentFrm, const SwAccessibleChild& rFrmOrObj, const SwRect& rR ) : maOldBox( rR ), maFrmOrObj( rFrmOrObj ), meType( eT ), mnStates( 0 ), mpParentFrm( pParentFrm ) { OSL_ENSURE( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType, "wrong event constructor, CHILD_POS_CHANGED only" ); } //-----IAccessibility2 Implementation 2009 // <SetType(..)> only used in method <SwAccessibleMap::AppendEvent(..)> inline void SetType( EventType eT ) { meType = eT; } inline EventType GetType() const { return meType; } inline ::vos::ORef < SwAccessibleContext > GetContext() const { uno::Reference < XAccessible > xTmp( mxAcc ); ::vos::ORef < SwAccessibleContext > xAccImpl( static_cast<SwAccessibleContext*>( xTmp.get() ) ); return xAccImpl; } inline const SwRect& GetOldBox() const { return maOldBox; } // <SetOldBox(..)> only used in method <SwAccessibleMap::AppendEvent(..)> inline void SetOldBox( const SwRect& rOldBox ) { maOldBox = rOldBox; } inline const SwAccessibleChild& GetFrmOrObj() const { return maFrmOrObj; } // <SetStates(..)> only used in method <SwAccessibleMap::AppendEvent(..)> // --> OD 2005-12-12 #i27301# - use new type definition for parameter <_nStates> inline void SetStates( tAccessibleStates _nStates ) { mnStates |= _nStates; } // <-- inline sal_Bool IsUpdateCursorPos() const { return (mnStates & ACC_STATE_CARET) != 0; } inline sal_Bool IsInvalidateStates() const { return (mnStates & ACC_STATE_MASK) != 0; } inline sal_Bool IsInvalidateRelation() const { return (mnStates & ACC_STATE_RELATION_MASK) != 0; } // --> OD 2005-12-12 #i27301# - new event TEXT_SELECTION_CHANGED inline sal_Bool IsInvalidateTextSelection() const { return ( mnStates & ACC_STATE_TEXT_SELECTION_CHANGED ) != 0; } // <-- // --> OD 2009-01-07 #i88069# - new event TEXT_ATTRIBUTE_CHANGED inline sal_Bool IsInvalidateTextAttrs() const { return ( mnStates & ACC_STATE_TEXT_ATTRIBUTE_CHANGED ) != 0; } // <-- // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates> // for return value inline tAccessibleStates GetStates() const { return mnStates & ACC_STATE_MASK; } // <-- // --> OD 2005-12-12 #i27301# - use new type definition <tAccessibleStates> // for return value inline tAccessibleStates GetAllStates() const { return mnStates; } // <-- }; //------------------------------------------------------------------------------ typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl; class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl { sal_Bool mbFiring; public: SwAccessibleEventList_Impl() : mbFiring( sal_False ) {} inline void SetFiring() { mbFiring = sal_True; } inline sal_Bool IsFiring() const { return mbFiring; } //IAccessibility2 Implementation 2009----- struct XAccisNULL { bool operator()(const SwAccessibleEvent_Impl& e) { return e.IsNoXaccParentFrm(); } }; void MoveInvalidXAccToEnd(); //-----IAccessibility2 Implementation 2009 }; //IAccessibility2 Implementation 2009----- void SwAccessibleEventList_Impl::MoveInvalidXAccToEnd() { int nSize = size(); if (nSize < 2 ) { return; } SwAccessibleEventList_Impl lstEvent; iterator li = begin(); for ( ;li != end();) { SwAccessibleEvent_Impl e = *li; if (e.IsNoXaccParentFrm()) { iterator liNext = li; ++liNext; erase(li); li = liNext; lstEvent.insert(lstEvent.end(),e); } else ++li; } OSL_ENSURE(size() + lstEvent.size() == nSize ,""); insert(end(),lstEvent.begin(),lstEvent.end()); OSL_ENSURE(size() == nSize ,""); } //-----IAccessibility2 Implementation 2009 //------------------------------------------------------------------------------ // The shape list is filled if an accessible shape is destroyed. It // simply keeps a reference to the accessible shape's XShape. These // references are destroyed within the EndAction when firing events, // There are twp reason for this. First of all, a new accessible shape // for the XShape might be created soon. It's then cheaper if the XShape // still exists. The other reason are situations where an accessible shape // is destroyed within an SwFrmFmt::Modify. In this case, destryoing // the XShape at the same time (indirectly by destroying the accessible // shape) leads to an assert, because a client of the Modify is destroyed // within a Modify call. typedef ::std::list < uno::Reference < drawing::XShape > > _SwShapeList_Impl; class SwShapeList_Impl: public _SwShapeList_Impl { public: SwShapeList_Impl() {} }; //------------------------------------------------------------------------------ struct SwAccessibleChildFunc { sal_Bool operator()( const SwAccessibleChild& r1, const SwAccessibleChild& r2 ) const { const void *p1 = r1.GetSwFrm() ? static_cast < const void * >( r1.GetSwFrm()) : ( r1.GetDrawObject() ? static_cast < const void * >( r1.GetDrawObject() ) : static_cast < const void * >( r1.GetWindow() ) ); const void *p2 = r2.GetSwFrm() ? static_cast < const void * >( r2.GetSwFrm()) : ( r2.GetDrawObject() ? static_cast < const void * >( r2.GetDrawObject() ) : static_cast < const void * >( r2.GetWindow() ) ); return p1 < p2; } }; typedef ::std::map < SwAccessibleChild, SwAccessibleEventList_Impl::iterator, SwAccessibleChildFunc > _SwAccessibleEventMap_Impl; class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl { }; //------------------------------------------------------------------------------ // --> OD 2005-12-13 #i27301# - map containing the accessible paragraph, which // have a selection. Needed to keep this information to submit corresponding // TEXT_SELECTION_CHANGED events. struct SwAccessibleParaSelection { xub_StrLen nStartOfSelection; xub_StrLen nEndOfSelection; SwAccessibleParaSelection( const xub_StrLen _nStartOfSelection, const xub_StrLen _nEndOfSelection ) : nStartOfSelection( _nStartOfSelection ), nEndOfSelection( _nEndOfSelection ) {} }; struct SwXAccWeakRefComp { sal_Bool operator()( const uno::WeakReference<XAccessible>& _rXAccWeakRef1, const uno::WeakReference<XAccessible>& _rXAccWeakRef2 ) const { return _rXAccWeakRef1.get() < _rXAccWeakRef2.get(); } }; typedef ::std::map< uno::WeakReference < XAccessible >, SwAccessibleParaSelection, SwXAccWeakRefComp > _SwAccessibleSelectedParas_Impl; class SwAccessibleSelectedParas_Impl: public _SwAccessibleSelectedParas_Impl {}; // <-- // helper class that stores preview data class SwAccPreviewData { typedef std::vector<Rectangle> Rectangles; Rectangles maPreviewRects; Rectangles maLogicRects; SwRect maVisArea; Fraction maScale; const SwPageFrm *mpSelPage; /** adjust logic page retangle to its visible part OD 17.01.2003 #103492# @author OD @param _iorLogicPgSwRect input/output parameter - reference to the logic page rectangle, which has to be adjusted. @param _rPrevwPgSwRect input parameter - constant reference to the corresponding preview page rectangle; needed to determine the visible part of the logic page rectangle. @param _rPrevwWinSize input paramter - constant reference to the preview window size in TWIP; needed to determine the visible part of the logic page rectangle */ void AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect, const SwRect& _rPrevwPgSwRect, const Size& _rPrevwWinSize ); public: SwAccPreviewData(); ~SwAccPreviewData(); // OD 14.01.2003 #103492# - complete re-factoring of method due to new // page/print preview functionality. void Update( const SwAccessibleMap& rAccMap, const std::vector<PrevwPage*>& _rPrevwPages, const Fraction& _rScale, const SwPageFrm* _pSelectedPageFrm, const Size& _rPrevwWinSize ); // OD 14.01.2003 #103492# - complete re-factoring of method due to new // page/print preview functionality. void InvalidateSelection( const SwPageFrm* _pSelectedPageFrm ); const SwRect& GetVisArea() const; MapMode GetMapModeForPreview( ) const; /** Adjust the MapMode so that the preview page appears at the * proper position. rPoint identifies the page for which the * MapMode should be adjusted. If bFromPreview is true, rPoint is * a preview coordinate; else it's a document coordinate. */ // OD 17.01.2003 #103492# - delete unused 3rd parameter. void AdjustMapMode( MapMode& rMapMode, const Point& rPoint ) const; inline const SwPageFrm *GetSelPage() const { return mpSelPage; } void DisposePage(const SwPageFrm *pPageFrm ); }; SwAccPreviewData::SwAccPreviewData() : mpSelPage( 0 ) { } SwAccPreviewData::~SwAccPreviewData() { } // OD 13.01.2003 #103492# - complete re-factoring of method due to new page/print // preview functionality. void SwAccPreviewData::Update( const SwAccessibleMap& rAccMap, const std::vector<PrevwPage*>& _rPrevwPages, const Fraction& _rScale, const SwPageFrm* _pSelectedPageFrm, const Size& _rPrevwWinSize ) { // store preview scaling, maximal preview page size and selected page maScale = _rScale; mpSelPage = _pSelectedPageFrm; // prepare loop on preview pages maPreviewRects.clear(); maLogicRects.clear(); SwAccessibleChild aPage; maVisArea.Clear(); // loop on preview pages to calculate <maPreviewRects>, <maLogicRects> and // <maVisArea> for ( std::vector<PrevwPage*>::const_iterator aPageIter = _rPrevwPages.begin(); aPageIter != _rPrevwPages.end(); ++aPageIter ) { aPage = (*aPageIter)->pPage; // add preview page rectangle to <maPreviewRects> Rectangle aPrevwPgRect( (*aPageIter)->aPrevwWinPos, (*aPageIter)->aPageSize ); maPreviewRects.push_back( aPrevwPgRect ); // add logic page rectangle to <maLogicRects> SwRect aLogicPgSwRect( aPage.GetBox( rAccMap ) ); Rectangle aLogicPgRect( aLogicPgSwRect.SVRect() ); maLogicRects.push_back( aLogicPgRect ); // union visible area with visible part of logic page rectangle if ( (*aPageIter)->bVisible ) { if ( !(*aPageIter)->pPage->IsEmptyPage() ) { AdjustLogicPgRectToVisibleArea( aLogicPgSwRect, SwRect( aPrevwPgRect ), _rPrevwWinSize ); } if ( maVisArea.IsEmpty() ) maVisArea = aLogicPgSwRect; else maVisArea.Union( aLogicPgSwRect ); } } } // OD 16.01.2003 #103492# - complete re-factoring of method due to new page/print // preview functionality. void SwAccPreviewData::InvalidateSelection( const SwPageFrm* _pSelectedPageFrm ) { mpSelPage = _pSelectedPageFrm; ASSERT( mpSelPage, "selected page not found" ); } struct ContainsPredicate { const Point& mrPoint; ContainsPredicate( const Point& rPoint ) : mrPoint(rPoint) {} bool operator() ( const Rectangle& rRect ) const { return rRect.IsInside( mrPoint ) ? true : false; } }; const SwRect& SwAccPreviewData::GetVisArea() const { return maVisArea; } void SwAccPreviewData::AdjustMapMode( MapMode& rMapMode, const Point& rPoint ) const { // adjust scale rMapMode.SetScaleX( maScale ); rMapMode.SetScaleY( maScale ); // find proper rectangle Rectangles::const_iterator aBegin = maLogicRects.begin(); Rectangles::const_iterator aEnd = maLogicRects.end(); Rectangles::const_iterator aFound = ::std::find_if( aBegin, aEnd, ContainsPredicate( rPoint ) ); if( aFound != aEnd ) { // found! set new origin Point aPoint = (maPreviewRects.begin() + (aFound - aBegin))->TopLeft(); aPoint -= (maLogicRects.begin() + (aFound-aBegin))->TopLeft(); rMapMode.SetOrigin( aPoint ); } // else: don't adjust MapMode } void SwAccPreviewData::DisposePage(const SwPageFrm *pPageFrm ) { if( mpSelPage == pPageFrm ) mpSelPage = 0; } /** adjust logic page retangle to its visible part OD 17.01.2003 #103492# @author OD */ void SwAccPreviewData::AdjustLogicPgRectToVisibleArea( SwRect& _iorLogicPgSwRect, const SwRect& _rPrevwPgSwRect, const Size& _rPrevwWinSize ) { // determine preview window rectangle const SwRect aPrevwWinSwRect( Point( 0, 0 ), _rPrevwWinSize ); // calculate visible preview page rectangle SwRect aVisPrevwPgSwRect( _rPrevwPgSwRect ); aVisPrevwPgSwRect.Intersection( aPrevwWinSwRect ); // adjust logic page rectangle SwTwips nTmpDiff; // left nTmpDiff = aVisPrevwPgSwRect.Left() - _rPrevwPgSwRect.Left(); if ( nTmpDiff > 0 ) _iorLogicPgSwRect.Left( _iorLogicPgSwRect.Left() + nTmpDiff ); // top nTmpDiff = aVisPrevwPgSwRect.Top() - _rPrevwPgSwRect.Top(); if ( nTmpDiff > 0 ) _iorLogicPgSwRect.Top( _iorLogicPgSwRect.Top() + nTmpDiff ); // right nTmpDiff = _rPrevwPgSwRect.Right() - aVisPrevwPgSwRect.Right(); if ( nTmpDiff > 0 ) _iorLogicPgSwRect.Right( _iorLogicPgSwRect.Right() - nTmpDiff ); // bottom nTmpDiff = _rPrevwPgSwRect.Bottom() - aVisPrevwPgSwRect.Bottom(); if ( nTmpDiff > 0 ) _iorLogicPgSwRect.Bottom( _iorLogicPgSwRect.Bottom() - nTmpDiff ); } //------------------------------------------------------------------------------ static sal_Bool AreInSameTable( const uno::Reference< XAccessible >& rAcc, const SwFrm *pFrm ) { sal_Bool bRet = sal_False; if( pFrm && pFrm->IsCellFrm() && rAcc.is() ) { // Is it in the same table? We check that // by comparing the last table frame in the // follow chain, because that's cheaper than // searching the first one. SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( rAcc.get() ); if( pAccImpl->GetFrm()->IsCellFrm() ) { const SwTabFrm *pTabFrm1 = pAccImpl->GetFrm()->FindTabFrm(); while( pTabFrm1->GetFollow() ) pTabFrm1 = pTabFrm1->GetFollow(); const SwTabFrm *pTabFrm2 = pFrm->FindTabFrm(); while( pTabFrm2->GetFollow() ) pTabFrm2 = pTabFrm2->GetFollow(); bRet = (pTabFrm1 == pTabFrm2); } } return bRet; } void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent ) { ::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() ); //IAccessibility2 Implementation 2009----- if (!xAccImpl.isValid() && rEvent.mpParentFrm != 0 ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( rEvent.mpParentFrm ); if( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if (xAcc.is()) { uno::Reference < XAccessibleContext > xContext(xAcc,uno::UNO_QUERY); if (xContext.is() && xContext->getAccessibleRole() == AccessibleRole::PARAGRAPH) { xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); } } } } //-----IAccessibility2 Implementation 2009 if( SwAccessibleEvent_Impl::SHAPE_SELECTION == rEvent.GetType() ) { DoInvalidateShapeSelection(); } else if( xAccImpl.isValid() && xAccImpl->GetFrm() ) { // --> OD 2009-01-07 #i88069# if ( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE && rEvent.IsInvalidateTextAttrs() ) { xAccImpl->InvalidateAttr(); } // <-- switch( rEvent.GetType() ) { case SwAccessibleEvent_Impl::INVALID_CONTENT: xAccImpl->InvalidateContent(); break; case SwAccessibleEvent_Impl::POS_CHANGED: xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() ); break; case SwAccessibleEvent_Impl::CHILD_POS_CHANGED: xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrmOrObj(), rEvent.GetOldBox() ); break; case SwAccessibleEvent_Impl::DISPOSE: ASSERT( xAccImpl.isValid(), "dispose event has been stored" ); break; // --> OD 2009-01-06 #i88069# case SwAccessibleEvent_Impl::INVALID_ATTR: // nothing to do here - handled above break; // <-- default: break; } if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() ) { if( rEvent.IsUpdateCursorPos() ) xAccImpl->InvalidateCursorPos(); if( rEvent.IsInvalidateStates() ) xAccImpl->InvalidateStates( rEvent.GetStates() ); if( rEvent.IsInvalidateRelation() ) { // --> OD 2005-12-01 #i27138# // both events CONTENT_FLOWS_FROM_RELATION_CHANGED and // CONTENT_FLOWS_TO_RELATION_CHANGED are possible if ( rEvent.GetAllStates() & ACC_STATE_RELATION_FROM ) { xAccImpl->InvalidateRelation( AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED ); } if ( rEvent.GetAllStates() & ACC_STATE_RELATION_TO ) { xAccImpl->InvalidateRelation( AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED ); } // <-- } // --> OD 2005-12-12 #i27301# - submit event TEXT_SELECTION_CHANGED if ( rEvent.IsInvalidateTextSelection() ) { xAccImpl->InvalidateTextSelection(); } // <-- } } } void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent ) { vos::OGuard aGuard( maEventMutex ); if( !mpEvents ) mpEvents = new SwAccessibleEventList_Impl; if( !mpEventMap ) mpEventMap = new SwAccessibleEventMap_Impl; if( mpEvents->IsFiring() ) { // While events are fired new ones are generated. They have to be fired // now. This does not work for DISPOSE events! ASSERT( rEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, "dispose event while firing events" ); FireEvent( rEvent ); } else { SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->find( rEvent.GetFrmOrObj() ); if( aIter != mpEventMap->end() ) { SwAccessibleEvent_Impl aEvent( *(*aIter).second ); ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, "dispose events should not be stored" ); sal_Bool bAppendEvent = sal_True; switch( rEvent.GetType() ) { case SwAccessibleEvent_Impl::CARET_OR_STATES: // A CARET_OR_STATES event is added to any other // event only. It is broadcasted after any other event, so the // event should be put to the back. ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED, "invalid event combination" ); aEvent.SetStates( rEvent.GetAllStates() ); break; case SwAccessibleEvent_Impl::INVALID_CONTENT: // An INVALID_CONTENT event overwrites a CARET_OR_STATES // event (but keeps its flags) and it is contained in a // POS_CHANGED event. // Therefor, the event's type has to be adapted and the event // has to be put at the end. ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED, "invalid event combination" ); if( aEvent.GetType() == SwAccessibleEvent_Impl::CARET_OR_STATES ) aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT ); break; case SwAccessibleEvent_Impl::POS_CHANGED: // A pos changed event overwrites CARET_STATES (keeping its // flags) as well as INVALID_CONTENT. The old box position // has to be stored however if the old event is not a // POS_CHANGED itself. ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::CHILD_POS_CHANGED, "invalid event combination" ); if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED ) aEvent.SetOldBox( rEvent.GetOldBox() ); aEvent.SetType( SwAccessibleEvent_Impl::POS_CHANGED ); break; case SwAccessibleEvent_Impl::CHILD_POS_CHANGED: // CHILD_POS_CHANGED events can only follow CHILD_POS_CHANGED // events. The only action that needs to be done again is // to put the old event to the back. The new one cannot be used, // because we are interested in the old frame bounds. ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::CHILD_POS_CHANGED, "invalid event combination" ); break; case SwAccessibleEvent_Impl::SHAPE_SELECTION: ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::SHAPE_SELECTION, "invalid event combination" ); break; case SwAccessibleEvent_Impl::DISPOSE: // DISPOSE events overwrite all others. They are not stored // but executed immediatly to avoid broadcasting of // defunctional objects. So what needs to be done here is to // remove all events for the frame in question. bAppendEvent = sal_False; break; // --> OD 2009-01-06 #i88069# case SwAccessibleEvent_Impl::INVALID_ATTR: ASSERT( aEvent.GetType() == SwAccessibleEvent_Impl::INVALID_ATTR, "invalid event combination" ); break; // <-- } if( bAppendEvent ) { mpEvents->erase( (*aIter).second ); (*aIter).second = mpEvents->insert( mpEvents->end(), aEvent ); } else { mpEvents->erase( (*aIter).second ); mpEventMap->erase( aIter ); } } else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() ) { SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrmOrObj(), mpEvents->insert( mpEvents->end(), rEvent ) ); mpEventMap->insert( aEntry ); } } } void SwAccessibleMap::InvalidateCursorPosition( const uno::Reference< XAccessible >& rAcc ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( rAcc.get() ); ASSERT( pAccImpl, "no caret context" ); ASSERT( pAccImpl->GetFrm(), "caret context is disposed" ); if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl, SwAccessibleChild(pAccImpl->GetFrm()), ACC_STATE_CARET ); AppendEvent( aEvent ); } else { FireEvents(); // While firing events the current frame might have // been disposed because it moved out of the vis area. // Setting the cursor for such frames is useless and even // causes asserts. if( pAccImpl->GetFrm() ) pAccImpl->InvalidateCursorPos(); } } void SwAccessibleMap::InvalidateShapeSelection() { if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::SHAPE_SELECTION ); AppendEvent( aEvent ); } else { FireEvents(); DoInvalidateShapeSelection(); } } //IAccessibility2 Implementation 2009----- //This method should implement the following functions: //1.find the shape objects and set the selected state. //2.find the Swframe objects and set the selected state. //3.find the paragraph objects and set the selected state. void SwAccessibleMap::InvalidateShapeInParaSelection() { SwAccessibleObjShape_Impl *pShapes = 0; SwAccessibleObjShape_Impl *pSelShape = 0; size_t nShapes = 0; const ViewShell *pVSh = GetShell(); const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ? static_cast< const SwFEShell * >( pVSh ) : 0; SwPaM* pCrsr = pFESh ? pFESh->GetCrsr( sal_False /* ??? */ ) : NULL;//IAccessibility2 Implementation 2009 //sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape ); } sal_Bool bIsSelAll =IsDocumentSelAll(); if( mpShapeMap ) { //Checked for shapes. _SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin(); _SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end(); ::vos::ORef< SwAccessibleContext > xParentAccImpl; if( bIsSelAll) { while( aIter != aEndIter ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if( xAcc.is() ) (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED ); ++aIter; } } else { while( aIter != aEndIter ) { sal_Bool bChanged = sal_False; sal_Bool bMarked = sal_False; SwAccessibleChild pFrm( (*aIter).first ); const SwFrmFmt *pFrmFmt = (*aIter).first ? ::FindFrmFmt( (*aIter).first ) : 0; if( !pFrmFmt ) { ++aIter; continue; } const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor(); const SwPosition *pPos = pAnchor.GetCntntAnchor(); if(pAnchor.GetAnchorId() == FLY_AT_PAGE) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if(xAcc.is()) (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED ); ++aIter; continue; } if( !pPos ) { ++aIter; continue; } if( pPos->nNode.GetNode().GetTxtNode() ) { int pIndex = pPos->nContent.GetIndex(); SwPaM* pTmpCrsr = pCrsr; if( pTmpCrsr != NULL ) { const SwTxtNode* pNode = pPos->nNode.GetNode().GetTxtNode(); sal_uLong nHere = pNode->GetIndex(); do { // ignore, if no mark if( pTmpCrsr->HasMark() ) { bMarked = sal_True; // check whether nHere is 'inside' pCrsr SwPosition* pStart = pTmpCrsr->Start(); sal_uLong nStartIndex = pStart->nNode.GetIndex(); SwPosition* pEnd = pTmpCrsr->End(); sal_uLong nEndIndex = pEnd->nNode.GetIndex(); if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex) ) { if( pAnchor.GetAnchorId() == FLY_AS_CHAR ) { if( ( (nHere == nStartIndex) && (pIndex >= pStart->nContent.GetIndex()) || (nHere > nStartIndex) ) &&( (nHere == nEndIndex) && (pIndex < pEnd->nContent.GetIndex()) || (nHere < nEndIndex) ) ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if( xAcc.is() ) bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED ); } else { uno::Reference < XAccessible > xAcc( (*aIter).second ); if( xAcc.is() ) bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED ); } } else if( pAnchor.GetAnchorId() == FLY_AT_PARA ) { if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 ) && (nHere < nEndIndex ) ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if( xAcc.is() ) bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->SetState( AccessibleStateType::SELECTED ); } else { uno::Reference < XAccessible > xAcc( (*aIter).second ); if(xAcc.is()) bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED ); } } } } // next PaM in ring pTmpCrsr = static_cast<SwPaM*>( pTmpCrsr->GetNext() ); } while( pTmpCrsr != pCrsr ); } if( !bMarked ) { SwAccessibleObjShape_Impl *pShape = pShapes; size_t nNumShapes = nShapes; while( nNumShapes ) { if( pShape < pSelShape && (pShape->first==(*aIter).first) ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); if(xAcc.is()) bChanged = (static_cast < ::accessibility::AccessibleShape* >(xAcc.get()))->ResetState( AccessibleStateType::SELECTED ); } --nNumShapes; ++pShape; } } } ++aIter; }//while( aIter != aEndIter ) }//else } //Checked for FlyFrm SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin(); while( aIter != mpFrmMap->end() ) { const SwFrm *pFrm = (*aIter).first; if(pFrm->IsFlyFrm()) { sal_Bool bFrmChanged = sal_False; uno::Reference < XAccessible > xAcc = (*aIter).second; if(xAcc.is()) { SwAccessibleFrameBase *pAccFrame = (static_cast< SwAccessibleFrameBase * >(xAcc.get())); bFrmChanged = pAccFrame->SetSelectedState( sal_True ); if (bFrmChanged) { const SwFlyFrm *pFlyFrm = static_cast< const SwFlyFrm * >( pFrm ); const SwFrmFmt *pFrmFmt = pFlyFrm->GetFmt(); if (pFrmFmt) { const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor(); if( pAnchor.GetAnchorId() == FLY_AS_CHAR ) { uno::Reference< XAccessible > xAccParent = pAccFrame->getAccessibleParent(); if (xAccParent.is()) { uno::Reference< XAccessibleContext > xAccContext = xAccParent->getAccessibleContext(); if(xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::PARAGRAPH) { SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xAccContext.get()); if(pAccFrame->IsSeletedInDoc()) { m_setParaAdd.insert(pAccPara); } else if(m_setParaAdd.count(pAccPara) == 0) { m_setParaRemove.insert(pAccPara); } } } } } } } } ++aIter; } typedef std::vector< SwAccessibleContext* > VEC_PARA; VEC_PARA vecAdd; VEC_PARA vecRemove; //Checked for Paras. SwPaM* pTmpCrsr = pCrsr; sal_Bool bMarkChanged = sal_False; SwAccessibleContextMap_Impl mapTemp; if( pTmpCrsr != NULL ) { do { if( pTmpCrsr->HasMark() ) { SwNodeIndex nStartIndex( pTmpCrsr->Start()->nNode ); SwNodeIndex nEndIndex( pTmpCrsr->End()->nNode ); while(nStartIndex <= nEndIndex) { SwFrm *pFrm = NULL; if(nStartIndex.GetNode().IsCntntNode()) { SwCntntNode* pCNd = (SwCntntNode*)&(nStartIndex.GetNode()); SwClientIter aClientIter( *pCNd ); pFrm = (SwFrm*)aClientIter.First( TYPE(SwFrm)); } else if( nStartIndex.GetNode().IsTableNode() ) { SwTableNode * pTable= (SwTableNode *)&(nStartIndex.GetNode()); SwFrmFmt* pFmt = const_cast<SwFrmFmt*>(pTable->GetTable().GetFrmFmt()); SwClientIter aClientIter( *pFmt ); pFrm = (SwFrm*)aClientIter.First( TYPE(SwFrm)); } if( pFrm && mpFrmMap) { aIter = mpFrmMap->find( pFrm ); if( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xAcc = (*aIter).second; sal_Bool isChanged = sal_False; if( xAcc.is() ) { isChanged = (static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( sal_True ); } if(!isChanged) { SwAccessibleContextMap_Impl::iterator aEraseIter = mpSeletedFrmMap->find( pFrm ); if(aEraseIter != mpSeletedFrmMap->end()) mpSeletedFrmMap->erase(aEraseIter); } else { bMarkChanged = sal_True; vecAdd.push_back(static_cast< SwAccessibleContext * >(xAcc.get())); } mapTemp.insert( SwAccessibleContextMap_Impl::value_type( pFrm, xAcc ) ); } } nStartIndex++; } } pTmpCrsr = static_cast<SwPaM*>( pTmpCrsr->GetNext() ); } while( pTmpCrsr != pCrsr ); } if( !mpSeletedFrmMap ) mpSeletedFrmMap = new SwAccessibleContextMap_Impl; if( !mpSeletedFrmMap->empty() ) { aIter = mpSeletedFrmMap->begin(); while( aIter != mpSeletedFrmMap->end() ) { uno::Reference < XAccessible > xAcc = (*aIter).second; if(xAcc.is()) (static_cast< SwAccessibleContext * >(xAcc.get()))->SetSelectedState( sal_False ); ++aIter; vecRemove.push_back(static_cast< SwAccessibleContext * >(xAcc.get())); } bMarkChanged = sal_True; mpSeletedFrmMap->clear(); } if( !mapTemp.empty() ) { aIter = mapTemp.begin(); while( aIter != mapTemp.end() ) { mpSeletedFrmMap->insert( SwAccessibleContextMap_Impl::value_type( (*aIter).first, (*aIter).second ) ); ++aIter; } mapTemp.clear(); } if( bMarkChanged && mpFrmMap) { VEC_PARA::iterator vi = vecAdd.begin(); for (; vi != vecAdd.end() ; ++vi) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; SwAccessibleContext* pAccPara = *vi; if (pAccPara) { pAccPara->FireAccessibleEvent( aEvent ); } } vi = vecRemove.begin(); for (; vi != vecRemove.end() ; ++vi) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE; SwAccessibleContext* pAccPara = *vi; if (pAccPara) { pAccPara->FireAccessibleEvent( aEvent ); } } } } //Marge with DoInvalidateShapeFocus void SwAccessibleMap::DoInvalidateShapeSelection(sal_Bool bInvalidateFocusMode /*=sal_False*/) { SwAccessibleObjShape_Impl *pShapes = 0; SwAccessibleObjShape_Impl *pSelShape = 0; size_t nShapes = 0; const ViewShell *pVSh = GetShell(); const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ? static_cast< const SwFEShell * >( pVSh ) : 0; sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; //when InvalidateFocus Call this function ,and the current selected shape count is not 1 , //return if (bInvalidateFocusMode && nSelShapes != 1) { return; } { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape ); } if( pShapes ) { typedef std::vector< ::vos::ORef < ::accessibility::AccessibleShape > > VEC_SHAPE; VEC_SHAPE vecxShapeAdd; VEC_SHAPE vecxShapeRemove; int nCountSelectedShape=0; Window *pWin = GetShell()->GetWin(); sal_Bool bFocused = pWin && pWin->HasFocus(); SwAccessibleObjShape_Impl *pShape = pShapes; int nShapeCount = nShapes; while( nShapeCount ) { //if( pShape->second.isValid() ) if (pShape->second.isValid() && IsInSameLevel(pShape->first, pFESh)) { if( pShape < pSelShape ) { if(pShape->second->ResetState( AccessibleStateType::SELECTED )) { vecxShapeRemove.push_back(pShape->second); } pShape->second->ResetState( AccessibleStateType::FOCUSED ); } } --nShapeCount; ++pShape; } VEC_SHAPE::iterator vi =vecxShapeRemove.begin(); for (; vi != vecxShapeRemove.end(); ++vi) { ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr()); if (pAccShape) { pAccShape->CommitChange(AccessibleEventId::SELECTION_CHANGED_REMOVE, uno::Any(), uno::Any()); } } pShape = pShapes; while( nShapes ) { //if( pShape->second.isValid() ) if (pShape->second.isValid() && IsInSameLevel(pShape->first, pFESh)) { // IA2 - why? // sal_Bool bChanged; if( pShape >= pSelShape ) { // IA2: first fire focus event // bChanged = pShape->second->SetState( AccessibleStateType::SELECTED ); //first fire focus event if( bFocused && 1 == nSelShapes ) pShape->second->SetState( AccessibleStateType::FOCUSED ); else pShape->second->ResetState( AccessibleStateType::FOCUSED ); // IA2 CWS: if(pShape->second->SetState( AccessibleStateType::SELECTED )) { vecxShapeAdd.push_back(pShape->second); } ++nCountSelectedShape; } /* MT: This still was in DEV300m80, but was removed in IA2 CWS. Someone needs to check what should happen here, see original diff CWS oo31ia2 vs. OOO310M11 else { bChanged = pShape->second->ResetState( AccessibleStateType::SELECTED ); pShape->second->ResetState( AccessibleStateType::FOCUSED ); } if( bChanged ) { const SwFrm* pParent = SwAccessibleFrame::GetParent( SwAccessibleChild( pShape->first ), GetShell()->IsPreView() ); aParents.push_back( pParent ); } */ } --nShapes; ++pShape; } const unsigned int SELECTION_WITH_NUM = 10; if (vecxShapeAdd.size() > SELECTION_WITH_NUM ) { uno::Reference< XAccessible > xDoc = GetDocumentView( ); SwAccessibleContext * pCont = static_cast<SwAccessibleContext *>(xDoc.get()); if (pCont) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_WITHIN; pCont->FireAccessibleEvent(aEvent); } } else { short nEventID = AccessibleEventId::SELECTION_CHANGED_ADD; if (nCountSelectedShape <= 1 && vecxShapeAdd.size() == 1 ) { nEventID = AccessibleEventId::SELECTION_CHANGED; } vi = vecxShapeAdd.begin(); for (; vi != vecxShapeAdd.end(); ++vi) { ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr()); if (pAccShape) { pAccShape->CommitChange(nEventID, uno::Any(), uno::Any()); } } } vi = vecxShapeAdd.begin(); for (; vi != vecxShapeAdd.end(); ++vi) { ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr()); if (pAccShape) { SdrObject *pObj = GetSdrObjectFromXShape(pAccShape->GetXShape()); SwFrmFmt *pFrmFmt = pObj ? FindFrmFmt( pObj ) : NULL; if (pFrmFmt) { const SwFmtAnchor& pAnchor = pFrmFmt->GetAnchor(); if( pAnchor.GetAnchorId() == FLY_AS_CHAR ) { uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent(); if (xPara.is()) { uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext(); if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH) { SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get()); if (pAccPara) { m_setParaAdd.insert(pAccPara); } } } } } } } vi = vecxShapeRemove.begin(); for (; vi != vecxShapeRemove.end(); ++vi) { ::accessibility::AccessibleShape *pAccShape = static_cast< ::accessibility::AccessibleShape * >(vi->getBodyPtr()); if (pAccShape) { uno::Reference< XAccessible > xPara = pAccShape->getAccessibleParent(); uno::Reference< XAccessibleContext > xParaContext = xPara->getAccessibleContext(); if (xParaContext.is() && xParaContext->getAccessibleRole() == AccessibleRole::PARAGRAPH) { SwAccessibleParagraph* pAccPara = static_cast< SwAccessibleParagraph *>(xPara.get()); if (m_setParaAdd.count(pAccPara) == 0 ) { m_setParaRemove.insert(pAccPara); } } } } delete[] pShapes; } } //Marge with DoInvalidateShapeSelection /* void SwAccessibleMap::DoInvalidateShapeFocus() { const ViewShell *pVSh = GetShell(); const SwFEShell *pFESh = pVSh->ISA( SwFEShell ) ? static_cast< const SwFEShell * >( pVSh ) : 0; sal_uInt16 nSelShapes = pFESh ? pFESh->IsObjSelected() : 0; if( nSelShapes != 1 ) return; SwAccessibleObjShape_Impl *pShapes = 0; SwAccessibleObjShape_Impl *pSelShape = 0; size_t nShapes = 0; { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) pShapes = mpShapeMap->Copy( nShapes, pFESh, &pSelShape ); } if( pShapes ) { Window *pWin = GetShell()->GetWin(); sal_Bool bFocused = pWin && pWin->HasFocus(); SwAccessibleObjShape_Impl *pShape = pShapes; while( nShapes ) { if( pShape->second.isValid() ) { if( bFocused && pShape >= pSelShape ) pShape->second->SetState( AccessibleStateType::FOCUSED ); else pShape->second->ResetState( AccessibleStateType::FOCUSED ); } --nShapes; ++pShape; } delete[] pShapes; } } */ //-----IAccessibility2 Implementation 2009 SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) : mpFrmMap( 0 ), mpShapeMap( 0 ), mpShapes( 0 ), mpEvents( 0 ), mpEventMap( 0 ), // --> OD 2005-12-13 #i27301# mpSelectedParas( 0 ), // <-- mpVSh( pSh ), mpPreview( 0 ), mnPara( 1 ), mnFootnote( 1 ), mnEndnote( 1 ), mbShapeSelected( sal_False ), mpSeletedFrmMap(NULL)//IAccessibility2 Implementation 2009 { pSh->GetLayout()->AddAccessibleShell(); } SwAccessibleMap::~SwAccessibleMap() { uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { const SwRootFrm *pRootFrm = GetShell()->GetLayout(); SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; if( !xAcc.is() ) xAcc = new SwAccessibleDocument( this ); } } //IAccessibility2 Implementation 2009----- if(xAcc.is()) { SwAccessibleDocument *pAcc = static_cast< SwAccessibleDocument * >( xAcc.get() ); pAcc->Dispose( sal_True ); } if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin(); while( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xTmp = (*aIter).second; if( xTmp.is() ) { SwAccessibleContext *pTmp = static_cast< SwAccessibleContext * >( xTmp.get() ); pTmp->SetMap(NULL); } ++aIter; } } //-----IAccessibility2 Implementation 2009 { vos::OGuard aGuard( maMutex ); #ifdef DBG_UTIL ASSERT( !mpFrmMap || mpFrmMap->empty(), "Frame map should be empty after disposing the root frame" ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->begin(); while( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xTmp = (*aIter).second; if( xTmp.is() ) { SwAccessibleContext *pTmp = static_cast< SwAccessibleContext * >( xTmp.get() ); (void) pTmp; } ++aIter; } } ASSERT( !mpShapeMap || mpShapeMap->empty(), "Object map should be empty after disposing the root frame" ); if( mpShapeMap ) { SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->begin(); while( aIter != mpShapeMap->end() ) { uno::Reference < XAccessible > xTmp = (*aIter).second; if( xTmp.is() ) { ::accessibility::AccessibleShape *pTmp = static_cast< ::accessibility::AccessibleShape* >( xTmp.get() ); (void) pTmp; } ++aIter; } } #endif delete mpFrmMap; mpFrmMap = 0; delete mpShapeMap; mpShapeMap = 0; delete mpShapes; mpShapes = 0; // --> OD 2005-12-13 #i27301# delete mpSelectedParas; mpSelectedParas = 0; // <-- } delete mpPreview; mpPreview = NULL; { vos::OGuard aGuard( maEventMutex ); #ifdef DBG_UTIL ASSERT( !(mpEvents || mpEventMap), "pending events" ); if( mpEvents ) { SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin(); while( aIter != mpEvents->end() ) { ++aIter; } } if( mpEventMap ) { SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->begin(); while( aIter != mpEventMap->end() ) { ++aIter; } } #endif delete mpEventMap; mpEventMap = 0; delete mpEvents; mpEvents = 0; } mpVSh->GetLayout()->RemoveAccessibleShell(); delete mpSeletedFrmMap;//IAccessibility2 Implementation 2009 } uno::Reference< XAccessible > SwAccessibleMap::_GetDocumentView( sal_Bool bPagePreview ) { uno::Reference < XAccessible > xAcc; sal_Bool bSetVisArea = sal_False; { vos::OGuard aGuard( maMutex ); if( !mpFrmMap ) { mpFrmMap = new SwAccessibleContextMap_Impl; #ifdef DBG_UTIL mpFrmMap->mbLocked = sal_False; #endif } #ifdef DBG_UTIL ASSERT( !mpFrmMap->mbLocked, "Map is locked" ); mpFrmMap->mbLocked = sal_True; #endif const SwRootFrm *pRootFrm = GetShell()->GetLayout(); SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pRootFrm ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; if( xAcc.is() ) { bSetVisArea = sal_True; // Set VisArea when map mutex is not // locked } else { if( bPagePreview ) xAcc = new SwAccessiblePreview( this ); else xAcc = new SwAccessibleDocument( this ); if( aIter != mpFrmMap->end() ) { (*aIter).second = xAcc; } else { SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc ); mpFrmMap->insert( aEntry ); } } #ifdef DBG_UTIL mpFrmMap->mbLocked = sal_False; #endif } if( bSetVisArea ) { SwAccessibleDocumentBase *pAcc = static_cast< SwAccessibleDocumentBase * >( xAcc.get() ); pAcc->SetVisArea(); } return xAcc; } uno::Reference< XAccessible > SwAccessibleMap::GetDocumentView( ) { return _GetDocumentView( sal_False ); } // OD 14.01.2003 #103492# - complete re-factoring of method due to new page/print // preview functionality. uno::Reference<XAccessible> SwAccessibleMap::GetDocumentPreview( const std::vector<PrevwPage*>& _rPrevwPages, const Fraction& _rScale, const SwPageFrm* _pSelectedPageFrm, const Size& _rPrevwWinSize ) { // create & update preview data object if( mpPreview == NULL ) mpPreview = new SwAccPreviewData(); mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize ); uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True ); return xAcc; } uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm, sal_Bool bCreate ) { uno::Reference < XAccessible > xAcc; uno::Reference < XAccessible > xOldCursorAcc; sal_Bool bOldShapeSelected = sal_False; { vos::OGuard aGuard( maMutex ); if( !mpFrmMap && bCreate ) mpFrmMap = new SwAccessibleContextMap_Impl; if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; if( !xAcc.is() && bCreate ) { SwAccessibleContext *pAcc = 0; switch( pFrm->GetType() ) { case FRM_TXT: mnPara++; pAcc = new SwAccessibleParagraph( *this, static_cast< const SwTxtFrm& >( *pFrm ) ); break; case FRM_HEADER: pAcc = new SwAccessibleHeaderFooter( this, static_cast< const SwHeaderFrm *>( pFrm ) ); break; case FRM_FOOTER: pAcc = new SwAccessibleHeaderFooter( this, static_cast< const SwFooterFrm *>( pFrm ) ); break; case FRM_FTN: { const SwFtnFrm *pFtnFrm = static_cast < const SwFtnFrm * >( pFrm ); sal_Bool bIsEndnote = SwAccessibleFootnote::IsEndnote( pFtnFrm ); pAcc = new SwAccessibleFootnote( this, bIsEndnote, /*(bIsEndnote ? mnEndnote++ : mnFootnote++),*/ pFtnFrm ); } break; case FRM_FLY: { const SwFlyFrm *pFlyFrm = static_cast < const SwFlyFrm * >( pFrm ); switch( SwAccessibleFrameBase::GetNodeType( pFlyFrm ) ) { case ND_GRFNODE: pAcc = new SwAccessibleGraphic( this, pFlyFrm ); break; case ND_OLENODE: pAcc = new SwAccessibleEmbeddedObject( this, pFlyFrm ); break; default: pAcc = new SwAccessibleTextFrame( this, pFlyFrm ); break; } } break; case FRM_CELL: pAcc = new SwAccessibleCell( this, static_cast< const SwCellFrm *>( pFrm ) ); break; case FRM_TAB: pAcc = new SwAccessibleTable( this, static_cast< const SwTabFrm *>( pFrm ) ); break; case FRM_PAGE: DBG_ASSERT( GetShell()->IsPreView(), "accessible page frames only in PagePreview" ); pAcc = new SwAccessiblePage( this, pFrm ); break; } xAcc = pAcc; ASSERT( xAcc.is(), "unknown frame type" ); if( xAcc.is() ) { if( aIter != mpFrmMap->end() ) { (*aIter).second = xAcc; } else { SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc ); mpFrmMap->insert( aEntry ); } if( pAcc->HasCursor() && !AreInSameTable( mxCursorContext, pFrm ) ) { // If the new context has the focus, and if we know // another context that had the focus, then the focus // just moves from the old context to the new one. We // have to send a focus event and a caret event for // the old context then. We have to to that know, // because after we have left this method, anyone might // call getStates for the new context and will get a // focused state then. Sending the focus changes event // after that seems to be strange. However, we cannot // send a focus event fo the new context now, because // noone except us knows it. In any case, we remeber // the new context as the one that has the focus // currently. xOldCursorAcc = mxCursorContext; mxCursorContext = xAcc; bOldShapeSelected = mbShapeSelected; mbShapeSelected = sal_False; } } } } } // Invalidate focus for old object when map is not locked if( xOldCursorAcc.is() ) InvalidateCursorPosition( xOldCursorAcc ); if( bOldShapeSelected ) InvalidateShapeSelection(); return xAcc; } ::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl( const SwFrm *pFrm, sal_Bool bCreate ) { uno::Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) ); ::vos::ORef < SwAccessibleContext > xAccImpl( static_cast< SwAccessibleContext * >( xAcc.get() ) ); return xAccImpl; } uno::Reference< XAccessible> SwAccessibleMap::GetContext( const SdrObject *pObj, SwAccessibleContext *pParentImpl, sal_Bool bCreate ) { uno::Reference < XAccessible > xAcc; uno::Reference < XAccessible > xOldCursorAcc; { vos::OGuard aGuard( maMutex ); if( !mpShapeMap && bCreate ) mpShapeMap = new SwAccessibleShapeMap_Impl( this ); if( mpShapeMap ) { SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj ); if( aIter != mpShapeMap->end() ) xAcc = (*aIter).second; if( !xAcc.is() && bCreate ) { ::accessibility::AccessibleShape *pAcc = 0; uno::Reference < drawing::XShape > xShape( const_cast< SdrObject * >( pObj )->getUnoShape(), uno::UNO_QUERY ); if( xShape.is() ) { ::accessibility::ShapeTypeHandler& rShapeTypeHandler = ::accessibility::ShapeTypeHandler::Instance(); uno::Reference < XAccessible > xParent( pParentImpl ); ::accessibility::AccessibleShapeInfo aShapeInfo( xShape, xParent, this ); pAcc = rShapeTypeHandler.CreateAccessibleObject( aShapeInfo, mpShapeMap->GetInfo() ); } xAcc = pAcc; ASSERT( xAcc.is(), "unknown shape type" ); if( xAcc.is() ) { pAcc->Init(); if( aIter != mpShapeMap->end() ) { (*aIter).second = xAcc; } else { SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc ); mpShapeMap->insert( aEntry ); } // TODO: focus!!! } //IAccessibility2 Implementation 2009----- if (xAcc.is()) AddGroupContext(pObj, xAcc); //-----IAccessibility2 Implementation 2009 } } } // Invalidate focus for old object when map is not locked if( xOldCursorAcc.is() ) InvalidateCursorPosition( xOldCursorAcc ); return xAcc; } //IAccessibility2 Implementation 2009----- sal_Bool SwAccessibleMap::IsInSameLevel(const SdrObject* pObj, const SwFEShell* pFESh) { if (pFESh) return pFESh->IsObjSameLevelWithMarked(pObj); return sal_False; } void SwAccessibleMap::AddShapeContext(const SdrObject *pObj, uno::Reference < XAccessible > xAccShape) { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) { SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAccShape ); mpShapeMap->insert( aEntry ); } } //Added by yanjun for sym2_6407 void SwAccessibleMap::RemoveGroupContext(const SdrObject *pParentObj, ::com::sun::star::uno::Reference < ::com::sun::star::accessibility::XAccessible > xAccParent) { vos::OGuard aGuard( maMutex ); if (mpShapeMap && pParentObj && pParentObj->IsGroupObject() && xAccParent.is()) { uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext(); if (xContext.is()) { for (sal_Int32 i = 0; i < xContext->getAccessibleChildCount(); ++i) { uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i); if (xChild.is()) { uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext(); if (xChildContext.is()) { if (xChildContext->getAccessibleRole() == AccessibleRole::SHAPE) { ::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get()); uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape(); if (xShape.is()) { SdrObject* pObj = GetSdrObjectFromXShape(xShape); if (pObj) RemoveContext(pObj); } } } } } } } } //End void SwAccessibleMap::AddGroupContext(const SdrObject *pParentObj, uno::Reference < XAccessible > xAccParent) { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) { //here get all the sub list. if (pParentObj->IsGroupObject()) { if (xAccParent.is()) { uno::Reference < XAccessibleContext > xContext = xAccParent->getAccessibleContext(); if (xContext.is()) { sal_Int32 nChildren = xContext->getAccessibleChildCount(); for(sal_Int32 i = 0; i<nChildren; i++) { uno::Reference < XAccessible > xChild = xContext->getAccessibleChild(i); if (xChild.is()) { uno::Reference < XAccessibleContext > xChildContext = xChild->getAccessibleContext(); if (xChildContext.is()) { short nRole = xChildContext->getAccessibleRole(); if (nRole == AccessibleRole::SHAPE) { ::accessibility::AccessibleShape* pAccShape = static_cast < ::accessibility::AccessibleShape* >( xChild.get()); uno::Reference < drawing::XShape > xShape = pAccShape->GetXShape(); if (xShape.is()) { SdrObject* pObj = GetSdrObjectFromXShape(xShape); AddShapeContext(pObj, xChild); AddGroupContext(pObj,xChild); } } } } } } } } } } //-----IAccessibility2 Implementation 2009 ::vos::ORef < ::accessibility::AccessibleShape > SwAccessibleMap::GetContextImpl( const SdrObject *pObj, SwAccessibleContext *pParentImpl, sal_Bool bCreate ) { uno::Reference < XAccessible > xAcc( GetContext( pObj, pParentImpl, bCreate ) ); ::vos::ORef < ::accessibility::AccessibleShape > xAccImpl( static_cast< ::accessibility::AccessibleShape* >( xAcc.get() ) ); return xAccImpl; } void SwAccessibleMap::RemoveContext( const SwFrm *pFrm ) { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pFrm ); if( aIter != mpFrmMap->end() ) { mpFrmMap->erase( aIter ); // Remove reference to old caret object. Though mxCursorContext // is a weak reference and cleared automatically, clearing it // directly makes sure to not keep a defunctional object. uno::Reference < XAccessible > xOldAcc( mxCursorContext ); if( xOldAcc.is() ) { SwAccessibleContext *pOldAccImpl = static_cast< SwAccessibleContext *>( xOldAcc.get() ); ASSERT( pOldAccImpl->GetFrm(), "old caret context is disposed" ); if( pOldAccImpl->GetFrm() == pFrm ) { xOldAcc.clear(); // get an empty ref mxCursorContext = xOldAcc; } } if( mpFrmMap->empty() ) { delete mpFrmMap; mpFrmMap = 0; } } } } void SwAccessibleMap::RemoveContext( const SdrObject *pObj ) { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) { SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj ); if( aIter != mpShapeMap->end() ) { //IAccessible2 Implementation 2009 ---- uno::Reference < XAccessible > xAcc( (*aIter).second ); mpShapeMap->erase( aIter ); RemoveGroupContext(pObj, xAcc); // The shape selection flag is not cleared, but one might do // so but has to make sure that the removed context is the one // that is selected. if( mpShapeMap && mpShapeMap->empty() ) //---- IAccessible2 Implementation 2009 { delete mpShapeMap; mpShapeMap = 0; } } } } void SwAccessibleMap::Dispose( const SwFrm *pFrm, const SdrObject *pObj, Window* pWindow, sal_Bool bRecursive ) { SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow ); // Indeed, the following assert checks the frame's accessible flag, // because that's the one that is evaluated in the layout. The frame // might not be accessible anyway. That's the case for cell frames that // contain further cells. ASSERT( !aFrmOrObj.GetSwFrm() || aFrmOrObj.GetSwFrm()->IsAccessibleFrm(), "non accessible frame should be disposed" ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { ::vos::ORef< SwAccessibleContext > xAccImpl; ::vos::ORef< SwAccessibleContext > xParentAccImpl; ::vos::ORef< ::accessibility::AccessibleShape > xShapeAccImpl; // get accessible context for frame { vos::OGuard aGuard( maMutex ); // First of all look for an accessible context for a frame if( aFrmOrObj.GetSwFrm() && mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); } } if( !xAccImpl.isValid() && mpFrmMap ) { // If there is none, look if the parent is accessible. const SwFrm *pParent = SwAccessibleFrame::GetParent( aFrmOrObj, GetShell()->IsPreView()); if( pParent ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pParent ); if( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); xParentAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); } } } if( !xParentAccImpl.isValid() && !aFrmOrObj.GetSwFrm() && mpShapeMap ) { SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( aFrmOrObj.GetDrawObject() ); if( aIter != mpShapeMap->end() ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); xShapeAccImpl = static_cast< ::accessibility::AccessibleShape *>( xAcc.get() ); } } if( pObj && GetShell()->ActionPend() && (xParentAccImpl.isValid() || xShapeAccImpl.isValid()) ) { // Keep a reference to the XShape to avoid that it // is deleted with a SwFrmFmt::Modify. uno::Reference < drawing::XShape > xShape( const_cast< SdrObject * >( pObj )->getUnoShape(), uno::UNO_QUERY ); if( xShape.is() ) { if( !mpShapes ) mpShapes = new SwShapeList_Impl; mpShapes->push_back( xShape ); } } } // remove events stored for the frame { vos::OGuard aGuard( maEventMutex ); if( mpEvents ) { SwAccessibleEventMap_Impl::iterator aIter = mpEventMap->find( aFrmOrObj ); if( aIter != mpEventMap->end() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj ); AppendEvent( aEvent ); } } } // If the frame is accessible and there is a context for it, dispose // the frame. If the frame is no context for it but disposing should // take place recursive, the frame's children have to be disposed // anyway, so we have to create the context then. if( xAccImpl.isValid() ) { xAccImpl->Dispose( bRecursive ); } else if( xParentAccImpl.isValid() ) { // If the frame is a cell frame, the table must be notified. // If we are in an action, a table model change event will // be broadcasted at the end of the action to give the table // a chance to generate a single table change event. xParentAccImpl->DisposeChild( aFrmOrObj, bRecursive ); } else if( xShapeAccImpl.isValid() ) { RemoveContext( aFrmOrObj.GetDrawObject() ); xShapeAccImpl->dispose(); } if( mpPreview && pFrm && pFrm->IsPageFrm() ) mpPreview->DisposePage( static_cast< const SwPageFrm *>( pFrm ) ); } } void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm, const SdrObject *pObj, Window* pWindow, const SwRect& rOldBox ) { SwAccessibleChild aFrmOrObj( pFrm, pObj, pWindow ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { ::vos::ORef< SwAccessibleContext > xAccImpl; ::vos::ORef< SwAccessibleContext > xParentAccImpl; const SwFrm *pParent =NULL; //IAccessibility2 Implementation 2009 { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { if( aFrmOrObj.GetSwFrm() ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) { // If there is an accesible object already it is // notified directly. uno::Reference < XAccessible > xAcc( (*aIter).second ); xAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); } } if( !xAccImpl.isValid() ) { // Otherwise we look if the parent is accessible. // If not, there is nothing to do. pParent = //IAccessibility2 Implementation 2009 SwAccessibleFrame::GetParent( aFrmOrObj, GetShell()->IsPreView()); if( pParent ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pParent ); if( aIter != mpFrmMap->end() ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); xParentAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); } } } } } if( xAccImpl.isValid() ) { if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::POS_CHANGED, xAccImpl.getBodyPtr(), aFrmOrObj, rOldBox ); AppendEvent( aEvent ); } else { FireEvents(); xAccImpl->InvalidatePosOrSize( rOldBox ); } } else if( xParentAccImpl.isValid() ) { if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CHILD_POS_CHANGED, xParentAccImpl.getBodyPtr(), aFrmOrObj, rOldBox ); AppendEvent( aEvent ); } else { FireEvents(); xParentAccImpl->InvalidateChildPosOrSize( aFrmOrObj, rOldBox ); } } //IAccessibility2 Implementation 2009----- else if(pParent) { /* For child graphic and it's parent paragraph,if split 2 graphic to 2 paragraph, will delete one graphic swfrm and new create 1 graphic swfrm , then the new paragraph and the new graphic SwFrm will add . but when add graphic SwFrm ,the accessible of the new Paragraph is not created yet. so the new graphic accessible 'parent is NULL, so run here: save the parent's SwFrm not the accessible object parent, */ sal_Bool bIsValidFrm = sal_False; sal_Bool bIsTxtParent = sal_False; if (aFrmOrObj.GetSwFrm()) { int nType = pFrm->GetType(); if ( FRM_FLY == nType ) { bIsValidFrm =sal_True; } } else if(pObj) { int nType = pParent->GetType(); if (FRM_TXT == nType) { bIsTxtParent =sal_True; } } // sal_Bool bIsVisibleChildrenOnly =aFrmOrObj.IsVisibleChildrenOnly() ; // sal_Bool bIsBoundAsChar =aFrmOrObj.IsBoundAsChar() ;//bIsVisibleChildrenOnly && bIsBoundAsChar && if((bIsValidFrm || bIsTxtParent) ) { if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CHILD_POS_CHANGED, pParent, aFrmOrObj, rOldBox ); AppendEvent( aEvent ); } else { OSL_ENSURE(false,""); } } } } //-----IAccessibility2 Implementation 2009 } void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm ) { SwAccessibleChild aFrmOrObj( pFrm ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; } } if( xAcc.is() ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl, aFrmOrObj ); AppendEvent( aEvent ); } else { FireEvents(); pAccImpl->InvalidateContent(); } } } } // --> OD 2009-01-06 #i88069# void SwAccessibleMap::InvalidateAttr( const SwTxtFrm& rTxtFrm ) { SwAccessibleChild aFrmOrObj( &rTxtFrm ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; } } if( xAcc.is() ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::INVALID_ATTR, pAccImpl, aFrmOrObj ); aEvent.SetStates( ACC_STATE_TEXT_ATTRIBUTE_CHANGED ); AppendEvent( aEvent ); } else { FireEvents(); pAccImpl->InvalidateAttr(); } } } } // <-- void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm ) { SwAccessibleChild aFrmOrObj( pFrm ); sal_Bool bShapeSelected = sal_False; const ViewShell *pVSh = GetShell(); if( pVSh->ISA( SwCrsrShell ) ) { const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh ); if( pCSh->IsTableMode() ) { while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() ) aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper(); } else if( pVSh->ISA( SwFEShell ) ) { sal_uInt16 nObjCount; const SwFEShell *pFESh = static_cast< const SwFEShell * >( pVSh ); const SwFrm *pFlyFrm = pFESh->GetCurrFlyFrm(); if( pFlyFrm ) { ASSERT( !pFrm || pFrm->FindFlyFrm() == pFlyFrm, "cursor is not contained in fly frame" ); aFrmOrObj = pFlyFrm; } else if( (nObjCount = pFESh->IsObjSelected()) > 0 ) { bShapeSelected = sal_True; aFrmOrObj = static_cast<const SwFrm *>( 0 ); } } } ASSERT( bShapeSelected || aFrmOrObj.IsAccessible(GetShell()->IsPreView()), "frame is not accessible" ); uno::Reference < XAccessible > xOldAcc; uno::Reference < XAccessible > xAcc; sal_Bool bOldShapeSelected = sal_False; { vos::OGuard aGuard( maMutex ); xOldAcc = mxCursorContext; mxCursorContext = xAcc; // clear reference bOldShapeSelected = mbShapeSelected; mbShapeSelected = bShapeSelected; if( aFrmOrObj.GetSwFrm() && mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; //IAccessibility2 Implementation 2009----- else { SwRect rcEmpty; const SwTabFrm* pTabFrm = aFrmOrObj.GetSwFrm()->FindTabFrm(); if (pTabFrm) { InvalidatePosOrSize(pTabFrm,0,0,rcEmpty); } else { InvalidatePosOrSize(aFrmOrObj.GetSwFrm(),0,0,rcEmpty); } aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) { xAcc = (*aIter).second; } } //-----IAccessibility2 Implementation 2009 // For cells, some extra thoughts are necessary, // because invalidating the cursor for one cell // invalidates the cursor for all cells of the same // table. For this reason, we don't want to // invalidate the cursor for the old cursor object // and the new one if they are within the same table, // because this would result in doing the work twice. // Moreover, we have to make sure to invalidate the // cursor even if the current cell has no accessible object. // If the old cursor objects exists and is in the same // table, its the best choice, because using it avoids // an unnessarary cursor invalidation cycle when creating // a new object for the current cell. if( aFrmOrObj.GetSwFrm()->IsCellFrm() ) { if( xOldAcc.is() && AreInSameTable( xOldAcc, aFrmOrObj.GetSwFrm() ) ) { if( xAcc.is() ) xOldAcc = xAcc; // avoid extra invalidation else xAcc = xOldAcc; // make sure ate least one } if( !xAcc.is() ) xAcc = GetContext( aFrmOrObj.GetSwFrm(), sal_True ); } } //IAccessibility2 Implementation 2009----- else if (bShapeSelected) { const SwFEShell *pFESh = pVSh ? static_cast< const SwFEShell * >( pVSh ) : NULL ; if(pFESh) { const SdrMarkList *pMarkList = pFESh->GetMarkList(); if (pMarkList != NULL && pMarkList->GetMarkCount() == 1) { SdrObject *pObj = pMarkList->GetMark( 0 )->GetMarkedSdrObj(); ::vos::ORef < ::accessibility::AccessibleShape > pAccShapeImpl = GetContextImpl(pObj,NULL,sal_False); if (!pAccShapeImpl.isValid()) { while (pObj && pObj->GetUpGroup()) { pObj = pObj->GetUpGroup(); } if (pObj != NULL) { const SwFrm *pParent = SwAccessibleFrame::GetParent( SwAccessibleChild(pObj), GetShell()->IsPreView() ); if( pParent ) { ::vos::ORef< SwAccessibleContext > xParentAccImpl = GetContextImpl(pParent,sal_False); if (!xParentAccImpl.isValid()) { const SwTabFrm* pTabFrm = pParent->FindTabFrm(); if (pTabFrm) { //The Table should not add in acc.because the "pParent" is not add to acc . uno::Reference< XAccessible> xAccParentTab = GetContext(pTabFrm,sal_True);//Should Create. const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pTabFrm), GetShell()->IsPreView() ); if (pParentRoot) { ::vos::ORef< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,sal_False); if(xParentAccImplRoot.isValid()) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= xAccParentTab; xParentAccImplRoot->FireAccessibleEvent( aEvent ); } } //Get "pParent" acc again. xParentAccImpl = GetContextImpl(pParent,sal_False); } else { //directly create this acc para . xParentAccImpl = GetContextImpl(pParent,sal_True);//Should Create. const SwFrm *pParentRoot = SwAccessibleFrame::GetParent( SwAccessibleChild(pParent), GetShell()->IsPreView() ); ::vos::ORef< SwAccessibleContext > xParentAccImplRoot = GetContextImpl(pParentRoot,sal_False); if(xParentAccImplRoot.isValid()) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= uno::Reference< XAccessible>(xParentAccImpl.getBodyPtr()); xParentAccImplRoot->FireAccessibleEvent( aEvent ); } } } if (xParentAccImpl.isValid()) { uno::Reference< XAccessible> xAccShape = GetContext(pObj,xParentAccImpl.getBodyPtr(),sal_True); AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= xAccShape; xParentAccImpl->FireAccessibleEvent( aEvent ); } } } } } } } } m_setParaAdd.clear(); m_setParaRemove.clear(); if( xOldAcc.is() && xOldAcc != xAcc ) InvalidateCursorPosition( xOldAcc ); if( bOldShapeSelected || bShapeSelected ) InvalidateShapeSelection(); if( xAcc.is() ) InvalidateCursorPosition( xAcc ); InvalidateShapeInParaSelection(); SET_PARA::iterator si = m_setParaRemove.begin(); for (; si != m_setParaRemove.end() ; ++si) { SwAccessibleParagraph* pAccPara = *si; if(pAccPara && pAccPara->getSelectedAccessibleChildCount() == 0 && pAccPara->getSelectedText().getLength() == 0) { if(pAccPara->SetSelectedState(sal_False)) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE; pAccPara->FireAccessibleEvent( aEvent ); } } } si = m_setParaAdd.begin(); for (; si != m_setParaAdd.end() ; ++si) { SwAccessibleParagraph* pAccPara = *si; if(pAccPara && pAccPara->SetSelectedState(sal_True)) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::SELECTION_CHANGED; pAccPara->FireAccessibleEvent( aEvent ); } } //-----IAccessibility2 Implementation 2009 } //IAccessibility2 Implementation 2009----- //Notify the page change event to bridge. void SwAccessibleMap::FirePageChangeEvent(sal_uInt16 nOldPage, sal_uInt16 nNewPage) { uno::Reference<XAccessible> xAcc = GetDocumentView( ); if ( xAcc.is() ) { SwAccessibleDocumentBase *pAcc = static_cast< SwAccessibleDocumentBase * >( xAcc.get() ); if (pAcc) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::PAGE_CHANGED; aEvent.OldValue <<= nOldPage; aEvent.NewValue <<= nNewPage; pAcc->FireAccessibleEvent( aEvent ); } } } void SwAccessibleMap::FireSectionChangeEvent(sal_uInt16 nOldSection, sal_uInt16 nNewSection) { uno::Reference<XAccessible> xAcc = GetDocumentView( ); if ( xAcc.is() ) { SwAccessibleDocumentBase *pAcc = static_cast< SwAccessibleDocumentBase * >( xAcc.get() ); if (pAcc) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::SECTION_CHANGED; aEvent.OldValue <<= nOldSection; aEvent.NewValue <<= nNewSection; pAcc->FireAccessibleEvent( aEvent ); } } } void SwAccessibleMap::FireColumnChangeEvent(sal_uInt16 nOldColumn, sal_uInt16 nNewColumn) { uno::Reference<XAccessible> xAcc = GetDocumentView( ); if ( xAcc.is() ) { SwAccessibleDocumentBase *pAcc = static_cast< SwAccessibleDocumentBase * >( xAcc.get() ); if (pAcc) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::COLUMN_CHANGED; aEvent.OldValue <<= nOldColumn; aEvent.NewValue <<= nNewColumn; pAcc->FireAccessibleEvent( aEvent ); } } } //-----IAccessibility2 Implementation 2009 void SwAccessibleMap::InvalidateFocus() { //IAccessibility2 Implementation 2009----- if(GetShell()->IsPreView()) { uno::Reference<XAccessible> xAcc = _GetDocumentView( sal_True ); if (xAcc.get()) { SwAccessiblePreview *pAccPreview = static_cast<SwAccessiblePreview *>(xAcc.get()); if (pAccPreview) { pAccPreview->InvalidateFocus(); return ; } } } //-----IAccessibility2 Implementation 2009 uno::Reference < XAccessible > xAcc; sal_Bool bShapeSelected; { vos::OGuard aGuard( maMutex ); xAcc = mxCursorContext; bShapeSelected = mbShapeSelected; } if( xAcc.is() ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); pAccImpl->InvalidateFocus(); } //IAccessibility2 Implementation 2009----- else { DoInvalidateShapeSelection(sal_True); } //-----IAccessibility2 Implementation 2009 } void SwAccessibleMap::SetCursorContext( const ::vos::ORef < SwAccessibleContext >& rCursorContext ) { vos::OGuard aGuard( maMutex ); uno::Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() ); mxCursorContext = xAcc; } // --> OD 2005-12-12 #i27301# - use new type definition for <_nStates> void SwAccessibleMap::InvalidateStates( tAccessibleStates _nStates, const SwFrm* _pFrm ) { // Start with the frame or the first upper that is accessible SwAccessibleChild aFrmOrObj( _pFrm ); while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper(); if( !aFrmOrObj.GetSwFrm() ) aFrmOrObj = GetShell()->GetLayout(); uno::Reference< XAccessible > xAcc( GetContext( aFrmOrObj.GetSwFrm(), sal_True ) ); SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl, SwAccessibleChild(pAccImpl->GetFrm()), _nStates ); AppendEvent( aEvent ); } else { FireEvents(); pAccImpl->InvalidateStates( _nStates ); } } // <-- void SwAccessibleMap::_InvalidateRelationSet( const SwFrm* pFrm, sal_Bool bFrom ) { // first, see if this frame is accessible, and if so, get the respective SwAccessibleChild aFrmOrObj( pFrm ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) { xAcc = (*aIter).second; } } } // deliver event directly, or queue event if( xAcc.is() ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl, SwAccessibleChild(pFrm), ( bFrom ? ACC_STATE_RELATION_FROM : ACC_STATE_RELATION_TO ) ); AppendEvent( aEvent ); } else { FireEvents(); pAccImpl->InvalidateRelation( bFrom ? AccessibleEventId::CONTENT_FLOWS_FROM_RELATION_CHANGED : AccessibleEventId::CONTENT_FLOWS_TO_RELATION_CHANGED ); } } } } void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster, const SwFrm* pFollow ) { _InvalidateRelationSet( pMaster, sal_False ); _InvalidateRelationSet( pFollow, sal_True ); } /** invalidation CONTENT_FLOW_FROM/_TO relation of a paragraph OD 2005-12-01 #i27138# @author OD */ void SwAccessibleMap::InvalidateParaFlowRelation( const SwTxtFrm& _rTxtFrm, const bool _bFrom ) { _InvalidateRelationSet( &_rTxtFrm, _bFrom ); } /** invalidation of text selection of a paragraph OD 2005-12-12 #i27301# @author OD */ void SwAccessibleMap::InvalidateParaTextSelection( const SwTxtFrm& _rTxtFrm ) { // first, see if this frame is accessible, and if so, get the respective SwAccessibleChild aFrmOrObj( &_rTxtFrm ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) { xAcc = (*aIter).second; } } } // deliver event directly, or queue event if( xAcc.is() ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); if( GetShell()->ActionPend() ) { SwAccessibleEvent_Impl aEvent( SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl, SwAccessibleChild( &_rTxtFrm ), ACC_STATE_TEXT_SELECTION_CHANGED ); AppendEvent( aEvent ); } else { FireEvents(); pAccImpl->InvalidateTextSelection(); } } } } sal_Int32 SwAccessibleMap::GetChildIndex( const SwFrm& rParentFrm, Window& rChild ) const { sal_Int32 nIndex( -1 ); SwAccessibleChild aFrmOrObj( &rParentFrm ); if( aFrmOrObj.IsAccessible( GetShell()->IsPreView() ) ) { uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); if( mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( aFrmOrObj.GetSwFrm() ); if( aIter != mpFrmMap->end() ) { xAcc = (*aIter).second; } } } if( xAcc.is() ) { SwAccessibleContext *pAccImpl = static_cast< SwAccessibleContext *>( xAcc.get() ); nIndex = pAccImpl->GetChildIndex( const_cast<SwAccessibleMap&>(*this), SwAccessibleChild( &rChild ) ); } } return nIndex; } // OD 15.01.2003 #103492# - complete re-factoring of method due to new page/print // preview functionality. void SwAccessibleMap::UpdatePreview( const std::vector<PrevwPage*>& _rPrevwPages, const Fraction& _rScale, const SwPageFrm* _pSelectedPageFrm, const Size& _rPrevwWinSize ) { DBG_ASSERT( GetShell()->IsPreView(), "no preview?" ); DBG_ASSERT( mpPreview != NULL, "no preview data?" ); // OD 15.01.2003 #103492# - adjustments for changed method signature mpPreview->Update( *this, _rPrevwPages, _rScale, _pSelectedPageFrm, _rPrevwWinSize ); // propagate change of VisArea through the document's // accessibility tree; this will also send appropriate scroll // events SwAccessibleContext* pDoc = GetContextImpl( GetShell()->GetLayout() ).getBodyPtr(); static_cast<SwAccessibleDocumentBase*>( pDoc )->SetVisArea(); uno::Reference < XAccessible > xOldAcc; uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); xOldAcc = mxCursorContext; const SwPageFrm *pSelPage = mpPreview->GetSelPage(); if( pSelPage && mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pSelPage ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; } } if( xOldAcc.is() && xOldAcc != xAcc ) InvalidateCursorPosition( xOldAcc ); if( xAcc.is() ) InvalidateCursorPosition( xAcc ); } void SwAccessibleMap::InvalidatePreViewSelection( sal_uInt16 nSelPage ) { DBG_ASSERT( GetShell()->IsPreView(), "no preview?" ); DBG_ASSERT( mpPreview != NULL, "no preview data?" ); // OD 16.01.2003 #103492# - changed metthod call due to method signature change. mpPreview->InvalidateSelection( GetShell()->GetLayout()->GetPageByPageNum( nSelPage ) ); uno::Reference < XAccessible > xOldAcc; uno::Reference < XAccessible > xAcc; { vos::OGuard aGuard( maMutex ); xOldAcc = mxCursorContext; const SwPageFrm *pSelPage = mpPreview->GetSelPage(); if( pSelPage && mpFrmMap ) { SwAccessibleContextMap_Impl::iterator aIter = mpFrmMap->find( pSelPage ); if( aIter != mpFrmMap->end() ) xAcc = (*aIter).second; } } if( xOldAcc.is() && xOldAcc != xAcc ) InvalidateCursorPosition( xOldAcc ); if( xAcc.is() ) InvalidateCursorPosition( xAcc ); } sal_Bool SwAccessibleMap::IsPageSelected( const SwPageFrm *pPageFrm ) const { return mpPreview && mpPreview->GetSelPage() == pPageFrm; } void SwAccessibleMap::FireEvents() { { vos::OGuard aGuard( maEventMutex ); if( mpEvents ) { mpEvents->SetFiring(); //IAccessibility2 Implementation 2009----- mpEvents->MoveInvalidXAccToEnd(); //-----IAccessibility2 Implementation 2009 SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin(); while( aIter != mpEvents->end() ) { FireEvent( *aIter ); ++aIter; } delete mpEventMap; mpEventMap = 0; delete mpEvents; mpEvents = 0; } } { vos::OGuard aGuard( maMutex ); if( mpShapes ) { delete mpShapes; mpShapes = 0; } } } sal_Bool SwAccessibleMap::IsValid() const { return sal_True; } Rectangle SwAccessibleMap::GetVisibleArea() const { MapMode aSrc( MAP_TWIP ); MapMode aDest( MAP_100TH_MM ); return OutputDevice::LogicToLogic( GetVisArea().SVRect(), aSrc, aDest ); } // Convert a MM100 value realtive to the document root into a pixel value // realtive to the screen! Point SwAccessibleMap::LogicToPixel( const Point& rPoint ) const { MapMode aSrc( MAP_100TH_MM ); MapMode aDest( MAP_TWIP ); Point aPoint = rPoint; aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest ); Window *pWin = GetShell()->GetWin(); if( pWin ) { // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion MapMode aMapMode; GetMapMode( aPoint, aMapMode ); aPoint = pWin->LogicToPixel( aPoint, aMapMode ); aPoint = pWin->OutputToAbsoluteScreenPixel( aPoint ); } return aPoint; } Size SwAccessibleMap::LogicToPixel( const Size& rSize ) const { MapMode aSrc( MAP_100TH_MM ); MapMode aDest( MAP_TWIP ); Size aSize( OutputDevice::LogicToLogic( rSize, aSrc, aDest ) ); if( GetShell()->GetWin() ) { // OD 16.01.2003 #103492# - get mapping mode for LogicToPixel conversion MapMode aMapMode; GetMapMode( Point(0,0), aMapMode ); aSize = GetShell()->GetWin()->LogicToPixel( aSize, aMapMode ); } return aSize; } Point SwAccessibleMap::PixelToLogic( const Point& rPoint ) const { Point aPoint; Window *pWin = GetShell()->GetWin(); if( pWin ) { aPoint = pWin->ScreenToOutputPixel( rPoint ); // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion MapMode aMapMode; GetMapMode( aPoint, aMapMode ); aPoint = pWin->PixelToLogic( aPoint, aMapMode ); MapMode aSrc( MAP_TWIP ); MapMode aDest( MAP_100TH_MM ); aPoint = OutputDevice::LogicToLogic( aPoint, aSrc, aDest ); } return aPoint; } Size SwAccessibleMap::PixelToLogic( const Size& rSize ) const { Size aSize; if( GetShell()->GetWin() ) { // OD 16.01.2003 #103492# - get mapping mode for PixelToLogic conversion MapMode aMapMode; GetMapMode( Point(0,0), aMapMode ); aSize = GetShell()->GetWin()->PixelToLogic( rSize, aMapMode ); MapMode aSrc( MAP_TWIP ); MapMode aDest( MAP_100TH_MM ); aSize = OutputDevice::LogicToLogic( aSize, aSrc, aDest ); } return aSize; } sal_Bool SwAccessibleMap::ReplaceChild ( ::accessibility::AccessibleShape* pCurrentChild, const uno::Reference< drawing::XShape >& _rxShape, const long /*_nIndex*/, const ::accessibility::AccessibleShapeTreeInfo& /*_rShapeTreeInfo*/ ) throw (uno::RuntimeException) { const SdrObject *pObj = 0; { vos::OGuard aGuard( maMutex ); if( mpShapeMap ) { SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin(); SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end(); while( aIter != aEndIter && !pObj ) { uno::Reference < XAccessible > xAcc( (*aIter).second ); ::accessibility::AccessibleShape *pAccShape = static_cast < ::accessibility::AccessibleShape* >( xAcc.get() ); if( pAccShape == pCurrentChild ) { pObj = (*aIter).first; } ++aIter; } } } if( !pObj ) return sal_False; uno::Reference < drawing::XShape > xShape( _rxShape ); //keep reference to shape, because // we might be the only one that // hold it. // Also get keep parent. uno::Reference < XAccessible > xParent( pCurrentChild->getAccessibleParent() ); pCurrentChild = 0; // well be realease by dispose Dispose( 0, pObj, 0 ); { vos::OGuard aGuard( maMutex ); if( !mpShapeMap ) mpShapeMap = new SwAccessibleShapeMap_Impl( this ); // create the new child ::accessibility::ShapeTypeHandler& rShapeTypeHandler = ::accessibility::ShapeTypeHandler::Instance(); ::accessibility::AccessibleShapeInfo aShapeInfo( xShape, xParent, this ); ::accessibility::AccessibleShape* pReplacement = rShapeTypeHandler.CreateAccessibleObject ( aShapeInfo, mpShapeMap->GetInfo() ); uno::Reference < XAccessible > xAcc( pReplacement ); if( xAcc.is() ) { pReplacement->Init(); SwAccessibleShapeMap_Impl::iterator aIter = mpShapeMap->find( pObj ); if( aIter != mpShapeMap->end() ) { (*aIter).second = xAcc; } else { SwAccessibleShapeMap_Impl::value_type aEntry( pObj, xAcc ); mpShapeMap->insert( aEntry ); } } } SwRect aEmptyRect; InvalidatePosOrSize( 0, pObj, 0, aEmptyRect ); return sal_True; } //IAccessibility2 Implementation 2009----- //Get the accessible control shape from the model object, here model object is with XPropertySet type ::accessibility::AccessibleControlShape * SwAccessibleMap::GetAccControlShapeFromModel(::com::sun::star::beans::XPropertySet* pSet) throw (::com::sun::star::uno::RuntimeException) { if( mpShapeMap ) { SwAccessibleShapeMap_Impl::const_iterator aIter = mpShapeMap->begin(); SwAccessibleShapeMap_Impl::const_iterator aEndIter = mpShapeMap->end(); while( aIter != aEndIter) { uno::Reference < XAccessible > xAcc( (*aIter).second ); ::accessibility::AccessibleShape *pAccShape = static_cast < ::accessibility::AccessibleShape* >( xAcc.get() ); if(pAccShape && ::accessibility::ShapeTypeHandler::Instance().GetTypeId (pAccShape->GetXShape()) == ::accessibility::DRAWING_CONTROL) { ::accessibility::AccessibleControlShape *pCtlAccShape = static_cast < ::accessibility::AccessibleControlShape* >(pAccShape); if (pCtlAccShape && pCtlAccShape->GetControlModel() == pSet) return pCtlAccShape; } ++aIter; } } return NULL; } ::com::sun::star::uno::Reference< XAccessible > SwAccessibleMap::GetAccessibleCaption (const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& xShape) throw (::com::sun::star::uno::RuntimeException) { SdrObject* captionedObject = GetSdrObjectFromXShape(xShape); SwDrawContact *pContact = (SwDrawContact*)GetUserCall( captionedObject ); ASSERT( RES_DRAWFRMFMT == pContact->GetFmt()->Which(), "fail" ); if( !pContact ) return 0; SwDrawFrmFmt *pCaptionedFmt = (SwDrawFrmFmt *)pContact->GetFmt(); if( !pCaptionedFmt ) return 0; SwFlyFrm* pFrm = NULL; if (pCaptionedFmt->HasCaption()) { const SwFrmFmt *pCaptionFrmFmt = pCaptionedFmt->GetCaptionFmt(); SwClientIter aIter (*(SwModify*)pCaptionFrmFmt); pFrm = (SwFlyFrm*)aIter.First( TYPE ( SwFlyFrm )); } if (!pFrm) return 0; //SwFrmFmt* pFrm = pCaptionedFmt->GetCaptionFmt(); uno::Reference < XAccessible > xAcc( GetContext((SwFrm*)pFrm,sal_True) ); //Reference < XAccessibleShape > xAccShape( xAcc, UNO_QUERY ); uno::Reference< XAccessibleContext > xAccContext = xAcc->getAccessibleContext(); if( xAccContext.is() ) { //get the parent of caption frame, which is paragaph uno::Reference< XAccessible > xAccParent = xAccContext->getAccessibleParent(); if(xAccParent.is()) { //get the great parent of caption frame which is text frame. uno::Reference< XAccessibleContext > xAccParentContext = xAccParent->getAccessibleContext(); uno::Reference< XAccessible > xAccGreatParent = xAccParentContext->getAccessibleParent(); if(xAccGreatParent.is()) { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= xAccParent; ( static_cast< SwAccessibleContext * >(xAccGreatParent.get()) )->FireAccessibleEvent( aEvent ); } AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::CHILD; aEvent.NewValue <<= xAcc; ( static_cast< SwAccessibleContext * >(xAccParent.get()) )->FireAccessibleEvent( aEvent ); } } if(xAcc.get()) return xAcc; else return NULL; } //-----IAccessibility2 Implementation 2009 Point SwAccessibleMap::PixelToCore( const Point& rPoint ) const { Point aPoint; if( GetShell()->GetWin() ) { // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)> MapMode aMapMode; GetMapMode( rPoint, aMapMode ); aPoint = GetShell()->GetWin()->PixelToLogic( rPoint, aMapMode ); } return aPoint; } static inline long lcl_CorrectCoarseValue(long aCoarseValue, long aFineValue, long aRefValue, bool bToLower) { long aResult = aCoarseValue; if (bToLower) { if (aFineValue < aRefValue) aResult -= 1; } else { if (aFineValue > aRefValue) aResult += 1; } return aResult; } static inline void lcl_CorrectRectangle(Rectangle & rRect, const Rectangle & rSource, const Rectangle & rInGrid) { rRect.nLeft = lcl_CorrectCoarseValue(rRect.nLeft, rSource.nLeft, rInGrid.nLeft, false); rRect.nTop = lcl_CorrectCoarseValue(rRect.nTop, rSource.nTop, rInGrid.nTop, false); rRect.nRight = lcl_CorrectCoarseValue(rRect.nRight, rSource.nRight, rInGrid.nRight, true); rRect.nBottom = lcl_CorrectCoarseValue(rRect.nBottom, rSource.nBottom, rInGrid.nBottom, true); } Rectangle SwAccessibleMap::CoreToPixel( const Rectangle& rRect ) const { Rectangle aRect; if( GetShell()->GetWin() ) { // OD 15.01.2003 #103492# - replace <PreviewAdjust(..)> by <GetMapMode(..)> MapMode aMapMode; GetMapMode( rRect.TopLeft(), aMapMode ); aRect = GetShell()->GetWin()->LogicToPixel( rRect, aMapMode ); Rectangle aTmpRect = GetShell()->GetWin()->PixelToLogic( aRect, aMapMode ); lcl_CorrectRectangle(aRect, rRect, aTmpRect); } return aRect; } /** get mapping mode for LogicToPixel and PixelToLogic conversions OD 15.01.2003 #103492# Replacement method <PreviewAdjust(..)> by new method <GetMapMode>. Method returns mapping mode of current output device and adjusts it, if the shell is in page/print preview. Necessary, because <PreviewAdjust(..)> changes mapping mode at current output device for mapping logic document positions to page preview window positions and vice versa and doesn't take care to recover its changes. @author OD */ void SwAccessibleMap::GetMapMode( const Point& _rPoint, MapMode& _orMapMode ) const { MapMode aMapMode = GetShell()->GetWin()->GetMapMode(); if( GetShell()->IsPreView() ) { DBG_ASSERT( mpPreview != NULL, "need preview data" ); mpPreview->AdjustMapMode( aMapMode, _rPoint ); } _orMapMode = aMapMode; } /** get size of a dedicated preview page OD 15.01.2003 #103492# @author OD */ Size SwAccessibleMap::GetPreViewPageSize( sal_uInt16 _nPrevwPageNum ) const { DBG_ASSERT( mpVSh->IsPreView(), "no page preview accessible." ); DBG_ASSERT( mpVSh->IsPreView() && ( mpPreview != NULL ), "missing accessible preview data at page preview" ); if ( mpVSh->IsPreView() && ( mpPreview != NULL ) ) { return mpVSh->PagePreviewLayout()->GetPrevwPageSizeByPageNum( _nPrevwPageNum ); } else { return Size( 0, 0 ); } } /** method to build up a new data structure of the accessible pararaphs, which have a selection OD 2005-12-13 #i27301# Important note: method has to used inside a mutual exclusive section @author OD */ SwAccessibleSelectedParas_Impl* SwAccessibleMap::_BuildSelectedParas() { // no accessible contexts, no selection if ( !mpFrmMap ) { return 0L; } // get cursor as an instance of its base class <SwPaM> SwPaM* pCrsr( 0L ); { SwCrsrShell* pCrsrShell = dynamic_cast<SwCrsrShell*>(GetShell()); if ( pCrsrShell ) { SwFEShell* pFEShell = dynamic_cast<SwFEShell*>(pCrsrShell); if ( !pFEShell || ( !pFEShell->IsFrmSelected() && pFEShell->IsObjSelected() == 0 ) ) { // get cursor without updating an existing table cursor. pCrsr = pCrsrShell->GetCrsr( sal_False ); } } } // no cursor, no selection if ( !pCrsr ) { return 0L; } SwAccessibleSelectedParas_Impl* pRetSelectedParas( 0L ); // loop on all cursors SwPaM* pRingStart = pCrsr; do { // for a selection the cursor has to have a mark. // for savety reasons assure that point and mark are in text nodes if ( pCrsr->HasMark() && pCrsr->GetPoint()->nNode.GetNode().IsTxtNode() && pCrsr->GetMark()->nNode.GetNode().IsTxtNode() ) { SwPosition* pStartPos = pCrsr->Start(); SwPosition* pEndPos = pCrsr->End(); // loop on all text nodes inside the selection SwNodeIndex aIdx( pStartPos->nNode ); for ( ; aIdx.GetIndex() <= pEndPos->nNode.GetIndex(); ++aIdx ) { SwTxtNode* pTxtNode( aIdx.GetNode().GetTxtNode() ); if ( pTxtNode ) { // loop on all text frames registered at the text node. SwIterator<SwTxtFrm,SwTxtNode> aIter( *pTxtNode ); for( SwTxtFrm* pTxtFrm = aIter.First(); pTxtFrm; pTxtFrm = aIter.Next() ) { uno::WeakReference < XAccessible > xWeakAcc; SwAccessibleContextMap_Impl::iterator aMapIter = mpFrmMap->find( pTxtFrm ); if( aMapIter != mpFrmMap->end() ) { xWeakAcc = (*aMapIter).second; SwAccessibleParaSelection aDataEntry( pTxtNode == &(pStartPos->nNode.GetNode()) ? pStartPos->nContent.GetIndex() : 0, pTxtNode == &(pEndPos->nNode.GetNode()) ? pEndPos->nContent.GetIndex() : STRING_LEN ); SwAccessibleSelectedParas_Impl::value_type aEntry( xWeakAcc, aDataEntry ); if ( !pRetSelectedParas ) { pRetSelectedParas = new SwAccessibleSelectedParas_Impl; } pRetSelectedParas->insert( aEntry ); } } } } } // prepare next turn: get next cursor in ring pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); } while ( pCrsr != pRingStart ); return pRetSelectedParas; } /** invalidation of text selection of all paragraphs OD 2005-12-13 #i27301# @author OD */ void SwAccessibleMap::InvalidateTextSelectionOfAllParas() { vos::OGuard aGuard( maMutex ); // keep previously known selected paragraphs SwAccessibleSelectedParas_Impl* pPrevSelectedParas( mpSelectedParas ); // determine currently selected paragraphs mpSelectedParas = _BuildSelectedParas(); // compare currently selected paragraphs with the previously selected // paragraphs and submit corresponding TEXT_SELECTION_CHANGED events. // first, search for new and changed selections. // on the run remove selections from previously known ones, if they are // also in the current ones. if ( mpSelectedParas ) { SwAccessibleSelectedParas_Impl::iterator aIter = mpSelectedParas->begin(); for ( ; aIter != mpSelectedParas->end(); ++aIter ) { bool bSubmitEvent( false ); if ( !pPrevSelectedParas ) { // new selection bSubmitEvent = true; } else { SwAccessibleSelectedParas_Impl::iterator aPrevSelected = pPrevSelectedParas->find( (*aIter).first ); if ( aPrevSelected != pPrevSelectedParas->end() ) { // check, if selection has changed if ( (*aIter).second.nStartOfSelection != (*aPrevSelected).second.nStartOfSelection || (*aIter).second.nEndOfSelection != (*aPrevSelected).second.nEndOfSelection ) { // changed selection bSubmitEvent = true; } pPrevSelectedParas->erase( aPrevSelected ); } else { // new selection bSubmitEvent = true; } } if ( bSubmitEvent ) { uno::Reference < XAccessible > xAcc( (*aIter).first ); if ( xAcc.is() ) { ::vos::ORef < SwAccessibleContext > xAccImpl( static_cast<SwAccessibleContext*>( xAcc.get() ) ); if ( xAccImpl.isValid() && xAccImpl->GetFrm() ) { const SwTxtFrm* pTxtFrm( dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) ); ASSERT( pTxtFrm, "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" ); if ( pTxtFrm ) { InvalidateParaTextSelection( *pTxtFrm ); } } } } } } // second, handle previous selections - after the first step the data // structure of the previously known only contains the 'old' selections if ( pPrevSelectedParas ) { SwAccessibleSelectedParas_Impl::iterator aIter = pPrevSelectedParas->begin(); for ( ; aIter != pPrevSelectedParas->end(); ++aIter ) { uno::Reference < XAccessible > xAcc( (*aIter).first ); if ( xAcc.is() ) { ::vos::ORef < SwAccessibleContext > xAccImpl( static_cast<SwAccessibleContext*>( xAcc.get() ) ); if ( xAccImpl.isValid() && xAccImpl->GetFrm() ) { const SwTxtFrm* pTxtFrm( dynamic_cast<const SwTxtFrm*>(xAccImpl->GetFrm()) ); ASSERT( pTxtFrm, "<SwAccessibleMap::_SubmitTextSelectionChangedEvents()> - unexcepted type of frame" ); if ( pTxtFrm ) { InvalidateParaTextSelection( *pTxtFrm ); } } } } delete pPrevSelectedParas; } } const SwRect& SwAccessibleMap::GetVisArea() const { DBG_ASSERT( !GetShell()->IsPreView() || (mpPreview != NULL), "preview without preview data?" ); return GetShell()->IsPreView() ? mpPreview->GetVisArea() : GetShell()->VisArea(); } //IAccessibility2 Implementation 2009----- sal_Bool SwAccessibleMap::IsDocumentSelAll() { return GetShell()->GetDoc()->IsPrepareSelAll(); } //-----IAccessibility2 Implementation 2009