blob: ab85051b6e8ee8443503ac52b68bd8574afc9af7 [file] [log] [blame]
/**************************************************************
*
* 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>
#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 );
if( nSelShapes && pFESh &&pFESh->IsObjSelected( *pObj ) )
{
// 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:
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;}
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" );
}
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" );
}
// <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;
}
struct XAccisNULL
{
bool operator()(const SwAccessibleEvent_Impl& e)
{
return e.IsNoXaccParentFrm();
}
};
void MoveInvalidXAccToEnd();
};
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 ,"");
}
//------------------------------------------------------------------------------
// 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() );
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() );
}
}
}
}
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();
}
}
//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;
//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 );
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;
}
}
*/
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)
{
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 );
}
}
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;
}
}
{
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;
}
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!!!
}
if (xAcc.is())
AddGroupContext(pObj, xAcc);
}
}
}
// Invalidate focus for old object when map is not locked
if( xOldCursorAcc.is() )
InvalidateCursorPosition( xOldCursorAcc );
return xAcc;
}
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);
}
}
}
}
}
}
}
}
}
}
::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() )
{
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() )
{
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;
{
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 = 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 );
}
}
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,"");
}
}
}
}
}
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;
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;
}
}
// 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 );
}
}
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 );
}
}
}
//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 );
}
}
}
void SwAccessibleMap::InvalidateFocus()
{
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 ;
}
}
}
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();
}
else
{
DoInvalidateShapeSelection(sal_True);
}
}
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();
mpEvents->MoveInvalidXAccToEnd();
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;
}
//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;
}
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();
}
sal_Bool SwAccessibleMap::IsDocumentSelAll()
{
return GetShell()->GetDoc()->IsPrepareSelAll();
}