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

Generated by: LCOV version 1.10