1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #ifndef INCLUDED_SVL_UNDO_HXX
20 #define INCLUDED_SVL_UNDO_HXX
22 #include <svl/svldllapi.h>
23 #include <rtl/ustring.hxx>
24 #include <tools/rtti.hxx>
29 struct MarkedUndoAction
;
31 class SVL_DLLPUBLIC SfxRepeatTarget
35 virtual ~SfxRepeatTarget() = 0;
40 class SVL_DLLPUBLIC SfxUndoContext
43 virtual ~SfxUndoContext() = 0;
47 class SfxLinkUndoAction
;
49 class SVL_DLLPUBLIC SfxUndoAction
52 SfxLinkUndoAction
* mpSfxLinkUndoAction
;
57 virtual ~SfxUndoAction();
59 virtual void SetLinkToSfxLinkUndoAction(SfxLinkUndoAction
* pSfxLinkUndoAction
);
62 virtual void UndoWithContext( SfxUndoContext
& i_context
);
64 virtual void RedoWithContext( SfxUndoContext
& i_context
);
65 virtual void Repeat(SfxRepeatTarget
&);
66 virtual bool CanRepeat(SfxRepeatTarget
&) const;
68 virtual bool Merge( SfxUndoAction
*pNextAction
);
70 virtual OUString
GetComment() const;
71 virtual OUString
GetRepeatComment(SfxRepeatTarget
&) const;
72 virtual sal_uInt16
GetId() const;
73 virtual void dumpAsXml(struct _xmlTextWriter
* pWriter
) const;
76 SfxUndoAction( const SfxUndoAction
& ) SAL_DELETED_FUNCTION
;
77 SfxUndoAction
& operator=( const SfxUndoAction
& ) SAL_DELETED_FUNCTION
;
82 /// is a mark on the Undo stack
83 typedef sal_Int32 UndoStackMark
;
84 #define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
86 class SVL_DLLPUBLIC SfxUndoActions
93 SfxUndoActions( const SfxUndoActions
& r
);
99 const MarkedUndoAction
& operator[]( size_t i
) const;
100 MarkedUndoAction
& operator[]( size_t i
);
102 const SfxUndoAction
* GetUndoAction( size_t i
) const;
103 SfxUndoAction
* GetUndoAction( size_t i
);
105 void Remove( size_t i_pos
);
106 void Remove( size_t i_pos
, size_t i_count
);
107 void Insert( SfxUndoAction
* i_action
, size_t i_pos
);
110 /** do not make use of these implementation details, unless you
111 really really have to! */
112 struct SVL_DLLPUBLIC SfxUndoArray
114 SfxUndoActions aUndoActions
;
115 size_t nMaxUndoActions
;
116 size_t nCurUndoAction
;
117 SfxUndoArray
*pFatherUndoArray
;
118 SfxUndoArray(size_t nMax
=0):
119 nMaxUndoActions(nMax
), nCurUndoAction(0),
120 pFatherUndoArray(0) {}
121 virtual ~SfxUndoArray();
126 /** do not make use of these implementation details, unless you
127 really really have to! */
128 class SVL_DLLPUBLIC SfxListUndoAction
: public SfxUndoAction
, public SfxUndoArray
132 UndoAction to composite multiple Undos in one UndoAction.
133 These actions are used by SfxUndomanager. With < SfxUndoManager::EnterListAction >
134 you can go one composite level down and with < SfxUndoManager::LeaveListAction > up again.
135 Redo and Undo work element wise on SfxListUndoActions.
145 const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
, SfxUndoArray
*pFather
);
146 virtual ~SfxListUndoAction();
148 virtual void Undo() SAL_OVERRIDE
;
149 virtual void UndoWithContext( SfxUndoContext
& i_context
) SAL_OVERRIDE
;
150 virtual void Redo() SAL_OVERRIDE
;
151 virtual void RedoWithContext( SfxUndoContext
& i_context
) SAL_OVERRIDE
;
152 virtual void Repeat(SfxRepeatTarget
&) SAL_OVERRIDE
;
153 virtual bool CanRepeat(SfxRepeatTarget
&) const SAL_OVERRIDE
;
155 virtual bool Merge( SfxUndoAction
*pNextAction
) SAL_OVERRIDE
;
157 virtual OUString
GetComment() const SAL_OVERRIDE
;
158 virtual OUString
GetRepeatComment(SfxRepeatTarget
&) const SAL_OVERRIDE
;
159 virtual sal_uInt16
GetId() const SAL_OVERRIDE
;
161 void SetComment(const OUString
& rComment
);
162 void dumpAsXml(struct _xmlTextWriter
* pWriter
) const SAL_OVERRIDE
;
167 /** is a callback interface for notifications about state changes of an SfxUndoManager
169 class SAL_NO_VTABLE SfxUndoListener
172 virtual void actionUndone( const OUString
& i_actionComment
) = 0;
173 virtual void actionRedone( const OUString
& i_actionComment
) = 0;
174 virtual void undoActionAdded( const OUString
& i_actionComment
) = 0;
175 virtual void cleared() = 0;
176 virtual void clearedRedo() = 0;
177 virtual void resetAll() = 0;
178 virtual void listActionEntered( const OUString
& i_comment
) = 0;
179 virtual void listActionLeft( const OUString
& i_comment
) = 0;
180 virtual void listActionLeftAndMerged() = 0;
181 virtual void listActionCancelled() = 0;
182 virtual void undoManagerDying() = 0;
185 ~SfxUndoListener() {}
192 class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI IUndoManager
195 static bool const CurrentLevel
= true;
196 static bool const TopLevel
= false;
198 virtual ~IUndoManager() { };
200 virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount
) = 0;
201 virtual size_t GetMaxUndoActionCount() const = 0;
203 virtual void AddUndoAction( SfxUndoAction
*pAction
, bool bTryMerg
=false ) = 0;
205 virtual size_t GetUndoActionCount( bool const i_currentLevel
= CurrentLevel
) const = 0;
206 virtual sal_uInt16
GetUndoActionId() const = 0;
207 virtual OUString
GetUndoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const = 0;
208 virtual SfxUndoAction
* GetUndoAction( size_t nNo
=0 ) const = 0;
210 virtual size_t GetRedoActionCount( bool const i_currentLevel
= CurrentLevel
) const = 0;
211 virtual OUString
GetRedoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const = 0;
212 virtual SfxUndoAction
* GetRedoAction( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const = 0;
214 virtual bool Undo() = 0;
215 virtual bool Redo() = 0;
217 /** clears both the Redo and the Undo stack.
219 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
221 virtual void Clear() = 0;
223 /** clears the Redo stack.
225 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
227 virtual void ClearRedo() = 0;
229 /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the
232 Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>,
233 followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an
234 atomic operation, also resulting in only one notification.
236 virtual void Reset() = 0;
238 /** determines whether an Undo or Redo is currently running
240 virtual bool IsDoing() const = 0;
242 virtual size_t GetRepeatActionCount() const = 0;
243 virtual OUString
GetRepeatActionComment( SfxRepeatTarget
&rTarget
) const = 0;
244 virtual bool Repeat( SfxRepeatTarget
&rTarget
) = 0;
245 virtual bool CanRepeat( SfxRepeatTarget
&rTarget
) const = 0;
247 virtual void EnterListAction(const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
=0) = 0;
249 /** leaves the list action entered with EnterListAction
250 @return the number of the sub actions in the list which has just been left. Note that in case no such
251 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
253 virtual size_t LeaveListAction() = 0;
255 /** leaves the list action entered with EnterListAction, and forcefully merges the previous
256 action on the stack into the newly created list action.
258 Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to
259 AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo
260 stack will now still contain one undo action: the newly created list action, whose first child is the
261 original A, whose other children are those you added via AddUndoAction, and whose comment is the same as
264 Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are
265 hidden from the user.
267 @return the number of the sub actions in the list which has just been left. Note that in case no such
268 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
270 virtual size_t LeaveAndMergeListAction() = 0;
272 /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
273 virtual bool IsInListAction() const = 0;
275 /// determines how many nested list actions are currently open
276 virtual size_t GetListActionDepth() const = 0;
278 /** clears the redo stack and removes the top undo action */
279 virtual void RemoveLastUndoAction() = 0;
281 /** enables (true) or disables (false) recording of undo actions
283 If undo actions are added while undo is disabled, they are deleted.
284 Disabling undo does not clear the current undo buffer!
286 Multiple calls to <code>EnableUndo</code> are not cumulative. That is, calling <code>EnableUndo( false )</code>
287 twice, and then calling <code>EnableUndo( true )</code> means that Undo is enable afterwards.
289 virtual void EnableUndo( bool bEnable
) = 0;
291 // returns true if undo is currently enabled
292 // This returns false if undo was disabled using EnableUndo( false ) and
293 // also during the runtime of the Undo() and Redo() methods.
294 virtual bool IsUndoEnabled() const = 0;
296 /// adds a new listener to be notified about changes in the UndoManager's state
297 virtual void AddUndoListener( SfxUndoListener
& i_listener
) = 0;
298 virtual void RemoveUndoListener( SfxUndoListener
& i_listener
) = 0;
304 namespace svl
{ namespace undo
{ namespace impl
306 class UndoManagerGuard
;
310 struct SfxUndoManager_Data
;
311 class SVL_DLLPUBLIC SfxUndoManager
: public ::svl::IUndoManager
313 friend class SfxLinkUndoAction
;
315 std::unique_ptr
< SfxUndoManager_Data
>
318 SfxUndoManager( size_t nMaxUndoActionCount
= 20 );
319 virtual ~SfxUndoManager();
321 // IUndoManager overridables
322 virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount
) SAL_OVERRIDE
;
323 virtual size_t GetMaxUndoActionCount() const SAL_OVERRIDE
;
324 virtual void AddUndoAction( SfxUndoAction
*pAction
, bool bTryMerg
=false ) SAL_OVERRIDE
;
325 virtual size_t GetUndoActionCount( bool const i_currentLevel
= CurrentLevel
) const SAL_OVERRIDE
;
326 virtual sal_uInt16
GetUndoActionId() const SAL_OVERRIDE
;
327 virtual OUString
GetUndoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const SAL_OVERRIDE
;
328 virtual SfxUndoAction
* GetUndoAction( size_t nNo
=0 ) const SAL_OVERRIDE
;
329 virtual size_t GetRedoActionCount( bool const i_currentLevel
= CurrentLevel
) const SAL_OVERRIDE
;
330 virtual OUString
GetRedoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const SAL_OVERRIDE
;
331 virtual SfxUndoAction
* GetRedoAction( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const SAL_OVERRIDE
;
332 virtual bool Undo() SAL_OVERRIDE
;
333 virtual bool Redo() SAL_OVERRIDE
;
334 virtual void Clear() SAL_OVERRIDE
;
335 virtual void ClearRedo() SAL_OVERRIDE
;
336 virtual void Reset() SAL_OVERRIDE
;
337 virtual bool IsDoing() const SAL_OVERRIDE
;
338 virtual size_t GetRepeatActionCount() const SAL_OVERRIDE
;
339 virtual OUString
GetRepeatActionComment( SfxRepeatTarget
&rTarget
) const SAL_OVERRIDE
;
340 virtual bool Repeat( SfxRepeatTarget
&rTarget
) SAL_OVERRIDE
;
341 virtual bool CanRepeat( SfxRepeatTarget
&rTarget
) const SAL_OVERRIDE
;
342 virtual void EnterListAction(const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
=0) SAL_OVERRIDE
;
343 virtual size_t LeaveListAction() SAL_OVERRIDE
;
344 virtual size_t LeaveAndMergeListAction() SAL_OVERRIDE
;
345 virtual bool IsInListAction() const SAL_OVERRIDE
;
346 virtual size_t GetListActionDepth() const SAL_OVERRIDE
;
347 virtual void RemoveLastUndoAction() SAL_OVERRIDE
;
348 virtual void EnableUndo( bool bEnable
) SAL_OVERRIDE
;
349 virtual bool IsUndoEnabled() const SAL_OVERRIDE
;
350 virtual void AddUndoListener( SfxUndoListener
& i_listener
) SAL_OVERRIDE
;
351 virtual void RemoveUndoListener( SfxUndoListener
& i_listener
) SAL_OVERRIDE
;
353 /** marks the current top-level element of the Undo stack, and returns a unique ID for it
355 UndoStackMark
MarkTopUndoAction();
357 /** removes a mark given by its ID.
358 After the call, the mark ID is invalid.
360 void RemoveMark( UndoStackMark
const i_mark
);
362 /** determines whether the top action on the Undo stack has a given mark
364 bool HasTopUndoActionMark( UndoStackMark
const i_mark
);
366 /** removes the oldest Undo actions from the stack
368 void RemoveOldestUndoActions( size_t const i_count
);
370 void dumpAsXml(struct _xmlTextWriter
* pWriter
) const;
373 bool UndoWithContext( SfxUndoContext
& i_context
);
374 bool RedoWithContext( SfxUndoContext
& i_context
);
376 void ImplClearRedo_NoLock( bool const i_currentLevel
);
378 /** clears all undo actions on the current level, plus all undo actions on superordinate levels,
379 as soon as those levels are reached.
381 If no list action is active currently, i.e. we're on the top level already, this method is equivalent to
384 Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all
385 undo actions on the then-current level are removed, too. This is continued until the top level is reached.
387 void ClearAllLevels();
390 size_t ImplLeaveListAction( const bool i_merge
, ::svl::undo::impl::UndoManagerGuard
& i_guard
);
391 bool ImplAddUndoAction_NoNotify( SfxUndoAction
* pAction
, bool bTryMerge
, bool bClearRedo
, ::svl::undo::impl::UndoManagerGuard
& i_guard
);
392 void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard
& i_guard
, bool const i_currentLevel
);
393 void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard
& i_guard
);
394 void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard
& i_guard
);
395 size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel
= CurrentLevel
) const;
396 bool ImplIsUndoEnabled_Lock() const;
397 bool ImplIsInListAction_Lock() const;
398 void ImplEnableUndo_Lock( bool const i_enable
);
400 bool ImplUndo( SfxUndoContext
* i_contextOrNull
);
401 bool ImplRedo( SfxUndoContext
* i_contextOrNull
);
403 friend class ::svl::undo::impl::LockGuard
;
408 class SVL_DLLPUBLIC SfxLinkUndoAction
: public SfxUndoAction
412 SfxLinkUndoAction is used to link two SfxUndoManager. The Undo/Redos inserted
413 in the first SfxUndoManager redict their Undo/Redo to the second. With this it
414 does not matter, if the undo/redo initially was on the first or the second.
416 After inserting SfxLinkUndoAction on the first SfxUndoManager, you have to
417 insert it on the second as well. While the second SfxUndoManager is steered
418 from the first, you must not insert neither Actions nor issue a undo/redo
419 command to the second, while it is steered by the first.
424 friend class SfxUndoAction
;
425 void LinkedSfxUndoActionDestructed(const SfxUndoAction
& rCandidate
);
429 SfxLinkUndoAction(::svl::IUndoManager
*pManager
);
430 virtual ~SfxLinkUndoAction();
432 virtual void Undo() SAL_OVERRIDE
;
433 virtual void Redo() SAL_OVERRIDE
;
434 virtual bool CanRepeat(SfxRepeatTarget
& r
) const SAL_OVERRIDE
;
436 virtual void Repeat(SfxRepeatTarget
&r
) SAL_OVERRIDE
;
438 virtual OUString
GetComment() const SAL_OVERRIDE
;
439 virtual OUString
GetRepeatComment(SfxRepeatTarget
&r
) const SAL_OVERRIDE
;
440 virtual sal_uInt16
GetId() const SAL_OVERRIDE
;
442 SfxUndoAction
* GetAction() const { return pAction
; }
445 ::svl::IUndoManager
* pUndoManager
;
446 SfxUndoAction
* pAction
;
452 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */