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>
28 struct MarkedUndoAction
;
30 class SVL_DLLPUBLIC SfxRepeatTarget
33 virtual ~SfxRepeatTarget() = 0;
37 class SVL_DLLPUBLIC SfxUndoContext
40 virtual ~SfxUndoContext() = 0;
44 class SfxLinkUndoAction
;
46 class SVL_DLLPUBLIC SfxUndoAction
49 SfxLinkUndoAction
* mpSfxLinkUndoAction
;
53 virtual ~SfxUndoAction();
55 virtual void SetLinkToSfxLinkUndoAction(SfxLinkUndoAction
* pSfxLinkUndoAction
);
58 virtual void UndoWithContext( SfxUndoContext
& i_context
);
60 virtual void RedoWithContext( SfxUndoContext
& i_context
);
61 virtual void Repeat(SfxRepeatTarget
&);
62 virtual bool CanRepeat(SfxRepeatTarget
&) const;
64 virtual bool Merge( SfxUndoAction
*pNextAction
);
66 virtual OUString
GetComment() const;
67 virtual OUString
GetRepeatComment(SfxRepeatTarget
&) const;
68 virtual sal_uInt16
GetId() const;
69 virtual void dumpAsXml(struct _xmlTextWriter
* pWriter
) const;
72 SfxUndoAction( const SfxUndoAction
& ) = delete;
73 SfxUndoAction
& operator=( const SfxUndoAction
& ) = delete;
77 /// is a mark on the Undo stack
78 typedef sal_Int32 UndoStackMark
;
79 #define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
81 class SVL_DLLPUBLIC SfxUndoActions
84 std::unique_ptr
<Impl
> mpImpl
;
88 SfxUndoActions( const SfxUndoActions
& r
);
94 const MarkedUndoAction
& operator[]( size_t i
) const;
95 MarkedUndoAction
& operator[]( size_t i
);
97 const SfxUndoAction
* GetUndoAction( size_t i
) const;
98 SfxUndoAction
* GetUndoAction( size_t i
);
100 void Remove( size_t i_pos
);
101 void Remove( size_t i_pos
, size_t i_count
);
102 void Insert( SfxUndoAction
* i_action
, size_t i_pos
);
105 /** do not make use of these implementation details, unless you
106 really really have to! */
107 struct SVL_DLLPUBLIC SfxUndoArray
109 SfxUndoActions aUndoActions
;
110 size_t nMaxUndoActions
;
111 size_t nCurUndoAction
;
112 SfxUndoArray
*pFatherUndoArray
;
113 SfxUndoArray(size_t nMax
=0):
114 nMaxUndoActions(nMax
), nCurUndoAction(0),
115 pFatherUndoArray(nullptr) {}
116 virtual ~SfxUndoArray();
120 /** do not make use of these implementation details, unless you
121 really really have to! */
122 class SVL_DLLPUBLIC SfxListUndoAction
: public SfxUndoAction
, public SfxUndoArray
126 UndoAction to composite multiple Undos in one UndoAction.
127 These actions are used by SfxUndomanager. With < SfxUndoManager::EnterListAction >
128 you can go one composite level down and with < SfxUndoManager::LeaveListAction > up again.
129 Redo and Undo work element wise on SfxListUndoActions.
133 std::unique_ptr
<Impl
> mpImpl
;
138 const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
, SfxUndoArray
*pFather
);
139 virtual ~SfxListUndoAction();
141 virtual void Undo() override
;
142 virtual void UndoWithContext( SfxUndoContext
& i_context
) override
;
143 virtual void Redo() override
;
144 virtual void RedoWithContext( SfxUndoContext
& i_context
) override
;
145 virtual void Repeat(SfxRepeatTarget
&) override
;
146 virtual bool CanRepeat(SfxRepeatTarget
&) const override
;
148 virtual bool Merge( SfxUndoAction
*pNextAction
) override
;
150 virtual OUString
GetComment() const override
;
151 virtual OUString
GetRepeatComment(SfxRepeatTarget
&) const override
;
152 virtual sal_uInt16
GetId() const override
;
154 void SetComment(const OUString
& rComment
);
155 void dumpAsXml(struct _xmlTextWriter
* pWriter
) const override
;
159 /** is a callback interface for notifications about state changes of an SfxUndoManager
161 class SAL_NO_VTABLE SfxUndoListener
164 virtual void actionUndone( const OUString
& i_actionComment
) = 0;
165 virtual void actionRedone( const OUString
& i_actionComment
) = 0;
166 virtual void undoActionAdded( const OUString
& i_actionComment
) = 0;
167 virtual void cleared() = 0;
168 virtual void clearedRedo() = 0;
169 virtual void resetAll() = 0;
170 virtual void listActionEntered( const OUString
& i_comment
) = 0;
171 virtual void listActionLeft( const OUString
& i_comment
) = 0;
172 virtual void listActionCancelled() = 0;
173 virtual void undoManagerDying() = 0;
176 ~SfxUndoListener() {}
182 class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI IUndoManager
185 static bool const CurrentLevel
= true;
186 static bool const TopLevel
= false;
188 virtual ~IUndoManager() { };
190 virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount
) = 0;
191 virtual size_t GetMaxUndoActionCount() const = 0;
193 virtual void AddUndoAction( SfxUndoAction
*pAction
, bool bTryMerg
=false ) = 0;
195 virtual size_t GetUndoActionCount( bool const i_currentLevel
= CurrentLevel
) const = 0;
196 virtual sal_uInt16
GetUndoActionId() const = 0;
197 virtual OUString
GetUndoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const = 0;
198 virtual SfxUndoAction
* GetUndoAction( size_t nNo
=0 ) const = 0;
200 virtual size_t GetRedoActionCount( bool const i_currentLevel
= CurrentLevel
) const = 0;
201 virtual OUString
GetRedoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const = 0;
202 virtual SfxUndoAction
* GetRedoAction() const = 0;
204 virtual bool Undo() = 0;
205 virtual bool Redo() = 0;
207 /** clears both the Redo and the Undo stack.
209 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
211 virtual void Clear() = 0;
213 /** clears the Redo stack.
215 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
217 virtual void ClearRedo() = 0;
219 /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the
222 Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>,
223 followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an
224 atomic operation, also resulting in only one notification.
226 virtual void Reset() = 0;
228 /** determines whether an Undo or Redo is currently running
230 virtual bool IsDoing() const = 0;
232 virtual size_t GetRepeatActionCount() const = 0;
233 virtual OUString
GetRepeatActionComment( SfxRepeatTarget
&rTarget
) const = 0;
234 virtual bool Repeat( SfxRepeatTarget
&rTarget
) = 0;
235 virtual bool CanRepeat( SfxRepeatTarget
&rTarget
) const = 0;
237 virtual void EnterListAction(const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
=0) = 0;
239 /** leaves the list action entered with EnterListAction
240 @return the number of the sub actions in the list which has just been left. Note that in case no such
241 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
243 virtual size_t LeaveListAction() = 0;
245 /** leaves the list action entered with EnterListAction, and forcefully merges the previous
246 action on the stack into the newly created list action.
248 Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to
249 AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo
250 stack will now still contain one undo action: the newly created list action, whose first child is the
251 original A, whose other children are those you added via AddUndoAction, and whose comment is the same as
254 Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are
255 hidden from the user.
257 @return the number of the sub actions in the list which has just been left. Note that in case no such
258 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
260 virtual size_t LeaveAndMergeListAction() = 0;
262 /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
263 virtual bool IsInListAction() const = 0;
265 /// determines how many nested list actions are currently open
266 virtual size_t GetListActionDepth() const = 0;
268 /** clears the redo stack and removes the top undo action */
269 virtual void RemoveLastUndoAction() = 0;
271 /** enables (true) or disables (false) recording of undo actions
273 If undo actions are added while undo is disabled, they are deleted.
274 Disabling undo does not clear the current undo buffer!
276 Multiple calls to <code>EnableUndo</code> are not cumulative. That is, calling <code>EnableUndo( false )</code>
277 twice, and then calling <code>EnableUndo( true )</code> means that Undo is enable afterwards.
279 virtual void EnableUndo( bool bEnable
) = 0;
281 // returns true if undo is currently enabled
282 // This returns false if undo was disabled using EnableUndo( false ) and
283 // also during the runtime of the Undo() and Redo() methods.
284 virtual bool IsUndoEnabled() const = 0;
286 /// adds a new listener to be notified about changes in the UndoManager's state
287 virtual void AddUndoListener( SfxUndoListener
& i_listener
) = 0;
288 virtual void RemoveUndoListener( SfxUndoListener
& i_listener
) = 0;
293 namespace svl
{ namespace undo
{ namespace impl
295 class UndoManagerGuard
;
299 struct SfxUndoManager_Data
;
300 class SVL_DLLPUBLIC SfxUndoManager
: public ::svl::IUndoManager
302 friend class SfxLinkUndoAction
;
304 std::unique_ptr
< SfxUndoManager_Data
>
307 SfxUndoManager( size_t nMaxUndoActionCount
= 20 );
308 virtual ~SfxUndoManager();
310 // IUndoManager overridables
311 virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount
) override
;
312 virtual size_t GetMaxUndoActionCount() const override
;
313 virtual void AddUndoAction( SfxUndoAction
*pAction
, bool bTryMerg
=false ) override
;
314 virtual size_t GetUndoActionCount( bool const i_currentLevel
= CurrentLevel
) const override
;
315 virtual sal_uInt16
GetUndoActionId() const override
;
316 virtual OUString
GetUndoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const override
;
317 virtual SfxUndoAction
* GetUndoAction( size_t nNo
=0 ) const override
;
318 virtual size_t GetRedoActionCount( bool const i_currentLevel
= CurrentLevel
) const override
;
319 virtual OUString
GetRedoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const override
;
320 virtual SfxUndoAction
* GetRedoAction() const override
;
321 virtual bool Undo() override
;
322 virtual bool Redo() override
;
323 virtual void Clear() override
;
324 virtual void ClearRedo() override
;
325 virtual void Reset() override
;
326 virtual bool IsDoing() const override
;
327 virtual size_t GetRepeatActionCount() const override
;
328 virtual OUString
GetRepeatActionComment( SfxRepeatTarget
&rTarget
) const override
;
329 virtual bool Repeat( SfxRepeatTarget
&rTarget
) override
;
330 virtual bool CanRepeat( SfxRepeatTarget
&rTarget
) const override
;
331 virtual void EnterListAction(const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
=0) override
;
332 virtual size_t LeaveListAction() override
;
333 virtual size_t LeaveAndMergeListAction() override
;
334 virtual bool IsInListAction() const override
;
335 virtual size_t GetListActionDepth() const override
;
336 virtual void RemoveLastUndoAction() override
;
337 virtual void EnableUndo( bool bEnable
) override
;
338 virtual bool IsUndoEnabled() const override
;
339 virtual void AddUndoListener( SfxUndoListener
& i_listener
) override
;
340 virtual void RemoveUndoListener( SfxUndoListener
& i_listener
) override
;
342 /** marks the current top-level element of the Undo stack, and returns a unique ID for it
344 UndoStackMark
MarkTopUndoAction();
346 /** removes a mark given by its ID.
347 After the call, the mark ID is invalid.
349 void RemoveMark( UndoStackMark
const i_mark
);
351 /** determines whether the top action on the Undo stack has a given mark
353 bool HasTopUndoActionMark( UndoStackMark
const i_mark
);
355 /** removes the oldest Undo actions from the stack
357 void RemoveOldestUndoAction();
359 void dumpAsXml(struct _xmlTextWriter
* pWriter
) const;
362 bool UndoWithContext( SfxUndoContext
& i_context
);
363 bool RedoWithContext( SfxUndoContext
& i_context
);
365 void ImplClearRedo_NoLock( bool const i_currentLevel
);
367 /** clears all undo actions on the current level, plus all undo actions on superordinate levels,
368 as soon as those levels are reached.
370 If no list action is active currently, i.e. we're on the top level already, this method is equivalent to
373 Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all
374 undo actions on the then-current level are removed, too. This is continued until the top level is reached.
376 void ClearAllLevels();
379 size_t ImplLeaveListAction( const bool i_merge
, ::svl::undo::impl::UndoManagerGuard
& i_guard
);
380 bool ImplAddUndoAction_NoNotify( SfxUndoAction
* pAction
, bool bTryMerge
, bool bClearRedo
, ::svl::undo::impl::UndoManagerGuard
& i_guard
);
381 void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard
& i_guard
, bool const i_currentLevel
);
382 void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard
& i_guard
);
383 void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard
& i_guard
);
384 size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel
= CurrentLevel
) const;
385 bool ImplIsUndoEnabled_Lock() const;
386 bool ImplIsInListAction_Lock() const;
387 void ImplEnableUndo_Lock( bool const i_enable
);
389 bool ImplUndo( SfxUndoContext
* i_contextOrNull
);
390 bool ImplRedo( SfxUndoContext
* i_contextOrNull
);
392 friend class ::svl::undo::impl::LockGuard
;
396 class SVL_DLLPUBLIC SfxLinkUndoAction
: public SfxUndoAction
400 SfxLinkUndoAction is used to link two SfxUndoManager. The Undo/Redos inserted
401 in the first SfxUndoManager redirect their Undo/Redo to the second. With this it
402 does not matter, if the undo/redo initially was on the first or the second.
404 After inserting SfxLinkUndoAction on the first SfxUndoManager, you have to
405 insert it on the second as well. While the second SfxUndoManager is steered
406 from the first, you must not insert neither Actions nor issue a undo/redo
407 command to the second, while it is steered by the first.
412 friend class SfxUndoAction
;
413 void LinkedSfxUndoActionDestructed(const SfxUndoAction
& rCandidate
);
416 SfxLinkUndoAction(::svl::IUndoManager
*pManager
);
417 virtual ~SfxLinkUndoAction();
419 virtual void Undo() override
;
420 virtual void Redo() override
;
421 virtual bool CanRepeat(SfxRepeatTarget
& r
) const override
;
423 virtual void Repeat(SfxRepeatTarget
&r
) override
;
425 virtual OUString
GetComment() const override
;
426 virtual OUString
GetRepeatComment(SfxRepeatTarget
&r
) const override
;
427 virtual sal_uInt16
GetId() const override
;
429 SfxUndoAction
* GetAction() const { return pAction
; }
432 ::svl::IUndoManager
* pUndoManager
;
433 SfxUndoAction
* pAction
;
439 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */