LCOV - code coverage report
Current view: top level - framework/source/fwe/helper - undomanagerhelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 406 437 92.9 %
Date: 2012-08-25 Functions: 79 87 90.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 385 714 53.9 %

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

Generated by: LCOV version 1.10