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:
parent
7b8f9e3ecb
commit
d729112009
8 changed files with 1064 additions and 620 deletions
147
framework/inc/helper/undomanagerhelper.hxx
Executable file
147
framework/inc/helper/undomanagerhelper.hxx
Executable 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
|
|
@ -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
|
||||
|
|
|
@ -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 ------------------------------------------------------
|
||||
|
||||
|
|
754
framework/source/helper/undomanagerhelper.cxx
Executable file
754
framework/source/helper/undomanagerhelper.cxx
Executable 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
|
||||
//......................................................................................................................
|
|
@ -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>>$@
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <comphelper/flagguard.hxx>
|
||||
#include <svl/undo.hxx>
|
||||
#include <tools/diagnose_ex.h>
|
||||
#include <framework/undomanagerhelper.hxx>
|
||||
|
||||
#include <stack>
|
||||
|
||||
|
@ -80,163 +81,89 @@ 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()
|
||||
// IUndoManagerImplementation
|
||||
virtual ::osl::Mutex& getMutex();
|
||||
virtual ::svl::IUndoManager& getImplUndoManager();
|
||||
virtual Reference< XUndoManager > getThis();
|
||||
|
||||
void disposing()
|
||||
{
|
||||
ENSURE_OR_THROW( pUndoManager != NULL, "DocumentUndoManager_Impl::getUndoManager: no access to the doc's UndoManager implementation!" );
|
||||
aUndoHelper.disposing();
|
||||
ENSURE_OR_RETURN_VOID( pUndoManager, "DocumentUndoManager_Impl::disposing: already disposed!" );
|
||||
pUndoManager = NULL;
|
||||
}
|
||||
|
||||
void invalidateXDo_nolck();
|
||||
void enterViewStandardMode();
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
::osl::Mutex& DocumentUndoManager_Impl::getMutex()
|
||||
{
|
||||
return rAntiImpl.getMutex();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
::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::getUndoManager: the UndoManager changed meanwhile - what about our listener?" );
|
||||
"DocumentUndoManager_Impl::getImplUndoManager: the UndoManager changed meanwhile - what about our listener?" );
|
||||
#endif
|
||||
|
||||
return *pUndoManager;
|
||||
}
|
||||
|
||||
void disposing()
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
Reference< XUndoManager > DocumentUndoManager_Impl::getThis()
|
||||
{
|
||||
ENSURE_OR_RETURN_VOID( pUndoManager, "DocumentUndoManager_Impl::disposing: already disposed!" );
|
||||
pUndoManager->RemoveUndoListener( *this );
|
||||
pUndoManager = NULL;
|
||||
return static_cast< XUndoManager* >( &rAntiImpl );
|
||||
}
|
||||
|
||||
// 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 );
|
||||
};
|
||||
|
||||
//==================================================================================================================
|
||||
namespace
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
void DocumentUndoManager_Impl::invalidateXDo_nolck()
|
||||
{
|
||||
//..............................................................................................................
|
||||
void lcl_invalidateXDo( const DocumentUndoManager_Impl& i_impl )
|
||||
{
|
||||
const SfxObjectShell* pDocShell = i_impl.getObjectShell();
|
||||
SfxModelGuard aGuard( 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 )
|
||||
|
@ -247,144 +174,43 @@ namespace sfx2
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
void DocumentUndoManager_Impl::enterUndoContext( const ::rtl::OUString& i_title, const bool i_hidden )
|
||||
void DocumentUndoManager_Impl::enterViewStandardMode()
|
||||
{
|
||||
// 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 )
|
||||
);
|
||||
|
||||
// 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 )
|
||||
{
|
||||
::comphelper::FlagGuard aNotificationGuard( bAPIActionRunning );
|
||||
rUndoManager.EnterListAction( i_title, ::rtl::OUString() );
|
||||
SfxViewShell* pViewShell = pViewFrame->GetViewShell();
|
||||
ENSURE_OR_CONTINUE( pViewShell, "DocumentUndoManager_Impl::enterViewStandardMode: no view shell in the frame!" );
|
||||
pViewShell->EnterStandardMode();
|
||||
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 )
|
||||
//==================================================================================================================
|
||||
//= SfxModelGuardFacade
|
||||
//==================================================================================================================
|
||||
class SfxModelGuardFacade : public ::framework::IClearableInstanceLock
|
||||
{
|
||||
if ( bAPIActionRunning )
|
||||
return;
|
||||
|
||||
rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::actionUndone );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
void DocumentUndoManager_Impl::actionRedone( SfxUndoAction& i_action )
|
||||
public:
|
||||
SfxModelGuardFacade( SfxModelGuard& i_guard )
|
||||
:m_guard( i_guard )
|
||||
{
|
||||
if ( bAPIActionRunning )
|
||||
return;
|
||||
|
||||
rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::actionRedone );
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
void DocumentUndoManager_Impl::undoActionAdded( SfxUndoAction& i_action )
|
||||
virtual void clear()
|
||||
{
|
||||
if ( bAPIActionRunning )
|
||||
return;
|
||||
|
||||
rAntiImpl.impl_notify( i_action.GetComment(), &XUndoManagerListener::undoActionAdded );
|
||||
m_guard.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
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 );
|
||||
}
|
||||
|
||||
//......................................................................................................................
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue