1*6d739b60SAndrew Rist /**************************************************************
2*6d739b60SAndrew Rist  *
3*6d739b60SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*6d739b60SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*6d739b60SAndrew Rist  * distributed with this work for additional information
6*6d739b60SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*6d739b60SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*6d739b60SAndrew Rist  * "License"); you may not use this file except in compliance
9*6d739b60SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*6d739b60SAndrew Rist  *
11*6d739b60SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*6d739b60SAndrew Rist  *
13*6d739b60SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*6d739b60SAndrew Rist  * software distributed under the License is distributed on an
15*6d739b60SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*6d739b60SAndrew Rist  * KIND, either express or implied.  See the License for the
17*6d739b60SAndrew Rist  * specific language governing permissions and limitations
18*6d739b60SAndrew Rist  * under the License.
19*6d739b60SAndrew Rist  *
20*6d739b60SAndrew Rist  *************************************************************/
21*6d739b60SAndrew Rist 
22*6d739b60SAndrew 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(
190cdf0e10cSrcweir                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Concurrency error: an ealier 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