1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include "precompiled_dbaccess.hxx"
25 
26 #include "dbaundomanager.hxx"
27 
28 /** === begin UNO includes === **/
29 #include <com/sun/star/lang/DisposedException.hpp>
30 /** === end UNO includes === **/
31 
32 #include <svl/undo.hxx>
33 #include <vcl/svapp.hxx>
34 #include <vos/mutex.hxx>
35 #include <framework/undomanagerhelper.hxx>
36 
37 //......................................................................................................................
38 namespace dbaui
39 {
40 //......................................................................................................................
41 
42 	/** === begin UNO using === **/
43 	using ::com::sun::star::uno::Reference;
44 	using ::com::sun::star::uno::XInterface;
45 	using ::com::sun::star::uno::UNO_QUERY;
46 	using ::com::sun::star::uno::UNO_QUERY_THROW;
47 	using ::com::sun::star::uno::UNO_SET_THROW;
48 	using ::com::sun::star::uno::Exception;
49 	using ::com::sun::star::uno::RuntimeException;
50 	using ::com::sun::star::uno::Any;
51 	using ::com::sun::star::uno::makeAny;
52 	using ::com::sun::star::uno::Sequence;
53 	using ::com::sun::star::uno::Type;
54     using ::com::sun::star::document::XUndoManager;
55     using ::com::sun::star::lang::DisposedException;
56     using ::com::sun::star::document::UndoContextNotClosedException;
57     using ::com::sun::star::document::UndoFailedException;
58     using ::com::sun::star::document::EmptyUndoStackException;
59     using ::com::sun::star::util::InvalidStateException;
60     using ::com::sun::star::document::XUndoAction;
61     using ::com::sun::star::lang::IllegalArgumentException;
62     using ::com::sun::star::document::XUndoManagerListener;
63     using ::com::sun::star::util::NotLockedException;
64     using ::com::sun::star::lang::NoSupportException;
65 	/** === end UNO using === **/
66 
67 	//==================================================================================================================
68 	//= UndoManager_Impl
69 	//==================================================================================================================
70     struct UndoManager_Impl : public ::framework::IUndoManagerImplementation
71     {
72         UndoManager_Impl( UndoManager& i_antiImpl, ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
73             :rAntiImpl( i_antiImpl )
74             ,rParent( i_parent )
75             ,rMutex( i_mutex )
76             ,bDisposed( false )
77             ,aUndoManager()
78             ,aUndoHelper( *this )
79         {
80         }
81 
82         virtual ~UndoManager_Impl()
83         {
84         }
85 
86         UndoManager&                    rAntiImpl;
87         ::cppu::OWeakObject&            rParent;
88         ::osl::Mutex&                   rMutex;
89         bool                            bDisposed;
90         SfxUndoManager                  aUndoManager;
91         ::framework::UndoManagerHelper  aUndoHelper;
92 
93         // IUndoManagerImplementation
94         virtual ::svl::IUndoManager&        getImplUndoManager();
95         virtual Reference< XUndoManager >   getThis();
96     };
97 
98 	//------------------------------------------------------------------------------------------------------------------
99     ::svl::IUndoManager& UndoManager_Impl::getImplUndoManager()
100     {
101         return aUndoManager;
102     }
103 
104 	//------------------------------------------------------------------------------------------------------------------
105     Reference< XUndoManager > UndoManager_Impl::getThis()
106     {
107         return static_cast< XUndoManager* >( &rAntiImpl );
108     }
109 
110     //==============================================================================================================
111     //= OslMutexFacade
112     //==============================================================================================================
113     class OslMutexFacade : public ::framework::IMutex
114     {
115     public:
116         OslMutexFacade( ::osl::Mutex& i_mutex )
117             :m_rMutex( i_mutex )
118         {
119         }
120 
121         virtual void acquire();
122         virtual void release();
123 
124     private:
125         ::osl::Mutex&   m_rMutex;
126     };
127 
128     //--------------------------------------------------------------------------------------------------------------
129     void OslMutexFacade::acquire()
130     {
131         m_rMutex.acquire();
132     }
133 
134     //--------------------------------------------------------------------------------------------------------------
135     void OslMutexFacade::release()
136     {
137         m_rMutex.release();
138     }
139 
140     //==============================================================================================================
141     //= UndoManagerMethodGuard
142     //==============================================================================================================
143     /** guard for public UNO methods of the UndoManager
144     */
145     class UndoManagerMethodGuard : public ::framework::IMutexGuard
146     {
147     public:
148         UndoManagerMethodGuard( UndoManager_Impl& i_impl )
149             :m_aGuard( i_impl.rMutex )
150             ,m_aMutexFacade( i_impl.rMutex )
151         {
152             // throw if the instance is already disposed
153             if ( i_impl.bDisposed )
154                 throw DisposedException( ::rtl::OUString(), i_impl.getThis() );
155         }
156         virtual ~UndoManagerMethodGuard()
157         {
158         }
159 
160         // IMutexGuard
161         virtual ::framework::IMutex& getGuardedMutex();
162 
163         // IGuard
164         virtual void clear();
165         virtual void reset();
166 
167     private:
168         ::osl::ResettableMutexGuard m_aGuard;
169         OslMutexFacade              m_aMutexFacade;
170     };
171 
172     //--------------------------------------------------------------------------------------------------------------
173     ::framework::IMutex& UndoManagerMethodGuard::getGuardedMutex()
174     {
175         return m_aMutexFacade;
176     }
177 
178     //--------------------------------------------------------------------------------------------------------------
179     void UndoManagerMethodGuard::clear()
180     {
181         m_aGuard.clear();
182     }
183 
184     //--------------------------------------------------------------------------------------------------------------
185     void UndoManagerMethodGuard::reset()
186     {
187         m_aGuard.reset();
188     }
189 
190 	//==================================================================================================================
191 	//= UndoManager
192 	//==================================================================================================================
193 	//------------------------------------------------------------------------------------------------------------------
194     UndoManager::UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
195         :m_pImpl( new UndoManager_Impl( *this, i_parent, i_mutex ) )
196     {
197     }
198 
199 	//------------------------------------------------------------------------------------------------------------------
200     UndoManager::~UndoManager()
201     {
202     }
203 
204 	//------------------------------------------------------------------------------------------------------------------
205     SfxUndoManager& UndoManager::GetSfxUndoManager() const
206     {
207         return m_pImpl->aUndoManager;
208     }
209 
210     //------------------------------------------------------------------------------------------------------------------
211     void SAL_CALL UndoManager::acquire(  ) throw ()
212     {
213         m_pImpl->rParent.acquire();
214     }
215 
216     //------------------------------------------------------------------------------------------------------------------
217     void SAL_CALL UndoManager::release(  ) throw ()
218     {
219         m_pImpl->rParent.release();
220     }
221 
222     //------------------------------------------------------------------------------------------------------------------
223     void UndoManager::disposing()
224     {
225         {
226             ::osl::MutexGuard aGuard( m_pImpl->rMutex );
227             m_pImpl->bDisposed = true;
228         }
229         m_pImpl->aUndoHelper.disposing();
230     }
231 
232     //------------------------------------------------------------------------------------------------------------------
233     void SAL_CALL UndoManager::enterUndoContext( const ::rtl::OUString& i_title ) throw (RuntimeException)
234     {
235         UndoManagerMethodGuard aGuard( *m_pImpl );
236         m_pImpl->aUndoHelper.enterUndoContext( i_title, aGuard );
237     }
238 
239     //------------------------------------------------------------------------------------------------------------------
240     void SAL_CALL UndoManager::enterHiddenUndoContext(  ) throw (EmptyUndoStackException, RuntimeException)
241     {
242         UndoManagerMethodGuard aGuard( *m_pImpl );
243         m_pImpl->aUndoHelper.enterHiddenUndoContext( aGuard );
244     }
245 
246     //------------------------------------------------------------------------------------------------------------------
247     void SAL_CALL UndoManager::leaveUndoContext(  ) throw (InvalidStateException, RuntimeException)
248     {
249         UndoManagerMethodGuard aGuard( *m_pImpl );
250         m_pImpl->aUndoHelper.leaveUndoContext( aGuard );
251     }
252 
253     //------------------------------------------------------------------------------------------------------------------
254     void SAL_CALL UndoManager::addUndoAction( const Reference< XUndoAction >& i_action ) throw (IllegalArgumentException, RuntimeException)
255     {
256         UndoManagerMethodGuard aGuard( *m_pImpl );
257         m_pImpl->aUndoHelper.addUndoAction( i_action, aGuard );
258     }
259 
260     //------------------------------------------------------------------------------------------------------------------
261     void SAL_CALL UndoManager::undo(  ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException)
262     {
263         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
264             // (all our UndoActions work directly on VCL code, usually, so ...)
265         UndoManagerMethodGuard aGuard( *m_pImpl );
266         m_pImpl->aUndoHelper.undo( aGuard );
267     }
268 
269     //------------------------------------------------------------------------------------------------------------------
270     void SAL_CALL UndoManager::redo(  ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException)
271     {
272         ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
273             // (all our UndoActions work directly on VCL code, usually, so ...)
274         UndoManagerMethodGuard aGuard( *m_pImpl );
275         m_pImpl->aUndoHelper.redo( aGuard );
276     }
277 
278     //------------------------------------------------------------------------------------------------------------------
279     ::sal_Bool SAL_CALL UndoManager::isUndoPossible(  ) throw (RuntimeException)
280     {
281         UndoManagerMethodGuard aGuard( *m_pImpl );
282         return m_pImpl->aUndoHelper.isUndoPossible();
283     }
284 
285     //------------------------------------------------------------------------------------------------------------------
286     ::sal_Bool SAL_CALL UndoManager::isRedoPossible(  ) throw (RuntimeException)
287     {
288         UndoManagerMethodGuard aGuard( *m_pImpl );
289         return m_pImpl->aUndoHelper.isRedoPossible();
290     }
291 
292     //------------------------------------------------------------------------------------------------------------------
293     ::rtl::OUString SAL_CALL UndoManager::getCurrentUndoActionTitle(  ) throw (EmptyUndoStackException, RuntimeException)
294     {
295         UndoManagerMethodGuard aGuard( *m_pImpl );
296         return m_pImpl->aUndoHelper.getCurrentUndoActionTitle();
297     }
298 
299     //------------------------------------------------------------------------------------------------------------------
300     ::rtl::OUString SAL_CALL UndoManager::getCurrentRedoActionTitle(  ) throw (EmptyUndoStackException, RuntimeException)
301     {
302         UndoManagerMethodGuard aGuard( *m_pImpl );
303         return m_pImpl->aUndoHelper.getCurrentRedoActionTitle();
304     }
305 
306     //------------------------------------------------------------------------------------------------------------------
307     Sequence< ::rtl::OUString > SAL_CALL UndoManager::getAllUndoActionTitles(  ) throw (RuntimeException)
308     {
309         UndoManagerMethodGuard aGuard( *m_pImpl );
310         return m_pImpl->aUndoHelper.getAllUndoActionTitles();
311     }
312 
313     //------------------------------------------------------------------------------------------------------------------
314     Sequence< ::rtl::OUString > SAL_CALL UndoManager::getAllRedoActionTitles(  ) throw (RuntimeException)
315     {
316         UndoManagerMethodGuard aGuard( *m_pImpl );
317         return m_pImpl->aUndoHelper.getAllRedoActionTitles();
318     }
319 
320     //------------------------------------------------------------------------------------------------------------------
321     void SAL_CALL UndoManager::clear(  ) throw (UndoContextNotClosedException, RuntimeException)
322     {
323         UndoManagerMethodGuard aGuard( *m_pImpl );
324         m_pImpl->aUndoHelper.clear( aGuard );
325     }
326 
327     //------------------------------------------------------------------------------------------------------------------
328     void SAL_CALL UndoManager::clearRedo(  ) throw (UndoContextNotClosedException, RuntimeException)
329     {
330         UndoManagerMethodGuard aGuard( *m_pImpl );
331         m_pImpl->aUndoHelper.clearRedo( aGuard );
332     }
333 
334     //------------------------------------------------------------------------------------------------------------------
335     void SAL_CALL UndoManager::reset(  ) throw (RuntimeException)
336     {
337         UndoManagerMethodGuard aGuard( *m_pImpl );
338         m_pImpl->aUndoHelper.reset( aGuard );
339     }
340 
341     //------------------------------------------------------------------------------------------------------------------
342     void SAL_CALL UndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) throw (RuntimeException)
343     {
344         UndoManagerMethodGuard aGuard( *m_pImpl );
345         m_pImpl->aUndoHelper.addUndoManagerListener( i_listener );
346     }
347 
348     //------------------------------------------------------------------------------------------------------------------
349     void SAL_CALL UndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) throw (RuntimeException)
350     {
351         UndoManagerMethodGuard aGuard( *m_pImpl );
352         m_pImpl->aUndoHelper.removeUndoManagerListener( i_listener );
353     }
354 
355     //------------------------------------------------------------------------------------------------------------------
356     void SAL_CALL UndoManager::lock(  ) throw (RuntimeException)
357     {
358         UndoManagerMethodGuard aGuard( *m_pImpl );
359         m_pImpl->aUndoHelper.lock();
360     }
361 
362     //------------------------------------------------------------------------------------------------------------------
363     void SAL_CALL UndoManager::unlock(  ) throw (NotLockedException, RuntimeException)
364     {
365         UndoManagerMethodGuard aGuard( *m_pImpl );
366         m_pImpl->aUndoHelper.unlock();
367     }
368 
369     //------------------------------------------------------------------------------------------------------------------
370     ::sal_Bool SAL_CALL UndoManager::isLocked(  ) throw (RuntimeException)
371     {
372         UndoManagerMethodGuard aGuard( *m_pImpl );
373         return m_pImpl->aUndoHelper.isLocked();
374     }
375 
376     //------------------------------------------------------------------------------------------------------------------
377     Reference< XInterface > SAL_CALL UndoManager::getParent(  ) throw (RuntimeException)
378     {
379         UndoManagerMethodGuard aGuard( *m_pImpl );
380         return *&m_pImpl->rParent;
381     }
382 
383     //------------------------------------------------------------------------------------------------------------------
384     void SAL_CALL UndoManager::setParent( const Reference< XInterface >& i_parent ) throw (NoSupportException, RuntimeException)
385     {
386         (void)i_parent;
387         throw NoSupportException( ::rtl::OUString(), m_pImpl->getThis() );
388     }
389 
390 //......................................................................................................................
391 } // namespace dbaui
392 //......................................................................................................................
393