1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UndoManager.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_chart2.hxx"
34 #include "UndoManager.hxx"
35 #include "ImplUndoManager.hxx"
36 #include "DisposeHelper.hxx"
37 #include "MutexContainer.hxx"
39 #include "ChartViewHelper.hxx"
41 #include <com/sun/star/util/XCloneable.hpp>
42 #include <com/sun/star/frame/XModel.hpp>
43 #include <com/sun/star/chart2/XChartDocument.hpp>
45 #include <unotools/configitem.hxx>
46 #include <cppuhelper/compbase1.hxx>
50 using namespace ::com::sun::star
;
52 using ::com::sun::star::uno::Reference
;
53 using ::com::sun::star::uno::Sequence
;
54 using ::rtl::OUString
;
57 // --------------------------------------------------------------------------------
64 typedef ::cppu::WeakComponentImplHelper1
<
65 util::XModifyBroadcaster
>
66 ModifyBroadcaster_Base
;
68 class ModifyBroadcaster
:
69 public ::chart::MutexContainer
,
70 public ModifyBroadcaster_Base
78 // ____ XModifyBroadcaster ____
79 virtual void SAL_CALL
addModifyListener( const Reference
< util::XModifyListener
>& xListener
)
80 throw (uno::RuntimeException
);
81 virtual void SAL_CALL
removeModifyListener( const Reference
< util::XModifyListener
>& xListener
)
82 throw (uno::RuntimeException
);
85 ModifyBroadcaster::ModifyBroadcaster() :
86 ModifyBroadcaster_Base( m_aMutex
)
89 void SAL_CALL
ModifyBroadcaster::addModifyListener(
90 const Reference
< util::XModifyListener
>& xListener
)
91 throw (uno::RuntimeException
)
93 rBHelper
.addListener( ::getCppuType( & xListener
), xListener
);
96 void SAL_CALL
ModifyBroadcaster::removeModifyListener(
97 const Reference
< util::XModifyListener
>& xListener
)
98 throw (uno::RuntimeException
)
100 rBHelper
.removeListener( ::getCppuType( & xListener
), xListener
);
103 void ModifyBroadcaster::fireEvent()
105 ::cppu::OInterfaceContainerHelper
* pIC
= rBHelper
.getContainer(
106 ::getCppuType((const uno::Reference
< util::XModifyListener
>*)0) );
109 lang::EventObject
aEvent( static_cast< lang::XComponent
* >( this ) );
110 ::cppu::OInterfaceIteratorHelper
aIt( *pIC
);
111 while( aIt
.hasMoreElements() )
112 (static_cast< util::XModifyListener
*>(aIt
.next()))->modified( aEvent
);
118 UndoManager::UndoManager() :
119 impl::UndoManager_Base( m_aMutex
),
120 m_apUndoStack( new impl::UndoStack()),
121 m_apRedoStack( new impl::UndoStack()),
122 m_pLastRemeberedUndoElement( 0 ),
123 m_nMaxNumberOfUndos( 100 ),
124 m_pModifyBroadcaster( 0 )
127 UndoManager::~UndoManager()
129 DisposeHelper::Dispose( m_xModifyBroadcaster
);
130 m_apUndoStack
->disposeAndClear();
131 m_apRedoStack
->disposeAndClear();
133 delete m_pLastRemeberedUndoElement
;
134 m_pLastRemeberedUndoElement
= 0;
137 void UndoManager::impl_undoRedo(
138 Reference
< frame::XModel
> & xCurrentModel
,
139 impl::UndoStack
* pStackToRemoveFrom
,
140 impl::UndoStack
* pStackToAddTo
)
142 if( pStackToRemoveFrom
&& ! pStackToRemoveFrom
->empty() )
144 // get model from undo/redo
145 impl::UndoElement
* pTop( pStackToRemoveFrom
->top());
148 // put a clone of current model into redo/undo stack with the same
149 // action string as the undo/redo
150 pStackToAddTo
->push( pTop
->createFromModel( xCurrentModel
));
151 // change current model by properties of the model from undo
152 pTop
->applyToModel( xCurrentModel
);
153 // remove the top undo element
154 pStackToRemoveFrom
->pop(), pTop
= 0;
155 ChartViewHelper::setViewToDirtyState( xCurrentModel
);
161 OSL_ENSURE( false, "Can't Undo/Redo" );
165 void UndoManager::fireModifyEvent()
167 if( m_xModifyBroadcaster
.is())
168 m_pModifyBroadcaster
->fireEvent();
172 // ____ ConfigItemListener ____
173 void UndoManager::notify( const ::rtl::OUString
& rPropertyName
)
175 OSL_ENSURE( rPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Steps" )),
176 "Unwanted config property change Notified" );
177 if( rPropertyName
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Steps" )))
178 retrieveConfigUndoSteps();
181 void UndoManager::retrieveConfigUndoSteps()
183 if( ! m_apUndoStepsConfigItem
.get())
184 m_apUndoStepsConfigItem
.reset( new impl::UndoStepsConfigItem( *this ));
185 m_nMaxNumberOfUndos
= m_apUndoStepsConfigItem
->getUndoSteps();
186 m_apUndoStack
->limitSize( m_nMaxNumberOfUndos
);
187 m_apRedoStack
->limitSize( m_nMaxNumberOfUndos
);
189 // a list of available undo steps could shrink here
193 // ____ XModifyBroadcaster ____
194 void SAL_CALL
UndoManager::addModifyListener( const Reference
< util::XModifyListener
>& aListener
)
195 throw (uno::RuntimeException
)
197 if( ! m_xModifyBroadcaster
.is())
199 m_pModifyBroadcaster
= new impl::ModifyBroadcaster();
200 m_xModifyBroadcaster
.set( static_cast< cppu::OWeakObject
* >( m_pModifyBroadcaster
), uno::UNO_QUERY
);
202 m_xModifyBroadcaster
->addModifyListener( aListener
);
205 void SAL_CALL
UndoManager::removeModifyListener( const Reference
< util::XModifyListener
>& aListener
)
206 throw (uno::RuntimeException
)
208 if( ! m_xModifyBroadcaster
.is())
210 m_pModifyBroadcaster
= new impl::ModifyBroadcaster();
211 m_xModifyBroadcaster
.set( static_cast< cppu::OWeakObject
* >( m_pModifyBroadcaster
), uno::UNO_QUERY
);
213 m_xModifyBroadcaster
->removeModifyListener( aListener
);
216 // ____ chart2::XUndoManager ____
217 void SAL_CALL
UndoManager::preAction( const Reference
< frame::XModel
>& xModelBeforeChange
)
218 throw (uno::RuntimeException
)
220 OSL_ENSURE( ! m_pLastRemeberedUndoElement
, "Looks like postAction or cancelAction call was missing" );
221 m_pLastRemeberedUndoElement
= new impl::UndoElement( xModelBeforeChange
);
224 void SAL_CALL
UndoManager::preActionWithArguments(
225 const Reference
< frame::XModel
>& xModelBeforeChange
,
226 const Sequence
< beans::PropertyValue
>& aArguments
)
227 throw (uno::RuntimeException
)
229 bool bActionHandled( false );
230 OSL_ENSURE( ! m_pLastRemeberedUndoElement
, "Looks like postAction or cancelAction call was missing" );
231 if( aArguments
.getLength() > 0 )
233 OSL_ENSURE( aArguments
.getLength() == 1, "More than one argument is not supported yet" );
234 if( aArguments
[0].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("WithData")))
236 m_pLastRemeberedUndoElement
= new impl::UndoElementWithData( xModelBeforeChange
);
237 bActionHandled
= true;
239 else if( aArguments
[0].Name
.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("WithSelection")))
241 m_pLastRemeberedUndoElement
= new impl::UndoElementWithSelection( xModelBeforeChange
);
242 bActionHandled
= true;
246 if( !bActionHandled
)
247 preAction( xModelBeforeChange
);
250 void SAL_CALL
UndoManager::postAction( const OUString
& aUndoText
)
251 throw (uno::RuntimeException
)
253 OSL_ENSURE( m_pLastRemeberedUndoElement
, "Looks like preAction call was missing" );
254 if( m_pLastRemeberedUndoElement
)
256 m_pLastRemeberedUndoElement
->setActionString( aUndoText
);
257 m_apUndoStack
->push( m_pLastRemeberedUndoElement
);
258 m_pLastRemeberedUndoElement
= 0;
260 // redo no longer possible
261 m_apRedoStack
->disposeAndClear();
263 // it suffices to get the number of undo steps from config after the
264 // first time postAction has been called
265 if( ! m_apUndoStepsConfigItem
.get())
266 retrieveConfigUndoSteps();
272 void SAL_CALL
UndoManager::cancelAction()
273 throw (uno::RuntimeException
)
275 delete m_pLastRemeberedUndoElement
;
276 m_pLastRemeberedUndoElement
= 0;
279 void SAL_CALL
UndoManager::cancelActionWithUndo( Reference
< frame::XModel
>& xModelToRestore
)
280 throw (uno::RuntimeException
)
282 if( m_pLastRemeberedUndoElement
)
284 m_pLastRemeberedUndoElement
->applyToModel( xModelToRestore
);
289 void SAL_CALL
UndoManager::undo( Reference
< frame::XModel
>& xCurrentModel
)
290 throw (uno::RuntimeException
)
292 OSL_ASSERT( m_apUndoStack
.get() && m_apRedoStack
.get());
293 impl_undoRedo( xCurrentModel
, m_apUndoStack
.get(), m_apRedoStack
.get());
296 void SAL_CALL
UndoManager::redo( Reference
< frame::XModel
>& xCurrentModel
)
297 throw (uno::RuntimeException
)
299 OSL_ASSERT( m_apUndoStack
.get() && m_apRedoStack
.get());
300 impl_undoRedo( xCurrentModel
, m_apRedoStack
.get(), m_apUndoStack
.get());
303 ::sal_Bool SAL_CALL
UndoManager::undoPossible()
304 throw (uno::RuntimeException
)
306 return ! m_apUndoStack
->empty();
309 ::sal_Bool SAL_CALL
UndoManager::redoPossible()
310 throw (uno::RuntimeException
)
312 return ! m_apRedoStack
->empty();
315 OUString SAL_CALL
UndoManager::getCurrentUndoString()
316 throw (uno::RuntimeException
)
318 return m_apUndoStack
->topUndoString();
321 OUString SAL_CALL
UndoManager::getCurrentRedoString()
322 throw (uno::RuntimeException
)
324 return m_apRedoStack
->topUndoString();
327 Sequence
< OUString
> SAL_CALL
UndoManager::getAllUndoStrings()
328 throw (uno::RuntimeException
)
330 return m_apUndoStack
->getUndoStrings();
333 Sequence
< OUString
> SAL_CALL
UndoManager::getAllRedoStrings()
334 throw (uno::RuntimeException
)
336 return m_apRedoStack
->getUndoStrings();
339 // ____ XUndoHelper ____
340 Reference
< frame::XModel
> SAL_CALL
UndoManager::getModelCloneForUndo(
341 const Reference
< frame::XModel
>& xModelBeforeChange
)
342 throw (uno::RuntimeException
)
344 return impl::UndoElement::cloneModel( xModelBeforeChange
);
347 void SAL_CALL
UndoManager::applyModelContent(
348 Reference
< frame::XModel
>& xModelToChange
,
349 const Reference
< frame::XModel
>& xModelToCopyFrom
)
350 throw (uno::RuntimeException
)
352 impl::UndoElement::applyModelContentToModel( xModelToChange
, xModelToCopyFrom
);