diff options
Diffstat (limited to 'sw/source')
-rw-r--r-- | sw/source/core/access/acccontext.cxx | 31 | ||||
-rw-r--r-- | sw/source/core/access/acccontext.hxx | 14 | ||||
-rw-r--r-- | sw/source/core/access/accmap.cxx | 293 | ||||
-rw-r--r-- | sw/source/core/access/accpara.cxx | 334 | ||||
-rw-r--r-- | sw/source/core/access/accpara.hxx | 28 |
5 files changed, 517 insertions, 183 deletions
diff --git a/sw/source/core/access/acccontext.cxx b/sw/source/core/access/acccontext.cxx index c7c7bc5223..fe4e48425f 100644 --- a/sw/source/core/access/acccontext.cxx +++ b/sw/source/core/access/acccontext.cxx @@ -2,9 +2,9 @@ * * $RCSfile: acccontext.cxx,v $ * - * $Revision: 1.9 $ + * $Revision: 1.10 $ * - * last change: $Author: mib $ $Date: 2002-02-27 09:32:33 $ + * last change: $Author: mib $ $Date: 2002-03-08 13:26:29 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -144,12 +144,12 @@ using namespace ::com::sun::star::uno; using namespace ::drafts::com::sun::star::accessibility; using namespace ::rtl; -void SwAccessibleContext::_Moved() +void SwAccessibleContext::FireVisibleDataEvent() { AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::ACCESSIBLE_VISIBLE_DATA_EVENT; - AccessibleEvent( aEvent ); + FireAccessibleEvent( aEvent ); DBG_MSG( "AccessibleVisibleData" ) } @@ -176,7 +176,7 @@ sal_Bool SwAccessibleContext::ChildScrolledIn( const SwFrm *pFrm ) Reference < XAccessible > xChild( xChildImpl.getBodyPtr() ); aEvent.NewValue <<= xChild; - AccessibleEvent( aEvent ); + FireAccessibleEvent( aEvent ); DBG_MSG_PARAM( "AccessibleChild (added)", xChildImpl.getBodyPtr() ) xWeakChild = xChild; @@ -256,7 +256,7 @@ sal_Bool SwAccessibleContext::ChildScrolled( const SwFrm *pFrm ) // the update event for the parent has been send. xChildImpl->SetVisArea( GetVisArea() ); - xChildImpl->_Moved(); + xChildImpl->FireVisibleDataEvent(); bUpdateChildren = sal_False; } } @@ -305,7 +305,7 @@ void SwAccessibleContext::Dispose( sal_Bool bRecursive ) AccessibleEventObject aEvent; aEvent.EventId = AccessibleEventId::ACCESSIBLE_CHILD_EVENT; aEvent.OldValue <<= xThis; - pAcc->AccessibleEvent( aEvent ); + pAcc->FireAccessibleEvent( aEvent ); DBG_MSG_THIS_PARAM( "AccessibleChild (removed)", pAcc, this ) } @@ -329,7 +329,9 @@ void SwAccessibleContext::PosChanged() if( IsShowing() ) { // The frame stays visible -> broadcast event - _Moved(); + FireVisibleDataEvent(); + + _InvalidateContent( sal_True ); } else { @@ -364,8 +366,13 @@ void SwAccessibleContext::ChildPosChanged( const SwFrm *pFrm, } } +void SwAccessibleContext::InvalidateContent() +{ + _InvalidateContent( sal_False ); +} -void SwAccessibleContext::AccessibleEvent( AccessibleEventObject& rEvent ) + +void SwAccessibleContext::FireAccessibleEvent( AccessibleEventObject& rEvent ) { Reference < XAccessibleContext > xThis( this ); rEvent.Source = xThis; @@ -414,6 +421,12 @@ void SwAccessibleContext::SetStates( } } +void SwAccessibleContext::_InvalidateContent( sal_Bool ) +{ +} + + + OUString SwAccessibleContext::GetResource( sal_uInt16 nResId, const OUString *pArg1, const OUString *pArg2 ) const diff --git a/sw/source/core/access/acccontext.hxx b/sw/source/core/access/acccontext.hxx index 0439da6169..45b938a97a 100644 --- a/sw/source/core/access/acccontext.hxx +++ b/sw/source/core/access/acccontext.hxx @@ -2,9 +2,9 @@ * * $RCSfile: acccontext.hxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: mib $ $Date: 2002-02-27 09:32:33 $ + * last change: $Author: mib $ $Date: 2002-03-08 13:26:29 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -144,7 +144,7 @@ protected: virtual sal_Bool DisposeChild( const SwFrm *pFrm, sal_Bool bRecursive ); - void AccessibleEvent( ::drafts::com::sun::star::accessibility::AccessibleEventObject& rEvent ); + void FireAccessibleEvent( ::drafts::com::sun::star::accessibility::AccessibleEventObject& rEvent ); ::rtl::OUString GetResource( sal_uInt16 nResId, const ::rtl::OUString *pArg1 = 0, @@ -155,8 +155,10 @@ protected: // SHOWING(0/1), OPAQUE(0/1) and VISIBLE(1). virtual void SetStates( ::utl::AccessibleStateSetHelper& rStateSet ); + virtual void _InvalidateContent( sal_Bool bVisibleDataFired ); + // broadcast visual data event - void _Moved(); + void FireVisibleDataEvent(); Window *GetWindow(); SwAccessibleMap *GetMap() { return pMap; } @@ -337,6 +339,10 @@ public: // The object has been moved by the layout void ChildPosChanged( const SwFrm *pFrm, const SwRect& rFrm ); + // The content may have changed (but it hasn't tohave changed) + virtual void InvalidateContent(); + + const ::rtl::OUString& GetName() const { return sName; } }; diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx index e8b5fb20aa..a4a8813c65 100644 --- a/sw/source/core/access/accmap.cxx +++ b/sw/source/core/access/accmap.cxx @@ -2,9 +2,9 @@ * * $RCSfile: accmap.cxx,v $ * - * $Revision: 1.6 $ + * $Revision: 1.7 $ * - * last change: $Author: mib $ $Date: 2002-03-06 08:14:51 $ + * last change: $Author: mib $ $Date: 2002-03-08 13:26:29 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -72,9 +72,8 @@ #include <cppuhelper/weakref.hxx> #endif -#ifndef __SGI_STL_MAP #include <map> -#endif +#include <list> #ifndef _ACCMAP_HXX #include <accmap.hxx> #endif @@ -125,14 +124,67 @@ struct SwFrmFunc } }; -typedef ::std::map < const SwFrm *, WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleMap_Impl; +typedef ::std::map < const SwFrm *, WeakReference < XAccessible >, SwFrmFunc > _SwAccessibleContextMap_Impl; + +class SwAccessibleContextMap_Impl: public _SwAccessibleContextMap_Impl +{ +}; -class SwAccessibleMap_Impl: public _SwAccessibleMap_Impl +struct SwAccessibleEvent_Impl { +public: + enum EventType { INVALID_CONTENT, POS_CHANGED, CHILD_POS_CHANGED, DISPOSE }; + +private: + EventType eType; // The event type + WeakReference < XAccessible > xAcc; // The object that fires the event + SwRect aOldFrm; // the old bounds for CHILD_POS_CHANGED + const SwFrm *pFrm; // the child for CHILD_POS_CHANGED and + // the same as xAcc for any other + // event type + +public: + SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA ) : + eType( eT ), xAcc( pA ), pFrm( pA->GetFrm() ) {} + SwAccessibleEvent_Impl( EventType eT, const SwFrm *pF ) : + eType( eT ), pFrm( pF ) {} + SwAccessibleEvent_Impl( EventType eT, SwAccessibleContext *pA, + const SwFrm *pF, const SwRect& rR ) : + eType( eT ), xAcc( pA ), pFrm( pF ), aOldFrm( rR ) {} + + inline EventType GetType() const { return eType; } + inline ::vos::ORef < SwAccessibleContext > GetContext() const; + inline const SwRect& GetOldFrm() const { return aOldFrm; } + inline const SwFrm *GetFrm() const { return pFrm; } }; +inline ::vos::ORef < SwAccessibleContext > + SwAccessibleEvent_Impl::GetContext() const +{ + Reference < XAccessible > xTmp( xAcc ); + ::vos::ORef < SwAccessibleContext > xAccImpl( + static_cast< SwAccessibleContext * >( xTmp.get() ) ); + + return xAccImpl; +} + +typedef ::std::list < SwAccessibleEvent_Impl > _SwAccessibleEventList_Impl; + +class SwAccessibleEventList_Impl: public _SwAccessibleEventList_Impl +{ +}; + +typedef ::std::map < const SwFrm *, SwAccessibleEventList_Impl::iterator, SwFrmFunc > _SwAccessibleEventMap_Impl; + +class SwAccessibleEventMap_Impl: public _SwAccessibleEventMap_Impl +{ +}; + + SwAccessibleMap::SwAccessibleMap( ViewShell *pSh ) : pMap( 0 ), + pEvents( 0 ), + pEventMap( 0 ), pVSh( pSh ), nPara( 1 ), nFootnote( 1 ), @@ -147,7 +199,7 @@ SwAccessibleMap::~SwAccessibleMap() { Reference < XAccessible > xAcc; const SwRootFrm *pRootFrm = GetShell()->GetDoc()->GetRootFrm(); - SwAccessibleMap_Impl::iterator aIter = pMap->find( pRootFrm ); + SwAccessibleContextMap_Impl::iterator aIter = pMap->find( pRootFrm ); if( aIter != pMap->end() ) xAcc = (*aIter).second; if( !xAcc.is() ) @@ -155,9 +207,92 @@ SwAccessibleMap::~SwAccessibleMap() SwAccessibleDocument *pAcc = static_cast< SwAccessibleDocument * >( xAcc.get() ); pAcc->Dispose( sal_True ); + + ASSERT( !pMap || pMap->empty(), + "Map should be empty after disposing the root frame" ); } delete pMap; + + ASSERT( !(pEvents || pEventMap), "pending events" ); + delete pEventMap; + delete pEvents; +} + +void SwAccessibleMap::AppendEvent( const SwAccessibleEvent_Impl& rEvent ) +{ + vos::OGuard aGuard( aEventMutex ); + + if( !pEvents ) + pEvents = new SwAccessibleEventList_Impl; + if( !pEventMap ) + pEventMap = new SwAccessibleEventMap_Impl; + + SwAccessibleEventMap_Impl::iterator aIter = + pEventMap->find( rEvent.GetFrm() ); + if( aIter != pEventMap->end() ) + { + SwAccessibleEvent_Impl aEvent( *(*aIter).second ); + sal_Bool bAppendEvent = sal_True; + switch( rEvent.GetType() ) + { + case SwAccessibleEvent_Impl::INVALID_CONTENT: + // All events include a INVALID_CONTENT, so the only action that + // needs to be done is to put the event to the back. That's done + // automatically. + ASSERT( aEvent.GetType()!=SwAccessibleEvent_Impl::CHILD_POS_CHANGED, + "invalid event combination" ); + ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, + "dispose events should not be stored" ); + break; + case SwAccessibleEvent_Impl::POS_CHANGED: + // If the the old event is not a DISPOSE event, the new event + // includes the old one. + ASSERT( aEvent.GetType()!=SwAccessibleEvent_Impl::CHILD_POS_CHANGED, + "invalid event combination" ); + ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, + "dispose events should not be stored" ); + if( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE ) + aEvent = rEvent; + 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::DISPOSE: + // DISPOSE events overwrite all others. They are not stored + // but executed immidiatly to avoid broadcasting of defuntional + // 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, + "invalid event combination" ); + ASSERT( aEvent.GetType() != SwAccessibleEvent_Impl::DISPOSE, + "dispose events should not be stored" ); + bAppendEvent = sal_False; + break; + } + if( bAppendEvent ) + { + pEvents->erase( (*aIter).second ); + (*aIter).second = pEvents->insert( pEvents->end(), aEvent ); + } + else + { + pEvents->erase( (*aIter).second ); + pEventMap->erase( aIter ); + } + } + else if( SwAccessibleEvent_Impl::DISPOSE != rEvent.GetType() ) + { + SwAccessibleEventMap_Impl::value_type aEntry( rEvent.GetFrm(), + pEvents->insert( pEvents->end(), rEvent ) ); + pEventMap->insert( aEntry ); + } + } Reference< XAccessible > SwAccessibleMap::GetDocumentView() @@ -167,9 +302,9 @@ Reference< XAccessible > SwAccessibleMap::GetDocumentView() Reference < XAccessible > xAcc; if( !pMap ) - pMap = new SwAccessibleMap_Impl; + pMap = new SwAccessibleContextMap_Impl; const SwRootFrm *pRootFrm = GetShell()->GetDoc()->GetRootFrm(); - SwAccessibleMap_Impl::iterator aIter = pMap->find( pRootFrm ); + SwAccessibleContextMap_Impl::iterator aIter = pMap->find( pRootFrm ); if( aIter != pMap->end() ) xAcc = (*aIter).second; if( xAcc.is() ) @@ -187,7 +322,7 @@ Reference< XAccessible > SwAccessibleMap::GetDocumentView() } else { - SwAccessibleMap_Impl::value_type aEntry( pRootFrm, xAcc ); + SwAccessibleContextMap_Impl::value_type aEntry( pRootFrm, xAcc ); pMap->insert( aEntry ); } } @@ -203,10 +338,10 @@ Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm, Reference < XAccessible > xAcc; if( !pMap && bCreate ) - pMap = new SwAccessibleMap_Impl; + pMap = new SwAccessibleContextMap_Impl; if( pMap ) { - SwAccessibleMap_Impl::iterator aIter = pMap->find( pFrm ); + SwAccessibleContextMap_Impl::iterator aIter = pMap->find( pFrm ); if( aIter != pMap->end() ) xAcc = (*aIter).second; @@ -248,7 +383,7 @@ Reference< XAccessible> SwAccessibleMap::GetContext( const SwFrm *pFrm, } else { - SwAccessibleMap_Impl::value_type aEntry( pFrm, xAcc ); + SwAccessibleContextMap_Impl::value_type aEntry( pFrm, xAcc ); pMap->insert( aEntry ); } } @@ -276,7 +411,8 @@ void SwAccessibleMap::RemoveContext( SwAccessibleContext *pAcc ) if( pMap ) { - SwAccessibleMap_Impl::iterator aIter = pMap->find( pAcc->GetFrm() ); + SwAccessibleContextMap_Impl::iterator aIter = + pMap->find( pAcc->GetFrm() ); if( aIter != pMap->end() ) { pMap->erase( aIter ); @@ -297,12 +433,28 @@ void SwAccessibleMap::DisposeFrm( const SwFrm *pFrm ) if( pMap ) { - SwAccessibleMap_Impl::iterator aIter = pMap->find( pFrm ); + SwAccessibleContextMap_Impl::iterator aIter = pMap->find( pFrm ); if( aIter != pMap->end() ) { Reference < XAccessible > xAcc = (*aIter).second; if( xAcc.is() ) - static_cast< SwAccessibleContext *>( xAcc.get())->Dispose(); + { + SwAccessibleContext *pAccImpl = + static_cast< SwAccessibleContext *>( xAcc.get() ); + pAccImpl->Dispose(); + } + } + } + if( pEvents ) + { + vos::OGuard aGuard( aEventMutex ); + SwAccessibleEventMap_Impl::iterator aIter = + pEventMap->find( pFrm ); + if( aIter != pEventMap->end() ) + { + SwAccessibleEvent_Impl aEvent( + SwAccessibleEvent_Impl::DISPOSE, pFrm ); + AppendEvent( aEvent ); } } } @@ -316,13 +468,27 @@ void SwAccessibleMap::MoveFrm( const SwFrm *pFrm, const SwRect& rOldFrm ) if( pMap ) { - SwAccessibleMap_Impl::iterator aIter = pMap->find( pFrm ); + SwAccessibleContextMap_Impl::iterator aIter = pMap->find( pFrm ); if( aIter != pMap->end() ) { // If there is an accesible object already it is // notified directly. Reference < XAccessible > xAcc = (*aIter).second; - static_cast< SwAccessibleContext * >(xAcc.get())->PosChanged(); + if( xAcc.is() ) + { + SwAccessibleContext *pAccImpl = + static_cast< SwAccessibleContext *>( xAcc.get() ); + if( GetShell()->ActionPend() ) + { + SwAccessibleEvent_Impl aEvent( + SwAccessibleEvent_Impl::POS_CHANGED, pAccImpl ); + AppendEvent( aEvent ); + } + else + { + pAccImpl->PosChanged(); + } + } } else { @@ -338,11 +504,98 @@ void SwAccessibleMap::MoveFrm( const SwFrm *pFrm, const SwRect& rOldFrm ) if( aIter != pMap->end() ) { Reference < XAccessible > xAcc = (*aIter).second; - static_cast<SwAccessibleContext *>(xAcc.get()) - ->ChildPosChanged( pFrm, rOldFrm ); + if( xAcc.is() ) + { + SwAccessibleContext *pAccImpl = + static_cast< SwAccessibleContext *>(xAcc.get()); + if( GetShell()->ActionPend() ) + { + SwAccessibleEvent_Impl aEvent( + SwAccessibleEvent_Impl::CHILD_POS_CHANGED, + pAccImpl, pFrm, rOldFrm ); + AppendEvent( aEvent ); + } + else + { + pAccImpl->ChildPosChanged( pFrm, rOldFrm ); + } + } + } + } + } + } + } +} + +void SwAccessibleMap::InvalidateFrmContent( const SwFrm *pFrm ) +{ + if( pFrm->IsAccessibleFrm() ) + { + vos::OGuard aGuard( aMutex ); + + if( pMap ) + { + SwAccessibleContextMap_Impl::iterator aIter = pMap->find( pFrm ); + if( aIter != pMap->end() ) + { + Reference < XAccessible > xAcc = (*aIter).second; + if( xAcc.is() ) + { + SwAccessibleContext *pAccImpl = + static_cast< SwAccessibleContext *>( xAcc.get() ); + if( GetShell()->ActionPend() ) + { + SwAccessibleEvent_Impl aEvent( + SwAccessibleEvent_Impl::INVALID_CONTENT, pAccImpl ); + AppendEvent( aEvent ); + } + else + { + pAccImpl->InvalidateContent(); } } } } } } + +void SwAccessibleMap::FireEvents() +{ + vos::OGuard aGuard( aEventMutex ); + if( pEvents ) + { + SwAccessibleEventList_Impl::iterator aIter = pEvents->begin(); + while( aIter != pEvents->end() ) + { + ::vos::ORef < SwAccessibleContext > xAccImpl( (*aIter).GetContext() ); + if( xAccImpl.isValid() ) + { + switch( (*aIter).GetType() ) + { + case SwAccessibleEvent_Impl::INVALID_CONTENT: + xAccImpl->InvalidateContent(); + break; + case SwAccessibleEvent_Impl::POS_CHANGED: + xAccImpl->PosChanged(); + break; + case SwAccessibleEvent_Impl::CHILD_POS_CHANGED: + xAccImpl->ChildPosChanged( (*aIter).GetFrm(), + (*aIter).GetOldFrm() ); + break; + case SwAccessibleEvent_Impl::DISPOSE: + ASSERT( xAccImpl.isValid(), + "dispose event has been stored" ); + break; + } + } + + aIter++; + } + } + + delete pEventMap; + pEventMap = 0; + + delete pEvents; + pEvents = 0; +} diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx index 30d7be8722..da6a6aa967 100644 --- a/sw/source/core/access/accpara.cxx +++ b/sw/source/core/access/accpara.cxx @@ -2,9 +2,9 @@ * * $RCSfile: accpara.cxx,v $ * - * $Revision: 1.13 $ + * $Revision: 1.14 $ * - * last change: $Author: dvo $ $Date: 2002-03-04 12:43:32 $ + * last change: $Author: mib $ $Date: 2002-03-08 13:26:29 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -109,6 +109,9 @@ #ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLETEXTTYPE_HPP_ #include <drafts/com/sun/star/accessibility/AccessibleTextType.hpp> #endif +#ifndef _DRAFTS_COM_SUN_STAR_ACCESSIBILITY_ACCESSIBLEEVENTID_HPP_ +#include <drafts/com/sun/star/accessibility/AccessibleEventId.hpp> +#endif #ifndef _UTL_ACCESSIBLESTATESETHELPER_HXX_ #include <unotools/accessiblestatesethelper.hxx> @@ -152,6 +155,145 @@ using ::com::sun::star::beans::PropertyValue; const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView"; const sal_Char sImplementationName[] = "SwAccessibleParagraph"; const xub_StrLen MAX_DESC_TEXT_LEN = 40; +const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const +{ + const SwFrm* pFrm = GetFrm(); + DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" ); + + const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode(); + DBG_ASSERT( pNode != NULL, "A text frame without a text node." ); + + return pNode; +} + +OUString SwAccessibleParagraph::GetString() +{ + return GetPortionData().GetAccessibleString(); +} + +OUString SwAccessibleParagraph::GetDescription() +{ + const OUString& rText = GetString(); + + // the description contains the first sentence up to + // MAX_DESC_TEXT_LEN characters (including the next full word) + Boundary aBound; + if( rText.getLength() > 0 ) + { + GetSentenceBoundary( aBound, rText, 0 ); + if( aBound.endPos > MAX_DESC_TEXT_LEN ) + { + GetWordBoundary( aBound, rText, MAX_DESC_TEXT_LEN ); + aBound.startPos = 0; + } + } + else + GetEmptyBoundary( aBound ); + OUString sArg1( rText.copy( aBound.startPos, aBound.endPos ) ); + + sal_Int16 nResId; + if( IsHeading() ) + { + nResId = STR_ACCESS_HEADING_DESC; + } + else + { + nResId = STR_ACCESS_PARAGRAPH_DESC; + } + + return GetResource( nResId, &sArg1 ); +} + +sal_Bool SwAccessibleParagraph::GetSelection( + sal_Int32& nStart, sal_Int32& nEnd) +{ + sal_Bool bRet = sal_False; + nStart = -1; + nEnd = -1; + + // get the selection, and test whether it affects our text node + SwPaM* pCrsr = GetCrsr(); + if( pCrsr != NULL ) + { + // get SwPosition for my node + const SwTxtNode* pNode = GetTxtNode(); + ULONG nHere = pNode->GetIndex(); + + // iterate over ring + SwPaM* pRingStart = pCrsr; + do + { + // ignore, if no mark + if( pCrsr->HasMark() ) + { + // check whether nHere is 'inside' pCrsr + SwPosition* pStart = pCrsr->Start(); + SwPosition* pEnd = pCrsr->End(); + if( ( nHere >= pStart->nNode.GetIndex() ) && + ( nHere <= pEnd->nNode.GetIndex() ) ) + { + // Yup, we are selected! + bRet = sal_True; + nStart = static_cast<sal_Int32>( + ( nHere > pStart->nNode.GetIndex() ) ? 0 + : pStart->nContent.GetIndex() ); + nEnd = static_cast<sal_Int32>( + ( nHere < pEnd->nNode.GetIndex() ) ? pNode->Len() + : pEnd->nContent.GetIndex() ); + } + // else: this PaM doesn't point to this paragraph + } + // else: this PaM is collapsed and doesn't select anything + + // next PaM in ring + pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); + } + while( !bRet && (pCrsr != pRingStart) ); + } + // else: nocursor -> no selection + + return bRet; +} + +SwPaM* SwAccessibleParagraph::GetCrsr() +{ + // get the cursor shell; if we don't have any, we don't have a + // cursor/selection either + SwPaM* pCrsr = NULL; + SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); + if( pCrsrShell != NULL ) + { + // get the selection, and test whether it affects our text node + pCrsr = pCrsrShell->GetCrsr( FALSE /* ??? */ ); + } + + return pCrsr; +} + +SwCrsrShell* SwAccessibleParagraph::GetCrsrShell() +{ + // first, get the view shell + DBG_ASSERT( GetMap() != NULL, "no map?" ); + ViewShell* pViewShell = GetMap()->GetShell(); + DBG_ASSERT( pViewShell != NULL, + "No view shell? Then what are you looking at?" ); + + SwCrsrShell* pCrsrShell = NULL; + + // see if our view shell is a cursor shell + if( pViewShell->ISA( SwCrsrShell ) ) + { + pCrsrShell = static_cast<SwCrsrShell*>( pViewShell ); + } + + return pCrsrShell; +} + +sal_Bool SwAccessibleParagraph::IsHeading() const +{ + const SwTxtNode *pTxtNd = GetTxtNode(); + return (pTxtNd->GetOutlineNum() && !pTxtNd->GetNum()); +} void SwAccessibleParagraph::SetStates( ::utl::AccessibleStateSetHelper& rStateSet ) @@ -167,6 +309,48 @@ void SwAccessibleParagraph::SetStates( // TODO: SELECTED } +void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired ) +{ + OUString sOldText( GetString() ); + + ClearPortionData(); + + const OUString& rText = GetString(); + + if( rText != sOldText ) + { + // The text is changed + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::ACCESSIBLE_TEXT_EVENT; + + FireAccessibleEvent( aEvent ); + } + else if( !bVisibleDataFired ) + { + FireVisibleDataEvent(); + } + + sal_Bool bIsNowHeading = IsHeading(); + if( bIsNowHeading != bIsHeading || rText != sOldText ) + { + bIsHeading = bIsNowHeading; + + OUString sNewDesc( GetDescription() ); + if( sNewDesc != sDesc ) + { + // The text is changed + AccessibleEventObject aEvent; + aEvent.EventId = AccessibleEventId::ACCESSIBLE_DESCRIPTION_EVENT; + aEvent.OldValue <<= sDesc; + aEvent.NewValue <<= sNewDesc; + sDesc = sNewDesc; + + FireAccessibleEvent( aEvent ); + } + } +} + + SwAccessibleParagraph::SwAccessibleParagraph( SwAccessibleMap *pMap, sal_Int32 nPara, @@ -176,10 +360,9 @@ SwAccessibleParagraph::SwAccessibleParagraph( { vos::OGuard aGuard(Application::GetSolarMutex()); - const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode(); - sal_uInt16 nResId = (pTxtNd->GetOutlineNum() && !pTxtNd->GetNum()) - ? STR_ACCESS_HEADING_NAME - : STR_ACCESS_PARAGRAPH_NAME; + bIsHeading = IsHeading(); + sal_uInt16 nResId = bIsHeading ? STR_ACCESS_HEADING_NAME + : STR_ACCESS_PARAGRAPH_NAME; OUString sArg( OUString::valueOf( nPara ) ); SetName( GetResource( nResId, &sArg ) ); } @@ -309,24 +492,6 @@ void SwAccessibleParagraph::GetTextBoundary( } } - -const SwTxtNode* SwAccessibleParagraph::GetTxtNode() -{ - const SwFrm* pFrm = GetFrm(); - DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" ); - - const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode(); - DBG_ASSERT( pNode != NULL, "A text frame without a text node." ); - - return pNode; -} - -OUString SwAccessibleParagraph::GetString() -{ - return GetPortionData().GetAccessibleString(); -} - - OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void) throw (::com::sun::star::uno::RuntimeException) { @@ -334,36 +499,10 @@ OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void) CHECK_FOR_DEFUNC( XAccessibleContext ); - const OUString& rText = GetString(); + if( !sDesc.getLength() ) + sDesc = GetDescription(); - // the description contains the first sentence up to - // MAX_DESC_TEXT_LEN characters (including the next full word) - Boundary aBound; - if( rText.getLength() > 0 ) - { - GetSentenceBoundary( aBound, rText, 0 ); - if( aBound.endPos > MAX_DESC_TEXT_LEN ) - { - GetWordBoundary( aBound, rText, MAX_DESC_TEXT_LEN ); - aBound.startPos = 0; - } - } - else - GetEmptyBoundary( aBound ); - OUString sArg1( rText.copy( aBound.startPos, aBound.endPos ) ); - - sal_uInt16 nResId; - const SwTxtNode* pTxtNd = GetTxtNode(); - if( pTxtNd->GetOutlineNum() && !pTxtNd->GetNum() ) - { - nResId = STR_ACCESS_HEADING_DESC; - } - else - { - nResId = STR_ACCESS_PARAGRAPH_DESC; - } - - return GetResource( nResId, &sArg1 ); + return sDesc; } Locale SAL_CALL SwAccessibleParagraph::getLocale (void) @@ -821,92 +960,3 @@ sal_Bool SwAccessibleParagraph::setText( const OUString& sText ) return replaceText(0, GetString().getLength(), sText); } - - - - - -SwCrsrShell* SwAccessibleParagraph::GetCrsrShell() -{ - // first, get the view shell - DBG_ASSERT( GetMap() != NULL, "no map?" ); - ViewShell* pViewShell = GetMap()->GetShell(); - DBG_ASSERT( pViewShell != NULL, - "No view shell? Then what are you looking at?" ); - - SwCrsrShell* pCrsrShell = NULL; - - // see if our view shell is a cursor shell - if( pViewShell->ISA( SwCrsrShell ) ) - { - pCrsrShell = static_cast<SwCrsrShell*>( pViewShell ); - } - - return pCrsrShell; -} - -SwPaM* SwAccessibleParagraph::GetCrsr() -{ - // get the cursor shell; if we don't have any, we don't have a - // cursor/selection either - SwPaM* pCrsr = NULL; - SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell(); - if( pCrsrShell != NULL ) - { - // get the selection, and test whether it affects our text node - pCrsr = pCrsrShell->GetCrsr( FALSE /* ??? */ ); - } - - return pCrsr; -} - -sal_Bool SwAccessibleParagraph::GetSelection( - sal_Int32& nStart, sal_Int32& nEnd) -{ - sal_Bool bRet = sal_False; - nStart = -1; - nEnd = -1; - - // get the selection, and test whether it affects our text node - SwPaM* pCrsr = GetCrsr(); - if( pCrsr != NULL ) - { - // get SwPosition for my node - const SwTxtNode* pNode = GetTxtNode(); - ULONG nHere = pNode->GetIndex(); - - // iterate over ring - SwPaM* pRingStart = pCrsr; - do - { - // ignore, if no mark - if( pCrsr->HasMark() ) - { - // check whether nHere is 'inside' pCrsr - SwPosition* pStart = pCrsr->Start(); - SwPosition* pEnd = pCrsr->End(); - if( ( nHere >= pStart->nNode.GetIndex() ) && - ( nHere <= pEnd->nNode.GetIndex() ) ) - { - // Yup, we are selected! - bRet = sal_True; - nStart = static_cast<sal_Int32>( - ( nHere > pStart->nNode.GetIndex() ) ? 0 - : pStart->nContent.GetIndex() ); - nEnd = static_cast<sal_Int32>( - ( nHere < pEnd->nNode.GetIndex() ) ? pNode->Len() - : pEnd->nContent.GetIndex() ); - } - // else: this PaM doesn't point to this paragraph - } - // else: this PaM is collapsed and doesn't select anything - - // next PaM in ring - pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() ); - } - while( !bRet && (pCrsr != pRingStart) ); - } - // else: nocursor -> no selection - - return bRet; -} diff --git a/sw/source/core/access/accpara.hxx b/sw/source/core/access/accpara.hxx index d939c4b7d4..27010fa624 100644 --- a/sw/source/core/access/accpara.hxx +++ b/sw/source/core/access/accpara.hxx @@ -2,9 +2,9 @@ * * $RCSfile: accpara.hxx,v $ * - * $Revision: 1.8 $ + * $Revision: 1.9 $ * - * last change: $Author: dvo $ $Date: 2002-03-01 16:07:57 $ + * last change: $Author: mib $ $Date: 2002-03-08 13:26:29 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -87,6 +87,8 @@ namespace com { namespace sun { namespace star { class SwAccessibleParagraph : public SwAccessibleContext, public drafts::com::sun::star::accessibility::XAccessibleEditableText { + ::rtl::OUString sDesc; + /// data for this paragraph's text portions; this contains the /// mapping from the core 'model string' to the accessible text /// string. @@ -94,17 +96,16 @@ class SwAccessibleParagraph : public SwAccessibleContext, /// Get/Clear/Has/UpdatePortionData() methods SwAccessiblePortionData* pPortionData; + sal_Bool bIsHeading; - // Set states for getAccessibleStateSet. - // This drived class additinaly sets MULTILINE(1), SELECTABLE(1) and - // SELECTED(0/1) - virtual void SetStates( ::utl::AccessibleStateSetHelper& rStateSet ); /// get the SwTxtNode (requires frame; check before) - const SwTxtNode* GetTxtNode(); + const SwTxtNode* GetTxtNode() const; /// get the (accessible) text string (requires frame; check before) - rtl::OUString GetString(); + ::rtl::OUString GetString(); + + ::rtl::OUString GetDescription(); /// determine whether the current selection. Fill the values with /// -1 if there is no selection in the this paragraph @@ -112,6 +113,17 @@ class SwAccessibleParagraph : public SwAccessibleContext, SwPaM* GetCrsr(); /// helper for GetSelection and getCaretPosition SwCrsrShell* GetCrsrShell(); /// helper for GetCrsr and setSelection + sal_Bool IsHeading() const; + +protected: + + // Set states for getAccessibleStateSet. + // This drived class additinaly sets MULTILINE(1), SELECTABLE(1) and + // SELECTED(0/1) + virtual void SetStates( ::utl::AccessibleStateSetHelper& rStateSet ); + + virtual void _InvalidateContent( sal_Bool bVisibleDataFired ); + public: SwAccessibleParagraph( SwAccessibleMap *pMap, sal_Int32 nPara, |