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