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_chart2.hxx"
25 
26 #include "UndoManager.hxx"
27 #include "ChartViewHelper.hxx"
28 
29 /** === begin UNO includes === **/
30 #include <com/sun/star/lang/DisposedException.hpp>
31 /** === end UNO includes === **/
32 
33 #include <framework/undomanagerhelper.hxx>
34 #include <svl/undo.hxx>
35 #include <unotools/undoopt.hxx>
36 
37 //......................................................................................................................
38 namespace chart
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::lang::DisposedException;
55     using ::com::sun::star::document::XUndoManager;
56     using ::com::sun::star::document::EmptyUndoStackException;
57     using ::com::sun::star::document::UndoContextNotClosedException;
58     using ::com::sun::star::document::UndoFailedException;
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     using ::com::sun::star::util::XModifyListener;
66     using ::com::sun::star::frame::XModel;
67 	/** === end UNO using === **/
68 
69     namespace impl
70     {
71 	    //==============================================================================================================
72 	    //= UndoManager_Impl
73 	    //==============================================================================================================
74         class UndoManager_Impl : public ::framework::IUndoManagerImplementation
75         {
76         public:
UndoManager_Impl(UndoManager & i_antiImpl,::cppu::OWeakObject & i_parent,::osl::Mutex & i_mutex)77             UndoManager_Impl( UndoManager& i_antiImpl, ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
78                 :m_rAntiImpl( i_antiImpl )
79                 ,m_rParent( i_parent )
80                 ,m_rMutex( i_mutex )
81                 ,m_bDisposed( false )
82                 ,m_aUndoManager()
83                 ,m_aUndoHelper( *this )
84             {
85                 m_aUndoManager.SetMaxUndoActionCount( (sal_uInt16)SvtUndoOptions().GetUndoCount() );
86             }
87 
~UndoManager_Impl()88             virtual ~UndoManager_Impl()
89             {
90             }
91 
92             // .........................................................................................................
93             // IUndoManagerImplementation
94             virtual ::osl::Mutex&               getMutex();
95             virtual ::svl::IUndoManager&        getImplUndoManager();
96             virtual Reference< XUndoManager >   getThis();
97 
98             // .........................................................................................................
99             // attribute access
getParent()100             ::cppu::OWeakObject&                getParent() { return m_rParent; }
getUndoHelper()101             ::framework::UndoManagerHelper&     getUndoHelper() { return m_aUndoHelper; }
102 
103             // .........................................................................................................
104             // public interface
105 
106             /// is called when the owner of the UndoManager is being disposed
107             void    disposing();
108 
109             /// checks whether we're already disposed, throws a DisposedException if so
110             void    checkDisposed_lck();
111 
112         private:
113             UndoManager&                        m_rAntiImpl;
114             ::cppu::OWeakObject&                m_rParent;
115             ::osl::Mutex&                       m_rMutex;
116             bool                                m_bDisposed;
117 
118             SfxUndoManager                      m_aUndoManager;
119             ::framework::UndoManagerHelper      m_aUndoHelper;
120         };
121 
122 	    //--------------------------------------------------------------------------------------------------------------
getMutex()123         ::osl::Mutex& UndoManager_Impl::getMutex()
124         {
125             return m_rMutex;
126         }
127 
128 	    //--------------------------------------------------------------------------------------------------------------
getImplUndoManager()129         ::svl::IUndoManager& UndoManager_Impl::getImplUndoManager()
130         {
131             return m_aUndoManager;
132         }
133 
134 	    //--------------------------------------------------------------------------------------------------------------
getThis()135         Reference< XUndoManager > UndoManager_Impl::getThis()
136         {
137             return &m_rAntiImpl;
138         }
139 
140 	    //--------------------------------------------------------------------------------------------------------------
disposing()141         void UndoManager_Impl::disposing()
142         {
143             {
144                 ::osl::MutexGuard aGuard( m_rMutex );
145                 m_bDisposed = true;
146             }
147             m_aUndoHelper.disposing();
148         }
149 
150 	    //--------------------------------------------------------------------------------------------------------------
checkDisposed_lck()151         void UndoManager_Impl::checkDisposed_lck()
152         {
153             if ( m_bDisposed )
154                 throw DisposedException( ::rtl::OUString(), getThis() );
155         }
156 
157         //==============================================================================================================
158 	    //= UndoManagerMethodGuard
159 	    //==============================================================================================================
160         /** guard for public UNO methods of the UndoManager
161 
162             The only purpose of this guard is to check for the instance being disposed already. Everything else,
163             in particular the IMutexGuard functionality required by the UndoManagerHelper class, is a dummy only,
164             as all involved classes (means we ourselves, the UndoManagerHelper, the SfxUndoManager, and the Undo actions
165             we create) are inherently thread-safe, thus need no external lock (in particular no SolarMutex!).
166         */
167         class UndoManagerMethodGuard : public ::framework::IMutexGuard
168         {
169         public:
UndoManagerMethodGuard(UndoManager_Impl & i_impl)170             UndoManagerMethodGuard( UndoManager_Impl& i_impl )
171             {
172                 ::osl::MutexGuard aGuard( i_impl.getMutex() );
173                 // throw if the instance is already disposed
174                 i_impl.checkDisposed_lck();
175             }
~UndoManagerMethodGuard()176             virtual ~UndoManagerMethodGuard()
177             {
178             }
179 
180             // IMutexGuard
181             virtual ::framework::IMutex& getGuardedMutex();
182 
183             // IGuard
184             virtual void clear();
185             virtual void reset();
186         };
187 
188         class DummyMutex : public ::framework::IMutex
189         {
190         public:
acquire()191             virtual void acquire() { }
release()192             virtual void release() { }
193         };
194 
195         //--------------------------------------------------------------------------------------------------------------
getGuardedMutex()196         ::framework::IMutex& UndoManagerMethodGuard::getGuardedMutex()
197         {
198             static DummyMutex s_aDummyMutex;
199             return s_aDummyMutex;
200         }
201 
202         //--------------------------------------------------------------------------------------------------------------
clear()203         void UndoManagerMethodGuard::clear()
204         {
205             // nothing to do. This interface implementation is a dummy.
206         }
207 
208         //--------------------------------------------------------------------------------------------------------------
reset()209         void UndoManagerMethodGuard::reset()
210         {
211             // nothing to do. This interface implementation is a dummy.
212         }
213     }
214 
215 	//==================================================================================================================
216 	//= UndoManager
217 	//==================================================================================================================
218     using impl::UndoManagerMethodGuard;
219 
220 	//------------------------------------------------------------------------------------------------------------------
UndoManager(::cppu::OWeakObject & i_parent,::osl::Mutex & i_mutex)221     UndoManager::UndoManager( ::cppu::OWeakObject& i_parent, ::osl::Mutex& i_mutex )
222         :m_pImpl( new impl::UndoManager_Impl( *this, i_parent, i_mutex ) )
223     {
224     }
225 
226 	//------------------------------------------------------------------------------------------------------------------
~UndoManager()227     UndoManager::~UndoManager()
228     {
229     }
230 
231 	//------------------------------------------------------------------------------------------------------------------
acquire()232     void SAL_CALL UndoManager::acquire() throw ()
233     {
234         m_pImpl->getParent().acquire();
235     }
236 
237 	//------------------------------------------------------------------------------------------------------------------
release()238     void SAL_CALL UndoManager::release() throw ()
239     {
240         m_pImpl->getParent().release();
241     }
242 
243 	//------------------------------------------------------------------------------------------------------------------
disposing()244     void UndoManager::disposing()
245     {
246         m_pImpl->disposing();
247     }
248 
249     //------------------------------------------------------------------------------------------------------------------
enterUndoContext(const::rtl::OUString & i_title)250     void SAL_CALL UndoManager::enterUndoContext( const ::rtl::OUString& i_title ) throw (RuntimeException)
251     {
252         UndoManagerMethodGuard aGuard( *m_pImpl );
253         m_pImpl->getUndoHelper().enterUndoContext( i_title, aGuard );
254     }
255 
256     //------------------------------------------------------------------------------------------------------------------
enterHiddenUndoContext()257     void SAL_CALL UndoManager::enterHiddenUndoContext(  ) throw (EmptyUndoStackException, RuntimeException)
258     {
259         UndoManagerMethodGuard aGuard( *m_pImpl );
260         m_pImpl->getUndoHelper().enterHiddenUndoContext( aGuard );
261     }
262 
263     //------------------------------------------------------------------------------------------------------------------
leaveUndoContext()264     void SAL_CALL UndoManager::leaveUndoContext(  ) throw (InvalidStateException, RuntimeException)
265     {
266         UndoManagerMethodGuard aGuard( *m_pImpl );
267         m_pImpl->getUndoHelper().leaveUndoContext( aGuard );
268     }
269 
270     //------------------------------------------------------------------------------------------------------------------
addUndoAction(const Reference<XUndoAction> & i_action)271     void SAL_CALL UndoManager::addUndoAction( const Reference< XUndoAction >& i_action ) throw (IllegalArgumentException, RuntimeException)
272     {
273         UndoManagerMethodGuard aGuard( *m_pImpl );
274         m_pImpl->getUndoHelper().addUndoAction( i_action, aGuard );
275     }
276 
277     //------------------------------------------------------------------------------------------------------------------
undo()278     void SAL_CALL UndoManager::undo(  ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException)
279     {
280         UndoManagerMethodGuard aGuard( *m_pImpl );
281         m_pImpl->getUndoHelper().undo( aGuard );
282 
283         ChartViewHelper::setViewToDirtyState( Reference< XModel >( getParent(), UNO_QUERY ) );
284     }
285 
286     //------------------------------------------------------------------------------------------------------------------
redo()287     void SAL_CALL UndoManager::redo(  ) throw (EmptyUndoStackException, UndoContextNotClosedException, UndoFailedException, RuntimeException)
288     {
289         UndoManagerMethodGuard aGuard( *m_pImpl );
290         m_pImpl->getUndoHelper().redo( aGuard );
291 
292         ChartViewHelper::setViewToDirtyState( Reference< XModel >( getParent(), UNO_QUERY ) );
293     }
294 
295     //------------------------------------------------------------------------------------------------------------------
isUndoPossible()296     ::sal_Bool SAL_CALL UndoManager::isUndoPossible(  ) throw (RuntimeException)
297     {
298         UndoManagerMethodGuard aGuard( *m_pImpl );
299         return m_pImpl->getUndoHelper().isUndoPossible();
300     }
301 
302     //------------------------------------------------------------------------------------------------------------------
isRedoPossible()303     ::sal_Bool SAL_CALL UndoManager::isRedoPossible(  ) throw (RuntimeException)
304     {
305         UndoManagerMethodGuard aGuard( *m_pImpl );
306         return m_pImpl->getUndoHelper().isRedoPossible();
307     }
308 
309     //------------------------------------------------------------------------------------------------------------------
getCurrentUndoActionTitle()310     ::rtl::OUString SAL_CALL UndoManager::getCurrentUndoActionTitle(  ) throw (EmptyUndoStackException, RuntimeException)
311     {
312         UndoManagerMethodGuard aGuard( *m_pImpl );
313         return m_pImpl->getUndoHelper().getCurrentUndoActionTitle();
314     }
315 
316     //------------------------------------------------------------------------------------------------------------------
getCurrentRedoActionTitle()317     ::rtl::OUString SAL_CALL UndoManager::getCurrentRedoActionTitle(  ) throw (EmptyUndoStackException, RuntimeException)
318     {
319         UndoManagerMethodGuard aGuard( *m_pImpl );
320         return m_pImpl->getUndoHelper().getCurrentRedoActionTitle();
321     }
322 
323     //------------------------------------------------------------------------------------------------------------------
getAllUndoActionTitles()324     Sequence< ::rtl::OUString > SAL_CALL UndoManager::getAllUndoActionTitles(  ) throw (RuntimeException)
325     {
326         UndoManagerMethodGuard aGuard( *m_pImpl );
327         return m_pImpl->getUndoHelper().getAllUndoActionTitles();
328     }
329 
330     //------------------------------------------------------------------------------------------------------------------
getAllRedoActionTitles()331     Sequence< ::rtl::OUString > SAL_CALL UndoManager::getAllRedoActionTitles(  ) throw (RuntimeException)
332     {
333         UndoManagerMethodGuard aGuard( *m_pImpl );
334         return m_pImpl->getUndoHelper().getAllRedoActionTitles();
335     }
336 
337     //------------------------------------------------------------------------------------------------------------------
clear()338     void SAL_CALL UndoManager::clear(  ) throw (UndoContextNotClosedException, RuntimeException)
339     {
340         UndoManagerMethodGuard aGuard( *m_pImpl );
341         m_pImpl->getUndoHelper().clear( aGuard );
342     }
343 
344     //------------------------------------------------------------------------------------------------------------------
clearRedo()345     void SAL_CALL UndoManager::clearRedo(  ) throw (UndoContextNotClosedException, RuntimeException)
346     {
347         UndoManagerMethodGuard aGuard( *m_pImpl );
348         m_pImpl->getUndoHelper().clearRedo( aGuard );
349     }
350 
351     //------------------------------------------------------------------------------------------------------------------
reset()352     void SAL_CALL UndoManager::reset(  ) throw (RuntimeException)
353     {
354         UndoManagerMethodGuard aGuard( *m_pImpl );
355         m_pImpl->getUndoHelper().reset( aGuard );
356     }
357 
358     //------------------------------------------------------------------------------------------------------------------
addUndoManagerListener(const Reference<XUndoManagerListener> & i_listener)359     void SAL_CALL UndoManager::addUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) throw (RuntimeException)
360     {
361         UndoManagerMethodGuard aGuard( *m_pImpl );
362         m_pImpl->getUndoHelper().addUndoManagerListener( i_listener );
363     }
364 
365     //------------------------------------------------------------------------------------------------------------------
removeUndoManagerListener(const Reference<XUndoManagerListener> & i_listener)366     void SAL_CALL UndoManager::removeUndoManagerListener( const Reference< XUndoManagerListener >& i_listener ) throw (RuntimeException)
367     {
368         UndoManagerMethodGuard aGuard( *m_pImpl );
369         m_pImpl->getUndoHelper().removeUndoManagerListener( i_listener );
370     }
371 
372     //------------------------------------------------------------------------------------------------------------------
lock()373     void SAL_CALL UndoManager::lock(  ) throw (RuntimeException)
374     {
375         UndoManagerMethodGuard aGuard( *m_pImpl );
376         m_pImpl->getUndoHelper().lock();
377     }
378 
379     //------------------------------------------------------------------------------------------------------------------
unlock()380     void SAL_CALL UndoManager::unlock(  ) throw (NotLockedException, RuntimeException)
381     {
382         UndoManagerMethodGuard aGuard( *m_pImpl );
383         m_pImpl->getUndoHelper().unlock();
384     }
385 
386     //------------------------------------------------------------------------------------------------------------------
isLocked()387     ::sal_Bool SAL_CALL UndoManager::isLocked(  ) throw (RuntimeException)
388     {
389         UndoManagerMethodGuard aGuard( *m_pImpl );
390         return m_pImpl->getUndoHelper().isLocked();
391     }
392 
393     //------------------------------------------------------------------------------------------------------------------
getParent()394     Reference< XInterface > SAL_CALL UndoManager::getParent(  ) throw (RuntimeException)
395     {
396         UndoManagerMethodGuard aGuard( *m_pImpl );
397         return *&m_pImpl->getParent();
398     }
399 
400     //------------------------------------------------------------------------------------------------------------------
setParent(const Reference<XInterface> & i_parent)401     void SAL_CALL UndoManager::setParent( const Reference< XInterface >& i_parent ) throw (NoSupportException, RuntimeException)
402     {
403         UndoManagerMethodGuard aGuard( *m_pImpl );
404         (void)i_parent;
405         throw NoSupportException( ::rtl::OUString(), m_pImpl->getThis() );
406     }
407 
408     //------------------------------------------------------------------------------------------------------------------
addModifyListener(const Reference<XModifyListener> & i_listener)409     void SAL_CALL UndoManager::addModifyListener( const Reference< XModifyListener >& i_listener ) throw (RuntimeException)
410     {
411         UndoManagerMethodGuard aGuard( *m_pImpl );
412         m_pImpl->getUndoHelper().addModifyListener( i_listener );
413     }
414 
415     //------------------------------------------------------------------------------------------------------------------
removeModifyListener(const Reference<XModifyListener> & i_listener)416     void SAL_CALL UndoManager::removeModifyListener( const Reference< XModifyListener >& i_listener ) throw (RuntimeException)
417     {
418         UndoManagerMethodGuard aGuard( *m_pImpl );
419         m_pImpl->getUndoHelper().removeModifyListener( i_listener );
420     }
421 
422 //......................................................................................................................
423 } // namespace chart
424 //......................................................................................................................
425