LCOV - code coverage report
Current view: top level - libreoffice/framework/source/fwe/helper - undomanagerhelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 38 437 8.7 %
Date: 2012-12-27 Functions: 12 87 13.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "framework/undomanagerhelper.hxx"
      22             : 
      23             : #include <com/sun/star/lang/XComponent.hpp>
      24             : 
      25             : #include <cppuhelper/interfacecontainer.hxx>
      26             : #include <cppuhelper/exc_hlp.hxx>
      27             : #include <comphelper/flagguard.hxx>
      28             : #include <comphelper/asyncnotification.hxx>
      29             : #include <svl/undo.hxx>
      30             : #include <tools/diagnose_ex.h>
      31             : #include <osl/conditn.hxx>
      32             : 
      33             : #include <stack>
      34             : #include <queue>
      35             : #include <boost/function.hpp>
      36             : 
      37             : //......................................................................................................................
      38             : namespace framework
      39             : {
      40             : //......................................................................................................................
      41             : 
      42             :     /** === begin UNO using === **/
      43             :     using ::com::sun::star::uno::Reference;
      44             :     using ::com::sun::star::uno::XInterface;
      45             :     using ::com::sun::star::uno::UNO_QUERY;
      46             :     using ::com::sun::star::uno::UNO_QUERY_THROW;
      47             :     using ::com::sun::star::uno::UNO_SET_THROW;
      48             :     using ::com::sun::star::uno::Exception;
      49             :     using ::com::sun::star::uno::RuntimeException;
      50             :     using ::com::sun::star::uno::Any;
      51             :     using ::com::sun::star::uno::makeAny;
      52             :     using ::com::sun::star::uno::Sequence;
      53             :     using ::com::sun::star::uno::Type;
      54             :     using ::com::sun::star::document::XUndoManagerListener;
      55             :     using ::com::sun::star::document::UndoManagerEvent;
      56             :     using ::com::sun::star::document::EmptyUndoStackException;
      57             :     using ::com::sun::star::document::UndoContextNotClosedException;
      58             :     using ::com::sun::star::document::UndoFailedException;
      59             :     using ::com::sun::star::util::NotLockedException;
      60             :     using ::com::sun::star::lang::EventObject;
      61             :     using ::com::sun::star::document::XUndoAction;
      62             :     using ::com::sun::star::lang::XComponent;
      63             :     using ::com::sun::star::document::XUndoManager;
      64             :     using ::com::sun::star::util::InvalidStateException;
      65             :     using ::com::sun::star::lang::IllegalArgumentException;
      66             :     using ::com::sun::star::util::XModifyListener;
      67             :     /** === end UNO using === **/
      68             :     using ::svl::IUndoManager;
      69             : 
      70             :     //==================================================================================================================
      71             :     //= UndoActionWrapper
      72             :     //==================================================================================================================
      73             :     class UndoActionWrapper : public SfxUndoAction
      74             :     {
      75             :     public:
      76             :                             UndoActionWrapper(
      77             :                                 Reference< XUndoAction > const& i_undoAction
      78             :                             );
      79             :         virtual             ~UndoActionWrapper();
      80             : 
      81             :         virtual rtl::OUString GetComment() const;
      82             :         virtual void        Undo();
      83             :         virtual void        Redo();
      84             :         virtual sal_Bool    CanRepeat(SfxRepeatTarget&) const;
      85             : 
      86             :     private:
      87             :         const Reference< XUndoAction >  m_xUndoAction;
      88             :     };
      89             : 
      90             :     //------------------------------------------------------------------------------------------------------------------
      91           0 :     UndoActionWrapper::UndoActionWrapper( Reference< XUndoAction > const& i_undoAction )
      92             :         :SfxUndoAction()
      93           0 :         ,m_xUndoAction( i_undoAction )
      94             :     {
      95           0 :         ENSURE_OR_THROW( m_xUndoAction.is(), "illegal undo action" );
      96           0 :     }
      97             : 
      98             :     //------------------------------------------------------------------------------------------------------------------
      99           0 :     UndoActionWrapper::~UndoActionWrapper()
     100             :     {
     101             :         try
     102             :         {
     103           0 :             Reference< XComponent > xComponent( m_xUndoAction, UNO_QUERY );
     104           0 :             if ( xComponent.is() )
     105           0 :                 xComponent->dispose();
     106             :         }
     107           0 :         catch( const Exception& )
     108             :         {
     109             :             DBG_UNHANDLED_EXCEPTION();
     110             :         }
     111           0 :     }
     112             : 
     113             :     //------------------------------------------------------------------------------------------------------------------
     114           0 :     rtl::OUString UndoActionWrapper::GetComment() const
     115             :     {
     116           0 :         rtl::OUString sComment;
     117             :         try
     118             :         {
     119           0 :             sComment = m_xUndoAction->getTitle();
     120             :         }
     121           0 :         catch( const Exception& )
     122             :         {
     123             :             DBG_UNHANDLED_EXCEPTION();
     124             :         }
     125           0 :         return sComment;
     126             :     }
     127             : 
     128             :     //------------------------------------------------------------------------------------------------------------------
     129           0 :     void UndoActionWrapper::Undo()
     130             :     {
     131           0 :         m_xUndoAction->undo();
     132           0 :     }
     133             : 
     134             :     //------------------------------------------------------------------------------------------------------------------
     135           0 :     void UndoActionWrapper::Redo()
     136             :     {
     137           0 :         m_xUndoAction->redo();
     138           0 :     }
     139             : 
     140             :     //------------------------------------------------------------------------------------------------------------------
     141           0 :     sal_Bool UndoActionWrapper::CanRepeat(SfxRepeatTarget&) const
     142             :     {
     143           0 :         return sal_False;
     144             :     }
     145             : 
     146             :     //==================================================================================================================
     147             :     //= UndoManagerRequest
     148             :     //==================================================================================================================
     149             :     class UndoManagerRequest : public ::comphelper::AnyEvent
     150             :     {
     151             :     public:
     152           0 :         UndoManagerRequest( ::boost::function0< void > const& i_request )
     153             :             :m_request( i_request )
     154             :             ,m_caughtException()
     155           0 :             ,m_finishCondition()
     156             :         {
     157           0 :             m_finishCondition.reset();
     158           0 :         }
     159             : 
     160           0 :         void execute()
     161             :         {
     162             :             try
     163             :             {
     164           0 :                 m_request();
     165             :             }
     166           0 :             catch( const Exception& )
     167             :             {
     168           0 :                 m_caughtException = ::cppu::getCaughtException();
     169             :             }
     170           0 :             m_finishCondition.set();
     171           0 :         }
     172             : 
     173           0 :         void wait()
     174             :         {
     175           0 :             m_finishCondition.wait();
     176           0 :             if ( m_caughtException.hasValue() )
     177           0 :                 ::cppu::throwException( m_caughtException );
     178           0 :         }
     179             : 
     180           0 :         void cancel( const Reference< XInterface >& i_context )
     181             :         {
     182             :             m_caughtException <<= RuntimeException(
     183             :                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Concurrency error: an ealier operation on the stack failed." ) ),
     184             :                 i_context
     185           0 :             );
     186           0 :             m_finishCondition.set();
     187           0 :         }
     188             : 
     189             :     protected:
     190           0 :         ~UndoManagerRequest()
     191           0 :         {
     192           0 :         }
     193             : 
     194             :     private:
     195             :         ::boost::function0< void >  m_request;
     196             :         Any                         m_caughtException;
     197             :         ::osl::Condition            m_finishCondition;
     198             :     };
     199             : 
     200             :     //------------------------------------------------------------------------------------------------------------------
     201             : 
     202             :     //==================================================================================================================
     203             :     //= UndoManagerHelper_Impl
     204             :     //==================================================================================================================
     205             :     class UndoManagerHelper_Impl : public SfxUndoListener
     206             :     {
     207             :     private:
     208             :         ::osl::Mutex                        m_aMutex;
     209             :         ::osl::Mutex                        m_aQueueMutex;
     210             :         bool                                m_disposed;
     211             :         bool                                m_bAPIActionRunning;
     212             :         bool                                m_bProcessingEvents;
     213             :         sal_Int32                           m_nLockCount;
     214             :         ::cppu::OInterfaceContainerHelper   m_aUndoListeners;
     215             :         ::cppu::OInterfaceContainerHelper   m_aModifyListeners;
     216             :         IUndoManagerImplementation&         m_rUndoManagerImplementation;
     217             :         ::std::stack< bool >                m_aContextVisibilities;
     218             : #if OSL_DEBUG_LEVEL > 0
     219             :         ::std::stack< bool >                m_aContextAPIFlags;
     220             : #endif
     221             :         ::std::queue< ::rtl::Reference< UndoManagerRequest > >
     222             :                                             m_aEventQueue;
     223             : 
     224             :     public:
     225           0 :         ::osl::Mutex&   getMutex() { return m_aMutex; }
     226             : 
     227             :     public:
     228           1 :         UndoManagerHelper_Impl( IUndoManagerImplementation& i_undoManagerImpl )
     229             :             :m_aMutex()
     230             :             ,m_aQueueMutex()
     231             :             ,m_disposed( false )
     232             :             ,m_bAPIActionRunning( false )
     233             :             ,m_bProcessingEvents( false )
     234             :             ,m_nLockCount( 0 )
     235             :             ,m_aUndoListeners( m_aMutex )
     236             :             ,m_aModifyListeners( m_aMutex )
     237           1 :             ,m_rUndoManagerImplementation( i_undoManagerImpl )
     238             :         {
     239           1 :             getUndoManager().AddUndoListener( *this );
     240           1 :         }
     241             : 
     242           0 :         virtual ~UndoManagerHelper_Impl()
     243           0 :         {
     244           0 :         }
     245             : 
     246             :         //..............................................................................................................
     247           2 :         IUndoManager& getUndoManager() const
     248             :         {
     249           2 :             return m_rUndoManagerImplementation.getImplUndoManager();
     250             :         }
     251             : 
     252             :         //..............................................................................................................
     253           1 :         Reference< XUndoManager > getXUndoManager() const
     254             :         {
     255           1 :             return m_rUndoManagerImplementation.getThis();
     256             :         }
     257             : 
     258             :         // SfxUndoListener
     259             :         virtual void actionUndone( const String& i_actionComment );
     260             :         virtual void actionRedone( const String& i_actionComment );
     261             :         virtual void undoActionAdded( const String& i_actionComment );
     262             :         virtual void cleared();
     263             :         virtual void clearedRedo();
     264             :         virtual void resetAll();
     265             :         virtual void listActionEntered( const String& i_comment );
     266             :         virtual void listActionLeft( const String& i_comment );
     267             :         virtual void listActionLeftAndMerged();
     268             :         virtual void listActionCancelled();
     269             :         virtual void undoManagerDying();
     270             : 
     271             :         // public operations
     272             :         void disposing();
     273             : 
     274             :         void enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden, IMutexGuard& i_instanceLock );
     275             :         void leaveUndoContext( IMutexGuard& i_instanceLock );
     276             :         void addUndoAction( const Reference< XUndoAction >& i_action, IMutexGuard& i_instanceLock );
     277             :         void undo( IMutexGuard& i_instanceLock );
     278             :         void redo( IMutexGuard& i_instanceLock );
     279             :         void clear( IMutexGuard& i_instanceLock );
     280             :         void clearRedo( IMutexGuard& i_instanceLock );
     281             :         void reset( IMutexGuard& i_instanceLock );
     282             : 
     283             :         void lock();
     284             :         void unlock();
     285             : 
     286           1 :         void addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
     287             :         {
     288           1 :             m_aUndoListeners.addInterface( i_listener );
     289           1 :         }
     290             : 
     291           1 :         void removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
     292             :         {
     293           1 :             m_aUndoListeners.removeInterface( i_listener );
     294           1 :         }
     295             : 
     296           0 :         void addModifyListener( const Reference< XModifyListener >& i_listener )
     297             :         {
     298           0 :             m_aModifyListeners.addInterface( i_listener );
     299           0 :         }
     300             : 
     301           0 :         void removeModifyListener( const Reference< XModifyListener >& i_listener )
     302             :         {
     303           0 :             m_aModifyListeners.removeInterface( i_listener );
     304           0 :         }
     305             : 
     306             :         UndoManagerEvent
     307             :             buildEvent( ::rtl::OUString const& i_title ) const;
     308             : 
     309             :         void impl_notifyModified();
     310             :         void notify(    ::rtl::OUString const& i_title,
     311             :                         void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& )
     312             :                     );
     313           0 :         void notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ) )
     314             :         {
     315           0 :             notify( ::rtl::OUString(), i_notificationMethod );
     316           0 :         }
     317             : 
     318             :         void notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ) );
     319             : 
     320             :     private:
     321             :         /// adds a function to be called to the request processor's queue
     322             :         void impl_processRequest( ::boost::function0< void > const& i_request, IMutexGuard& i_instanceLock );
     323             : 
     324             :         /// impl-versions of the XUndoManager API.
     325             :         void impl_enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden );
     326             :         void impl_leaveUndoContext();
     327             :         void impl_addUndoAction( const Reference< XUndoAction >& i_action );
     328             :         void impl_doUndoRedo( IMutexGuard& i_externalLock, const bool i_undo );
     329             :         void impl_clear();
     330             :         void impl_clearRedo();
     331             :         void impl_reset();
     332             :     };
     333             : 
     334             :     //------------------------------------------------------------------------------------------------------------------
     335           1 :     void UndoManagerHelper_Impl::disposing()
     336             :     {
     337           1 :         EventObject aEvent;
     338           1 :         aEvent.Source = getXUndoManager();
     339           1 :         m_aUndoListeners.disposeAndClear( aEvent );
     340           1 :         m_aModifyListeners.disposeAndClear( aEvent );
     341             : 
     342           1 :         ::osl::MutexGuard aGuard( m_aMutex );
     343             : 
     344           1 :         getUndoManager().RemoveUndoListener( *this );
     345             : 
     346           1 :         m_disposed = true;
     347           1 :     }
     348             : 
     349             :     //------------------------------------------------------------------------------------------------------------------
     350           0 :     UndoManagerEvent UndoManagerHelper_Impl::buildEvent( ::rtl::OUString const& i_title ) const
     351             :     {
     352           0 :         UndoManagerEvent aEvent;
     353           0 :         aEvent.Source = getXUndoManager();
     354           0 :         aEvent.UndoActionTitle = i_title;
     355           0 :         aEvent.UndoContextDepth = getUndoManager().GetListActionDepth();
     356           0 :         return aEvent;
     357             :     }
     358             : 
     359             :     //------------------------------------------------------------------------------------------------------------------
     360           0 :     void UndoManagerHelper_Impl::impl_notifyModified()
     361             :     {
     362           0 :         const EventObject aEvent( getXUndoManager() );
     363           0 :         m_aModifyListeners.notifyEach( &XModifyListener::modified, aEvent );
     364           0 :     }
     365             : 
     366             :     //------------------------------------------------------------------------------------------------------------------
     367           0 :     void UndoManagerHelper_Impl::notify( ::rtl::OUString const& i_title,
     368             :         void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ) )
     369             :     {
     370           0 :         const UndoManagerEvent aEvent( buildEvent( i_title ) );
     371             : 
     372             :         // TODO: this notification method here is used by UndoManagerHelper_Impl, to multiplex the notifications we
     373             :         // receive from the IUndoManager. Those notitications are sent with a locked SolarMutex, which means
     374             :         // we're doing the multiplexing here with a locked SM, too. Which is Bad (TM).
     375             :         // Fixing this properly would require outsourcing all the notifications into an own thread - which might lead
     376             :         // to problems of its own, since clients might expect synchronous notifications.
     377             : 
     378           0 :         m_aUndoListeners.notifyEach( i_notificationMethod, aEvent );
     379           0 :         impl_notifyModified();
     380           0 :     }
     381             : 
     382             :     //------------------------------------------------------------------------------------------------------------------
     383           0 :     void UndoManagerHelper_Impl::notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ) )
     384             :     {
     385           0 :         const EventObject aEvent( getXUndoManager() );
     386             : 
     387             :         // TODO: the same comment as in the other notify, regarding SM locking applies here ...
     388             : 
     389           0 :         m_aUndoListeners.notifyEach( i_notificationMethod, aEvent );
     390           0 :         impl_notifyModified();
     391           0 :     }
     392             : 
     393             :     //------------------------------------------------------------------------------------------------------------------
     394           0 :     void UndoManagerHelper_Impl::enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden, IMutexGuard& i_instanceLock )
     395             :     {
     396             :         impl_processRequest(
     397             :             ::boost::bind(
     398             :                 &UndoManagerHelper_Impl::impl_enterUndoContext,
     399             :                 this,
     400             :                 ::boost::cref( i_title ),
     401             :                 i_hidden
     402             :             ),
     403             :             i_instanceLock
     404           0 :         );
     405           0 :     }
     406             : 
     407             :     //------------------------------------------------------------------------------------------------------------------
     408           0 :     void UndoManagerHelper_Impl::leaveUndoContext( IMutexGuard& i_instanceLock )
     409             :     {
     410             :         impl_processRequest(
     411             :             ::boost::bind(
     412             :                 &UndoManagerHelper_Impl::impl_leaveUndoContext,
     413             :                 this
     414             :             ),
     415             :             i_instanceLock
     416           0 :         );
     417           0 :     }
     418             : 
     419             :     //------------------------------------------------------------------------------------------------------------------
     420           0 :     void UndoManagerHelper_Impl::addUndoAction( const Reference< XUndoAction >& i_action, IMutexGuard& i_instanceLock )
     421             :     {
     422           0 :         if ( !i_action.is() )
     423             :             throw IllegalArgumentException(
     424             :                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal undo action object" ) ),
     425             :                 getXUndoManager(),
     426             :                 1
     427           0 :             );
     428             : 
     429             :         impl_processRequest(
     430             :             ::boost::bind(
     431             :                 &UndoManagerHelper_Impl::impl_addUndoAction,
     432             :                 this,
     433             :                 ::boost::ref( i_action )
     434             :             ),
     435             :             i_instanceLock
     436           0 :         );
     437           0 :     }
     438             : 
     439             :     //------------------------------------------------------------------------------------------------------------------
     440           0 :     void UndoManagerHelper_Impl::clear( IMutexGuard& i_instanceLock )
     441             :     {
     442             :         impl_processRequest(
     443             :             ::boost::bind(
     444             :                 &UndoManagerHelper_Impl::impl_clear,
     445             :                 this
     446             :             ),
     447             :             i_instanceLock
     448           0 :         );
     449           0 :     }
     450             : 
     451             :     //------------------------------------------------------------------------------------------------------------------
     452           0 :     void UndoManagerHelper_Impl::clearRedo( IMutexGuard& i_instanceLock )
     453             :     {
     454             :         impl_processRequest(
     455             :             ::boost::bind(
     456             :                 &UndoManagerHelper_Impl::impl_clearRedo,
     457             :                 this
     458             :             ),
     459             :             i_instanceLock
     460           0 :         );
     461           0 :     }
     462             : 
     463             :     //------------------------------------------------------------------------------------------------------------------
     464           0 :     void UndoManagerHelper_Impl::reset( IMutexGuard& i_instanceLock )
     465             :     {
     466             :         impl_processRequest(
     467             :             ::boost::bind(
     468             :                 &UndoManagerHelper_Impl::impl_reset,
     469             :                 this
     470             :             ),
     471             :             i_instanceLock
     472           0 :         );
     473           0 :     }
     474             : 
     475             :     //------------------------------------------------------------------------------------------------------------------
     476           0 :     void UndoManagerHelper_Impl::lock()
     477             :     {
     478             :         // SYNCHRONIZED --->
     479           0 :         ::osl::MutexGuard aGuard( getMutex() );
     480             : 
     481           0 :         if ( ++m_nLockCount == 1 )
     482             :         {
     483           0 :             IUndoManager& rUndoManager = getUndoManager();
     484           0 :             rUndoManager.EnableUndo( false );
     485           0 :         }
     486             :         // <--- SYNCHRONIZED
     487           0 :     }
     488             : 
     489             :     //------------------------------------------------------------------------------------------------------------------
     490           0 :     void UndoManagerHelper_Impl::unlock()
     491             :     {
     492             :         // SYNCHRONIZED --->
     493           0 :         ::osl::MutexGuard aGuard( getMutex() );
     494             : 
     495           0 :         if ( m_nLockCount == 0 )
     496           0 :             throw NotLockedException( "Undo manager is not locked", getXUndoManager() );
     497             : 
     498           0 :         if ( --m_nLockCount == 0 )
     499             :         {
     500           0 :             IUndoManager& rUndoManager = getUndoManager();
     501           0 :             rUndoManager.EnableUndo( true );
     502           0 :         }
     503             :         // <--- SYNCHRONIZED
     504           0 :     }
     505             : 
     506             :     //------------------------------------------------------------------------------------------------------------------
     507           0 :     void UndoManagerHelper_Impl::impl_processRequest( ::boost::function0< void > const& i_request, IMutexGuard& i_instanceLock )
     508             :     {
     509             :         // create the request, and add it to our queue
     510           0 :         ::rtl::Reference< UndoManagerRequest > pRequest( new UndoManagerRequest( i_request ) );
     511             :         {
     512           0 :             ::osl::MutexGuard aQueueGuard( m_aQueueMutex );
     513           0 :             m_aEventQueue.push( pRequest );
     514             :         }
     515             : 
     516           0 :         i_instanceLock.clear();
     517             : 
     518           0 :         if ( m_bProcessingEvents )
     519             :         {
     520             :             // another thread is processing the event queue currently => it will also process the event which we just added
     521           0 :             pRequest->wait();
     522             :             return;
     523             :         }
     524             : 
     525           0 :         m_bProcessingEvents = true;
     526           0 :         do
     527             :         {
     528           0 :             pRequest.clear();
     529             :             {
     530           0 :                 ::osl::MutexGuard aQueueGuard( m_aQueueMutex );
     531           0 :                 if ( m_aEventQueue.empty() )
     532             :                 {
     533             :                     // reset the flag before releasing the queue mutex, otherwise it's possible that another thread
     534             :                     // could add an event after we release the mutex, but before we reset the flag. If then this other
     535             :                     // thread checks the flag before be reset it, this thread's event would starve.
     536           0 :                     m_bProcessingEvents = false;
     537             :                     return;
     538             :                 }
     539           0 :                 pRequest = m_aEventQueue.front();
     540           0 :                 m_aEventQueue.pop();
     541             :             }
     542             :             try
     543             :             {
     544           0 :                 pRequest->execute();
     545           0 :                 pRequest->wait();
     546             :             }
     547           0 :             catch( ... )
     548             :             {
     549             :                 {
     550             :                     // no chance to process further requests, if the current one failed
     551             :                     // => discard them
     552           0 :                     ::osl::MutexGuard aQueueGuard( m_aQueueMutex );
     553           0 :                     while ( !m_aEventQueue.empty() )
     554             :                     {
     555           0 :                         pRequest = m_aEventQueue.front();
     556           0 :                         m_aEventQueue.pop();
     557           0 :                         pRequest->cancel( getXUndoManager() );
     558             :                     }
     559           0 :                     m_bProcessingEvents = false;
     560             :                 }
     561             :                 // re-throw the error
     562           0 :                 throw;
     563             :             }
     564             :         }
     565           0 :         while ( true );
     566             :     }
     567             : 
     568             :     //------------------------------------------------------------------------------------------------------------------
     569           0 :     void UndoManagerHelper_Impl::impl_enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden )
     570             :     {
     571             :         // SYNCHRONIZED --->
     572           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     573             : 
     574           0 :         IUndoManager& rUndoManager = getUndoManager();
     575           0 :         if ( !rUndoManager.IsUndoEnabled() )
     576             :             // ignore this request if the manager is locked
     577           0 :             return;
     578             : 
     579           0 :         if ( i_hidden && ( rUndoManager.GetUndoActionCount( IUndoManager::CurrentLevel ) == 0 ) )
     580             :             throw EmptyUndoStackException(
     581             :                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "can't enter a hidden context without a previous Undo action" ) ),
     582           0 :                 m_rUndoManagerImplementation.getThis()
     583           0 :             );
     584             : 
     585             :         {
     586           0 :             ::comphelper::FlagGuard aNotificationGuard( m_bAPIActionRunning );
     587           0 :             rUndoManager.EnterListAction( i_title, ::rtl::OUString() );
     588             :         }
     589             : 
     590           0 :         m_aContextVisibilities.push( i_hidden );
     591             : 
     592           0 :         const UndoManagerEvent aEvent( buildEvent( i_title ) );
     593           0 :         aGuard.clear();
     594             :         // <--- SYNCHRONIZED
     595             : 
     596           0 :         m_aUndoListeners.notifyEach( i_hidden ? &XUndoManagerListener::enteredHiddenContext : &XUndoManagerListener::enteredContext, aEvent );
     597           0 :         impl_notifyModified();
     598             :     }
     599             : 
     600             :     //------------------------------------------------------------------------------------------------------------------
     601           0 :     void UndoManagerHelper_Impl::impl_leaveUndoContext()
     602             :     {
     603             :         // SYNCHRONIZED --->
     604           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     605             : 
     606           0 :         IUndoManager& rUndoManager = getUndoManager();
     607           0 :         if ( !rUndoManager.IsUndoEnabled() )
     608             :             // ignore this request if the manager is locked
     609           0 :             return;
     610             : 
     611           0 :         if ( !rUndoManager.IsInListAction() )
     612             :             throw InvalidStateException(
     613             :                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no active undo context" ) ),
     614             :                 getXUndoManager()
     615           0 :             );
     616             : 
     617           0 :         size_t nContextElements = 0;
     618             : 
     619           0 :         const bool isHiddenContext = m_aContextVisibilities.top();;
     620           0 :         m_aContextVisibilities.pop();
     621             : 
     622           0 :         const bool bHadRedoActions = ( rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ) > 0 );
     623             :         {
     624           0 :             ::comphelper::FlagGuard aNotificationGuard( m_bAPIActionRunning );
     625           0 :             if ( isHiddenContext )
     626           0 :                 nContextElements = rUndoManager.LeaveAndMergeListAction();
     627             :             else
     628           0 :                 nContextElements = rUndoManager.LeaveListAction();
     629             :         }
     630           0 :         const bool bHasRedoActions = ( rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ) > 0 );
     631             : 
     632             :         // prepare notification
     633           0 :         void ( SAL_CALL XUndoManagerListener::*notificationMethod )( const UndoManagerEvent& ) = NULL;
     634             : 
     635           0 :         UndoManagerEvent aContextEvent( buildEvent( ::rtl::OUString() ) );
     636           0 :         const EventObject aClearedEvent( getXUndoManager() );
     637           0 :         if ( nContextElements == 0 )
     638             :         {
     639           0 :             notificationMethod = &XUndoManagerListener::cancelledContext;
     640             :         }
     641           0 :         else if ( isHiddenContext )
     642             :         {
     643           0 :             notificationMethod = &XUndoManagerListener::leftHiddenContext;
     644             :         }
     645             :         else
     646             :         {
     647           0 :             aContextEvent.UndoActionTitle = rUndoManager.GetUndoActionComment( 0, IUndoManager::CurrentLevel );
     648           0 :             notificationMethod = &XUndoManagerListener::leftContext;
     649             :         }
     650             : 
     651           0 :         aGuard.clear();
     652             :         // <--- SYNCHRONIZED
     653             : 
     654           0 :         if ( bHadRedoActions && !bHasRedoActions )
     655           0 :             m_aUndoListeners.notifyEach( &XUndoManagerListener::redoActionsCleared, aClearedEvent );
     656           0 :         m_aUndoListeners.notifyEach( notificationMethod, aContextEvent );
     657           0 :         impl_notifyModified();
     658             :     }
     659             : 
     660             :     //------------------------------------------------------------------------------------------------------------------
     661           0 :     void UndoManagerHelper_Impl::impl_doUndoRedo( IMutexGuard& i_externalLock, const bool i_undo )
     662             :     {
     663           0 :         ::osl::Guard< ::framework::IMutex > aExternalGuard( i_externalLock.getGuardedMutex() );
     664             :             // note that this assumes that the mutex has been released in the thread which added the
     665             :             // Undo/Redo request, so we can successfully acquire it
     666             : 
     667             :         // SYNCHRONIZED --->
     668           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     669             : 
     670           0 :         IUndoManager& rUndoManager = getUndoManager();
     671           0 :         if ( rUndoManager.IsInListAction() )
     672           0 :             throw UndoContextNotClosedException( ::rtl::OUString(), getXUndoManager() );
     673             : 
     674             :         const size_t nElements  =   i_undo
     675           0 :                                 ?   rUndoManager.GetUndoActionCount( IUndoManager::TopLevel )
     676           0 :                                 :   rUndoManager.GetRedoActionCount( IUndoManager::TopLevel );
     677           0 :         if ( nElements == 0 )
     678           0 :             throw EmptyUndoStackException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "stack is empty" )), getXUndoManager() );
     679             : 
     680           0 :         aGuard.clear();
     681             :         // <--- SYNCHRONIZED
     682             : 
     683             :         try
     684             :         {
     685           0 :             if ( i_undo )
     686           0 :                 rUndoManager.Undo();
     687             :             else
     688           0 :                 rUndoManager.Redo();
     689             :         }
     690           0 :         catch( const RuntimeException& ) { /* allowed to leave here */ throw; }
     691           0 :         catch( const UndoFailedException& ) { /* allowed to leave here */ throw; }
     692           0 :         catch( const Exception& )
     693             :         {
     694             :             // not allowed to leave
     695           0 :             const Any aError( ::cppu::getCaughtException() );
     696           0 :             throw UndoFailedException( ::rtl::OUString(), getXUndoManager(), aError );
     697           0 :         }
     698             : 
     699             :         // note that in opposite to all of the other methods, we do *not* have our mutex locked when calling
     700             :         // into the IUndoManager implementation. This ensures that an actual XUndoAction::undo/redo is also
     701             :         // called without our mutex being locked.
     702             :         // As a consequence, we do not set m_bAPIActionRunning here. Instead, our actionUndone/actionRedone methods
     703             :         // *always* multiplex the event to our XUndoManagerListeners, not only when m_bAPIActionRunning is FALSE (This
     704             :         // again is different from all other SfxUndoListener methods).
     705             :         // So, we do not need to do this notification here ourself.
     706           0 :     }
     707             : 
     708             :     //------------------------------------------------------------------------------------------------------------------
     709           0 :     void UndoManagerHelper_Impl::impl_addUndoAction( const Reference< XUndoAction >& i_action )
     710             :     {
     711             :         // SYNCHRONIZED --->
     712           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     713             : 
     714           0 :         IUndoManager& rUndoManager = getUndoManager();
     715           0 :         if ( !rUndoManager.IsUndoEnabled() )
     716             :             // ignore the request if the manager is locked
     717           0 :             return;
     718             : 
     719           0 :         const UndoManagerEvent aEventAdd( buildEvent( i_action->getTitle() ) );
     720           0 :         const EventObject aEventClear( getXUndoManager() );
     721             : 
     722           0 :         const bool bHadRedoActions = ( rUndoManager.GetRedoActionCount( IUndoManager::CurrentLevel ) > 0 );
     723             :         {
     724           0 :             ::comphelper::FlagGuard aNotificationGuard( m_bAPIActionRunning );
     725           0 :             rUndoManager.AddUndoAction( new UndoActionWrapper( i_action ) );
     726             :         }
     727           0 :         const bool bHasRedoActions = ( rUndoManager.GetRedoActionCount( IUndoManager::CurrentLevel ) > 0 );
     728             : 
     729           0 :         aGuard.clear();
     730             :         // <--- SYNCHRONIZED
     731             : 
     732           0 :         m_aUndoListeners.notifyEach( &XUndoManagerListener::undoActionAdded, aEventAdd );
     733           0 :         if ( bHadRedoActions && !bHasRedoActions )
     734           0 :             m_aUndoListeners.notifyEach( &XUndoManagerListener::redoActionsCleared, aEventClear );
     735           0 :         impl_notifyModified();
     736             :     }
     737             : 
     738             :     //------------------------------------------------------------------------------------------------------------------
     739           0 :     void UndoManagerHelper_Impl::impl_clear()
     740             :     {
     741             :         // SYNCHRONIZED --->
     742           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     743             : 
     744           0 :         IUndoManager& rUndoManager = getUndoManager();
     745           0 :         if ( rUndoManager.IsInListAction() )
     746           0 :             throw UndoContextNotClosedException( ::rtl::OUString(), getXUndoManager() );
     747             : 
     748             :         {
     749           0 :             ::comphelper::FlagGuard aNotificationGuard( m_bAPIActionRunning );
     750           0 :             rUndoManager.Clear();
     751             :         }
     752             : 
     753           0 :         const EventObject aEvent( getXUndoManager() );
     754           0 :         aGuard.clear();
     755             :         // <--- SYNCHRONIZED
     756             : 
     757           0 :         m_aUndoListeners.notifyEach( &XUndoManagerListener::allActionsCleared, aEvent );
     758           0 :         impl_notifyModified();
     759           0 :     }
     760             : 
     761             :     //------------------------------------------------------------------------------------------------------------------
     762           0 :     void UndoManagerHelper_Impl::impl_clearRedo()
     763             :     {
     764             :         // SYNCHRONIZED --->
     765           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     766             : 
     767           0 :         IUndoManager& rUndoManager = getUndoManager();
     768           0 :         if ( rUndoManager.IsInListAction() )
     769           0 :             throw UndoContextNotClosedException( ::rtl::OUString(), getXUndoManager() );
     770             : 
     771             :         {
     772           0 :             ::comphelper::FlagGuard aNotificationGuard( m_bAPIActionRunning );
     773           0 :             rUndoManager.ClearRedo();
     774             :         }
     775             : 
     776           0 :         const EventObject aEvent( getXUndoManager() );
     777           0 :         aGuard.clear();
     778             :         // <--- SYNCHRONIZED
     779             : 
     780           0 :         m_aUndoListeners.notifyEach( &XUndoManagerListener::redoActionsCleared, aEvent );
     781           0 :         impl_notifyModified();
     782           0 :     }
     783             : 
     784             :     //------------------------------------------------------------------------------------------------------------------
     785           0 :     void UndoManagerHelper_Impl::impl_reset()
     786             :     {
     787             :         // SYNCHRONIZED --->
     788           0 :         ::osl::ClearableMutexGuard aGuard( m_aMutex );
     789             : 
     790           0 :         IUndoManager& rUndoManager = getUndoManager();
     791             :         {
     792           0 :             ::comphelper::FlagGuard aNotificationGuard( m_bAPIActionRunning );
     793           0 :             rUndoManager.Reset();
     794             :         }
     795             : 
     796           0 :         const EventObject aEvent( getXUndoManager() );
     797           0 :         aGuard.clear();
     798             :         // <--- SYNCHRONIZED
     799             : 
     800           0 :         m_aUndoListeners.notifyEach( &XUndoManagerListener::resetAll, aEvent );
     801           0 :         impl_notifyModified();
     802           0 :     }
     803             : 
     804             :     //------------------------------------------------------------------------------------------------------------------
     805           0 :     void UndoManagerHelper_Impl::actionUndone( const String& i_actionComment )
     806             :     {
     807           0 :         UndoManagerEvent aEvent;
     808           0 :         aEvent.Source = getXUndoManager();
     809           0 :         aEvent.UndoActionTitle = i_actionComment;
     810           0 :         aEvent.UndoContextDepth = 0;    // Undo can happen on level 0 only
     811           0 :         m_aUndoListeners.notifyEach( &XUndoManagerListener::actionUndone, aEvent );
     812           0 :         impl_notifyModified();
     813           0 :     }
     814             : 
     815             :      //------------------------------------------------------------------------------------------------------------------
     816           0 :     void UndoManagerHelper_Impl::actionRedone( const String& i_actionComment )
     817             :     {
     818           0 :         UndoManagerEvent aEvent;
     819           0 :         aEvent.Source = getXUndoManager();
     820           0 :         aEvent.UndoActionTitle = i_actionComment;
     821           0 :         aEvent.UndoContextDepth = 0;    // Redo can happen on level 0 only
     822           0 :         m_aUndoListeners.notifyEach( &XUndoManagerListener::actionRedone, aEvent );
     823           0 :         impl_notifyModified();
     824           0 :     }
     825             : 
     826             :      //------------------------------------------------------------------------------------------------------------------
     827           0 :     void UndoManagerHelper_Impl::undoActionAdded( const String& i_actionComment )
     828             :     {
     829           0 :         if ( m_bAPIActionRunning )
     830           0 :             return;
     831             : 
     832           0 :         notify( i_actionComment, &XUndoManagerListener::undoActionAdded );
     833             :     }
     834             : 
     835             :      //------------------------------------------------------------------------------------------------------------------
     836           0 :     void UndoManagerHelper_Impl::cleared()
     837             :     {
     838           0 :         if ( m_bAPIActionRunning )
     839           0 :             return;
     840             : 
     841           0 :         notify( &XUndoManagerListener::allActionsCleared );
     842             :     }
     843             : 
     844             :      //------------------------------------------------------------------------------------------------------------------
     845           0 :     void UndoManagerHelper_Impl::clearedRedo()
     846             :     {
     847           0 :         if ( m_bAPIActionRunning )
     848           0 :             return;
     849             : 
     850           0 :         notify( &XUndoManagerListener::redoActionsCleared );
     851             :     }
     852             : 
     853             :      //------------------------------------------------------------------------------------------------------------------
     854           0 :     void UndoManagerHelper_Impl::resetAll()
     855             :     {
     856           0 :         if ( m_bAPIActionRunning )
     857           0 :             return;
     858             : 
     859           0 :         notify( &XUndoManagerListener::resetAll );
     860             :     }
     861             : 
     862             :      //------------------------------------------------------------------------------------------------------------------
     863           0 :     void UndoManagerHelper_Impl::listActionEntered( const String& i_comment )
     864             :     {
     865             : #if OSL_DEBUG_LEVEL > 0
     866             :         m_aContextAPIFlags.push( m_bAPIActionRunning );
     867             : #endif
     868             : 
     869           0 :         if ( m_bAPIActionRunning )
     870           0 :             return;
     871             : 
     872           0 :         notify( i_comment, &XUndoManagerListener::enteredContext );
     873             :     }
     874             : 
     875             :      //------------------------------------------------------------------------------------------------------------------
     876           0 :     void UndoManagerHelper_Impl::listActionLeft( const String& i_comment )
     877             :     {
     878             : #if OSL_DEBUG_LEVEL > 0
     879             :         const bool bCurrentContextIsAPIContext = m_aContextAPIFlags.top();
     880             :         m_aContextAPIFlags.pop();
     881             :         OSL_ENSURE( bCurrentContextIsAPIContext == m_bAPIActionRunning, "UndoManagerHelper_Impl::listActionLeft: API and non-API contexts interwoven!" );
     882             : #endif
     883             : 
     884           0 :         if ( m_bAPIActionRunning )
     885           0 :             return;
     886             : 
     887           0 :         notify( i_comment, &XUndoManagerListener::leftContext );
     888             :     }
     889             : 
     890             :      //------------------------------------------------------------------------------------------------------------------
     891           0 :     void UndoManagerHelper_Impl::listActionLeftAndMerged()
     892             :     {
     893             : #if OSL_DEBUG_LEVEL > 0
     894             :         const bool bCurrentContextIsAPIContext = m_aContextAPIFlags.top();
     895             :         m_aContextAPIFlags.pop();
     896             :         OSL_ENSURE( bCurrentContextIsAPIContext == m_bAPIActionRunning, "UndoManagerHelper_Impl::listActionLeftAndMerged: API and non-API contexts interwoven!" );
     897             : #endif
     898             : 
     899           0 :         if ( m_bAPIActionRunning )
     900           0 :             return;
     901             : 
     902           0 :         notify( &XUndoManagerListener::leftHiddenContext );
     903             :     }
     904             : 
     905             :      //------------------------------------------------------------------------------------------------------------------
     906           0 :     void UndoManagerHelper_Impl::listActionCancelled()
     907             :     {
     908             : #if OSL_DEBUG_LEVEL > 0
     909             :         const bool bCurrentContextIsAPIContext = m_aContextAPIFlags.top();
     910             :         m_aContextAPIFlags.pop();
     911             :         OSL_ENSURE( bCurrentContextIsAPIContext == m_bAPIActionRunning, "UndoManagerHelper_Impl::listActionCancelled: API and non-API contexts interwoven!" );
     912             : #endif
     913             : 
     914           0 :         if ( m_bAPIActionRunning )
     915           0 :             return;
     916             : 
     917           0 :         notify( &XUndoManagerListener::cancelledContext );
     918             :     }
     919             : 
     920             :      //------------------------------------------------------------------------------------------------------------------
     921           0 :     void UndoManagerHelper_Impl::undoManagerDying()
     922             :     {
     923             :         // TODO: do we need to care? Or is this the responsibility of our owner?
     924           0 :     }
     925             : 
     926             :     //==================================================================================================================
     927             :     //= UndoManagerHelper
     928             :     //==================================================================================================================
     929             :     //------------------------------------------------------------------------------------------------------------------
     930           1 :     UndoManagerHelper::UndoManagerHelper( IUndoManagerImplementation& i_undoManagerImpl )
     931           1 :         :m_pImpl( new UndoManagerHelper_Impl( i_undoManagerImpl ) )
     932             :     {
     933           1 :     }
     934             : 
     935             :     //------------------------------------------------------------------------------------------------------------------
     936           0 :     UndoManagerHelper::~UndoManagerHelper()
     937             :     {
     938           0 :     }
     939             : 
     940             :     //------------------------------------------------------------------------------------------------------------------
     941           1 :     void UndoManagerHelper::disposing()
     942             :     {
     943           1 :         m_pImpl->disposing();
     944           1 :     }
     945             : 
     946             :     //------------------------------------------------------------------------------------------------------------------
     947           0 :     void UndoManagerHelper::enterUndoContext( const ::rtl::OUString& i_title, IMutexGuard& i_instanceLock )
     948             :     {
     949           0 :         m_pImpl->enterUndoContext( i_title, false, i_instanceLock );
     950           0 :     }
     951             : 
     952             :     //------------------------------------------------------------------------------------------------------------------
     953           0 :     void UndoManagerHelper::enterHiddenUndoContext( IMutexGuard& i_instanceLock )
     954             :     {
     955           0 :         m_pImpl->enterUndoContext( ::rtl::OUString(), true, i_instanceLock );
     956           0 :     }
     957             : 
     958             :     //------------------------------------------------------------------------------------------------------------------
     959           0 :     void UndoManagerHelper::leaveUndoContext( IMutexGuard& i_instanceLock )
     960             :     {
     961           0 :         m_pImpl->leaveUndoContext( i_instanceLock );
     962           0 :     }
     963             : 
     964             :     //------------------------------------------------------------------------------------------------------------------
     965           0 :     void UndoManagerHelper_Impl::undo( IMutexGuard& i_instanceLock )
     966             :     {
     967             :         impl_processRequest(
     968             :             ::boost::bind(
     969             :                 &UndoManagerHelper_Impl::impl_doUndoRedo,
     970             :                 this,
     971             :                 ::boost::ref( i_instanceLock ),
     972             :                 true
     973             :             ),
     974             :             i_instanceLock
     975           0 :         );
     976           0 :     }
     977             : 
     978             :     //------------------------------------------------------------------------------------------------------------------
     979           0 :     void UndoManagerHelper_Impl::redo( IMutexGuard& i_instanceLock )
     980             :     {
     981             :         impl_processRequest(
     982             :             ::boost::bind(
     983             :                 &UndoManagerHelper_Impl::impl_doUndoRedo,
     984             :                 this,
     985             :                 ::boost::ref( i_instanceLock ),
     986             :                 false
     987             :             ),
     988             :             i_instanceLock
     989           0 :         );
     990           0 :     }
     991             : 
     992             :     //------------------------------------------------------------------------------------------------------------------
     993           0 :     void UndoManagerHelper::addUndoAction( const Reference< XUndoAction >& i_action, IMutexGuard& i_instanceLock )
     994             :     {
     995           0 :         m_pImpl->addUndoAction( i_action, i_instanceLock );
     996           0 :     }
     997             : 
     998             :     //------------------------------------------------------------------------------------------------------------------
     999           0 :     void UndoManagerHelper::undo( IMutexGuard& i_instanceLock )
    1000             :     {
    1001           0 :         m_pImpl->undo( i_instanceLock );
    1002           0 :     }
    1003             : 
    1004             :     //------------------------------------------------------------------------------------------------------------------
    1005           0 :     void UndoManagerHelper::redo( IMutexGuard& i_instanceLock )
    1006             :     {
    1007           0 :         m_pImpl->redo( i_instanceLock );
    1008           0 :     }
    1009             : 
    1010             :     //------------------------------------------------------------------------------------------------------------------
    1011           0 :     ::sal_Bool UndoManagerHelper::isUndoPossible() const
    1012             :     {
    1013             :         // SYNCHRONIZED --->
    1014           0 :         ::osl::MutexGuard aGuard( m_pImpl->getMutex() );
    1015           0 :         IUndoManager& rUndoManager = m_pImpl->getUndoManager();
    1016           0 :         if ( rUndoManager.IsInListAction() )
    1017           0 :             return sal_False;
    1018           0 :         return rUndoManager.GetUndoActionCount( IUndoManager::TopLevel ) > 0;
    1019             :         // <--- SYNCHRONIZED
    1020             :     }
    1021             : 
    1022             :     //------------------------------------------------------------------------------------------------------------------
    1023           0 :     ::sal_Bool UndoManagerHelper::isRedoPossible() const
    1024             :     {
    1025             :         // SYNCHRONIZED --->
    1026           0 :         ::osl::MutexGuard aGuard( m_pImpl->getMutex() );
    1027           0 :         const IUndoManager& rUndoManager = m_pImpl->getUndoManager();
    1028           0 :         if ( rUndoManager.IsInListAction() )
    1029           0 :             return sal_False;
    1030           0 :         return rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ) > 0;
    1031             :         // <--- SYNCHRONIZED
    1032             :     }
    1033             : 
    1034             :     //------------------------------------------------------------------------------------------------------------------
    1035             :     namespace
    1036             :     {
    1037             :         //..............................................................................................................
    1038           0 :         ::rtl::OUString lcl_getCurrentActionTitle( UndoManagerHelper_Impl& i_impl, const bool i_undo )
    1039             :         {
    1040             :             // SYNCHRONIZED --->
    1041           0 :             ::osl::MutexGuard aGuard( i_impl.getMutex() );
    1042             : 
    1043           0 :             const IUndoManager& rUndoManager = i_impl.getUndoManager();
    1044             :             const size_t nActionCount = i_undo
    1045           0 :                                     ?   rUndoManager.GetUndoActionCount( IUndoManager::TopLevel )
    1046           0 :                                     :   rUndoManager.GetRedoActionCount( IUndoManager::TopLevel );
    1047           0 :             if ( nActionCount == 0 )
    1048             :                 throw EmptyUndoStackException(
    1049             :                     i_undo ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no action on the undo stack" ) )
    1050             :                            : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no action on the redo stack" ) ),
    1051             :                     i_impl.getXUndoManager()
    1052           0 :                 );
    1053             :             return  i_undo
    1054           0 :                 ?   rUndoManager.GetUndoActionComment( 0, IUndoManager::TopLevel )
    1055           0 :                 :   rUndoManager.GetRedoActionComment( 0, IUndoManager::TopLevel );
    1056             :             // <--- SYNCHRONIZED
    1057             :         }
    1058             : 
    1059             :         //..............................................................................................................
    1060           0 :         Sequence< ::rtl::OUString > lcl_getAllActionTitles( UndoManagerHelper_Impl& i_impl, const bool i_undo )
    1061             :         {
    1062             :             // SYNCHRONIZED --->
    1063           0 :             ::osl::MutexGuard aGuard( i_impl.getMutex() );
    1064             : 
    1065           0 :             const IUndoManager& rUndoManager = i_impl.getUndoManager();
    1066             :             const size_t nCount =   i_undo
    1067           0 :                                 ?   rUndoManager.GetUndoActionCount( IUndoManager::TopLevel )
    1068           0 :                                 :   rUndoManager.GetRedoActionCount( IUndoManager::TopLevel );
    1069             : 
    1070           0 :             Sequence< ::rtl::OUString > aTitles( nCount );
    1071           0 :             for ( size_t i=0; i<nCount; ++i )
    1072             :             {
    1073           0 :                 aTitles[i] =    i_undo
    1074           0 :                             ?   rUndoManager.GetUndoActionComment( i, IUndoManager::TopLevel )
    1075           0 :                             :   rUndoManager.GetRedoActionComment( i, IUndoManager::TopLevel );
    1076             :             }
    1077           0 :             return aTitles;
    1078             :             // <--- SYNCHRONIZED
    1079             :         }
    1080             :     }
    1081             : 
    1082             :     //------------------------------------------------------------------------------------------------------------------
    1083           0 :     ::rtl::OUString UndoManagerHelper::getCurrentUndoActionTitle() const
    1084             :     {
    1085           0 :         return lcl_getCurrentActionTitle( *m_pImpl, true );
    1086             :     }
    1087             : 
    1088             :     //------------------------------------------------------------------------------------------------------------------
    1089           0 :     ::rtl::OUString UndoManagerHelper::getCurrentRedoActionTitle() const
    1090             :     {
    1091           0 :         return lcl_getCurrentActionTitle( *m_pImpl, false );
    1092             :     }
    1093             : 
    1094             :     //------------------------------------------------------------------------------------------------------------------
    1095           0 :     Sequence< ::rtl::OUString > UndoManagerHelper::getAllUndoActionTitles() const
    1096             :     {
    1097           0 :         return lcl_getAllActionTitles( *m_pImpl, true );
    1098             :     }
    1099             : 
    1100             :     //------------------------------------------------------------------------------------------------------------------
    1101           0 :     Sequence< ::rtl::OUString > UndoManagerHelper::getAllRedoActionTitles() const
    1102             :     {
    1103           0 :         return lcl_getAllActionTitles( *m_pImpl, false );
    1104             :     }
    1105             : 
    1106             :     //------------------------------------------------------------------------------------------------------------------
    1107           0 :     void UndoManagerHelper::clear( IMutexGuard& i_instanceLock )
    1108             :     {
    1109           0 :         m_pImpl->clear( i_instanceLock );
    1110           0 :     }
    1111             : 
    1112             :     //------------------------------------------------------------------------------------------------------------------
    1113           0 :     void UndoManagerHelper::clearRedo( IMutexGuard& i_instanceLock )
    1114             :     {
    1115           0 :         m_pImpl->clearRedo( i_instanceLock );
    1116           0 :     }
    1117             : 
    1118             :     //------------------------------------------------------------------------------------------------------------------
    1119           0 :     void UndoManagerHelper::reset( IMutexGuard& i_instanceLock )
    1120             :     {
    1121           0 :         m_pImpl->reset( i_instanceLock );
    1122           0 :     }
    1123             : 
    1124             :     //------------------------------------------------------------------------------------------------------------------
    1125           0 :     void UndoManagerHelper::lock()
    1126             :     {
    1127           0 :         m_pImpl->lock();
    1128           0 :     }
    1129             : 
    1130             :     //------------------------------------------------------------------------------------------------------------------
    1131           0 :     void UndoManagerHelper::unlock()
    1132             :     {
    1133           0 :         m_pImpl->unlock();
    1134           0 :     }
    1135             : 
    1136             :     //------------------------------------------------------------------------------------------------------------------
    1137           0 :     ::sal_Bool UndoManagerHelper::isLocked()
    1138             :     {
    1139             :         // SYNCHRONIZED --->
    1140           0 :         ::osl::MutexGuard aGuard( m_pImpl->getMutex() );
    1141             : 
    1142           0 :         IUndoManager& rUndoManager = m_pImpl->getUndoManager();
    1143           0 :         return !rUndoManager.IsUndoEnabled();
    1144             :         // <--- SYNCHRONIZED
    1145             :     }
    1146             : 
    1147             :     //------------------------------------------------------------------------------------------------------------------
    1148           1 :     void UndoManagerHelper::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
    1149             :     {
    1150           1 :         if ( i_listener.is() )
    1151           1 :             m_pImpl->addUndoManagerListener( i_listener );
    1152           1 :     }
    1153             : 
    1154             :     //------------------------------------------------------------------------------------------------------------------
    1155           1 :     void UndoManagerHelper::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
    1156             :     {
    1157           1 :         if ( i_listener.is() )
    1158           1 :             m_pImpl->removeUndoManagerListener( i_listener );
    1159           1 :     }
    1160             : 
    1161             :     //------------------------------------------------------------------------------------------------------------------
    1162           0 :     void UndoManagerHelper::addModifyListener( const Reference< XModifyListener >& i_listener )
    1163             :     {
    1164           0 :         if ( i_listener.is() )
    1165           0 :             m_pImpl->addModifyListener( i_listener );
    1166           0 :     }
    1167             : 
    1168             :     //------------------------------------------------------------------------------------------------------------------
    1169           0 :     void UndoManagerHelper::removeModifyListener( const Reference< XModifyListener >& i_listener )
    1170             :     {
    1171           0 :         if ( i_listener.is() )
    1172           0 :             m_pImpl->removeModifyListener( i_listener );
    1173           0 :     }
    1174             : 
    1175             : //......................................................................................................................
    1176          66 : } // namespace framework
    1177             : //......................................................................................................................
    1178             : 
    1179             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10