summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xframework/inc/helper/undomanagerhelper.hxx147
-rw-r--r--framework/prj/d.lst1
-rw-r--r--framework/source/helper/makefile.mk49
-rwxr-xr-xframework/source/helper/undomanagerhelper.cxx754
-rw-r--r--framework/util/makefile.mk4
-rwxr-xr-xsfx2/qa/complex/sfx2/UndoManager.java2
-rwxr-xr-xsfx2/source/doc/docundomanager.cxx683
-rwxr-xr-xsfx2/source/inc/docundomanager.hxx28
8 files changed, 1056 insertions, 612 deletions
diff --git a/framework/inc/helper/undomanagerhelper.hxx b/framework/inc/helper/undomanagerhelper.hxx
new file mode 100755
index 000000000000..98503e08144f
--- /dev/null
+++ b/framework/inc/helper/undomanagerhelper.hxx
@@ -0,0 +1,147 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef FRAMEWORK_UNDOMANAGERHELPER_HXX
+#define FRAMEWORK_UNDOMANAGERHELPER_HXX
+
+/** === begin UNO includes === **/
+#include <com/sun/star/document/XUndoManager.hpp>
+/** === end UNO includes === **/
+
+#include <boost/scoped_ptr.hpp>
+
+namespace osl
+{
+ class Mutex;
+}
+
+namespace svl
+{
+ class IUndoManager;
+}
+
+//......................................................................................................................
+namespace framework
+{
+//......................................................................................................................
+
+ //==================================================================================================================
+ //= IUndoManagerImplementation
+ //==================================================================================================================
+ class SAL_NO_VTABLE IUndoManagerImplementation
+ {
+ public:
+ /** returns the mutex which is protecting the instance. Needed for listener administration synchronization.
+
+ Note that the mutex will <em>not</em> be used for multi-threading safety of the UndoManagerHelper.
+ */
+ virtual ::osl::Mutex& getMutex() = 0;
+
+ /** returns the IUndoManager interface to the actual Undo stack
+
+ @throws com::sun::star::lang::DisposedException
+ when the instance is already disposed, and no IUndoManager can be provided
+
+ @throws com::sun::star::lang::NotInitializedException
+ when the instance is not initialized, yet, and no IUndoManager can be provided
+ */
+ virtual ::svl::IUndoManager& getImplUndoManager() = 0;
+
+ /** provides access to an UNO interface for the XUndoManager implementation. Used when throwing exceptions.
+ */
+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::document::XUndoManager >
+ getThis() = 0;
+ };
+
+ //==================================================================================================================
+ //= IClearableInstanceLock
+ //==================================================================================================================
+ /** helper class for releasing a lock
+
+ Since clients of UndoManagerHelper are responsible for locking their instance, but the UndoManagerHelper
+ needs to notify its listeners, and this needs to happen without any instance lock, all affected methods
+ take an IClearableInstanceLock parameter, to be able to clear the owner's lock before doing any notifications.
+ */
+ class SAL_NO_VTABLE IClearableInstanceLock
+ {
+ public:
+ virtual void clear() = 0;
+ };
+
+ //==================================================================================================================
+ //= UndoManagerHelper
+ //==================================================================================================================
+ class UndoManagerHelper_Impl;
+ /** helper class for implementing an XUndoManager
+
+ The class defines the same methods as an XUndoManager does, but lacks certain aspects of a full-blown UNO
+ component. In particular, it is the responsibility of the owner of the instance to care for multi-threading
+ safety, and for disposal checks.
+ */
+ class UndoManagerHelper
+ {
+ public:
+ UndoManagerHelper( IUndoManagerImplementation& i_undoManagerImpl );
+ ~UndoManagerHelper();
+
+ // life time control
+ void disposing();
+
+ // XUndoManager equivalents
+ void enterUndoContext( const ::rtl::OUString& i_title, IClearableInstanceLock& i_instanceLock );
+ void enterHiddenUndoContext( IClearableInstanceLock& i_instanceLock );
+ void leaveUndoContext( IClearableInstanceLock& i_instanceLock );
+ void addUndoAction( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XUndoAction >& i_action, IClearableInstanceLock& i_instanceLock );
+ void undo( IClearableInstanceLock& i_instanceLock );
+ void redo( IClearableInstanceLock& i_instanceLock );
+ ::sal_Bool isUndoPossible() const;
+ ::sal_Bool isRedoPossible() const;
+ ::rtl::OUString getCurrentUndoActionTitle() const;
+ ::rtl::OUString getCurrentRedoActionTitle() const;
+ ::com::sun::star::uno::Sequence< ::rtl::OUString >
+ getAllUndoActionTitles() const;
+ ::com::sun::star::uno::Sequence< ::rtl::OUString >
+ getAllRedoActionTitles() const;
+ void clear( IClearableInstanceLock& i_instanceLock );
+ void clearRedo( IClearableInstanceLock& i_instanceLock );
+ void reset( IClearableInstanceLock& i_instanceLock );
+ void addUndoManagerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XUndoManagerListener >& i_listener );
+ void removeUndoManagerListener( const ::com::sun::star::uno::Reference< ::com::sun::star::document::XUndoManagerListener >& i_listener );
+
+ // XLockable, base of XUndoManager, equivalents
+ void lock();
+ void unlock();
+ ::sal_Bool isLocked();
+
+ private:
+ ::boost::scoped_ptr< UndoManagerHelper_Impl > m_pImpl;
+ };
+
+//......................................................................................................................
+} // namespace framework
+//......................................................................................................................
+
+#endif // FRAMEWORK_UNDOMANAGERHELPER_HXX
diff --git a/framework/prj/d.lst b/framework/prj/d.lst
index d9d030d95b5e..fb83f9a205e5 100644
--- a/framework/prj/d.lst
+++ b/framework/prj/d.lst
@@ -44,6 +44,7 @@ mkdir: %_DEST%\xml%_EXT%\uiconfig\modules\StartModule\statusbar
..\inc\helper\titlehelper.hxx %_DEST%\inc%_EXT%\framework\titlehelper.hxx
..\inc\classes\framelistanalyzer.hxx %_DEST%\inc%_EXT%\framework\framelistanalyzer.hxx
..\inc\helper\documentundoguard.hxx %_DEST%\inc%_EXT%\framework\documentundoguard.hxx
+..\inc\helper\undomanagerhelper.hxx %_DEST%\inc%_EXT%\framework\undomanagerhelper.hxx
..\uiconfig\startmodule\menubar\*.xml %_DEST%\xml%_EXT%\uiconfig\modules\StartModule\menubar\*.xml
..\uiconfig\startmodule\toolbar\*.xml %_DEST%\xml%_EXT%\uiconfig\modules\StartModule\toolbar\*.xml
diff --git a/framework/source/helper/makefile.mk b/framework/source/helper/makefile.mk
index 158fba424c51..9199f556ff2d 100644
--- a/framework/source/helper/makefile.mk
+++ b/framework/source/helper/makefile.mk
@@ -24,7 +24,7 @@
# for a copy of the LGPLv3 License.
#
#*************************************************************************
-PRJ=..$/..
+PRJ=../..
PRJNAME= framework
TARGET= fwk_helper
@@ -41,29 +41,30 @@ CDEFS+=-DCOMPMOD_NAMESPACE=framework
# --- Generate -----------------------------------------------------
-SLOFILES= $(SLO)$/ocomponentaccess.obj \
- $(SLO)$/ocomponentenumeration.obj \
- $(SLO)$/oframes.obj \
- $(SLO)$/statusindicatorfactory.obj \
- $(SLO)$/statusindicator.obj \
- $(SLO)$/imageproducer.obj \
- $(SLO)$/propertysetcontainer.obj \
- $(SLO)$/actiontriggerhelper.obj \
- $(SLO)$/persistentwindowstate.obj \
- $(SLO)$/networkdomain.obj \
- $(SLO)$/acceleratorinfo.obj \
- $(SLO)$/uielementwrapperbase.obj \
- $(SLO)$/dockingareadefaultacceptor.obj \
- $(SLO)$/uiconfigelementwrapperbase.obj \
- $(SLO)$/shareablemutex.obj \
- $(SLO)$/vclstatusindicator.obj \
- $(SLO)$/wakeupthread.obj \
- $(SLO)$/configimporter.obj \
- $(SLO)$/tagwindowasmodified.obj \
- $(SLO)$/titlebarupdate.obj \
- $(SLO)$/titlehelper.obj \
- $(SLO)$/mischelper.obj \
- $(SLO)$/documentundoguard.obj \
+SLOFILES= $(SLO)/ocomponentaccess.obj \
+ $(SLO)/ocomponentenumeration.obj \
+ $(SLO)/oframes.obj \
+ $(SLO)/statusindicatorfactory.obj \
+ $(SLO)/statusindicator.obj \
+ $(SLO)/imageproducer.obj \
+ $(SLO)/propertysetcontainer.obj \
+ $(SLO)/actiontriggerhelper.obj \
+ $(SLO)/persistentwindowstate.obj \
+ $(SLO)/networkdomain.obj \
+ $(SLO)/acceleratorinfo.obj \
+ $(SLO)/uielementwrapperbase.obj \
+ $(SLO)/dockingareadefaultacceptor.obj \
+ $(SLO)/uiconfigelementwrapperbase.obj \
+ $(SLO)/shareablemutex.obj \
+ $(SLO)/vclstatusindicator.obj \
+ $(SLO)/wakeupthread.obj \
+ $(SLO)/configimporter.obj \
+ $(SLO)/tagwindowasmodified.obj \
+ $(SLO)/titlebarupdate.obj \
+ $(SLO)/titlehelper.obj \
+ $(SLO)/mischelper.obj \
+ $(SLO)/documentundoguard.obj \
+ $(SLO)/undomanagerhelper.obj \
# --- Targets ------------------------------------------------------
diff --git a/framework/source/helper/undomanagerhelper.cxx b/framework/source/helper/undomanagerhelper.cxx
new file mode 100755
index 000000000000..4831d3fff43d
--- /dev/null
+++ b/framework/source/helper/undomanagerhelper.cxx
@@ -0,0 +1,754 @@
+/*************************************************************************
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "precompiled_framework.hxx"
+
+#include "helper/undomanagerhelper.hxx"
+
+/** === begin UNO includes === **/
+#include <com/sun/star/lang/XComponent.hpp>
+/** === end UNO includes === **/
+
+#include <cppuhelper/interfacecontainer.hxx>
+#include <comphelper/flagguard.hxx>
+#include <svl/undo.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <stack>
+
+//......................................................................................................................
+namespace framework
+{
+//......................................................................................................................
+
+ /** === begin UNO using === **/
+ using ::com::sun::star::uno::Reference;
+ using ::com::sun::star::uno::XInterface;
+ using ::com::sun::star::uno::UNO_QUERY;
+ using ::com::sun::star::uno::UNO_QUERY_THROW;
+ using ::com::sun::star::uno::UNO_SET_THROW;
+ using ::com::sun::star::uno::Exception;
+ using ::com::sun::star::uno::RuntimeException;
+ using ::com::sun::star::uno::Any;
+ using ::com::sun::star::uno::makeAny;
+ using ::com::sun::star::uno::Sequence;
+ using ::com::sun::star::uno::Type;
+ using ::com::sun::star::document::XUndoManagerListener;
+ using ::com::sun::star::document::UndoManagerEvent;
+ using ::com::sun::star::document::EmptyUndoStackException;
+ using ::com::sun::star::document::UndoContextNotClosedException;
+ using ::com::sun::star::document::UndoFailedException;
+ using ::com::sun::star::util::NotLockedException;
+ using ::com::sun::star::lang::EventObject;
+ using ::com::sun::star::document::XUndoAction;
+ using ::com::sun::star::lang::XComponent;
+ using ::com::sun::star::document::XUndoManager;
+ using ::com::sun::star::util::InvalidStateException;
+ using ::com::sun::star::lang::IllegalArgumentException;
+ /** === end UNO using === **/
+ 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;
+ }
+
+ //==================================================================================================================
+ //= UndoManagerHelper_Impl
+ //==================================================================================================================
+ class UndoManagerHelper_Impl : public SfxUndoListener
+ {
+ public:
+ ::cppu::OInterfaceContainerHelper aUndoListeners;
+ IUndoManagerImplementation& rUndoManagerImplementation;
+ UndoManagerHelper& rAntiImpl;
+ bool bAPIActionRunning;
+ ::std::stack< bool > aContextVisibilities;
+#if OSL_DEBUG_LEVEL > 0
+ ::std::stack< bool > aContextAPIFlags;
+#endif
+
+ UndoManagerHelper_Impl( UndoManagerHelper& i_antiImpl, IUndoManagerImplementation& i_undoManagerImpl )
+ :aUndoListeners( i_undoManagerImpl.getMutex() )
+ ,rUndoManagerImplementation( i_undoManagerImpl )
+ ,rAntiImpl( i_antiImpl )
+ ,bAPIActionRunning( false )
+ {
+ getUndoManager().AddUndoListener( *this );
+ }
+
+ virtual ~UndoManagerHelper_Impl()
+ {
+ }
+
+ //..............................................................................................................
+ IUndoManager& getUndoManager()
+ {
+ return rUndoManagerImplementation.getImplUndoManager();
+ }
+
+ //..............................................................................................................
+ Reference< XUndoManager > getXUndoManager()
+ {
+ return rUndoManagerImplementation.getThis();
+ }
+
+ //..............................................................................................................
+ void disposing()
+ {
+ EventObject aEvent;
+ aEvent.Source = getXUndoManager();
+ aUndoListeners.disposeAndClear( aEvent );
+
+ getUndoManager().RemoveUndoListener( *this );
+ }
+
+ // 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, IClearableInstanceLock& i_instanceLock );
+
+ void doUndoRedo(
+ USHORT ( ::svl::IUndoManager::*i_checkMethod )( bool const ) const,
+ BOOL ( ::svl::IUndoManager::*i_doMethod )(),
+ UniString ( ::svl::IUndoManager::*i_titleRetriever )( USHORT, bool const ) const,
+ void ( SAL_CALL ::com::sun::star::document::XUndoManagerListener::*i_notificationMethod )( const ::com::sun::star::document::UndoManagerEvent& ),
+ IClearableInstanceLock& i_instanceLock
+ );
+ void notify( ::rtl::OUString const& i_title,
+ void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ),
+ IClearableInstanceLock& i_instanceLock
+ );
+ void notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ),
+ IClearableInstanceLock& i_instanceLock
+ );
+ void notify( ::rtl::OUString const& i_title,
+ void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& )
+ );
+ void notify(
+ void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& )
+ );
+ };
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::notify( ::rtl::OUString const& i_title, void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ),
+ IClearableInstanceLock& i_instanceLock )
+ {
+ UndoManagerEvent aEvent;
+ aEvent.Source = getXUndoManager();
+ aEvent.UndoActionTitle = i_title;
+ aEvent.UndoContextDepth = getUndoManager().GetListActionDepth();
+
+ i_instanceLock.clear();
+ aUndoListeners.notifyEach( i_notificationMethod, aEvent );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ),
+ IClearableInstanceLock& i_instanceLock )
+ {
+ EventObject aEvent;
+ aEvent.Source = getXUndoManager();
+ i_instanceLock.clear();
+ aUndoListeners.notifyEach( i_notificationMethod, aEvent );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::notify( ::rtl::OUString const& i_title,
+ void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const UndoManagerEvent& ) )
+ {
+ UndoManagerEvent aEvent;
+ aEvent.Source = getXUndoManager();
+ aEvent.UndoActionTitle = i_title;
+ aEvent.UndoContextDepth = getUndoManager().GetListActionDepth();
+
+ // TODO: this notification method here is used by UndoManagerHelper_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.
+
+ aUndoListeners.notifyEach( i_notificationMethod, aEvent );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::notify( void ( SAL_CALL XUndoManagerListener::*i_notificationMethod )( const EventObject& ) )
+ {
+ EventObject aEvent;
+ aEvent.Source = getXUndoManager();
+
+ // TODO: the same comment as in the other notify, regarding SM locking applies here ...
+
+ aUndoListeners.notifyEach( i_notificationMethod, aEvent );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden, IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ 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" ) ),
+ rUndoManagerImplementation.getThis()
+ );
+
+ {
+ ::comphelper::FlagGuard aNotificationGuard( bAPIActionRunning );
+ rUndoManager.EnterListAction( i_title, ::rtl::OUString() );
+ }
+
+ aContextVisibilities.push( i_hidden );
+
+ notify( i_title, i_hidden ? &XUndoManagerListener::enteredHiddenContext : &XUndoManagerListener::enteredContext, i_instanceLock );
+ // <--- SYNCHRONIZED
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::doUndoRedo(
+ 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& ),
+ IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ IUndoManager& rUndoManager = getUndoManager();
+ if ( rUndoManager.IsInListAction() )
+ throw UndoContextNotClosedException( ::rtl::OUString(), getXUndoManager() );
+
+ if ( (rUndoManager.*i_checkMethod)( IUndoManager::TopLevel ) == 0 )
+ throw EmptyUndoStackException( ::rtl::OUString::createFromAscii( "stack is empty" ), getXUndoManager() );
+
+ const ::rtl::OUString sUndoActionTitle = (rUndoManager.*i_titleRetriever)( 0, IUndoManager::TopLevel );
+ {
+ ::comphelper::FlagGuard aNotificationGuard( 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(), getXUndoManager(), aError );
+ }
+ }
+
+ notify( sUndoActionTitle, i_notificationMethod, i_instanceLock );
+ // <--- SYNCHRONIZED
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::actionUndone( SfxUndoAction& i_action )
+ {
+ if ( bAPIActionRunning )
+ return;
+
+ notify( i_action.GetComment(), &XUndoManagerListener::actionUndone );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::actionRedone( SfxUndoAction& i_action )
+ {
+ if ( bAPIActionRunning )
+ return;
+
+ notify( i_action.GetComment(), &XUndoManagerListener::actionRedone );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::undoActionAdded( SfxUndoAction& i_action )
+ {
+ if ( bAPIActionRunning )
+ return;
+
+ notify( i_action.GetComment(), &XUndoManagerListener::undoActionAdded );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::cleared()
+ {
+ if ( bAPIActionRunning )
+ return;
+
+ notify( &XUndoManagerListener::allActionsCleared );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::clearedRedo()
+ {
+ if ( bAPIActionRunning )
+ return;
+
+ notify( &XUndoManagerListener::redoActionsCleared );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::listActionEntered( const String& i_comment )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ aContextAPIFlags.push( bAPIActionRunning );
+#endif
+
+ if ( bAPIActionRunning )
+ return;
+
+ notify( i_comment, &XUndoManagerListener::enteredContext );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::listActionLeft()
+ {
+#if OSL_DEBUG_LEVEL > 0
+ const bool bCurrentContextIsAPIContext = aContextAPIFlags.top();
+ aContextAPIFlags.pop();
+ OSL_ENSURE( bCurrentContextIsAPIContext == bAPIActionRunning, "UndoManagerHelper_Impl::listActionLeft: API and non-API contexts interwoven!" );
+#endif
+
+ if ( bAPIActionRunning )
+ return;
+
+ notify( getUndoManager().GetUndoActionComment( 0, IUndoManager::CurrentLevel ), &XUndoManagerListener::leftContext );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::listActionLeftAndMerged()
+ {
+#if OSL_DEBUG_LEVEL > 0
+ const bool bCurrentContextIsAPIContext = aContextAPIFlags.top();
+ aContextAPIFlags.pop();
+ OSL_ENSURE( bCurrentContextIsAPIContext == bAPIActionRunning, "UndoManagerHelper_Impl::listActionLeftAndMerged: API and non-API contexts interwoven!" );
+#endif
+
+ if ( bAPIActionRunning )
+ return;
+
+ notify( ::rtl::OUString(), &XUndoManagerListener::leftHiddenContext );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::listActionCancelled()
+ {
+#if OSL_DEBUG_LEVEL > 0
+ const bool bCurrentContextIsAPIContext = aContextAPIFlags.top();
+ aContextAPIFlags.pop();
+ OSL_ENSURE( bCurrentContextIsAPIContext == bAPIActionRunning, "UndoManagerHelper_Impl::listActionCancelled: API and non-API contexts interwoven!" );
+#endif
+
+ if ( bAPIActionRunning )
+ return;
+
+ notify( ::rtl::OUString(), &XUndoManagerListener::cancelledContext );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper_Impl::undoManagerDying()
+ {
+ // TODO: do we need to care? Or is this the responsibility of our owner?
+ }
+
+ //==================================================================================================================
+ //= UndoManagerHelper
+ //==================================================================================================================
+ //------------------------------------------------------------------------------------------------------------------
+ UndoManagerHelper::UndoManagerHelper( IUndoManagerImplementation& i_undoManagerImpl )
+ :m_pImpl( new UndoManagerHelper_Impl( *this, i_undoManagerImpl ) )
+ {
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ UndoManagerHelper::~UndoManagerHelper()
+ {
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::disposing()
+ {
+ m_pImpl->disposing();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::enterUndoContext( const ::rtl::OUString& i_title, IClearableInstanceLock& i_instanceLock )
+ {
+ m_pImpl->enterUndoContext( i_title, false, i_instanceLock );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::enterHiddenUndoContext( IClearableInstanceLock& i_instanceLock )
+ {
+ m_pImpl->enterUndoContext( ::rtl::OUString(), true, i_instanceLock );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::leaveUndoContext( IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ 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" ) ),
+ m_pImpl->getXUndoManager()
+ );
+
+ 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 )
+ m_pImpl->notify( ::rtl::OUString(), &XUndoManagerListener::cancelledContext, i_instanceLock );
+ else if ( isHiddenContext )
+ m_pImpl->notify( ::rtl::OUString(), &XUndoManagerListener::leftHiddenContext, i_instanceLock );
+ else
+ m_pImpl->notify( rUndoManager.GetUndoActionComment( 0, IUndoManager::CurrentLevel ), &XUndoManagerListener::leftContext, i_instanceLock );
+ // <--- SYNCHRONIZED
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::addUndoAction( const Reference< XUndoAction >& i_action, IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ if ( !i_action.is() )
+ throw IllegalArgumentException(
+ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal undo action object" ) ),
+ m_pImpl->getXUndoManager(),
+ 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 );
+
+ m_pImpl->notify( i_action->getTitle(), &XUndoManagerListener::undoActionAdded, i_instanceLock );
+ // <--- SYNCHRONIZED
+
+ if ( bHadRedoActions && !bHasRedoActions )
+ m_pImpl->notify( &XUndoManagerListener::redoActionsCleared );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::undo( IClearableInstanceLock& i_instanceLock )
+ {
+ m_pImpl->doUndoRedo(
+ &IUndoManager::GetUndoActionCount,
+ &IUndoManager::Undo,
+ &IUndoManager::GetUndoActionComment,
+ &XUndoManagerListener::actionUndone,
+ i_instanceLock
+ );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::redo( IClearableInstanceLock& i_instanceLock )
+ {
+ m_pImpl->doUndoRedo(
+ &IUndoManager::GetRedoActionCount,
+ &IUndoManager::Redo,
+ &IUndoManager::GetRedoActionComment,
+ &XUndoManagerListener::actionRedone,
+ i_instanceLock
+ );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::sal_Bool UndoManagerHelper::isUndoPossible() const
+ {
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ if ( rUndoManager.IsInListAction() )
+ return sal_False;
+ return rUndoManager.GetUndoActionCount( IUndoManager::TopLevel ) > 0;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::sal_Bool UndoManagerHelper::isRedoPossible() const
+ {
+ const IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ if ( rUndoManager.IsInListAction() )
+ return sal_False;
+ return rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ) > 0;
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ namespace
+ {
+ //..............................................................................................................
+ ::rtl::OUString lcl_getCurrentActionTitle( UndoManagerHelper_Impl& i_impl, const bool i_undo )
+ {
+ 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" ) ),
+ i_impl.getXUndoManager()
+ );
+ return i_undo
+ ? rUndoManager.GetUndoActionComment( 0, IUndoManager::TopLevel )
+ : rUndoManager.GetRedoActionComment( 0, IUndoManager::TopLevel );
+ }
+
+ //..............................................................................................................
+ Sequence< ::rtl::OUString > lcl_getAllActionTitles( UndoManagerHelper_Impl& i_impl, const bool i_undo )
+ {
+ const IUndoManager& rUndoManager = i_impl.getUndoManager();
+ const USHORT nCount = i_undo
+ ? rUndoManager.GetUndoActionCount( IUndoManager::TopLevel )
+ : rUndoManager.GetRedoActionCount( IUndoManager::TopLevel );
+
+ Sequence< ::rtl::OUString > aTitles( nCount );
+ for ( USHORT i=0; i<nCount; ++i )
+ {
+ aTitles[i] = i_undo
+ ? rUndoManager.GetUndoActionComment( i, IUndoManager::TopLevel )
+ : rUndoManager.GetRedoActionComment( i, IUndoManager::TopLevel );
+ }
+ return aTitles;
+ }
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString UndoManagerHelper::getCurrentUndoActionTitle() const
+ {
+ return lcl_getCurrentActionTitle( *m_pImpl, true );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::rtl::OUString UndoManagerHelper::getCurrentRedoActionTitle() const
+ {
+ return lcl_getCurrentActionTitle( *m_pImpl, false );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Sequence< ::rtl::OUString > UndoManagerHelper::getAllUndoActionTitles() const
+ {
+ return lcl_getAllActionTitles( *m_pImpl, true );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ Sequence< ::rtl::OUString > UndoManagerHelper::getAllRedoActionTitles() const
+ {
+ return lcl_getAllActionTitles( *m_pImpl, false );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::clear( IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ if ( rUndoManager.IsInListAction() )
+ throw UndoContextNotClosedException( ::rtl::OUString(), m_pImpl->getXUndoManager() );
+
+ {
+ ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning );
+ rUndoManager.Clear();
+ }
+
+ m_pImpl->notify( &XUndoManagerListener::allActionsCleared, i_instanceLock );
+ // <--- SYNCHRONIZED
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::clearRedo( IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ if ( rUndoManager.IsInListAction() )
+ throw UndoContextNotClosedException( ::rtl::OUString(), m_pImpl->getXUndoManager() );
+
+ {
+ ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning );
+ rUndoManager.ClearRedo();
+ }
+
+ m_pImpl->notify( &XUndoManagerListener::redoActionsCleared, i_instanceLock );
+ // <--- SYNCHRONIZED
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::reset( IClearableInstanceLock& i_instanceLock )
+ {
+ // SYNCHRONIZED --->
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ {
+ ::comphelper::FlagGuard aNotificationGuard( m_pImpl->bAPIActionRunning );
+ while ( rUndoManager.IsInListAction() )
+ rUndoManager.LeaveListAction();
+ rUndoManager.Clear();
+ }
+
+ m_pImpl->notify( &XUndoManagerListener::resetAll, i_instanceLock );
+ // <--- SYNCHRONIZED
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::lock()
+ {
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ rUndoManager.EnableUndo( false );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::unlock()
+ {
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ if ( rUndoManager.IsUndoEnabled() )
+ throw NotLockedException( ::rtl::OUString::createFromAscii( "Undo manager is not locked" ), m_pImpl->getXUndoManager() );
+ rUndoManager.EnableUndo( true );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ ::sal_Bool UndoManagerHelper::isLocked()
+ {
+ IUndoManager& rUndoManager = m_pImpl->getUndoManager();
+ return !rUndoManager.IsUndoEnabled();
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ if ( i_listener.is() )
+ m_pImpl->aUndoListeners.addInterface( i_listener );
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ void UndoManagerHelper::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener )
+ {
+ if ( i_listener.is() )
+ m_pImpl->aUndoListeners.removeInterface( i_listener );
+ }
+
+//......................................................................................................................
+} // namespace framework
+//......................................................................................................................
diff --git a/framework/util/makefile.mk b/framework/util/makefile.mk
index 3df1e6493c9f..13c3d70d0d3c 100644
--- a/framework/util/makefile.mk
+++ b/framework/util/makefile.mk
@@ -101,6 +101,7 @@ LIB2OBJFILES= \
$(SLO)$/framelistanalyzer.obj \
$(SLO)$/titlehelper.obj \
$(SLO)$/documentundoguard.obj \
+ $(SLO)$/undomanagerhelper.obj \
# --- import classes library ---------------------------------------------------
@@ -158,7 +159,7 @@ SHL2STDLIBS= \
$(CPPUHELPERLIB) \
$(CPPULIB) \
$(VOSLIB) \
- $(SALLIB)
+ $(SALLIB) \
SHL2DEF= $(MISC)$/$(SHL2TARGET).def
SHL2DEPN= $(SHL1IMPLIBN) $(SHL1TARGETN)
@@ -422,6 +423,7 @@ $(MISC)$/$(SHL2TARGET).flt: makefile.mk
@echo WEP>>$@
@echo m_pLoader>$@
@echo _TI2>>$@
+ @echo _TI3>>$@
@echo LIBMAIN>>$@
@echo LibMain>>$@
diff --git a/sfx2/qa/complex/sfx2/UndoManager.java b/sfx2/qa/complex/sfx2/UndoManager.java
index 548d2cb31591..421111e88f4e 100755
--- a/sfx2/qa/complex/sfx2/UndoManager.java
+++ b/sfx2/qa/complex/sfx2/UndoManager.java
@@ -85,8 +85,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Stack;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
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 );
}
//......................................................................................................................
diff --git a/sfx2/source/inc/docundomanager.hxx b/sfx2/source/inc/docundomanager.hxx
index 7998657fbb3a..cca8d1b77fd6 100755
--- a/sfx2/source/inc/docundomanager.hxx
+++ b/sfx2/source/inc/docundomanager.hxx
@@ -96,34 +96,6 @@ namespace sfx2
virtual ::sal_Bool SAL_CALL isLocked( ) throw (::com::sun::star::uno::RuntimeException);
private:
- void impl_notify(
- ::rtl::OUString const& i_title,
- void ( SAL_CALL ::com::sun::star::document::XUndoManagerListener::*i_notificationMethod )( const ::com::sun::star::document::UndoManagerEvent& ),
- SfxModelGuard& i_instanceLock
- );
-
- void impl_notify(
- void ( SAL_CALL ::com::sun::star::document::XUndoManagerListener::*i_notificationMethod )( const ::com::sun::star::lang::EventObject& ),
- SfxModelGuard& i_instanceLock
- );
-
- void impl_notify(
- ::rtl::OUString const& i_title,
- void ( SAL_CALL ::com::sun::star::document::XUndoManagerListener::*i_notificationMethod )( const ::com::sun::star::document::UndoManagerEvent& )
- );
-
- void impl_notify(
- void ( SAL_CALL ::com::sun::star::document::XUndoManagerListener::*i_notificationMethod )( const ::com::sun::star::lang::EventObject& )
- );
-
- void impl_do_nolck(
- USHORT ( ::svl::IUndoManager::*i_checkMethod )( bool const ) const,
- BOOL ( ::svl::IUndoManager::*i_doMethod )(),
- UniString ( ::svl::IUndoManager::*i_titleRetriever )( USHORT, bool const ) const,
- void ( SAL_CALL ::com::sun::star::document::XUndoManagerListener::*i_notificationMethod )( const ::com::sun::star::document::UndoManagerEvent& )
- );
-
- private:
::boost::scoped_ptr< DocumentUndoManager_Impl > m_pImpl;
};