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