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

This commit is contained in:
Frank Schoenheit [fs] 2010-11-09 21:36:57 +01:00
parent 7b8f9e3ecb
commit d729112009
8 changed files with 1064 additions and 620 deletions

View file

@ -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

View file

@ -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

View file

@ -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 ------------------------------------------------------

View file

@ -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
//......................................................................................................................

View file

@ -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>>$@

View file

@ -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;

View file

@ -42,6 +42,7 @@
#include <comphelper/flagguard.hxx>
#include <svl/undo.hxx>
#include <tools/diagnose_ex.h>
#include <framework/undomanagerhelper.hxx>
#include <stack>
@ -80,311 +81,136 @@ 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();
void invalidateXDo_nolck();
void enterViewStandardMode();
// public operations
void enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden );
private:
static IUndoManager* impl_retrieveUndoManager( SfxBaseModel& i_baseModel )
{
IUndoManager* pUndoManager( NULL );
SfxObjectShell* pObjectShell = i_baseModel.GetObjectShell();
if ( pObjectShell != NULL )
pUndoManager = pObjectShell->GetUndoManager();
if ( !pUndoManager )
throw NotInitializedException( ::rtl::OUString(), *&i_baseModel );
return pUndoManager;
}
};
//==================================================================================================================
namespace
//------------------------------------------------------------------------------------------------------------------
::osl::Mutex& DocumentUndoManager_Impl::getMutex()
{
//..............................................................................................................
void lcl_invalidateXDo( const DocumentUndoManager_Impl& i_impl )
{
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 );
}
}
return rAntiImpl.getMutex();
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden )
::svl::IUndoManager& DocumentUndoManager_Impl::getImplUndoManager()
{
ENSURE_OR_THROW( pUndoManager != NULL, "DocumentUndoManager_Impl::getImplUndoManager: 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::getImplUndoManager: the UndoManager changed meanwhile - what about our listener?" );
#endif
return *pUndoManager;
}
//------------------------------------------------------------------------------------------------------------------
Reference< XUndoManager > DocumentUndoManager_Impl::getThis()
{
return static_cast< XUndoManager* >( &rAntiImpl );
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::invalidateXDo_nolck()
{
// 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 )
);
const SfxObjectShell* pDocShell = getObjectShell();
ENSURE_OR_THROW( pDocShell != NULL, "lcl_invalidateUndo: no access to the doc shell!" );
SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst( pDocShell );
while ( pViewFrame )
{
::comphelper::FlagGuard aNotificationGuard( bAPIActionRunning );
rUndoManager.EnterListAction( i_title, ::rtl::OUString() );
pViewFrame->GetBindings().Invalidate( SID_UNDO );
pViewFrame->GetBindings().Invalidate( SID_REDO );
pViewFrame = SfxViewFrame::GetNext( *pViewFrame, pDocShell );
}
aContextVisibilities.push( i_hidden );
rAntiImpl.impl_notify( i_title, i_hidden ? &XUndoManagerListener::enteredHiddenContext : &XUndoManagerListener::enteredContext, aGuard );
// <--- SYNCHRONIZED
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::actionUndone( SfxUndoAction& i_action )
void DocumentUndoManager_Impl::enterViewStandardMode()
{
if ( bAPIActionRunning )
return;
rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::actionUndone );
// 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::actionRedone( SfxUndoAction& i_action )
//==================================================================================================================
//= SfxModelGuardFacade
//==================================================================================================================
class SfxModelGuardFacade : public ::framework::IClearableInstanceLock
{
if ( bAPIActionRunning )
return;
public:
SfxModelGuardFacade( SfxModelGuard& i_guard )
:m_guard( i_guard )
{
}
rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::actionRedone );
}
virtual void clear()
{
m_guard.clear();
}
//------------------------------------------------------------------------------------------------------------------
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 );
#endif
if ( bAPIActionRunning )
return;
rAntiImpl.impl_notify( i_comment, &XUndoManagerListener::enteredContext );
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::listActionLeft()
{
#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 );
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::listActionLeftAndMerged()
{
#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;
rAntiImpl.impl_notify( ::rtl::OUString(), &XUndoManagerListener::leftHiddenContext );
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::listActionCancelled()
{
#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 );
}
//------------------------------------------------------------------------------------------------------------------
void DocumentUndoManager_Impl::undoManagerDying()
{
pUndoManager = NULL;
}
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();
}
@ -423,67 +245,21 @@ namespace sfx2
SfxModelSubComponent::release();
}
//------------------------------------------------------------------------------------------------------------------
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 );
// <--- SYNCHRONIZED
if ( bHadRedoActions && !bHasRedoActions )
impl_notify( &XUndoManagerListener::redoActionsCleared );
}
//------------------------------------------------------------------------------------------------------------------
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& ) )
{
// 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->aUndoHelper.addUndoAction( i_action, SfxModelGuardFacade( aGuard ) );
// <--- SYNCHRONIZED
m_pImpl->invalidateXDo_nolck();
}
//------------------------------------------------------------------------------------------------------------------
void SAL_CALL DocumentUndoManager::undo( ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException)
{
impl_do_nolck(
&IUndoManager::GetUndoActionCount,
&IUndoManager::Undo,
&IUndoManager::GetUndoActionComment,
&XUndoManagerListener::actionUndone
);
// SYNCHRONIZED --->
SfxModelGuard aGuard( *this );
m_pImpl->enterViewStandardMode();
m_pImpl->aUndoHelper.undo( SfxModelGuardFacade( aGuard ) );
// <--- SYNCHRONIZED
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
);
// SYNCHRONIZED --->
SfxModelGuard aGuard( *this );
m_pImpl->enterViewStandardMode();
m_pImpl->aUndoHelper.redo( SfxModelGuardFacade( aGuard ) );
// <--- SYNCHRONIZED
m_pImpl->invalidateXDo_nolck();
}
//------------------------------------------------------------------------------------------------------------------
::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;
// <--- SYNCHRONIZED
return m_pImpl->aUndoHelper.isUndoPossible();
}
//------------------------------------------------------------------------------------------------------------------
::sal_Bool SAL_CALL DocumentUndoManager::isRedoPossible( ) throw (RuntimeException)
{
// SYNCHRONIZED --->
SfxModelGuard aGuard( *this );
IUndoManager& rUndoManager = m_pImpl->getUndoManager();
if ( rUndoManager.IsInListAction() )
return sal_False;
return rUndoManager.GetRedoActionCount( IUndoManager::TopLevel ) > 0;
// <--- SYNCHRONIZED
}
//------------------------------------------------------------------------------------------------------------------
namespace
{
//..............................................................................................................
::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
}
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 );
}
//......................................................................................................................

View file

@ -95,34 +95,6 @@ namespace sfx2
virtual void SAL_CALL unlock( ) throw (::com::sun::star::util::NotLockedException, ::com::sun::star::uno::RuntimeException);
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;
};