Files
libreoffice/sw/source/core/access/accmap.cxx

1142 lines
38 KiB
C++
Raw Normal View History

2002-02-04 13:10:18 +00:00
/*************************************************************************
*
* $RCSfile: accmap.cxx,v $
*
* $Revision: 1.18 $
2002-02-04 13:10:18 +00:00
*
* last change: $Author: dvo $ $Date: 2002-04-24 15:27:21 $
2002-02-04 13:10:18 +00:00
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (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.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#ifdef PRECOMPILED
#include "core_pch.hxx"
#endif
#pragma hdrstop
#ifndef _VOS_REF_HXX_
#include <vos/ref.hxx>
#endif
2002-02-05 14:52:06 +00:00
#ifndef _CPPUHELPER_WEAKREF_HXX_
#include <cppuhelper/weakref.hxx>
#endif
2002-02-04 13:10:18 +00:00
#include <map>
#include <list>
2002-02-04 13:10:18 +00:00
#ifndef _ACCMAP_HXX
#include <accmap.hxx>
#endif
#ifndef _ACCCONTEXT_HXX
#include <acccontext.hxx>
#endif
#ifndef _ACCDOC_HXX
#include <accdoc.hxx>
#endif
#ifndef _ACCPARA_HXX
#include <accpara.hxx>
#endif
2002-02-27 08:32:33 +00:00
#ifndef _ACCHEADERFOOTER_HXX
#include <accheaderfooter.hxx>
#endif
2002-03-06 07:15:41 +00:00
#ifndef _ACCFOOTNOTE_HXX
#include <accfootnote.hxx>
#endif
2002-04-05 11:18:25 +00:00
#ifndef _ACCTEXTFRAME_HXX
#include <acctextframe.hxx>
#endif
#ifndef _ACCGRAPHIC_HXX
#include <accgraphic.hxx>
#endif
#ifndef _ACCEMBEDDED_HXX
#include <accembedded.hxx>
#endif
2002-04-11 13:04:40 +00:00
#ifndef _ACCCELL_HXX
#include <acccell.hxx>
#endif
#ifndef _ACCTABLE_HXX
#include <acctable.hxx>
#endif
2002-04-05 11:18:25 +00:00
#ifndef _FESH_HXX
#include "fesh.hxx"
#endif
2002-02-04 13:10:18 +00:00
#ifndef _ROOTFRM_HXX
#include <rootfrm.hxx>
#endif
#ifndef _TXTFRM_HXX
#include <txtfrm.hxx>
#endif
2002-02-27 08:32:33 +00:00
#ifndef _HFFRM_HXX
#include <hffrm.hxx>
#endif
2002-03-06 07:15:41 +00:00
#ifndef _FTNFRM_HXX
#include <ftnfrm.hxx>
#endif
2002-04-11 13:04:40 +00:00
#ifndef _CELLFRM_HXX
#include <cellfrm.hxx>
#endif
#ifndef _TABFRM_HXX
#include <tabfrm.hxx>
#endif
2002-04-05 11:18:25 +00:00
#ifndef _NDTYP_HXX
#include <ndtyp.hxx>
#endif
2002-02-04 13:10:18 +00:00
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLERELATIONTYPE_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleRelationType.hpp>
#endif
#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_
#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp>
#endif
2002-02-04 13:10:18 +00:00
using namespace ::com::sun::star::uno;
using namespace ::drafts::com::sun::star::accessibility;
using namespace ::rtl;
struct SwFrmFunc
{
sal_Bool operator()( const SwFrm * p1,
const SwFrm * p2) const
{
return p1 < p2;
}
};
typedef ::std::map < const SwFrm *, WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl;
class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl
{
public:
2002-03-21 11:50:31 +00:00
#ifndef PRODUCT
2002-04-17 13:07:39 +00:00
sal_Bool mbLocked;
2002-03-21 11:50:31 +00:00
#endif
2002-04-17 13:07:39 +00:00
WeakReference < XAccessible > mxCursorContext;
2002-03-21 11:50:31 +00:00
SwAccessibleContextMap_Impl()
2002-03-21 11:50:31 +00:00
#ifndef PRODUCT
2002-04-17 13:07:39 +00:00
: mbLocked( sal_False )
2002-03-21 11:50:31 +00:00
#endif
{}
};
2002-02-04 13:10:18 +00:00
2002-04-11 13:04:40 +00:00
//------------------------------------------------------------------------------
struct SwAccessibleEvent_Impl
2002-02-04 13:10:18 +00:00
{
public:
2002-04-17 13:07:39 +00:00
enum EventType { CARET_OR_STATES, INVALID_CONTENT, POS_CHANGED,
CHILD_POS_CHANGED, DISPOSE };
private:
2002-04-17 13:07:39 +00:00
SwRect maOldBox; // the old bounds for CHILD_POS_CHANGED
// and POS_CHANGED
WeakReference < XAccessible > mxAcc; // The object that fires the event
SwFrmOrObj maFrmOrObj; // the child for CHILD_POS_CHANGED and
// the same as xAcc for any other
// event type
2002-04-17 13:07:39 +00:00
EventType meType; // The event type
sal_uInt8 mnStates; // check states or update caret pos
SwAccessibleEvent_Impl& operator==( const SwAccessibleEvent_Impl& );
public:
SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA,
2002-04-11 13:04:40 +00:00
const SwFrmOrObj& rFrmOrObj ) :
2002-04-17 13:07:39 +00:00
meType( eT ), mxAcc( pA ), maFrmOrObj( rFrmOrObj ), mnStates( 0 )
{}
2002-04-11 13:04:40 +00:00
SwAccessibleEvent_Impl( EventType eT, const SwFrmOrObj& rFrmOrObj ) :
2002-04-17 13:07:39 +00:00
meType( eT ), maFrmOrObj( rFrmOrObj ), mnStates( 0 )
{
2002-04-17 13:07:39 +00:00
ASSERT( SwAccessibleEvent_Impl::DISPOSE == meType,
"wrong event constructor, DISPOSE only" );
}
SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA,
2002-04-11 13:04:40 +00:00
const SwFrmOrObj& rFrmOrObj, const SwRect& rR ) :
2002-04-17 13:07:39 +00:00
meType( eT ), mxAcc( pA ), maFrmOrObj( rFrmOrObj ), maOldBox( rR ),
mnStates( 0 )
{
2002-04-17 13:07:39 +00:00
ASSERT( SwAccessibleEvent_Impl::CHILD_POS_CHANGED == meType,
"wrong event constructor, CHILD_POS_CHANGED only" );
}
SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA,
2002-04-11 13:04:40 +00:00
const SwFrmOrObj& rFrmOrObj, sal_uInt8 nSt ) :
2002-04-17 13:07:39 +00:00
meType( eT ), mxAcc( pA ), maFrmOrObj( rFrmOrObj ), mnStates( nSt )
{
2002-04-17 13:07:39 +00:00
ASSERT( SwAccessibleEvent_Impl::CARET_OR_STATES == meType,
"wrong event constructor, CARET_OR_STATES only" );
}
2002-04-17 13:07:39 +00:00
inline void SetType( EventType eT ){ meType = eT; }
inline EventType GetType() const { return meType; }
inline ::vos::ORef < SwAccessibleContext > GetContext() const;
2002-04-17 13:07:39 +00:00
inline const SwRect& GetOldBox() const { return maOldBox; }
2002-04-19 11:59:38 +00:00
inline void SetOldBox( const SwRect& rOldBox ) { maOldBox = rOldBox; }
2002-04-17 13:07:39 +00:00
inline const SwFrm *GetFrm() const { return maFrmOrObj.GetSwFrm(); }
2002-04-17 13:07:39 +00:00
inline void SetStates( sal_uInt8 nSt ) { mnStates |= nSt; }
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; }
2002-04-17 13:07:39 +00:00
inline sal_uInt8 GetStates() const { return mnStates & ACC_STATE_MASK; }
inline sal_uInt8 GetAllStates() const { return mnStates; }
2002-02-04 13:10:18 +00:00
};
inline ::vos::ORef < SwAccessibleContext >
SwAccessibleEvent_Impl::GetContext() const
{
2002-04-17 13:07:39 +00:00
Reference < XAccessible > xTmp( mxAcc );
::vos::ORef < SwAccessibleContext > xAccImpl(
static_cast< SwAccessibleContext * >( xTmp.get() ) );
return xAccImpl;
}
2002-04-11 13:04:40 +00:00
//------------------------------------------------------------------------------
typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl;
class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl
{
2002-04-17 13:07:39 +00:00
sal_Bool mbFiring;
2002-03-21 11:50:31 +00:00
public:
2002-04-17 13:07:39 +00:00
SwAccessibleEventList_Impl() : mbFiring( sal_False ) {}
2002-03-21 11:50:31 +00:00
2002-04-17 13:07:39 +00:00
inline void SetFiring() { mbFiring = sal_True; }
inline sal_Bool IsFiring() const { return mbFiring; }
};
2002-04-11 13:04:40 +00:00
//------------------------------------------------------------------------------
typedef ::std::map < const SwFrm *, SwAccessibleEventList_Impl::iterator, SwFrmFunc > _SwAccessibleEventMap_Impl;
class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl
{
};
2002-04-11 13:04:40 +00:00
//------------------------------------------------------------------------------
static sal_Bool AreInSameTable( const Reference< XAccessible >& rAcc,
const SwFrm *pFrm )
2002-02-04 13:10:18 +00:00
{
2002-04-11 13:04:40 +00:00
sal_Bool bRet = sal_False;
2002-02-04 13:10:18 +00:00
2002-04-11 13:04:40 +00:00
if( pFrm && pFrm->IsCellFrm() && rAcc.is() )
{
2002-04-11 13:04:40 +00:00
// 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() )
2002-03-21 11:50:31 +00:00
{
2002-04-11 13:04:40 +00:00
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);
2002-03-21 11:50:31 +00:00
}
}
2002-04-11 13:04:40 +00:00
return bRet;
}
2002-04-11 13:04:40 +00:00
void SwAccessibleMap::FireEvent( const SwAccessibleEvent_Impl& rEvent )
{
::vos::ORef < SwAccessibleContext > xAccImpl( rEvent.GetContext() );
if( xAccImpl.isValid() )
2002-03-21 11:50:31 +00:00
{
2002-04-11 13:04:40 +00:00
switch( rEvent.GetType() )
2002-04-05 11:18:25 +00:00
{
2002-04-11 13:04:40 +00:00
case SwAccessibleEvent_Impl::INVALID_CONTENT:
xAccImpl->InvalidateContent();
break;
case SwAccessibleEvent_Impl::POS_CHANGED:
2002-04-17 13:07:39 +00:00
xAccImpl->InvalidatePosOrSize( rEvent.GetOldBox() );
2002-04-11 13:04:40 +00:00
break;
case SwAccessibleEvent_Impl::CHILD_POS_CHANGED:
xAccImpl->InvalidateChildPosOrSize( rEvent.GetFrm(),
2002-04-17 13:07:39 +00:00
rEvent.GetOldBox() );
2002-04-11 13:04:40 +00:00
break;
case SwAccessibleEvent_Impl::DISPOSE:
ASSERT( xAccImpl.isValid(),
"dispose event has been stored" );
break;
}
if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
{
if( rEvent.IsUpdateCursorPos() )
xAccImpl->InvalidateCursorPos();
if( rEvent.IsInvalidateStates() )
xAccImpl->InvalidateStates( rEvent.GetStates() );
if( rEvent.IsInvalidateRelation() )
xAccImpl->InvalidateRelation(
(rEvent.GetAllStates() & ACC_STATE_RELATION_FROM) != 0 ?
AccessibleEventId::CONTENT_FLOWS_FROM :
AccessibleEventId::CONTENT_FLOWS_TO );
2002-04-05 11:18:25 +00:00
}
2002-03-21 11:50:31 +00:00
}
}
void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent )
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maEventMutex );
2002-04-17 13:07:39 +00:00
if( !mpEvents )
mpEvents = new SwAccessibleEventList_Impl;
if( !mpEventMap )
mpEventMap = new SwAccessibleEventMap_Impl;
2002-04-17 13:07:39 +00:00
if( mpEvents->IsFiring() )
2002-03-21 11:50:31 +00:00
{
// 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 =
2002-04-17 13:07:39 +00:00
mpEventMap->find( rEvent.GetFrm() );
if( aIter != mpEventMap->end() )
2002-03-21 11:50:31 +00:00
{
SwAccessibleEvent_Impl aEvent( *(*aIter).second );
2002-04-17 13:07:39 +00:00
ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE,
"dispose events should not be stored" );
2002-03-21 11:50:31 +00:00
sal_Bool bAppendEvent = sal_True;
switch( rEvent.GetType() )
{
case SwAccessibleEvent_Impl::CARET_OR_STATES:
2002-04-17 13:07:39 +00:00
// A CARET_OR_STATES event is added to any other
2002-03-21 11:50:31 +00:00
// event only. It is broadcasted after any other event, so the
// event should be put to the back.
2002-04-17 13:07:39 +00:00
ASSERT( aEvent.GetType() !=
SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2002-03-21 11:50:31 +00:00
"invalid event combination" );
aEvent.SetStates( rEvent.GetAllStates() );
break;
case SwAccessibleEvent_Impl::INVALID_CONTENT:
2002-04-17 13:07:39 +00:00
// 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,
2002-03-21 11:50:31 +00:00
"invalid event combination" );
2002-04-17 13:07:39 +00:00
if( aEvent.GetType() ==
SwAccessibleEvent_Impl::CARET_OR_STATES )
2002-03-21 11:50:31 +00:00
aEvent.SetType( SwAccessibleEvent_Impl::INVALID_CONTENT );
break;
case SwAccessibleEvent_Impl::POS_CHANGED:
2002-04-17 13:07:39 +00:00
// 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,
2002-03-21 11:50:31 +00:00
"invalid event combination" );
2002-04-17 13:07:39 +00:00
if( aEvent.GetType() != SwAccessibleEvent_Impl::POS_CHANGED )
aEvent.SetOldBox( rEvent.GetOldBox() );
2002-03-21 11:50:31 +00:00
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.
2002-04-17 13:07:39 +00:00
ASSERT( aEvent.GetType() ==
SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2002-03-21 11:50:31 +00:00
"invalid event combination" );
break;
case SwAccessibleEvent_Impl::DISPOSE:
// DISPOSE events overwrite all others. They are not stored
2002-04-17 13:07:39 +00:00
// 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.
ASSERT( aEvent.GetType() !=
SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2002-03-21 11:50:31 +00:00
"invalid event combination" );
bAppendEvent = sal_False;
break;
}
if( bAppendEvent )
{
2002-04-17 13:07:39 +00:00
mpEvents->erase( (*aIter).second );
(*aIter).second = mpEvents->insert( mpEvents->end(), aEvent );
2002-03-21 11:50:31 +00:00
}
else
{
2002-04-17 13:07:39 +00:00
mpEvents->erase( (*aIter).second );
mpEventMap->erase( aIter );
2002-03-21 11:50:31 +00:00
}
}
else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() )
{
SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrm(),
2002-04-17 13:07:39 +00:00
mpEvents->insert( mpEvents->end(), rEvent ) );
mpEventMap->insert( aEntry );
2002-03-21 11:50:31 +00:00
}
}
}
2002-04-05 11:18:25 +00:00
void SwAccessibleMap::InvalidateCursorPosition(
2002-03-21 11:50:31 +00:00
const 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() )
{
2002-03-21 11:50:31 +00:00
SwAccessibleEvent_Impl aEvent(
SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl,
pAccImpl->GetFrm(), ACC_STATE_CARET );
AppendEvent( aEvent );
}
else
{
2002-04-05 11:18:25 +00:00
pAccImpl->InvalidateCursorPos();
}
2002-02-04 13:10:18 +00:00
}
2002-04-11 13:04:40 +00:00
SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) :
2002-04-17 13:07:39 +00:00
mpMap( 0 ),
mpEvents( 0 ),
mpEventMap( 0 ),
mpVSh( pSh ),
mnPara( 1 ),
mnFootnote( 1 ),
mnEndnote( 1 )
2002-04-11 13:04:40 +00:00
{
}
SwAccessibleMap::~SwAccessibleMap()
{
Reference < XAccessible > xAcc;
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
if( mpMap )
2002-04-11 13:04:40 +00:00
{
const SwRootFrm *pRootFrm = GetShell()->GetLayout();
2002-04-17 13:07:39 +00:00
SwAccessibleContextMap_Impl::iterator aIter = mpMap->find( pRootFrm );
if( aIter != mpMap->end() )
2002-04-11 13:04:40 +00:00
xAcc = (*aIter).second;
if( !xAcc.is() )
xAcc = new SwAccessibleDocument( this );
}
}
SwAccessibleDocument *pAcc =
static_cast< SwAccessibleDocument * >( xAcc.get() );
pAcc->Dispose( sal_True );
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-04-11 13:04:40 +00:00
#ifndef PRODUCT
2002-04-17 13:07:39 +00:00
ASSERT( !mpMap || mpMap->empty(),
2002-04-11 13:04:40 +00:00
"Map should be empty after disposing the root frame" );
2002-04-17 13:07:39 +00:00
if( mpMap )
2002-04-11 13:04:40 +00:00
{
2002-04-17 13:07:39 +00:00
SwAccessibleContextMap_Impl::iterator aIter = mpMap->begin();
while( aIter != mpMap->end() )
2002-04-11 13:04:40 +00:00
{
Reference < XAccessible > xTmp = (*aIter).second;
if( xTmp.is() )
{
SwAccessibleContext *pTmp =
static_cast< SwAccessibleContext * >( xTmp.get() );
}
}
}
#endif
2002-04-17 13:07:39 +00:00
delete mpMap;
mpMap = 0;
2002-04-11 13:04:40 +00:00
}
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maEventMutex );
ASSERT( !(mpEvents || mpEventMap), "pending events" );
delete mpEventMap;
mpEventMap = 0;
delete mpEvents;
mpEvents = 0;
2002-04-11 13:04:40 +00:00
}
}
Reference< XAccessible > SwAccessibleMap::GetDocumentView()
2002-02-04 13:10:18 +00:00
{
2002-02-05 14:52:06 +00:00
Reference < XAccessible > xAcc;
2002-03-21 11:50:31 +00:00
sal_Bool bSetVisArea = sal_False;
2002-02-04 13:10:18 +00:00
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-03-21 11:50:31 +00:00
2002-04-17 13:07:39 +00:00
if( !mpMap )
2002-03-21 11:50:31 +00:00
{
2002-04-17 13:07:39 +00:00
mpMap = new SwAccessibleContextMap_Impl;
#ifndef PRODUCT
2002-04-17 13:07:39 +00:00
mpMap->mbLocked = sal_False;
#endif
2002-03-21 11:50:31 +00:00
}
#ifndef PRODUCT
2002-04-17 13:07:39 +00:00
ASSERT( !mpMap->mbLocked, "Map is locked" );
mpMap->mbLocked = sal_True;
2002-03-21 11:50:31 +00:00
#endif
const SwRootFrm *pRootFrm = GetShell()->GetLayout();
2002-04-17 13:07:39 +00:00
SwAccessibleContextMap_Impl::iterator aIter = mpMap->find( pRootFrm );
if( aIter != mpMap->end() )
2002-03-21 11:50:31 +00:00
xAcc = (*aIter).second;
if( xAcc.is() )
2002-02-05 14:52:06 +00:00
{
2002-03-21 11:50:31 +00:00
bSetVisArea = sal_True; // Set VisArea when map mutex is not
// locked
2002-02-05 14:52:06 +00:00
}
else
{
2002-03-21 11:50:31 +00:00
xAcc = new SwAccessibleDocument( this );
2002-04-17 13:07:39 +00:00
if( aIter != mpMap->end() )
2002-03-21 11:50:31 +00:00
{
(*aIter).second = xAcc;
}
else
{
SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc );
2002-04-17 13:07:39 +00:00
mpMap->insert( aEntry );
2002-03-21 11:50:31 +00:00
}
2002-02-05 14:52:06 +00:00
}
2002-03-21 11:50:31 +00:00
#ifndef PRODUCT
2002-04-17 13:07:39 +00:00
mpMap->mbLocked = sal_False;
2002-03-21 11:50:31 +00:00
#endif
2002-02-04 13:10:18 +00:00
}
2002-03-21 11:50:31 +00:00
if( bSetVisArea )
{
SwAccessibleDocument *pAcc =
static_cast< SwAccessibleDocument * >( xAcc.get() );
2002-04-11 13:04:40 +00:00
pAcc->SetVisArea();
2002-03-21 11:50:31 +00:00
}
2002-02-05 14:52:06 +00:00
return xAcc;
2002-02-04 13:10:18 +00:00
}
Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm,
2002-02-11 11:51:16 +00:00
sal_Bool bCreate )
2002-02-04 13:10:18 +00:00
{
2002-02-05 14:52:06 +00:00
Reference < XAccessible > xAcc;
2002-04-05 11:18:25 +00:00
Reference < XAccessible > xOldCursorAcc;
2002-02-04 13:10:18 +00:00
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-02-04 13:10:18 +00:00
2002-04-17 13:07:39 +00:00
if( !mpMap && bCreate )
mpMap = new SwAccessibleContextMap_Impl;
if( mpMap )
2002-02-04 13:10:18 +00:00
{
2002-04-17 13:07:39 +00:00
SwAccessibleContextMap_Impl::iterator aIter = mpMap->find( pFrm );
if( aIter != mpMap->end() )
2002-03-21 11:50:31 +00:00
xAcc = (*aIter).second;
2002-03-21 11:50:31 +00:00
if( !xAcc.is() && bCreate )
2002-02-05 14:52:06 +00:00
{
2002-03-21 11:50:31 +00:00
SwAccessibleContext *pAcc = 0;
switch( pFrm->GetType() )
{
2002-03-21 11:50:31 +00:00
case FRM_TXT:
2002-04-17 13:07:39 +00:00
pAcc = new SwAccessibleParagraph( this, mnPara++,
2002-03-21 11:50:31 +00:00
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,
2002-04-17 13:07:39 +00:00
(bIsEndnote ? mnEndnote++ : mnFootnote++),
2002-03-21 11:50:31 +00:00
pFtnFrm );
}
break;
2002-04-05 11:18:25 +00:00
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;
2002-04-11 13:04:40 +00:00
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;
}
2002-03-21 11:50:31 +00:00
xAcc = pAcc;
ASSERT( xAcc.is(), "unknown frame type" );
if( xAcc.is() )
{
2002-04-17 13:07:39 +00:00
if( aIter != mpMap->end() )
2002-03-21 11:50:31 +00:00
{
(*aIter).second = xAcc;
}
else
{
SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc );
2002-04-17 13:07:39 +00:00
mpMap->insert( aEntry );
2002-03-21 11:50:31 +00:00
}
2002-04-11 13:04:40 +00:00
if( pAcc->HasCursor() &&
2002-04-17 13:07:39 +00:00
!AreInSameTable( mpMap->mxCursorContext, pFrm ) )
2002-03-21 11:50:31 +00:00
{
// 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.
2002-04-17 13:07:39 +00:00
xOldCursorAcc = mpMap->mxCursorContext;
mpMap->mxCursorContext = xAcc;
2002-03-21 11:50:31 +00:00
}
}
2002-02-05 14:52:06 +00:00
}
2002-02-04 13:10:18 +00:00
}
}
2002-03-21 11:50:31 +00:00
// Invalidate focus for old object when map is not locked
2002-04-05 11:18:25 +00:00
if( xOldCursorAcc.is() )
InvalidateCursorPosition( xOldCursorAcc );
2002-03-21 11:50:31 +00:00
2002-02-05 14:52:06 +00:00
return xAcc;
}
::vos::ORef < SwAccessibleContext > SwAccessibleMap::GetContextImpl(
2002-02-11 11:51:16 +00:00
const SwFrm *pFrm,
sal_Bool bCreate )
2002-02-05 14:52:06 +00:00
{
Reference < XAccessible > xAcc( GetContext( pFrm, bCreate ) );
2002-02-05 14:52:06 +00:00
::vos::ORef < SwAccessibleContext > xAccImpl(
2002-03-06 07:15:41 +00:00
static_cast< SwAccessibleContext * >( xAcc.get() ) );
2002-02-05 14:52:06 +00:00
return xAccImpl;
2002-02-04 13:10:18 +00:00
}
void SwAccessibleMap::RemoveContext( const SwFrm *pFrm )
2002-02-04 13:10:18 +00:00
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-02-05 14:52:06 +00:00
2002-04-17 13:07:39 +00:00
if( mpMap )
2002-02-11 11:51:16 +00:00
{
SwAccessibleContextMap_Impl::iterator aIter =
2002-04-17 13:07:39 +00:00
mpMap->find( pFrm );
if( aIter != mpMap->end() )
2002-02-11 11:51:16 +00:00
{
2002-04-17 13:07:39 +00:00
mpMap->erase( aIter );
// Remove reference to old caret object
2002-04-17 13:07:39 +00:00
Reference < XAccessible > xOldAcc( mpMap->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
2002-04-17 13:07:39 +00:00
mpMap->mxCursorContext = xOldAcc;
}
}
2002-04-17 13:07:39 +00:00
if( mpMap->empty() )
2002-02-11 11:51:16 +00:00
{
2002-04-17 13:07:39 +00:00
delete mpMap;
mpMap = 0;
2002-02-11 11:51:16 +00:00
}
}
}
}
2002-04-11 13:04:40 +00:00
void SwAccessibleMap::Dispose( const SwFrm *pFrm, sal_Bool bRecursive )
2002-02-11 11:51:16 +00:00
{
2002-04-11 13:04:40 +00:00
// 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( pFrm->IsAccessibleFrm(),
"non accessible frame should be disposed" );
SwFrmOrObj aFrmOrObj( pFrm );
Reference < XAccessible > xAcc;
2002-04-17 13:07:39 +00:00
Reference < XAccessible > xParentAcc;
2002-04-11 13:04:40 +00:00
if( aFrmOrObj.IsAccessible() )
2002-02-11 11:51:16 +00:00
{
2002-04-11 13:04:40 +00:00
// get accessible context for frame
2002-02-11 11:51:16 +00:00
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-03-21 11:50:31 +00:00
2002-04-17 13:07:39 +00:00
if( mpMap )
2002-02-11 11:51:16 +00:00
{
2002-04-11 13:04:40 +00:00
SwAccessibleContextMap_Impl::iterator aIter =
2002-04-17 13:07:39 +00:00
mpMap->find( pFrm );
if( aIter != mpMap->end() )
{
2002-03-21 11:50:31 +00:00
xAcc = (*aIter).second;
2002-04-17 13:07:39 +00:00
}
else
{
// Otherwise we look if the parent is accessible.
// If not, there is nothing to do.
const SwFrm *pParent =
SwAccessibleFrame::GetParent( aFrmOrObj.GetSwFrm() );
if( pParent )
{
aIter = mpMap->find( pParent );
if( aIter != mpMap->end() )
{
xParentAcc = (*aIter).second;
}
}
}
}
}
2002-03-21 11:50:31 +00:00
2002-04-11 13:04:40 +00:00
// remove events stored for the frame
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maEventMutex );
if( mpEvents )
{
2002-03-21 11:50:31 +00:00
SwAccessibleEventMap_Impl::iterator aIter =
2002-04-17 13:07:39 +00:00
mpEventMap->find( aFrmOrObj.GetSwFrm() );
if( aIter != mpEventMap->end() )
2002-03-21 11:50:31 +00:00
{
SwAccessibleEvent_Impl aEvent(
2002-04-11 13:04:40 +00:00
SwAccessibleEvent_Impl::DISPOSE, aFrmOrObj );
2002-03-21 11:50:31 +00:00
AppendEvent( aEvent );
}
2002-02-11 11:51:16 +00:00
}
}
2002-03-21 11:50:31 +00:00
2002-04-11 13:04:40 +00:00
// 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.
2002-03-21 11:50:31 +00:00
if( xAcc.is() )
{
SwAccessibleContext *pAccImpl =
static_cast< SwAccessibleContext *>( xAcc.get() );
2002-04-05 11:18:25 +00:00
pAccImpl->Dispose( bRecursive );
2002-03-21 11:50:31 +00:00
}
2002-04-17 13:07:39 +00:00
else if( xParentAcc.is() )
{
// 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.
SwAccessibleContext *pAccImpl =
static_cast< SwAccessibleContext *>( xParentAcc.get() );
pAccImpl->DisposeChild( aFrmOrObj.GetSwFrm(), bRecursive );
}
2002-02-11 11:51:16 +00:00
}
}
2002-04-11 13:04:40 +00:00
void SwAccessibleMap::InvalidatePosOrSize( const SwFrm *pFrm,
2002-04-17 13:07:39 +00:00
const SwRect& rOldBox )
2002-02-11 11:51:16 +00:00
{
2002-04-11 13:04:40 +00:00
SwFrmOrObj aFrmOrObj( pFrm );
if( aFrmOrObj.IsAccessible() )
2002-02-11 11:51:16 +00:00
{
2002-03-21 11:50:31 +00:00
Reference < XAccessible > xAcc;
Reference < XAccessible > xParentAcc;
2002-02-11 11:51:16 +00:00
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-03-21 11:50:31 +00:00
2002-04-17 13:07:39 +00:00
if( mpMap )
2002-02-11 11:51:16 +00:00
{
2002-04-11 13:04:40 +00:00
SwAccessibleContextMap_Impl::iterator aIter =
2002-04-17 13:07:39 +00:00
mpMap->find( aFrmOrObj.GetSwFrm() );
if( aIter != mpMap->end() )
{
2002-03-21 11:50:31 +00:00
// If there is an accesible object already it is
// notified directly.
xAcc = (*aIter).second;
}
2002-03-21 11:50:31 +00:00
else
2002-02-11 11:51:16 +00:00
{
2002-03-21 11:50:31 +00:00
// Otherwise we look if the parent is accessible.
// If not, there is nothing to do.
2002-04-11 13:04:40 +00:00
const SwFrm *pParent =
SwAccessibleFrame::GetParent( aFrmOrObj.GetSwFrm() );
2002-03-21 11:50:31 +00:00
2002-04-05 11:18:25 +00:00
if( pParent )
2002-02-11 11:51:16 +00:00
{
2002-04-17 13:07:39 +00:00
aIter = mpMap->find( pParent );
if( aIter != mpMap->end() )
{
2002-03-21 11:50:31 +00:00
xParentAcc = (*aIter).second;
}
2002-02-11 11:51:16 +00:00
}
}
}
}
2002-03-21 11:50:31 +00:00
if( xAcc.is() )
{
2002-04-17 13:07:39 +00:00
ASSERT( !rOldBox.IsEmpty(), "context should have a size" );
2002-03-21 11:50:31 +00:00
SwAccessibleContext *pAccImpl =
static_cast< SwAccessibleContext *>( xAcc.get() );
if( GetShell()->ActionPend() )
{
SwAccessibleEvent_Impl aEvent(
SwAccessibleEvent_Impl::POS_CHANGED, pAccImpl,
2002-04-17 13:07:39 +00:00
aFrmOrObj, rOldBox );
2002-03-21 11:50:31 +00:00
AppendEvent( aEvent );
}
else
{
2002-04-17 13:07:39 +00:00
pAccImpl->InvalidatePosOrSize( rOldBox );
2002-03-21 11:50:31 +00:00
}
}
else if( xParentAcc.is() )
{
SwAccessibleContext *pAccImpl =
static_cast< SwAccessibleContext *>(xParentAcc.get());
if( GetShell()->ActionPend() )
{
SwAccessibleEvent_Impl aEvent(
SwAccessibleEvent_Impl::CHILD_POS_CHANGED,
2002-04-17 13:07:39 +00:00
pAccImpl, aFrmOrObj, rOldBox );
2002-03-21 11:50:31 +00:00
AppendEvent( aEvent );
}
else
{
2002-04-11 13:04:40 +00:00
pAccImpl->InvalidateChildPosOrSize( aFrmOrObj.GetSwFrm(),
2002-04-17 13:07:39 +00:00
rOldBox );
2002-03-21 11:50:31 +00:00
}
}
2002-02-11 11:51:16 +00:00
}
2002-02-04 13:10:18 +00:00
}
2002-04-11 13:04:40 +00:00
void SwAccessibleMap::InvalidateContent( const SwFrm *pFrm )
{
2002-04-11 13:04:40 +00:00
SwFrmOrObj aFrmOrObj( pFrm );
if( aFrmOrObj.IsAccessible() )
{
2002-03-21 11:50:31 +00:00
Reference < XAccessible > xAcc;
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-04-17 13:07:39 +00:00
if( mpMap )
2002-03-21 11:50:31 +00:00
{
2002-04-11 13:04:40 +00:00
SwAccessibleContextMap_Impl::iterator aIter =
2002-04-17 13:07:39 +00:00
mpMap->find( aFrmOrObj.GetSwFrm() );
if( aIter != mpMap->end() )
2002-03-21 11:50:31 +00:00
xAcc = (*aIter).second;
}
}
if( xAcc.is() )
{
2002-03-21 11:50:31 +00:00
SwAccessibleContext *pAccImpl =
static_cast< SwAccessibleContext *>( xAcc.get() );
if( GetShell()->ActionPend() )
{
2002-03-21 11:50:31 +00:00
SwAccessibleEvent_Impl aEvent(
SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl,
2002-04-11 13:04:40 +00:00
aFrmOrObj );
2002-03-21 11:50:31 +00:00
AppendEvent( aEvent );
}
else
{
pAccImpl->InvalidateContent();
}
}
}
}
2002-04-05 11:18:25 +00:00
void SwAccessibleMap::InvalidateCursorPosition( const SwFrm *pFrm )
{
2002-04-11 13:04:40 +00:00
SwFrmOrObj aFrmOrObj( pFrm );
const ViewShell *pVSh = GetShell();
if( pVSh->ISA( SwCrsrShell ) )
2002-04-05 11:18:25 +00:00
{
2002-04-11 13:04:40 +00:00
const SwCrsrShell *pCSh = static_cast< const SwCrsrShell * >( pVSh );
if( pCSh->IsTableMode() )
2002-04-05 11:18:25 +00:00
{
2002-04-11 13:04:40 +00:00
while( aFrmOrObj.GetSwFrm() && !aFrmOrObj.GetSwFrm()->IsCellFrm() )
aFrmOrObj = aFrmOrObj.GetSwFrm()->GetUpper();
2002-04-05 11:18:25 +00:00
}
2002-04-11 13:04:40 +00:00
else if( pVSh->ISA( SwFEShell ) )
2002-04-05 11:18:25 +00:00
{
2002-04-11 13:04:40 +00:00
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 )
{
aFrmOrObj = static_cast<const SwFrm *>( 0 );
}
2002-04-05 11:18:25 +00:00
}
}
2002-04-11 13:04:40 +00:00
ASSERT( aFrmOrObj.IsAccessible(), "frame is not accessible" );
2002-04-05 11:18:25 +00:00
Reference < XAccessible > xOldAcc;
Reference < XAccessible > xAcc;
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
2002-04-17 13:07:39 +00:00
if( mpMap )
{
2002-04-17 13:07:39 +00:00
xOldAcc = mpMap->mxCursorContext;
mpMap->mxCursorContext = xAcc; // clear reference
2002-04-11 13:04:40 +00:00
if( aFrmOrObj.IsAccessible() )
{
SwAccessibleContextMap_Impl::iterator aIter =
2002-04-17 13:07:39 +00:00
mpMap->find( aFrmOrObj.GetSwFrm() );
if( aIter != mpMap->end() )
xAcc = (*aIter).second;
2002-04-11 13:04:40 +00:00
// 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 );
}
}
}
}
2002-04-05 11:18:25 +00:00
if( xOldAcc.is() && xOldAcc != xAcc )
InvalidateCursorPosition( xOldAcc );
if( xAcc.is() )
InvalidateCursorPosition( xAcc );
}
2002-04-05 11:18:25 +00:00
void SwAccessibleMap::SetCursorContext(
const ::vos::ORef < SwAccessibleContext >& rCursorContext )
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maMutex );
if( mpMap )
{
2002-04-05 11:18:25 +00:00
Reference < XAccessible > xAcc( rCursorContext.getBodyPtr() );
2002-04-17 13:07:39 +00:00
mpMap->mxCursorContext = xAcc;
}
}
void SwAccessibleMap::InvalidateStates( sal_uInt8 nStates )
{
Reference< XAccessible > xAcc( GetDocumentView() );
SwAccessibleContext *pAccImpl =
static_cast< SwAccessibleContext *>( xAcc.get() );
if( GetShell()->ActionPend() )
{
SwAccessibleEvent_Impl aEvent(
SwAccessibleEvent_Impl::CARET_OR_STATES, pAccImpl,
pAccImpl->GetFrm(), nStates );
AppendEvent( aEvent );
}
else
{
2002-04-11 13:04:40 +00:00
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
SwFrmOrObj aFrmOrObj( pFrm );
if( aFrmOrObj.IsAccessible() )
{
Reference < XAccessible > xAcc;
Reference < XAccessible > xParentAcc;
{
vos::OGuard aGuard( maMutex );
if( mpMap )
{
SwAccessibleContextMap_Impl::iterator aIter =
mpMap->find( aFrmOrObj.GetSwFrm() );
if( aIter != mpMap->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,
pFrm, bFrom ? ACC_STATE_RELATION_FROM
: ACC_STATE_RELATION_TO );
AppendEvent( aEvent );
}
else
{
pAccImpl->InvalidateRelation( bFrom ?
AccessibleEventId::CONTENT_FLOWS_FROM :
AccessibleEventId::CONTENT_FLOWS_TO );
}
}
}
}
void SwAccessibleMap::InvalidateRelationSet( const SwFrm* pMaster,
const SwFrm* pFollow )
{
_InvalidateRelationSet( pMaster, sal_False );
_InvalidateRelationSet( pFollow, sal_True );
}
void SwAccessibleMap::FireEvents()
{
2002-04-17 13:07:39 +00:00
vos::OGuard aGuard( maEventMutex );
if( mpEvents )
{
2002-04-17 13:07:39 +00:00
mpEvents->SetFiring();
SwAccessibleEventList_Impl::iterator aIter = mpEvents->begin();
while( aIter != mpEvents->end() )
{
2002-03-21 11:50:31 +00:00
FireEvent( *aIter );
2002-04-17 13:07:39 +00:00
++aIter;
}
}
2002-04-17 13:07:39 +00:00
delete mpEventMap;
mpEventMap = 0;
2002-04-17 13:07:39 +00:00
delete mpEvents;
mpEvents = 0;
}