diff options
author | Frank Schoenheit [fs] <frank.schoenheit@oracle.com> | 2010-11-09 21:36:57 +0100 |
---|---|---|
committer | Frank Schoenheit [fs] <frank.schoenheit@oracle.com> | 2010-11-09 21:36:57 +0100 |
commit | d729112009418c02a2659b367bcb35a81ee9307c (patch) | |
tree | 0ac612a32368647ba8b7889b1f455edbc3dac40f /sfx2/source/doc/docundomanager.cxx | |
parent | 7b8f9e3ecb2d6cae3edd08c824cb551035d93635 (diff) |
undoapi: step 1 of the migration of css.chart2.XUndoManager to css.document.XUndoManager: separate the DocumentUndoManager into a (SFX-independent) UndoManagerHelper (which later on can be used in chart2) and the SFX-dependent part
Diffstat (limited to 'sfx2/source/doc/docundomanager.cxx')
-rwxr-xr-x | sfx2/source/doc/docundomanager.cxx | 683 |
1 files changed, 126 insertions, 557 deletions
diff --git a/sfx2/source/doc/docundomanager.cxx b/sfx2/source/doc/docundomanager.cxx index ade11d18b05f..39534bf9f90c 100755 --- a/sfx2/source/doc/docundomanager.cxx +++ b/sfx2/source/doc/docundomanager.cxx @@ -42,6 +42,7 @@ #include <comphelper/flagguard.hxx> #include <svl/undo.hxx> #include <tools/diagnose_ex.h> +#include <framework/undomanagerhelper.hxx> #include <stack> @@ -81,310 +82,135 @@ namespace sfx2 using ::svl::IUndoManager; //================================================================================================================== - //= UndoActionWrapper - //================================================================================================================== - class UndoActionWrapper : public SfxUndoAction - { - public: - UndoActionWrapper( - Reference< XUndoAction > const& i_undoAction - ); - virtual ~UndoActionWrapper(); - - virtual String GetComment() const; - virtual void Undo(); - virtual void Redo(); - virtual BOOL CanRepeat(SfxRepeatTarget&) const; - - private: - const Reference< XUndoAction > m_xUndoAction; - }; - - //------------------------------------------------------------------------------------------------------------------ - UndoActionWrapper::UndoActionWrapper( Reference< XUndoAction > const& i_undoAction ) - :SfxUndoAction() - ,m_xUndoAction( i_undoAction ) - { - ENSURE_OR_THROW( m_xUndoAction.is(), "illegal undo action" ); - } - - //------------------------------------------------------------------------------------------------------------------ - UndoActionWrapper::~UndoActionWrapper() - { - try - { - Reference< XComponent > xComponent( m_xUndoAction, UNO_QUERY ); - if ( xComponent.is() ) - xComponent->dispose(); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - } - - //------------------------------------------------------------------------------------------------------------------ - String UndoActionWrapper::GetComment() const - { - String sComment; - try - { - sComment = m_xUndoAction->getTitle(); - } - catch( const Exception& ) - { - DBG_UNHANDLED_EXCEPTION(); - } - return sComment; - } - - //------------------------------------------------------------------------------------------------------------------ - void UndoActionWrapper::Undo() - { - m_xUndoAction->undo(); - } - - //------------------------------------------------------------------------------------------------------------------ - void UndoActionWrapper::Redo() - { - m_xUndoAction->redo(); - } - - //------------------------------------------------------------------------------------------------------------------ - BOOL UndoActionWrapper::CanRepeat(SfxRepeatTarget&) const - { - return FALSE; - } - - //================================================================================================================== //= DocumentUndoManager_Impl //================================================================================================================== - struct DocumentUndoManager_Impl : public SfxUndoListener + struct DocumentUndoManager_Impl : public ::framework::IUndoManagerImplementation { - ::cppu::OInterfaceContainerHelper aUndoListeners; - IUndoManager* pUndoManager; DocumentUndoManager& rAntiImpl; - bool bAPIActionRunning; - ::std::stack< bool > aContextVisibilities; -#if OSL_DEBUG_LEVEL > 0 - ::std::stack< bool > aContextAPIFlags; -#endif + IUndoManager* pUndoManager; + ::framework::UndoManagerHelper aUndoHelper; DocumentUndoManager_Impl( DocumentUndoManager& i_antiImpl ) - :aUndoListeners( i_antiImpl.getMutex() ) - ,pUndoManager( NULL ) - ,rAntiImpl( i_antiImpl ) - ,bAPIActionRunning( false ) + :rAntiImpl( i_antiImpl ) + ,pUndoManager( impl_retrieveUndoManager( i_antiImpl.getBaseModel() ) ) + // do this *before* the construction of aUndoHelper (which actually means: put pUndoManager before + // aUndoHelper in the member list)! + ,aUndoHelper( *this ) { - SfxObjectShell* pObjectShell = i_antiImpl.getBaseModel().GetObjectShell(); - if ( pObjectShell != NULL ) - pUndoManager = pObjectShell->GetUndoManager(); - if ( !pUndoManager ) - throw NotInitializedException( ::rtl::OUString(), *&i_antiImpl.getBaseModel() ); - // TODO: we probably should add ourself as listener to the SfxObjectShell, in case somebody sets a new - // UndoManager - // (well, adding a listener for this is not possible currently, but I also think that setting a new - // UndoManager does not happen in real life) - pUndoManager->AddUndoListener( *this ); } const SfxObjectShell* getObjectShell() const { return rAntiImpl.getBaseModel().GetObjectShell(); } SfxObjectShell* getObjectShell() { return rAntiImpl.getBaseModel().GetObjectShell(); } - //.............................................................................................................. - IUndoManager& getUndoManager() - { - ENSURE_OR_THROW( pUndoManager != NULL, "DocumentUndoManager_Impl::getUndoManager: no access to the doc's UndoManager implementation!" ); - -#if OSL_DEBUG_LEVEL > 0 - // in a non-product build, assert if the current UndoManager at the shell is not the same we obtained - // (and cached) at construction time - SfxObjectShell* pObjectShell = rAntiImpl.getBaseModel().GetObjectShell(); - OSL_ENSURE( ( pObjectShell != NULL ) && ( pUndoManager == pObjectShell->GetUndoManager() ), - "DocumentUndoManager_Impl::getUndoManager: the UndoManager changed meanwhile - what about our listener?" ); -#endif - - return *pUndoManager; - } + // IUndoManagerImplementation + virtual ::osl::Mutex& getMutex(); + virtual ::svl::IUndoManager& getImplUndoManager(); + virtual Reference< XUndoManager > getThis(); void disposing() { + aUndoHelper.disposing(); ENSURE_OR_RETURN_VOID( pUndoManager, "DocumentUndoManager_Impl::disposing: already disposed!" ); - pUndoManager->RemoveUndoListener( *this ); pUndoManager = NULL; } - // SfxUndoListener - virtual void actionUndone( SfxUndoAction& i_action ); - virtual void actionRedone( SfxUndoAction& i_action ); - virtual void undoActionAdded( SfxUndoAction& i_action ); - virtual void cleared(); - virtual void clearedRedo(); - virtual void listActionEntered( const String& i_comment ); - virtual void listActionLeft(); - virtual void listActionLeftAndMerged(); - virtual void listActionCancelled(); - virtual void undoManagerDying(); - - // public operations - void enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden ); - }; + void invalidateXDo_nolck(); + void enterViewStandardMode(); - //================================================================================================================== - namespace - { - //.............................................................................................................. - void lcl_invalidateXDo( const DocumentUndoManager_Impl& i_impl ) + private: + static IUndoManager* impl_retrieveUndoManager( SfxBaseModel& i_baseModel ) { - const SfxObjectShell* pDocShell = i_impl.getObjectShell(); - ENSURE_OR_THROW( pDocShell != NULL, "lcl_invalidateUndo: no access to the doc shell!" ); - SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( pDocShell ); - while ( pViewFrame ) - { - pViewFrame->GetBindings().Invalidate( SID_UNDO ); - pViewFrame->GetBindings().Invalidate( SID_REDO ); - pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDocShell ); - } + IUndoManager* pUndoManager( NULL ); + SfxObjectShell* pObjectShell = i_baseModel.GetObjectShell(); + if ( pObjectShell != NULL ) + pUndoManager = pObjectShell->GetUndoManager(); + if ( !pUndoManager ) + throw NotInitializedException( ::rtl::OUString(), *&i_baseModel ); + return pUndoManager; } - - } + }; //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden ) + ::osl::Mutex& DocumentUndoManager_Impl::getMutex() { - // SYNCHRONIZED ---> - SfxModelGuard aGuard( rAntiImpl ); - - IUndoManager& rUndoManager = getUndoManager(); - if ( !rUndoManager.IsUndoEnabled() ) - // ignore this request if the manager is locked - return; - - if ( i_hidden && ( rUndoManager.GetUndoActionCount( IUndoManager::CurrentLevel ) == 0 ) ) - throw EmptyUndoStackException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "can't enter a hidden context without a previous Undo action" ) ), - static_cast< XUndoManager* >( &rAntiImpl ) - ); - - { - ::comphelper::FlagGuard aNotificationGuard( bAPIActionRunning ); - rUndoManager.EnterListAction( i_title, ::rtl::OUString() ); - } - - aContextVisibilities.push( i_hidden ); - - rAntiImpl.impl_notify( i_title, i_hidden ? &XUndoManagerListener::enteredHiddenContext : &XUndoManagerListener::enteredContext, aGuard ); - // <--- SYNCHRONIZED + return rAntiImpl.getMutex(); } //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::actionUndone( SfxUndoAction& i_action ) + ::svl::IUndoManager& DocumentUndoManager_Impl::getImplUndoManager() { - if ( bAPIActionRunning ) - return; + ENSURE_OR_THROW( pUndoManager != NULL, "DocumentUndoManager_Impl::getImplUndoManager: no access to the doc's UndoManager implementation!" ); - rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::actionUndone ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::actionRedone( SfxUndoAction& i_action ) - { - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::actionRedone ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::undoActionAdded( SfxUndoAction& i_action ) - { - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::undoActionAdded ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::cleared() - { - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( &XUndoManagerListener::allActionsCleared ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::clearedRedo() - { - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( &XUndoManagerListener::redoActionsCleared ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::listActionEntered( const String& i_comment ) - { #if OSL_DEBUG_LEVEL > 0 - aContextAPIFlags.push( bAPIActionRunning ); + // in a non-product build, assert if the current UndoManager at the shell is not the same we obtained + // (and cached) at construction time + SfxObjectShell* pObjectShell = rAntiImpl.getBaseModel().GetObjectShell(); + OSL_ENSURE( ( pObjectShell != NULL ) && ( pUndoManager == pObjectShell->GetUndoManager() ), + "DocumentUndoManager_Impl::getImplUndoManager: the UndoManager changed meanwhile - what about our listener?" ); #endif - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( i_comment, &XUndoManagerListener::enteredContext ); + return *pUndoManager; } - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::listActionLeft() + //------------------------------------------------------------------------------------------------------------------ + Reference< XUndoManager > DocumentUndoManager_Impl::getThis() { -#if OSL_DEBUG_LEVEL > 0 - const bool bCurrentContextIsAPIContext = aContextAPIFlags.top(); - aContextAPIFlags.pop(); - OSL_ENSURE( bCurrentContextIsAPIContext == bAPIActionRunning, "DocumentUndoManager_Impl::listActionLeft: API and non-API contexts interwoven!" ); -#endif - - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( pUndoManager->GetUndoActionComment( 0, IUndoManager::CurrentLevel ), &XUndoManagerListener::leftContext ); + return static_cast< XUndoManager* >( &rAntiImpl ); } - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::listActionLeftAndMerged() + //------------------------------------------------------------------------------------------------------------------ + void DocumentUndoManager_Impl::invalidateXDo_nolck() { -#if OSL_DEBUG_LEVEL > 0 - const bool bCurrentContextIsAPIContext = aContextAPIFlags.top(); - aContextAPIFlags.pop(); - OSL_ENSURE( bCurrentContextIsAPIContext == bAPIActionRunning, "DocumentUndoManager_Impl::listActionLeftAndMerged: API and non-API contexts interwoven!" ); -#endif - - if ( bAPIActionRunning ) - return; + SfxModelGuard aGuard( rAntiImpl ); - rAntiImpl.impl_notify( ::rtl::OUString(), &XUndoManagerListener::leftHiddenContext ); + const SfxObjectShell* pDocShell = getObjectShell(); + ENSURE_OR_THROW( pDocShell != NULL, "lcl_invalidateUndo: no access to the doc shell!" ); + SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( pDocShell ); + while ( pViewFrame ) + { + pViewFrame->GetBindings().Invalidate( SID_UNDO ); + pViewFrame->GetBindings().Invalidate( SID_REDO ); + pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDocShell ); + } } - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::listActionCancelled() + //------------------------------------------------------------------------------------------------------------------ + void DocumentUndoManager_Impl::enterViewStandardMode() { -#if OSL_DEBUG_LEVEL > 0 - const bool bCurrentContextIsAPIContext = aContextAPIFlags.top(); - aContextAPIFlags.pop(); - OSL_ENSURE( bCurrentContextIsAPIContext == bAPIActionRunning, "DocumentUndoManager_Impl::listActionCancelled: API and non-API contexts interwoven!" ); -#endif - - if ( bAPIActionRunning ) - return; - - rAntiImpl.impl_notify( ::rtl::OUString(), &XUndoManagerListener::cancelledContext ); + // TODO: not sure this is a good idea: This might add another action to the Undo/Redo stack, which + // will render the current call somewhat meaningless - finally, the caller can't be sure that really the action + // is undone/redone which s/he intended to. + SfxObjectShell* pDocShell = getObjectShell(); + ENSURE_OR_RETURN_VOID( pDocShell, "DocumentUndoManager_Impl::enterViewStandardMode: do doc shell!" ); + SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( pDocShell ); + while ( pViewFrame ) + { + SfxViewShell* pViewShell = pViewFrame->GetViewShell(); + ENSURE_OR_CONTINUE( pViewShell, "DocumentUndoManager_Impl::enterViewStandardMode: no view shell in the frame!" ); + pViewShell->EnterStandardMode(); + pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDocShell ); + } } - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager_Impl::undoManagerDying() + //================================================================================================================== + //= SfxModelGuardFacade + //================================================================================================================== + class SfxModelGuardFacade : public ::framework::IClearableInstanceLock { - pUndoManager = NULL; - } + public: + SfxModelGuardFacade( SfxModelGuard& i_guard ) + :m_guard( i_guard ) + { + } + + virtual void clear() + { + m_guard.clear(); + } + + private: + SfxModelGuard& m_guard; + }; //================================================================================================================== //= DocumentUndoManager @@ -404,10 +230,6 @@ namespace sfx2 //------------------------------------------------------------------------------------------------------------------ void DocumentUndoManager::disposing() { - EventObject aEvent; - aEvent.Source = static_cast< XUndoManager* >( this ); - m_pImpl->aUndoListeners.disposeAndClear( aEvent ); - m_pImpl->disposing(); } @@ -424,66 +246,20 @@ namespace sfx2 } //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager::impl_notify( ::rtl::OUString const& i_title, void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ), - SfxModelGuard& i_instanceLock ) - { - UndoManagerEvent aEvent; - aEvent.Source = static_cast< XUndoManager* >( this ); - aEvent.UndoActionTitle = i_title; - aEvent.UndoContextDepth = m_pImpl->getUndoManager().GetListActionDepth(); - - i_instanceLock.clear(); - m_pImpl->aUndoListeners.notifyEach( i_notificationMethod, aEvent ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager::impl_notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ), - SfxModelGuard& i_instanceLock ) - { - EventObject aEvent; - aEvent.Source = static_cast< XUndoManager* >( this ); - i_instanceLock.clear(); - m_pImpl->aUndoListeners.notifyEach( i_notificationMethod, aEvent ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager::impl_notify( ::rtl::OUString const& i_title, void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ) ) - { - UndoManagerEvent aEvent; - aEvent.Source = static_cast< XUndoManager* >( this ); - aEvent.UndoActionTitle = i_title; - aEvent.UndoContextDepth = m_pImpl->getUndoManager().GetListActionDepth(); - - // TODO: this notification method here is used by DocumentUndoManager_Impl, to multiplex the notifications we - // receive from the IUndoManager. Those notitications are sent with a locked SolarMutex, which means - // we're doing the multiplexing here with a locked SM, too. Which is Bad (TM). - // Fixing this properly would require outsourcing all the notifications into an own thread - which might lead - // to problems of its own, since clients might expect synchronous notifications. - - m_pImpl->aUndoListeners.notifyEach( i_notificationMethod, aEvent ); - } - - //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager::impl_notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ) ) - { - EventObject aEvent; - aEvent.Source = static_cast< XUndoManager* >( this ); - - // TODO: the same comment as in the other impl_notify, regarding SM locking applies here ... - - m_pImpl->aUndoListeners.notifyEach( i_notificationMethod, aEvent ); - } - - //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::enterUndoContext( const ::rtl::OUString& i_title ) throw (RuntimeException) { - m_pImpl->enterUndoContext( i_title, false ); + SfxModelGuard aGuard( *this ); + m_pImpl->aUndoHelper.enterUndoContext( i_title, SfxModelGuardFacade( aGuard ) ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::enterHiddenUndoContext( ) throw (EmptyUndoStackException, RuntimeException) { - m_pImpl->enterUndoContext( ::rtl::OUString(), true ); + // SYNCHRONIZED ---> + SfxModelGuard aGuard( *this ); + m_pImpl->aUndoHelper.enterHiddenUndoContext( SfxModelGuardFacade( aGuard ) ); + // <--- SYNCHRONIZED + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ @@ -491,38 +267,9 @@ namespace sfx2 { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( !rUndoManager.IsUndoEnabled() ) - // ignore this request if the manager is locked - return; - - if ( !rUndoManager.IsInListAction() ) - throw InvalidStateException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no active undo context" ) ), - static_cast< XUndoManager* >( this ) - ); - - USHORT nContextElements = 0; - bool isHiddenContext = false; - { - ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning ); - - isHiddenContext = m_pImpl->aContextVisibilities.top(); - m_pImpl->aContextVisibilities.pop(); - if ( isHiddenContext ) - nContextElements = rUndoManager.LeaveAndMergeListAction(); - else - nContextElements = rUndoManager.LeaveListAction(); - } - - if ( nContextElements == 0 ) - impl_notify( ::rtl::OUString(), &XUndoManagerListener::cancelledContext, aGuard ); - else if ( isHiddenContext ) - impl_notify( ::rtl::OUString(), &XUndoManagerListener::leftHiddenContext, aGuard ); - else - impl_notify( rUndoManager.GetUndoActionComment( 0, IUndoManager::CurrentLevel ), &XUndoManagerListener::leftContext, aGuard ); + m_pImpl->aUndoHelper.leaveUndoContext( SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ @@ -530,207 +277,73 @@ namespace sfx2 { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - if ( !i_action.is() ) - throw IllegalArgumentException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal undo action object" ) ), - static_cast< XUndoManager* >( this ), - 1 - ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( !rUndoManager.IsUndoEnabled() ) - // ignore the request if the manager is locked - return; - - const bool bHadRedoActions = ( rUndoManager.GetRedoActionCount( IUndoManager::CurrentLevel ) > 0 ); - { - ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning ); - rUndoManager.AddUndoAction( new UndoActionWrapper( i_action ) ); - } - const bool bHasRedoActions = ( rUndoManager.GetRedoActionCount( IUndoManager::CurrentLevel ) > 0 ); - - lcl_invalidateXDo( *m_pImpl ); - impl_notify( i_action->getTitle(), &XUndoManagerListener::undoActionAdded, aGuard ); + m_pImpl->aUndoHelper.addUndoAction( i_action, SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED - - if ( bHadRedoActions && !bHasRedoActions ) - impl_notify( &XUndoManagerListener::redoActionsCleared ); + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ - void DocumentUndoManager::impl_do_nolck( - USHORT ( IUndoManager::*i_checkMethod )( bool const ) const, BOOL ( IUndoManager::*i_doMethod )(), - String ( IUndoManager::*i_titleRetriever )( USHORT, bool const ) const, - void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ) ) + void SAL_CALL DocumentUndoManager::undo( ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException) { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( rUndoManager.IsInListAction() ) - throw UndoContextNotClosedException( ::rtl::OUString(), static_cast< XUndoManager* >( this ) ); - - if ( (rUndoManager.*i_checkMethod)( IUndoManager::TopLevel ) == 0 ) - throw EmptyUndoStackException( ::rtl::OUString::createFromAscii( "stack is empty" ), static_cast< XUndoManager* >( this ) ); - - // let all views enter the standard mode - // TODO: not sure this is a good idea: This might add another action to the Undo/Redo stack, which - // will render the call somewhat meaningless - finally, the caller can't be sure that really the action - // is undone/redone which s/he intended to. - SfxObjectShell* pDocShell = m_pImpl->getObjectShell(); - OSL_ENSURE( pDocShell, "DocumentUndoManager::impl_do_nolck: do doc shell!" ); - if ( pDocShell ) - { - SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( pDocShell ); - while ( pViewFrame ) - { - SfxViewShell* pViewShell = pViewFrame->GetViewShell(); - ENSURE_OR_CONTINUE( pViewShell, "DocumentUndoManager::impl_do_nolck: no view shell in the frame!" ); - pViewShell->EnterStandardMode(); - pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDocShell ); - } - } - - const ::rtl::OUString sUndoActionTitle = (rUndoManager.*i_titleRetriever)( 0, IUndoManager::TopLevel ); - { - ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning ); - try - { - (rUndoManager.*i_doMethod)(); - } - catch( const RuntimeException& ) { /* allowed to leave here */ throw; } - catch( const UndoFailedException& ) { /* allowed to leave here */ throw; } - catch( const Exception& ) - { - // not allowed to leave - const Any aError( ::cppu::getCaughtException() ); - throw UndoFailedException( ::rtl::OUString(), static_cast< XUndoManager* >( this ), aError ); - } - } - - impl_notify( sUndoActionTitle, i_notificationMethod, aGuard ); + m_pImpl->enterViewStandardMode(); + m_pImpl->aUndoHelper.undo( SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED - } - - //------------------------------------------------------------------------------------------------------------------ - void SAL_CALL DocumentUndoManager::undo( ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException) - { - impl_do_nolck( - &IUndoManager::GetUndoActionCount, - &IUndoManager::Undo, - &IUndoManager::GetUndoActionComment, - &XUndoManagerListener::actionUndone - ); + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::redo( ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException) { - impl_do_nolck( - &IUndoManager::GetRedoActionCount, - &IUndoManager::Redo, - &IUndoManager::GetRedoActionComment, - &XUndoManagerListener::actionRedone - ); - } - - //------------------------------------------------------------------------------------------------------------------ - ::sal_Bool SAL_CALL DocumentUndoManager::isUndoPossible( ) throw (RuntimeException) - { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( rUndoManager.IsInListAction() ) - return sal_False; - return rUndoManager.GetUndoActionCount( IUndoManager::TopLevel ) > 0; + m_pImpl->enterViewStandardMode(); + m_pImpl->aUndoHelper.redo( SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ - ::sal_Bool SAL_CALL DocumentUndoManager::isRedoPossible( ) throw (RuntimeException) + ::sal_Bool SAL_CALL DocumentUndoManager::isUndoPossible( ) throw (RuntimeException) { - // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( rUndoManager.IsInListAction() ) - return sal_False; - return rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ) > 0; - // <--- SYNCHRONIZED + return m_pImpl->aUndoHelper.isUndoPossible(); } //------------------------------------------------------------------------------------------------------------------ - namespace + ::sal_Bool SAL_CALL DocumentUndoManager::isRedoPossible( ) throw (RuntimeException) { - //.............................................................................................................. - ::rtl::OUString lcl_getCurrentActionTitle( DocumentUndoManager_Impl& i_impl, const bool i_undo ) - { - // SYNCHRONIZED ---> - SfxModelGuard aGuard( i_impl.rAntiImpl ); - - const IUndoManager& rUndoManager = i_impl.getUndoManager(); - const USHORT nActionCount = i_undo - ? rUndoManager.GetUndoActionCount( IUndoManager::TopLevel ) - : rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ); - if ( nActionCount == 0 ) - throw EmptyUndoStackException( - i_undo ? ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no action on the undo stack" ) ) - : ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "no action on the redo stack" ) ), - static_cast< XUndoManager* >( &i_impl.rAntiImpl ) - ); - return i_undo - ? rUndoManager.GetUndoActionComment( 0, IUndoManager::TopLevel ) - : rUndoManager.GetRedoActionComment( 0, IUndoManager::TopLevel ); - // <--- SYNCHRONIZED - } - - //.............................................................................................................. - Sequence< ::rtl::OUString > lcl_getAllActionTitles( DocumentUndoManager_Impl& i_impl, const bool i_undo ) - { - // SYNCHRONIZED ---> - SfxModelGuard aGuard( i_impl.rAntiImpl ); - - const IUndoManager& rUndoManager = i_impl.getUndoManager(); - const sal_Int32 nCount = i_undo - ? rUndoManager.GetUndoActionCount( IUndoManager::TopLevel ) - : rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ); - - Sequence< ::rtl::OUString > aTitles( nCount ); - for ( sal_Int32 i=0; i<nCount; ++i ) - { - aTitles[i] = i_undo - ? rUndoManager.GetUndoActionComment( i, IUndoManager::TopLevel ) - : rUndoManager.GetRedoActionComment( i, IUndoManager::TopLevel ); - } - return aTitles; - // <--- SYNCHRONIZED - } + SfxModelGuard aGuard( *this ); + return m_pImpl->aUndoHelper.isRedoPossible(); } //------------------------------------------------------------------------------------------------------------------ ::rtl::OUString SAL_CALL DocumentUndoManager::getCurrentUndoActionTitle( ) throw (EmptyUndoStackException, RuntimeException) { - return lcl_getCurrentActionTitle( *m_pImpl, true ); + SfxModelGuard aGuard( *this ); + return m_pImpl->aUndoHelper.getCurrentUndoActionTitle(); } //------------------------------------------------------------------------------------------------------------------ ::rtl::OUString SAL_CALL DocumentUndoManager::getCurrentRedoActionTitle( ) throw (EmptyUndoStackException, RuntimeException) { - return lcl_getCurrentActionTitle( *m_pImpl, false ); + SfxModelGuard aGuard( *this ); + return m_pImpl->aUndoHelper.getCurrentRedoActionTitle(); } //------------------------------------------------------------------------------------------------------------------ Sequence< ::rtl::OUString > SAL_CALL DocumentUndoManager::getAllUndoActionTitles( ) throw (RuntimeException) { - return lcl_getAllActionTitles( *m_pImpl, true ); + SfxModelGuard aGuard( *this ); + return m_pImpl->aUndoHelper.getAllUndoActionTitles(); } //------------------------------------------------------------------------------------------------------------------ Sequence< ::rtl::OUString > SAL_CALL DocumentUndoManager::getAllRedoActionTitles( ) throw (RuntimeException) { - return lcl_getAllActionTitles( *m_pImpl, false ); + SfxModelGuard aGuard( *this ); + return m_pImpl->aUndoHelper.getAllRedoActionTitles(); } //------------------------------------------------------------------------------------------------------------------ @@ -738,17 +351,9 @@ namespace sfx2 { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( rUndoManager.IsInListAction() ) - throw UndoContextNotClosedException( ::rtl::OUString(), static_cast< XUndoManager* >( this ) ); - - { - ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning ); - rUndoManager.Clear(); - } - impl_notify( &XUndoManagerListener::allActionsCleared, aGuard ); + m_pImpl->aUndoHelper.clear( SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ @@ -756,17 +361,9 @@ namespace sfx2 { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( rUndoManager.IsInListAction() ) - throw UndoContextNotClosedException( ::rtl::OUString(), static_cast< XUndoManager* >( this ) ); - - { - ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning ); - rUndoManager.ClearRedo(); - } - impl_notify( &XUndoManagerListener::redoActionsCleared, aGuard ); + m_pImpl->aUndoHelper.clearRedo( SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ @@ -774,72 +371,44 @@ namespace sfx2 { // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - { - ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning ); - while ( rUndoManager.IsInListAction() ) - rUndoManager.LeaveListAction(); - rUndoManager.Clear(); - } - - impl_notify( &XUndoManagerListener::resetAll, aGuard ); + m_pImpl->aUndoHelper.reset( SfxModelGuardFacade( aGuard ) ); // <--- SYNCHRONIZED + m_pImpl->invalidateXDo_nolck(); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::lock( ) throw (RuntimeException) { - // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - rUndoManager.EnableUndo( false ); - // <--- SYNCHRONIZED + m_pImpl->aUndoHelper.lock(); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::unlock( ) throw (RuntimeException, NotLockedException) { - // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - if ( rUndoManager.IsUndoEnabled() ) - throw NotLockedException( ::rtl::OUString::createFromAscii( "Undo manager is not locked" ), static_cast< XUndoManager* >( this ) ); - rUndoManager.EnableUndo( true ); - // <--- SYNCHRONIZED + m_pImpl->aUndoHelper.unlock(); } //------------------------------------------------------------------------------------------------------------------ ::sal_Bool SAL_CALL DocumentUndoManager::isLocked( ) throw (RuntimeException) { - // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - - IUndoManager& rUndoManager = m_pImpl->getUndoManager(); - return !rUndoManager.IsUndoEnabled(); - // <--- SYNCHRONIZED + return m_pImpl->aUndoHelper.isLocked(); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) throw (RuntimeException) { - // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - if ( i_listener.is() ) - m_pImpl->aUndoListeners.addInterface( i_listener ); - // <--- SYNCHRONIZED + return m_pImpl->aUndoHelper.addUndoManagerListener( i_listener ); } //------------------------------------------------------------------------------------------------------------------ void SAL_CALL DocumentUndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) throw (RuntimeException) { - // SYNCHRONIZED ---> SfxModelGuard aGuard( *this ); - if ( i_listener.is() ) - m_pImpl->aUndoListeners.removeInterface( i_listener ); - // <--- SYNCHRONIZED + return m_pImpl->aUndoHelper.removeUndoManagerListener( i_listener ); } //...................................................................................................................... |