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/datetime.hxx>
25 #include <o3tl/strong_int.hxx>
30 typedef o3tl::strong_int
<sal_Int32
, struct ViewShellIdTag
> ViewShellId
;
31 typedef o3tl::strong_int
<int, struct ViewShellDocIdTag
> ViewShellDocId
;
33 typedef struct _xmlTextWriter
* xmlTextWriterPtr
;
35 class SVL_DLLPUBLIC SfxRepeatTarget
38 virtual ~SfxRepeatTarget() = 0;
42 class SVL_DLLPUBLIC SfxUndoContext
45 virtual ~SfxUndoContext() = 0;
49 class SVL_DLLPUBLIC SfxUndoAction
53 virtual ~SfxUndoAction() COVERITY_NOEXCEPT_FALSE
;
56 virtual void UndoWithContext( SfxUndoContext
& i_context
);
58 virtual void RedoWithContext( SfxUndoContext
& i_context
);
59 virtual void Repeat(SfxRepeatTarget
&);
60 virtual bool CanRepeat(SfxRepeatTarget
&) const;
62 virtual bool Merge( SfxUndoAction
*pNextAction
);
64 virtual OUString
GetComment() const;
65 virtual OUString
GetRepeatComment(SfxRepeatTarget
&) const;
66 /// ID of the view shell that created this undo action.
67 virtual ViewShellId
GetViewShellId() const;
68 /// Timestamp when this undo item was created.
69 const DateTime
& GetDateTime() const;
70 virtual void dumpAsXml(xmlTextWriterPtr pWriter
) const;
73 SfxUndoAction( const SfxUndoAction
& ) = delete;
74 SfxUndoAction
& operator=( const SfxUndoAction
& ) = delete;
80 /// is a mark on the Undo stack
81 typedef sal_Int32 UndoStackMark
;
82 #define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
84 struct MarkedUndoAction
86 std::unique_ptr
<SfxUndoAction
> pAction
;
87 ::std::vector
< UndoStackMark
> aMarks
;
89 MarkedUndoAction(std::unique_ptr
<SfxUndoAction
> p
) : pAction(std::move(p
)) {}
92 /** do not make use of these implementation details, unless you
93 really really have to! */
94 struct SVL_DLLPUBLIC SfxUndoArray
96 std::vector
<MarkedUndoAction
> maUndoActions
;
97 size_t nMaxUndoActions
;
98 size_t nCurUndoAction
;
99 SfxUndoArray
*pFatherUndoArray
;
101 SfxUndoArray(size_t nMax
=0) :
102 nMaxUndoActions(nMax
), nCurUndoAction(0), pFatherUndoArray(nullptr) {}
103 virtual ~SfxUndoArray();
105 SfxUndoArray
& operator=( SfxUndoArray
const & ) = delete; // MSVC2017 workaround
106 SfxUndoArray( SfxUndoArray
const & ) = delete; // MSVC2017 workaround
108 SfxUndoAction
* GetUndoAction(size_t idx
) { return maUndoActions
[idx
].pAction
.get(); }
109 std::unique_ptr
<SfxUndoAction
> Remove(int idx
);
110 void Remove( size_t i_pos
, size_t i_count
);
111 void Insert( std::unique_ptr
<SfxUndoAction
> i_action
, size_t i_pos
);
115 /** do not make use of these implementation details, unless you
116 really really have to! */
117 class SVL_DLLPUBLIC SfxListUndoAction final
: public SfxUndoAction
, public SfxUndoArray
121 UndoAction to composite multiple Undos in one UndoAction.
122 These actions are used by SfxUndomanager. With < SfxUndoManager::EnterListAction >
123 you can go one composite level down and with < SfxUndoManager::LeaveListAction > up again.
124 Redo and Undo work element wise on SfxListUndoActions.
128 std::unique_ptr
<Impl
> mpImpl
;
133 const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
, ViewShellId nViewShellId
, SfxUndoArray
*pFather
);
134 virtual ~SfxListUndoAction() override
;
136 virtual void Undo() override
;
137 virtual void UndoWithContext( SfxUndoContext
& i_context
) override
;
138 virtual void Redo() override
;
139 virtual void RedoWithContext( SfxUndoContext
& i_context
) override
;
140 virtual void Repeat(SfxRepeatTarget
&) override
;
141 virtual bool CanRepeat(SfxRepeatTarget
&) const override
;
143 virtual bool Merge( SfxUndoAction
*pNextAction
) override
;
145 virtual OUString
GetComment() const override
;
146 /// See SfxUndoAction::GetViewShellId().
147 ViewShellId
GetViewShellId() const override
;
148 virtual OUString
GetRepeatComment(SfxRepeatTarget
&) const override
;
149 sal_uInt16
GetId() const;
151 void SetComment(const OUString
& rComment
);
152 void dumpAsXml(xmlTextWriterPtr pWriter
) const override
;
156 /** is a callback interface for notifications about state changes of an SfxUndoManager
158 class SAL_NO_VTABLE SfxUndoListener
161 virtual void actionUndone( const OUString
& i_actionComment
) = 0;
162 virtual void actionRedone( const OUString
& i_actionComment
) = 0;
163 virtual void undoActionAdded( const OUString
& i_actionComment
) = 0;
164 virtual void cleared() = 0;
165 virtual void clearedRedo() = 0;
166 virtual void resetAll() = 0;
167 virtual void listActionEntered( const OUString
& i_comment
) = 0;
168 virtual void listActionLeft( const OUString
& i_comment
) = 0;
169 virtual void listActionCancelled() = 0;
172 ~SfxUndoListener() {}
176 namespace svl
{ namespace undo
{ namespace impl
178 class UndoManagerGuard
;
182 struct SfxUndoManager_Data
;
183 class SVL_DLLPUBLIC SfxUndoManager
185 std::unique_ptr
< SfxUndoManager_Data
>
188 static bool const CurrentLevel
= true;
189 static bool const TopLevel
= false;
191 SfxUndoManager( size_t nMaxUndoActionCount
= 20 );
192 virtual ~SfxUndoManager();
194 void SetMaxUndoActionCount( size_t nMaxUndoActionCount
);
195 virtual void AddUndoAction( std::unique_ptr
<SfxUndoAction
> pAction
, bool bTryMerg
=false );
196 virtual size_t GetUndoActionCount( bool const i_currentLevel
= CurrentLevel
) const;
197 OUString
GetUndoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const;
198 SfxUndoAction
* GetUndoAction( size_t nNo
=0 ) const;
199 /// Get info about all undo actions (comment, view shell id, etc.)
200 OUString
GetUndoActionsInfo() const;
201 virtual size_t GetRedoActionCount( bool const i_currentLevel
= CurrentLevel
) const;
202 OUString
GetRedoActionComment( size_t nNo
=0, bool const i_currentLevel
= CurrentLevel
) const;
203 SfxUndoAction
* GetRedoAction() const;
204 /// Get info about all redo actions (comment, view shell id, etc.)
205 OUString
GetRedoActionsInfo() const;
208 /** 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();
212 /** Clears the Redo stack.
213 Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
215 virtual void ClearRedo();
216 /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the
219 Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>,
220 followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an
221 atomic operation, also resulting in only one notification.
224 /** determines whether an Undo or Redo is currently running
226 bool IsDoing() const;
227 size_t GetRepeatActionCount() const;
228 OUString
GetRepeatActionComment( SfxRepeatTarget
&rTarget
) const;
229 bool Repeat( SfxRepeatTarget
&rTarget
);
230 bool CanRepeat( SfxRepeatTarget
&rTarget
) const;
231 virtual void EnterListAction(const OUString
&rComment
, const OUString
& rRepeatComment
, sal_uInt16 nId
, ViewShellId nViewShellId
);
232 /** Leaves the list action entered with EnterListAction
233 @return the number of the sub actions in the list which has just been left. Note that in case no such
234 actions exist, the list action does not contribute to the Undo stack, but is silently removed.
236 size_t LeaveListAction();
238 /** Leaves the list action entered with EnterListAction, and forcefully merges the previous
239 action on the stack into the newly created list action.
241 Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to
242 AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo
243 stack will now still contain one undo action: the newly created list action, whose first child is the
244 original A, whose other children are those you added via AddUndoAction, and whose comment is the same as
247 Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are
248 hidden from the user.
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 size_t LeaveAndMergeListAction();
254 /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
255 bool IsInListAction() const;
256 /// Determines how many nested list actions are currently open
257 size_t GetListActionDepth() const;
258 /** Clears the redo stack and removes the top undo action */
259 void RemoveLastUndoAction();
260 /** enables (true) or disables (false) recording of undo actions
262 If undo actions are added while undo is disabled, they are deleted.
263 Disabling undo does not clear the current undo buffer!
265 Multiple calls to <code>EnableUndo</code> are not cumulative. That is, calling <code>EnableUndo( false )</code>
266 twice, and then calling <code>EnableUndo( true )</code> means that Undo is enable afterwards.
268 void EnableUndo( bool bEnable
);
269 /// returns true if undo is currently enabled.
270 /// This returns false if undo was disabled using EnableUndo( false ) and
271 /// also during the runtime of the Undo() and Redo() methods.
272 bool IsUndoEnabled() const;
273 /// Adds a new listener to be notified about changes in the UndoManager's state
274 void AddUndoListener( SfxUndoListener
& i_listener
);
275 void RemoveUndoListener( SfxUndoListener
& i_listener
);
276 bool IsEmptyActions() const;
279 /** marks the current top-level element of the Undo stack, and returns a unique ID for it
281 UndoStackMark
MarkTopUndoAction();
283 /** removes a mark given by its ID.
284 After the call, the mark ID is invalid.
286 void RemoveMark( UndoStackMark
const i_mark
);
288 /** determines whether the top action on the Undo stack has a given mark
290 bool HasTopUndoActionMark( UndoStackMark
const i_mark
);
292 /** removes the oldest Undo actions from the stack
294 void RemoveOldestUndoAction();
296 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
299 bool UndoWithContext( SfxUndoContext
& i_context
);
300 bool RedoWithContext( SfxUndoContext
& i_context
);
302 void ImplClearRedo_NoLock( bool const i_currentLevel
);
304 /** clears all undo actions on the current level, plus all undo actions on superordinate levels,
305 as soon as those levels are reached.
307 If no list action is active currently, i.e. we're on the top level already, this method is equivalent to
310 Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all
311 undo actions on the then-current level are removed, too. This is continued until the top level is reached.
313 void ClearAllLevels();
314 virtual void EmptyActionsChanged();
317 size_t ImplLeaveListAction( const bool i_merge
, ::svl::undo::impl::UndoManagerGuard
& i_guard
);
318 bool ImplAddUndoAction_NoNotify( std::unique_ptr
<SfxUndoAction
> pAction
, bool bTryMerge
, bool bClearRedo
, ::svl::undo::impl::UndoManagerGuard
& i_guard
);
319 void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard
& i_guard
, bool const i_currentLevel
);
320 void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard
& i_guard
);
321 void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard
& i_guard
);
322 size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel
= CurrentLevel
) const;
323 bool ImplIsUndoEnabled_Lock() const;
324 bool ImplIsInListAction_Lock() const;
325 void ImplEnableUndo_Lock( bool const i_enable
);
327 bool ImplUndo( SfxUndoContext
* i_contextOrNull
);
328 bool ImplRedo( SfxUndoContext
* i_contextOrNull
);
329 void ImplCheckEmptyActions();
330 inline bool ImplIsEmptyActions() const;
332 friend class ::svl::undo::impl::LockGuard
;
337 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */