summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--svx/source/accessibility/AccessibleTextEventQueue.cxx154
-rw-r--r--svx/source/accessibility/AccessibleTextEventQueue.hxx141
-rw-r--r--svx/source/accessibility/AccessibleTextHelper.cxx560
-rwxr-xr-xsvx/source/accessibility/makefile.mk6
4 files changed, 675 insertions, 186 deletions
diff --git a/svx/source/accessibility/AccessibleTextEventQueue.cxx b/svx/source/accessibility/AccessibleTextEventQueue.cxx
new file mode 100644
index 000000000000..cdc643118394
--- /dev/null
+++ b/svx/source/accessibility/AccessibleTextEventQueue.cxx
@@ -0,0 +1,154 @@
+/*************************************************************************
+ *
+ * $RCSfile: AccessibleTextEventQueue.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: thb $ $Date: 2002-12-12 12:36:50 $
+ *
+ * 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): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SVX_ACCESSIBLE_TEXT_EVENT_QUEUE_HXX
+#include "AccessibleTextEventQueue.hxx"
+#endif
+
+#ifndef _SVX_UNOSHAPE_HXX
+#include "unoshape.hxx"
+#endif
+
+#ifndef _UNO_LINGU_HXX
+#include "unolingu.hxx"
+#endif
+
+#ifndef _SVX_UNOTEXT_HXX
+#include "unotext.hxx"
+#endif
+
+#include "unoedhlp.hxx"
+#include "unopracc.hxx"
+#include "svdmodel.hxx"
+#include "svdpntv.hxx"
+#include "editdata.hxx"
+#include "editeng.hxx"
+#include "editview.hxx"
+
+namespace accessibility
+{
+ //------------------------------------------------------------------------
+ //
+ // EventQueue implementation
+ //
+ //------------------------------------------------------------------------
+
+ AccessibleTextEventQueue::AccessibleTextEventQueue()
+ {
+ }
+
+ AccessibleTextEventQueue::~AccessibleTextEventQueue()
+ {
+ Clear();
+ }
+
+ void AccessibleTextEventQueue::Append( const SfxHint& rHint )
+ {
+ maEventQueue.push_back( new SfxHint( rHint ) );
+ }
+
+ void AccessibleTextEventQueue::Append( const SdrHint& rHint )
+ {
+ maEventQueue.push_back( new SdrHint( rHint ) );
+ }
+
+ void AccessibleTextEventQueue::Append( const SfxSimpleHint& rHint )
+ {
+ maEventQueue.push_back( new SfxSimpleHint( rHint ) );
+ }
+
+ void AccessibleTextEventQueue::Append( const TextHint& rHint )
+ {
+ maEventQueue.push_back( new TextHint( rHint ) );
+ }
+
+ void AccessibleTextEventQueue::Append( const SvxViewHint& rHint )
+ {
+ maEventQueue.push_back( new SvxViewHint( rHint ) );
+ }
+
+ void AccessibleTextEventQueue::Append( const SvxEditSourceHint& rHint )
+ {
+ maEventQueue.push_back( new SvxEditSourceHint( rHint ) );
+ }
+
+ ::std::auto_ptr< SfxHint > AccessibleTextEventQueue::PopFront()
+ {
+ ::std::auto_ptr< SfxHint > aRes( *(maEventQueue.begin()) );
+ maEventQueue.pop_front();
+ return aRes;
+ }
+
+ bool AccessibleTextEventQueue::IsEmpty() const
+ {
+ return maEventQueue.empty();
+ }
+
+ void AccessibleTextEventQueue::Clear()
+ {
+ // clear queue
+ while( !IsEmpty() )
+ PopFront();
+ }
+
+} // end of namespace accessibility
+
+//------------------------------------------------------------------------
diff --git a/svx/source/accessibility/AccessibleTextEventQueue.hxx b/svx/source/accessibility/AccessibleTextEventQueue.hxx
new file mode 100644
index 000000000000..7f6dd717978e
--- /dev/null
+++ b/svx/source/accessibility/AccessibleTextEventQueue.hxx
@@ -0,0 +1,141 @@
+/*************************************************************************
+ *
+ * $RCSfile: AccessibleTextEventQueue.hxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: thb $ $Date: 2002-12-12 12:36:51 $
+ *
+ * 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): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _SVX_ACCESSIBLE_TEXT_EVENT_QUEUE_HXX
+#define _SVX_ACCESSIBLE_TEXT_EVENT_QUEUE_HXX
+
+#include <memory>
+#include <list>
+
+#ifndef _SOLAR_H
+#include <tools/solar.h>
+#endif
+
+#ifndef _RTTI_HXX
+#include <tools/rtti.hxx>
+#endif
+
+class SfxHint;
+class SdrHint;
+class SfxSimpleHint;
+class TextHint;
+class SvxViewHint;
+class SvxEditSourceHint;
+
+namespace accessibility
+{
+ /** This class handles the notification events for the
+ AccessibleTextHelper class.
+
+ For various reasons, we cannot process EditEngine events as
+ they arrive, but have to queue and handle them in a batch.
+ */
+ class AccessibleTextEventQueue
+ {
+ public:
+ typedef ::std::list< SfxHint* > EventQueue;
+
+ AccessibleTextEventQueue();
+ ~AccessibleTextEventQueue();
+
+ /// Append event to end of queue
+ void Append( const SfxHint& rHint );
+ /// Append event to end of queue
+ void Append( const SdrHint& rHint );
+ /// Append event to end of queue
+ void Append( const SfxSimpleHint& rHint );
+ /// Append event to end of queue
+ void Append( const TextHint& rHint );
+ /// Append event to end of queue
+ void Append( const SvxViewHint& rHint );
+ /// Append event to end of queue
+ void Append( const SvxEditSourceHint& rHint );
+
+ /** Pop first queue element
+
+ return first queue element, ownership transfers to caller
+ */
+ ::std::auto_ptr< SfxHint > PopFront();
+
+ /** Apply functor to every queue member
+
+ @param rFunctor
+ Functor to apply. Functor receives queue element as
+ parameter: void func( const SfxHint* );
+ */
+ template < typename Functor > void ForEach( Functor& rFunctor ) const
+ {
+ ::std::for_each( maEventQueue.begin(), maEventQueue.end(), rFunctor );
+ }
+
+ /// Query whether queue is empty
+ bool IsEmpty() const;
+
+ /// Clear event queue
+ void Clear();
+
+ private:
+ EventQueue maEventQueue;
+ };
+
+} // end of namespace accessibility
+
+#endif /* _SVX_ACCESSIBLE_TEXT_EVENT_QUEUE_HXX */
diff --git a/svx/source/accessibility/AccessibleTextHelper.cxx b/svx/source/accessibility/AccessibleTextHelper.cxx
index 30dd0f6a476a..e49bf55a7995 100644
--- a/svx/source/accessibility/AccessibleTextHelper.cxx
+++ b/svx/source/accessibility/AccessibleTextHelper.cxx
@@ -2,9 +2,9 @@
*
* $RCSfile: AccessibleTextHelper.cxx,v $
*
- * $Revision: 1.30 $
+ * $Revision: 1.31 $
*
- * last change: $Author: thb $ $Date: 2002-11-29 17:56:25 $
+ * last change: $Author: thb $ $Date: 2002-12-12 12:36:51 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
@@ -70,6 +70,7 @@
#include <limits.h>
#include <memory>
#include <algorithm>
+#include <deque>
#ifndef _VOS_MUTEX_HXX_
#include <vos/mutex.hxx>
@@ -149,6 +150,10 @@
//
//------------------------------------------------------------------------
+#ifndef _SVX_ACCESSIBLE_TEXT_EVENT_QUEUE_HXX
+#include "AccessibleTextEventQueue.hxx"
+#endif
+
#ifndef _SVX_ACCESSILE_TEXT_HELPER_HXX_
#include "AccessibleTextHelper.hxx"
#endif
@@ -244,7 +249,7 @@ namespace accessibility
#endif
// checks all children for visibility, throws away invisible ones
- void UpdateVisibleChildren();
+ void UpdateVisibleChildren( bool bBroadcastEvents=true );
// check all children for changes in positon and size
void UpdateBoundRect();
@@ -255,6 +260,9 @@ namespace accessibility
private:
+ // Process event queue
+ void ProcessQueue();
+
// syntactic sugar for FireEvent
void GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, rNewValue ); }
void LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const { FireEvent( nEventId, uno::Any(), rOldValue ); }
@@ -263,8 +271,6 @@ namespace accessibility
void ShutdownEditSource() SAL_THROW((uno::RuntimeException));
void ParagraphsMoved( sal_Int32 nFirst, sal_Int32 nMiddle, sal_Int32 nLast );
- void ParagraphsInserted( sal_Int32 nFirst );
- void ParagraphsRemoved( sal_Int32 nFirst );
virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint );
@@ -300,6 +306,12 @@ namespace accessibility
// the object handling our children (guarded by solar mutex)
accessibility::AccessibleParaManager maParaManager;
+ // number of not-yet-closed event frames (BEGIN/END sequences) (guarded by solar mutex)
+ sal_Int32 maEventOpenFrames;
+
+ // Queued events from Notify() (guarded by solar mutex)
+ AccessibleTextEventQueue maEventQueue;
+
// spin lock to prevent notify in notify (guarded by solar mutex)
sal_Bool mbInNotify;
@@ -332,6 +344,7 @@ namespace accessibility
mnFirstVisibleChild( -1 ),
mnLastVisibleChild( -2 ),
mnStartIndex( 0 ),
+ maEventOpenFrames( 0 ),
mbInNotify( sal_False ),
mbGroupHasFocus( sal_False ),
mbThisHasFocus( sal_False ),
@@ -696,7 +709,7 @@ namespace accessibility
UpdateBoundRect();
}
- void AccessibleTextHelper_Impl::UpdateVisibleChildren()
+ void AccessibleTextHelper_Impl::UpdateVisibleChildren( bool bBroadcastEvents )
{
try
{
@@ -748,7 +761,8 @@ namespace accessibility
accessibility::AccessibleParaManager::WeakChild aChild( maParaManager.GetChild(nCurrPara) );
if( aChild.second.Width == 0 &&
aChild.second.Height == 0 &&
- mxFrontEnd.is() )
+ mxFrontEnd.is() &&
+ bBroadcastEvents )
{
GotPropertyEvent( uno::makeAny( maParaManager.CreateChild( nCurrPara - mnFirstVisibleChild,
mxFrontEnd, GetEditSource(), nCurrPara ).first ),
@@ -760,8 +774,9 @@ namespace accessibility
// not or no longer visible
if( maParaManager.IsReferencable( nCurrPara ) )
{
- LostPropertyEvent( uno::makeAny( maParaManager.GetChild( nCurrPara ).first.get().getRef() ),
- AccessibleEventId::ACCESSIBLE_CHILD_EVENT );
+ if( bBroadcastEvents )
+ LostPropertyEvent( uno::makeAny( maParaManager.GetChild( nCurrPara ).first.get().getRef() ),
+ AccessibleEventId::ACCESSIBLE_CHILD_EVENT );
// clear reference
maParaManager.Release( nCurrPara );
@@ -779,7 +794,8 @@ namespace accessibility
maParaManager.SetNum(0);
// lost all children
- FireEvent(AccessibleEventId::ACCESSIBLE_ALL_CHILDREN_CHANGED_EVENT);
+ if( bBroadcastEvents )
+ FireEvent(AccessibleEventId::ACCESSIBLE_ALL_CHILDREN_CHANGED_EVENT);
}
}
@@ -933,76 +949,323 @@ namespace accessibility
}
}
- void AccessibleTextHelper_Impl::ParagraphsInserted( sal_Int32 nFirst )
+ /** functor processing queue events
+
+ Reacts on TEXT_HINT_PARAINSERTED/REMOVED events and stores
+ their content
+ */
+ class AccessibleTextHelper_QueueFunctor : public ::std::unary_function< const SfxHint*, void >
{
- const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
- const sal_Int32 nOldNumParas( maParaManager.GetNum() );
- const sal_Int32 nLast( nParas - 1 );
+ public:
+ AccessibleTextHelper_QueueFunctor() :
+ mnParasChanged( 0 ),
+ mnParaIndex(-1),
+ mnHintId(-1)
+ {}
+ void operator()( const SfxHint* pEvent )
+ {
+ if( pEvent &&
+ mnParasChanged != -1 )
+ {
+ // determine hint type
+ const TextHint* pTextHint = PTR_CAST( TextHint, pEvent );
+ const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, pEvent );
- // resize child vector to the current child count
- maParaManager.SetNum( nParas );
+ if( !pEditSourceHint && pTextHint &&
+ (pTextHint->GetId() == TEXT_HINT_PARAINSERTED ||
+ pTextHint->GetId() == TEXT_HINT_PARAREMOVED ) )
+ {
+ if( pTextHint->GetValue() == EE_PARA_ALL )
+ {
+ mnParasChanged = -1;
+ }
+ else
+ {
+ mnHintId = pTextHint->GetId();
+ mnParaIndex = pTextHint->GetValue();
+ ++mnParasChanged;
+ }
+ }
+ }
+ }
- if( nFirst < nOldNumParas && nFirst < nParas && nLast < nParas )
- {
- // since we have no "paragraph index
- // changed" event on UAA, remove
- // [first,last] and insert again later (in
- // UpdateVisibleChildren)
+ /** Query number of paragraphs changed during queue processing.
- // move successors of inserted paragraph one position further
- //maParaManager.MoveRightFrom( pTextHint->GetValue() );
+ @return number of changed paragraphs, -1 for
+ "every paragraph changed"
+ */
+ int GetNumberOfParasChanged() { return mnParasChanged; }
+ /** Query index of last added/removed paragraph
- // send CHILD_EVENT to affected children
- ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
- ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
+ @return index of lastly added paragraphs, -1 for none
+ added so far.
+ */
+ int GetParaIndex() { return mnParaIndex; }
+ /** Query hint id of last interesting event
- ::std::advance( begin, nFirst );
- ::std::advance( end, nLast+1 );
+ @return hint id of last interesting event (REMOVED/INSERTED).
+ */
+ int GetHintId() { return mnHintId; }
- // TODO: maybe optimize here in the following way. If the
- // number of removed children exceeds a certain threshold,
- // use ACCESSIBLE_ALL_CHILDREN_CHANGED_EVENT
- AccessibleTextHelper_LostChildEvent aFunctor( *this );
- ::std::for_each( begin, end, aFunctor );
+ private:
+ /** number of paragraphs changed during queue processing. -1 for
+ "every paragraph changed"
+ */
+ int mnParasChanged;
+ /// index of paragraph added/removed last
+ int mnParaIndex;
+ /// TextHint ID (removed/inserted) of last interesting event
+ int mnHintId;
+ };
- // release everything from the insertion position until the end
- // #102235# Perform the release after the CHILD_EVENT notification
- maParaManager.Release(nFirst, nLast+1);
+ void AccessibleTextHelper_Impl::ProcessQueue()
+ {
+ // inspect queue for paragraph insert/remove events. If there
+ // is exactly _one_ of those in the queue, and the number of
+ // paragraphs has changed by exactly one, use that event to
+ // determine a priori which paragraph was added/removed. This
+ // is necessary, since I must sync right here with the
+ // EditEngine state (number of paragraphs etc.), since I'm
+ // potentially sending listener events right away.
+ AccessibleTextHelper_QueueFunctor aFunctor;
+ maEventQueue.ForEach( aFunctor );
+
+ const sal_Int32 nNewParas( GetTextForwarder().GetParagraphCount() );
+ const sal_Int32 nCurrParas( maParaManager.GetNum() );
+
+ // whether every paragraph already is updated (no need to
+ // repeat that later on, e.g. for PARA_MOVED events)
+ bool bEverythingUpdated( false );
+
+ if( labs( nNewParas - nCurrParas ) == 1 &&
+ aFunctor.GetNumberOfParasChanged() == 1 )
+ {
+ // #103483# Exactly one paragraph added/removed. This is
+ // the normal case, optimize event handling here.
+
+ if( aFunctor.GetHintId() == TEXT_HINT_PARAINSERTED )
+ {
+ // update num of paras
+ maParaManager.SetNum( nNewParas );
+
+ // release everything from the insertion position until the end
+ maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
+
+ // TODO: Clarify whether this behaviour _really_ saves
+ // anybody anything!
+ // update children, _don't_ broadcast
+ UpdateVisibleChildren( false );
+ UpdateBoundRect();
+
+ // send insert event
+ AccessibleParaManager::WeakPara::HardRefType aChild( maParaManager.GetChild( aFunctor.GetParaIndex() ).first.get() );
+ GotPropertyEvent( uno::makeAny( aChild.getRef() ),
+ AccessibleEventId::ACCESSIBLE_CHILD_EVENT );
+ }
+ else if( aFunctor.GetHintId() == TEXT_HINT_PARAREMOVED )
+ {
+ ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
+ ::std::advance( begin, aFunctor.GetParaIndex() );
+ ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
+ ::std::advance( end, 1 );
+
+ // send remove event
+ AccessibleTextHelper_LostChildEvent aLooseFunctor( *this );
+ ::std::for_each( begin, end, aLooseFunctor );
+
+ // release everything from the remove position until the end
+ // #102235# Perform the release after the CHILD_EVENT notification
+ maParaManager.Release(aFunctor.GetParaIndex(), nCurrParas);
+
+ // update num of paras
+ maParaManager.SetNum( nNewParas );
+
+ // TODO: Clarify whether this behaviour _really_ saves
+ // anybody anything!
+ // update children, _don't_ broadcast
+ UpdateVisibleChildren( false );
+ UpdateBoundRect();
+ }
+#ifdef DBG_UTIL
+ else
+ DBG_ERROR("AccessibleTextHelper_Impl::ProcessQueue() invalid hint id");
+#endif
}
- }
+ else if( nNewParas != nCurrParas )
+ {
+ // number of paragraphs somehow changed - but we have no
+ // chance determining how. Thus, throw away everything and
+ // create from scratch.
+ FireEvent(AccessibleEventId::ACCESSIBLE_ALL_CHILDREN_CHANGED_EVENT);
- void AccessibleTextHelper_Impl::ParagraphsRemoved( sal_Int32 nFirst )
- {
- const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
- const sal_Int32 nLast( maParaManager.GetNum() - 1 );
+ // release all paras
+ maParaManager.Release(0, nCurrParas);
- // since we have no "paragraph index
- // changed" event on UAA, remove
- // [first,last] and insert again later (in
- // UpdateVisibleChildren)
+ // update num of paras
+ maParaManager.SetNum( nNewParas );
- // move successors of removed paragraph one position closer
- // maParaManager.MoveLeftFrom( pTextHint->GetValue() );
+ // create from scratch
+ UpdateVisibleChildren();
+ UpdateBoundRect();
- // send CHILD_EVENT to affected children
- ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator begin = maParaManager.begin();
- ::accessibility::AccessibleParaManager::VectorOfChildren::const_iterator end = begin;
+ // no need for further updates later on
+ bEverythingUpdated = true;
+ }
- ::std::advance( begin, nFirst );
- ::std::advance( end, nLast+1 );
+ while( !maEventQueue.IsEmpty() )
+ {
+ ::std::auto_ptr< SfxHint > pHint( maEventQueue.PopFront() );
+ if( pHint.get() )
+ {
+ const SfxHint& rHint = *(pHint.get());
- // TODO: maybe optimize here in the following way. If the
- // number of removed children exceeds a certain threshold,
- // use ACCESSIBLE_ALL_CHILDREN_CHANGED_EVENT
- AccessibleTextHelper_LostChildEvent aFunctor( *this );
- ::std::for_each( begin, end, aFunctor );
+ // determine hint type
+ const SdrHint* pSdrHint = PTR_CAST( SdrHint, &rHint );
+ const SfxSimpleHint* pSimpleHint = PTR_CAST( SfxSimpleHint, &rHint );
+ const TextHint* pTextHint = PTR_CAST( TextHint, &rHint );
+ const SvxViewHint* pViewHint = PTR_CAST( SvxViewHint, &rHint );
+ const SvxEditSourceHint* pEditSourceHint = PTR_CAST( SvxEditSourceHint, &rHint );
+
+ try
+ {
+ const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
- // release everything from the remove position until the end
- // #102235# Perform the release after the CHILD_EVENT notification
- maParaManager.Release(nFirst, nLast+1);
+ if( pEditSourceHint )
+ {
+ switch( pEditSourceHint->GetId() )
+ {
+ case EDITSOURCE_HINT_PARASMOVED:
+ {
+ DBG_ASSERT( pEditSourceHint->GetStartValue() < GetTextForwarder().GetParagraphCount() &&
+ pEditSourceHint->GetEndValue() < GetTextForwarder().GetParagraphCount(),
+ "AccessibleTextHelper_Impl::NotifyHdl: Invalid notification");
+
+ if( !bEverythingUpdated )
+ {
+ ParagraphsMoved(pEditSourceHint->GetStartValue(),
+ pEditSourceHint->GetValue(),
+ pEditSourceHint->GetEndValue());
+
+ // in all cases, check visibility afterwards.
+ UpdateVisibleChildren();
+ }
+ break;
+ }
+
+ case EDITSOURCE_HINT_SELECTIONCHANGED:
+ // notify listeners
+ try
+ {
+ UpdateSelection();
+ }
+ // maybe we're not in edit mode (this is not an error)
+ catch( const uno::Exception& ) {}
+ break;
+ }
+ }
+ else if( pTextHint )
+ {
+ switch( pTextHint->GetId() )
+ {
+ case TEXT_HINT_MODIFIED:
+ {
+ // notify listeners
+ sal_Int32 nPara( pTextHint->GetValue() );
+ if( nPara == static_cast<sal_Int32>(EE_PARA_ALL) )
+ maParaManager.FireEvent( 0, GetTextForwarder().GetParagraphCount(), AccessibleEventId::ACCESSIBLE_TEXT_EVENT );
+ else
+ if( nPara < nParas )
+ maParaManager.FireEvent( nPara, AccessibleEventId::ACCESSIBLE_TEXT_EVENT );
+ break;
+ }
+
+ case TEXT_HINT_PARAINSERTED:
+ // already happened above
+ break;
+
+ case TEXT_HINT_PARAREMOVED:
+ // already happened above
+ break;
+
+ case TEXT_HINT_TEXTHEIGHTCHANGED:
+ // visibility changed, done below
+ break;
+
+ case TEXT_HINT_VIEWSCROLLED:
+ // visibility changed, done below
+ break;
+ }
- // resize child vector to the current child count
- maParaManager.SetNum( nParas );
+ // in all cases, check visibility afterwards.
+ UpdateVisibleChildren();
+ UpdateBoundRect();
+ }
+ else if( pViewHint )
+ {
+ switch( pViewHint->GetId() )
+ {
+ case SVX_HINT_VIEWCHANGED:
+ // just check visibility
+ UpdateVisibleChildren();
+ UpdateBoundRect();
+ break;
+ }
+ }
+ else if( pSdrHint )
+ {
+ switch( pSdrHint->GetKind() )
+ {
+ case HINT_BEGEDIT:
+ {
+ // change children state
+ maParaManager.SetActive();
+
+ // per definition, edit mode text has the focus
+ SetFocus( sal_True );
+ break;
+ }
+
+ case HINT_ENDEDIT:
+ // focused child now looses focus
+ ESelection aSelection;
+ if( GetEditViewForwarder().GetSelection( aSelection ) )
+ SetChildFocus( aSelection.nEndPara, sal_False );
+
+ // change children state
+ maParaManager.SetActive( sal_False );
+
+ maLastSelection = ESelection( EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND,
+ EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND);
+ break;
+ }
+ }
+ // it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
+ else if( pSimpleHint )
+ {
+ switch( pSimpleHint->GetId() )
+ {
+ case SFX_HINT_DYING:
+ // edit source is dying under us, become defunc then
+ try
+ {
+ // make edit source inaccessible
+ // Note: cannot destroy it here, since we're called from there!
+ ShutdownEditSource();
+ }
+ catch( const uno::Exception& ) {}
+
+ break;
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+#ifdef DBG_UTIL
+ OSL_TRACE("AccessibleTextHelper_Impl::ProcessQueue: Unhandled exception.");
+#endif
+ }
+ }
+ }
}
void AccessibleTextHelper_Impl::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
@@ -1025,154 +1288,83 @@ namespace accessibility
try
{
- const sal_Int32 nParas = GetTextForwarder().GetParagraphCount();
-
- // precondition: edit engine and para manager consistent
-
- /* The problem here is the fact that the EditEngine events
- * do not always arrive in a logical order. For example,
- * when inserting a paragraph by pressing return at the
- * end of a line, currently the TEXT_MODIFIED hint arrives
- * before the PARAGRAPH_INSERTED hint. Therefore, we have
- * to update our paragraph count proactively here.
- */
- sal_Int32 nFirstParaInsert( 0 ); // default range is pessimization, don't know where to add
- if( (!pEditSourceHint && pTextHint && pTextHint->GetId() == TEXT_HINT_PARAINSERTED) )
- nFirstParaInsert = pTextHint->GetValue() == EE_PARA_ALL ? 0 : pTextHint->GetValue();
-
- if( nFirstParaInsert != 0 ||
- maParaManager.GetNum() < static_cast<sal_uInt32>(nParas) )
- {
- ParagraphsInserted( nFirstParaInsert );
- UpdateVisibleChildren();
- UpdateBoundRect();
- }
-
- sal_Int32 nFirstParaRemove( 0 ); // default range is pessimization, don't know where to add
- if( (!pEditSourceHint && pTextHint && pTextHint->GetId() == TEXT_HINT_PARAREMOVED) )
- nFirstParaRemove = pTextHint->GetValue() == EE_PARA_ALL ? 0 : pTextHint->GetValue();
-
- if( nFirstParaRemove != 0 ||
- maParaManager.GetNum() > static_cast<sal_uInt32>(nParas) )
- {
- // remove excess paragraphs (range is pessimization, don't know where to remove)
- ParagraphsRemoved( nFirstParaRemove );
- UpdateVisibleChildren();
- UpdateBoundRect();
- }
-
+ // Process notification event
if( pEditSourceHint )
{
- switch( pEditSourceHint->GetId() )
- {
- case EDITSOURCE_HINT_PARASMOVED:
- {
- DBG_ASSERT( pEditSourceHint->GetStartValue() < GetTextForwarder().GetParagraphCount() &&
- pEditSourceHint->GetEndValue() < GetTextForwarder().GetParagraphCount(),
- "AccessibleTextHelper_Impl::NotifyHdl: Invalid notification");
-
- ParagraphsMoved(pEditSourceHint->GetStartValue(),
- pEditSourceHint->GetValue(),
- pEditSourceHint->GetEndValue());
-
- // in all cases, check visibility afterwards.
- UpdateVisibleChildren();
-
- break;
- }
-
- case EDITSOURCE_HINT_SELECTIONCHANGED:
- // notify listeners
- try
- {
- UpdateSelection();
- }
- // maybe we're not in edit mode (this is not an error)
- catch( const uno::Exception& ) {}
- break;
- }
+ maEventQueue.Append( *pEditSourceHint );
}
else if( pTextHint )
{
switch( pTextHint->GetId() )
{
- case TEXT_HINT_MODIFIED:
- {
- // notify listeners
- sal_Int32 nPara( pTextHint->GetValue() );
- if( nPara == static_cast<sal_Int32>(EE_PARA_ALL) )
- maParaManager.FireEvent( 0, GetTextForwarder().GetParagraphCount(), AccessibleEventId::ACCESSIBLE_TEXT_EVENT );
- else
- if( nPara < nParas )
- maParaManager.FireEvent( nPara, AccessibleEventId::ACCESSIBLE_TEXT_EVENT );
- break;
- }
+ case TEXT_HINT_BLOCKNOTIFICATION_END:
+ case TEXT_HINT_INPUT_END:
+ --maEventOpenFrames;
- case TEXT_HINT_PARAINSERTED:
- // already happened above
- break;
-
- case TEXT_HINT_PARAREMOVED:
- // already happened above
+ if( maEventOpenFrames == 0 )
+ {
+ // #103483#
+ /* All information should have arrived
+ * now, process queue. As stated in the
+ * above bug, we can often avoid throwing
+ * away all paragraphs by looking forward
+ * in the event queue (searching for
+ * PARAINSERT/REMOVE events). Furthermore,
+ * processing the event queue only at the
+ * end of an interaction cycle, ensures
+ * that the EditEngine state and the
+ * AccessibleText state are the same
+ * (well, mostly. If there are _multiple_
+ * interaction cycles in the EE queues, it
+ * can still happen that EE state is
+ * different. That's so to say broken by
+ * design with that delayed EE event
+ * concept).
+ */
+ ProcessQueue();
+ }
break;
- case TEXT_HINT_TEXTHEIGHTCHANGED:
- break;
+ case TEXT_HINT_BLOCKNOTIFICATION_START:
+ case TEXT_HINT_INPUT_START:
+ ++maEventOpenFrames;
- case TEXT_HINT_VIEWSCROLLED:
+ default:
+ maEventQueue.Append( *pTextHint );
break;
}
-
- // in all cases, check visibility afterwards.
- UpdateVisibleChildren();
- UpdateBoundRect();
}
else if( pViewHint )
{
- switch( pViewHint->GetId() )
- {
- case SVX_HINT_VIEWCHANGED:
- // just check visibility
- UpdateVisibleChildren();
- UpdateBoundRect();
- break;
- }
+ maEventQueue.Append( *pViewHint );
+
+ // process visibility right away, if not within an
+ // open EE notification frame. Otherwise, event
+ // processing would be delayed until next EE
+ // notification sequence.
+ if( maEventOpenFrames == 0 )
+ ProcessQueue();
}
else if( pSdrHint )
{
- switch( pSdrHint->GetKind() )
- {
- case HINT_BEGEDIT:
- {
- // change children state
- maParaManager.SetActive();
-
- // per definition, edit mode text has the focus
- SetFocus( sal_True );
- break;
- }
-
- case HINT_ENDEDIT:
- // focused child now looses focus
- ESelection aSelection;
- if( GetEditViewForwarder().GetSelection( aSelection ) )
- SetChildFocus( aSelection.nEndPara, sal_False );
-
- // change children state
- maParaManager.SetActive( sal_False );
-
- maLastSelection = ESelection( EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND,
- EE_PARA_NOT_FOUND, EE_PARA_NOT_FOUND);
- break;
- }
+ maEventQueue.Append( *pSdrHint );
+
+ // process drawing layer events right away, if not
+ // within an open EE notification frame. Otherwise,
+ // event processing would be delayed until next EE
+ // notification sequence.
+ if( maEventOpenFrames == 0 )
+ ProcessQueue();
}
// it's VITAL to keep the SfxSimpleHint last! It's the base of some classes above!
else if( pSimpleHint )
{
+ // handle this event _at once_, because after that, objects are invalid
switch( pSimpleHint->GetId() )
{
case SFX_HINT_DYING:
// edit source is dying under us, become defunc then
+ maEventQueue.Clear();
try
{
// make edit source inaccessible
diff --git a/svx/source/accessibility/makefile.mk b/svx/source/accessibility/makefile.mk
index 5d07ff8ef1db..87c4c16cee8c 100755
--- a/svx/source/accessibility/makefile.mk
+++ b/svx/source/accessibility/makefile.mk
@@ -2,9 +2,9 @@
#
# $RCSfile: makefile.mk,v $
#
-# $Revision: 1.15 $
+# $Revision: 1.16 $
#
-# last change: $Author: oj $ $Date: 2002-07-30 10:32:22 $
+# last change: $Author: thb $ $Date: 2002-12-12 12:36:51 $
#
# The Contents of this file are made available subject to the terms of
# either of the following licenses
@@ -91,6 +91,7 @@ CXXFILES = \
AccessibleSelectionBase.cxx \
AccessibleShapeTreeInfo.cxx \
AccessibleTextHelper.cxx \
+ AccessibleTextEventQueue.cxx \
AccessibleStaticTextBase.cxx \
AccessibleParaManager.cxx \
AccessibleEditableTextPara.cxx \
@@ -115,6 +116,7 @@ SLOFILES = \
$(SLO)$/AccessibleShapeInfo.obj \
$(SLO)$/AccessibleShapeTreeInfo.obj \
$(SLO)$/AccessibleTextHelper.obj \
+ $(SLO)$/AccessibleTextEventQueue.obj \
$(SLO)$/AccessibleStaticTextBase.obj \
$(SLO)$/AccessibleParaManager.obj \
$(SLO)$/AccessibleEditableTextPara.obj \