Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 : #ifndef _UNDO_HXX
20 : #define _UNDO_HXX
21 :
22 : #include "svl/svldllapi.h"
23 : #include <tools/rtti.hxx>
24 : #include <tools/string.hxx>
25 :
26 : #include <boost/scoped_ptr.hpp>
27 :
28 : #include <vector>
29 : #include <limits>
30 :
31 : //====================================================================
32 :
33 3152 : class SVL_DLLPUBLIC SfxRepeatTarget
34 : {
35 : public:
36 : TYPEINFO();
37 : virtual ~SfxRepeatTarget() = 0;
38 : };
39 :
40 : //====================================================================
41 :
42 26 : class SVL_DLLPUBLIC SfxUndoContext
43 : {
44 : public:
45 : virtual ~SfxUndoContext() = 0;
46 : };
47 :
48 : //====================================================================
49 : class SfxLinkUndoAction;
50 :
51 : class SVL_DLLPUBLIC SfxUndoAction
52 : {
53 : private:
54 : SfxLinkUndoAction* mpSfxLinkUndoAction;
55 :
56 : public:
57 : TYPEINFO();
58 : SfxUndoAction();
59 : virtual ~SfxUndoAction();
60 :
61 : virtual void SetLinkToSfxLinkUndoAction(SfxLinkUndoAction* pSfxLinkUndoAction);
62 :
63 : virtual void Undo();
64 : virtual void UndoWithContext( SfxUndoContext& i_context );
65 : virtual void Redo();
66 : virtual void RedoWithContext( SfxUndoContext& i_context );
67 : virtual void Repeat(SfxRepeatTarget&);
68 : virtual bool CanRepeat(SfxRepeatTarget&) const;
69 :
70 : virtual bool Merge( SfxUndoAction *pNextAction );
71 :
72 : virtual OUString GetComment() const;
73 : virtual OUString GetRepeatComment(SfxRepeatTarget&) const;
74 : virtual sal_uInt16 GetId() const;
75 :
76 : private:
77 : SfxUndoAction& operator=( const SfxUndoAction& ); // n.i.!!
78 : };
79 :
80 : //========================================================================
81 :
82 : /// is a mark on the Undo stack
83 : typedef sal_Int32 UndoStackMark;
84 : #define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
85 :
86 : //========================================================================
87 :
88 1467689 : struct MarkedUndoAction
89 : {
90 : SfxUndoAction* pAction;
91 : ::std::vector< UndoStackMark > aMarks;
92 :
93 139537 : MarkedUndoAction( SfxUndoAction* i_action )
94 : :pAction( i_action )
95 139537 : ,aMarks()
96 : {
97 139537 : }
98 : };
99 :
100 92410 : class SfxUndoActions
101 : {
102 : private:
103 : ::std::vector< MarkedUndoAction > m_aActions;
104 :
105 : public:
106 92530 : SfxUndoActions()
107 92530 : {
108 92530 : }
109 :
110 2443123 : bool empty() const { return m_aActions.empty(); }
111 345325 : size_t size() const { return m_aActions.size(); }
112 :
113 418 : const MarkedUndoAction& operator[]( size_t i ) const { return m_aActions[i]; }
114 218232 : MarkedUndoAction& operator[]( size_t i ) { return m_aActions[i]; }
115 :
116 139441 : void Remove( size_t i_pos )
117 : {
118 139441 : m_aActions.erase( m_aActions.begin() + i_pos );
119 139441 : }
120 :
121 0 : void Remove( size_t i_pos, size_t i_count )
122 : {
123 0 : m_aActions.erase( m_aActions.begin() + i_pos, m_aActions.begin() + i_pos + i_count );
124 0 : }
125 :
126 139537 : void Insert( SfxUndoAction* i_action, size_t i_pos )
127 : {
128 139537 : m_aActions.insert( m_aActions.begin() + i_pos, MarkedUndoAction( i_action ) );
129 139537 : }
130 : };
131 :
132 : //====================================================================
133 :
134 : /** do not make use of these implementation details, unless you
135 : really really have to! */
136 : struct SVL_DLLPUBLIC SfxUndoArray
137 : {
138 : SfxUndoActions aUndoActions;
139 : size_t nMaxUndoActions;
140 : size_t nCurUndoAction;
141 : SfxUndoArray *pFatherUndoArray;
142 92530 : SfxUndoArray(size_t nMax=0):
143 : nMaxUndoActions(nMax), nCurUndoAction(0),
144 92530 : pFatherUndoArray(0) {}
145 : ~SfxUndoArray();
146 : };
147 :
148 : //=========================================================================
149 :
150 : /** do not make use of these implementation details, unless you
151 : really really have to! */
152 154938 : class SVL_DLLPUBLIC SfxListUndoAction : public SfxUndoAction, public SfxUndoArray
153 :
154 : /* [Beschreibung]
155 :
156 : UndoAction zur Klammerung mehrerer Undos in einer UndoAction.
157 : Diese Actions werden vom SfxUndoManager verwendet. Dort
158 : wird mit < SfxUndoManager::EnterListAction > eine Klammerebene
159 : geoeffnet und mit <SfxUndoManager::LeaveListAction > wieder
160 : geschlossen. Redo und Undo auf SfxListUndoActions wirken
161 : Elementweise.
162 :
163 : */
164 : {
165 : public:
166 : TYPEINFO();
167 :
168 : SfxListUndoAction( const OUString &rComment,
169 : const OUString rRepeatComment, sal_uInt16 Id, SfxUndoArray *pFather);
170 : virtual void Undo();
171 : virtual void UndoWithContext( SfxUndoContext& i_context );
172 : virtual void Redo();
173 : virtual void RedoWithContext( SfxUndoContext& i_context );
174 : virtual void Repeat(SfxRepeatTarget&);
175 : virtual bool CanRepeat(SfxRepeatTarget&) const;
176 :
177 : virtual bool Merge( SfxUndoAction *pNextAction );
178 :
179 : virtual OUString GetComment() const;
180 : virtual OUString GetRepeatComment(SfxRepeatTarget&) const;
181 : virtual sal_uInt16 GetId() const;
182 :
183 : void SetComment(const OUString& rComment);
184 :
185 : private:
186 :
187 : sal_uInt16 nId;
188 : OUString aComment;
189 : OUString aRepeatComment;
190 :
191 : };
192 :
193 : //=========================================================================
194 :
195 : /** is a callback interface for notifications about state changes of an SfxUndoManager
196 : */
197 49 : class SAL_NO_VTABLE SfxUndoListener
198 : {
199 : public:
200 : virtual void actionUndone( const OUString& i_actionComment ) = 0;
201 : virtual void actionRedone( const OUString& i_actionComment ) = 0;
202 : virtual void undoActionAdded( const OUString& i_actionComment ) = 0;
203 : virtual void cleared() = 0;
204 : virtual void clearedRedo() = 0;
205 : virtual void resetAll() = 0;
206 : virtual void listActionEntered( const OUString& i_comment ) = 0;
207 : virtual void listActionLeft( const OUString& i_comment ) = 0;
208 : virtual void listActionLeftAndMerged() = 0;
209 : virtual void listActionCancelled() = 0;
210 : virtual void undoManagerDying() = 0;
211 :
212 : protected:
213 0 : ~SfxUndoListener() {}
214 : };
215 :
216 : //=========================================================================
217 :
218 : namespace svl
219 : {
220 15023 : class SAL_NO_VTABLE IUndoManager
221 : {
222 : public:
223 : enum
224 : {
225 : CurrentLevel = true,
226 : TopLevel = false
227 : };
228 :
229 14941 : virtual ~IUndoManager() { };
230 :
231 : virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount ) = 0;
232 : virtual size_t GetMaxUndoActionCount() const = 0;
233 :
234 : virtual void AddUndoAction( SfxUndoAction *pAction, bool bTryMerg=false ) = 0;
235 :
236 : virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0;
237 : virtual sal_uInt16 GetUndoActionId() const = 0;
238 : virtual OUString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0;
239 : virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const = 0;
240 :
241 : virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0;
242 : virtual OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0;
243 : virtual SfxUndoAction* GetRedoAction( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0;
244 :
245 : virtual bool Undo() = 0;
246 : virtual bool Redo() = 0;
247 :
248 : /** clears both the Redo and the Undo stack.
249 :
250 : Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
251 : */
252 : virtual void Clear() = 0;
253 :
254 : /** clears the Redo stack.
255 :
256 : Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
257 : */
258 : virtual void ClearRedo() = 0;
259 :
260 : /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the
261 : Redo stack.
262 :
263 : Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>,
264 : followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an
265 : atomic operation, also resulting in only one notification.
266 : */
267 : virtual void Reset() = 0;
268 :
269 : /** determines whether an Undo or Redo is currently running
270 : */
271 : virtual bool IsDoing() const = 0;
272 :
273 : virtual size_t GetRepeatActionCount() const = 0;
274 : virtual OUString GetRepeatActionComment( SfxRepeatTarget &rTarget) const = 0;
275 : virtual bool Repeat( SfxRepeatTarget &rTarget ) = 0;
276 : virtual bool CanRepeat( SfxRepeatTarget &rTarget ) const = 0;
277 :
278 : virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId=0) = 0;
279 :
280 : /** leaves the list action entered with EnterListAction
281 : @return the number of the sub actions in the list which has just been left. Note that in case no such
282 : actions exist, the list action does not contribute to the Undo stack, but is silently removed.
283 : */
284 : virtual size_t LeaveListAction() = 0;
285 :
286 : /** leaves the list action entered with EnterListAction, and forcefully merges the previous
287 : action on the stack into the newly created list action.
288 :
289 : Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to
290 : AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo
291 : stack will now still contain one undo action: the newly created list action, whose first child is the
292 : original A, whose other children are those you added via AddUndoAction, and whose comment is the same as
293 : the comment of A.
294 :
295 : Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are
296 : hidden from the user.
297 :
298 : @return the number of the sub actions in the list which has just been left. Note that in case no such
299 : actions exist, the list action does not contribute to the Undo stack, but is silently removed.
300 : */
301 : virtual size_t LeaveAndMergeListAction() = 0;
302 :
303 : /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
304 : virtual bool IsInListAction() const = 0;
305 :
306 : /// determines how many nested list actions are currently open
307 : virtual size_t GetListActionDepth() const = 0;
308 :
309 : /** clears the redo stack and removes the top undo action */
310 : virtual void RemoveLastUndoAction() = 0;
311 :
312 : /** enables (true) or disables (false) recording of undo actions
313 :
314 : If undo actions are added while undo is disabled, they are deleted.
315 : Disabling undo does not clear the current undo buffer!
316 :
317 : Multiple calls to <code>EnableUndo</code> are not cumulative. That is, calling <code>EnableUndo( false )</code>
318 : twice, and then calling <code>EnableUndo( true )</code> means that Undo is enable afterwards.
319 : */
320 : virtual void EnableUndo( bool bEnable ) = 0;
321 :
322 : // returns true if undo is currently enabled
323 : // This returns false if undo was disabled using EnableUndo( false ) and
324 : // also during the runtime of the Undo() and Redo() methods.
325 : virtual bool IsUndoEnabled() const = 0;
326 :
327 : /// adds a new listener to be notified about changes in the UndoManager's state
328 : virtual void AddUndoListener( SfxUndoListener& i_listener ) = 0;
329 : virtual void RemoveUndoListener( SfxUndoListener& i_listener ) = 0;
330 : };
331 : }
332 :
333 : //=========================================================================
334 :
335 : namespace svl { namespace undo { namespace impl
336 : {
337 : class UndoManagerGuard;
338 : class LockGuard;
339 : } } }
340 :
341 : struct SfxUndoManager_Data;
342 : class SVL_DLLPUBLIC SfxUndoManager : public ::svl::IUndoManager
343 : {
344 : friend class SfxLinkUndoAction;
345 :
346 : ::boost::scoped_ptr< SfxUndoManager_Data >
347 : m_pData;
348 : public:
349 : SfxUndoManager( size_t nMaxUndoActionCount = 20 );
350 : virtual ~SfxUndoManager();
351 :
352 : // IUndoManager overridables
353 : virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount );
354 : virtual size_t GetMaxUndoActionCount() const;
355 : virtual void AddUndoAction( SfxUndoAction *pAction, bool bTryMerg=false );
356 : virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const;
357 : virtual sal_uInt16 GetUndoActionId() const;
358 : virtual OUString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
359 : virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const;
360 : virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const;
361 : virtual OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
362 : virtual SfxUndoAction* GetRedoAction( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
363 : virtual bool Undo();
364 : virtual bool Redo();
365 : virtual void Clear();
366 : virtual void ClearRedo();
367 : virtual void Reset();
368 : virtual bool IsDoing() const;
369 : virtual size_t GetRepeatActionCount() const;
370 : virtual OUString GetRepeatActionComment( SfxRepeatTarget &rTarget) const;
371 : virtual bool Repeat( SfxRepeatTarget &rTarget );
372 : virtual bool CanRepeat( SfxRepeatTarget &rTarget ) const;
373 : virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId=0);
374 : virtual size_t LeaveListAction();
375 : virtual size_t LeaveAndMergeListAction();
376 : virtual bool IsInListAction() const;
377 : virtual size_t GetListActionDepth() const;
378 : virtual void RemoveLastUndoAction();
379 : virtual void EnableUndo( bool bEnable );
380 : virtual bool IsUndoEnabled() const;
381 : virtual void AddUndoListener( SfxUndoListener& i_listener );
382 : virtual void RemoveUndoListener( SfxUndoListener& i_listener );
383 :
384 : /** marks the current top-level element of the Undo stack, and returns a unique ID for it
385 : */
386 : UndoStackMark MarkTopUndoAction();
387 :
388 : /** removes a mark given by its ID.
389 : After the call, the mark ID is invalid.
390 : */
391 : void RemoveMark( UndoStackMark const i_mark );
392 :
393 : /** determines whether the top action on the Undo stack has a given mark
394 : */
395 : bool HasTopUndoActionMark( UndoStackMark const i_mark );
396 :
397 : /** removes the oldest Undo actions from the stack
398 : */
399 : void RemoveOldestUndoActions( size_t const i_count );
400 :
401 : protected:
402 : bool UndoWithContext( SfxUndoContext& i_context );
403 : bool RedoWithContext( SfxUndoContext& i_context );
404 :
405 : void ImplClearRedo_NoLock( bool const i_currentLevel );
406 :
407 : /** clears all undo actions on the current level, plus all undo actions on superordinate levels,
408 : as soon as those levels are reached.
409 :
410 : If no list action is active currently, i.e. we're on the top level already, this method is equivalent to
411 : ->Clear.
412 :
413 : Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all
414 : undo actions on the then-current level are removed, too. This is continued until the top level is reached.
415 : */
416 : void ClearAllLevels();
417 :
418 : private:
419 : size_t ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard );
420 : bool ImplAddUndoAction_NoNotify( SfxUndoAction* pAction, bool bTryMerge, bool bClearRedo, ::svl::undo::impl::UndoManagerGuard& i_guard );
421 : void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard& i_guard, bool const i_currentLevel );
422 : void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard& i_guard );
423 : void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard& i_guard );
424 : size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel = CurrentLevel ) const;
425 : bool ImplIsUndoEnabled_Lock() const;
426 : bool ImplIsInListAction_Lock() const;
427 : void ImplEnableUndo_Lock( bool const i_enable );
428 :
429 : bool ImplUndo( SfxUndoContext* i_contextOrNull );
430 : bool ImplRedo( SfxUndoContext* i_contextOrNull );
431 :
432 : friend class ::svl::undo::impl::LockGuard;
433 : };
434 :
435 : //=========================================================================
436 :
437 : class SVL_DLLPUBLIC SfxLinkUndoAction : public SfxUndoAction
438 :
439 : /* [Beschreibung]
440 :
441 : Die SfxLinkUndoAction dient zur Verbindung zweier SfxUndoManager. Die
442 : im ersten SfxUndoManager eingefuegten SfxUndoAction leiten ihr Undo und Redo
443 : an den zweiten weiter, so dass ein Undo und Redo am ersten
444 : SfxUndoManager wie eine am zweiten wirkt.
445 :
446 : Die SfxLinkUndoAction ist nach dem Einfuegen der SfxUndoAction am
447 : zweiten SfxUndoManager einzufuegen. Waehrend der zweite SfxUndoManager
448 : vom ersten ferngesteuert wird, duerfen an ihm weder Actions eingefuegt werden,
449 : noch darf Undo/Redo aufgerufen werden.
450 :
451 : */
452 :
453 : {
454 : private:
455 : friend class SfxUndoAction;
456 : void LinkedSfxUndoActionDestructed(const SfxUndoAction& rCandidate);
457 :
458 : public:
459 : TYPEINFO();
460 : SfxLinkUndoAction(::svl::IUndoManager *pManager);
461 : ~SfxLinkUndoAction();
462 :
463 : virtual void Undo();
464 : virtual void Redo();
465 : virtual bool CanRepeat(SfxRepeatTarget& r) const;
466 :
467 : virtual void Repeat(SfxRepeatTarget&r);
468 :
469 : virtual OUString GetComment() const;
470 : virtual OUString GetRepeatComment(SfxRepeatTarget&r) const;
471 : virtual sal_uInt16 GetId() const;
472 :
473 0 : SfxUndoAction* GetAction() const { return pAction; }
474 :
475 : protected:
476 : ::svl::IUndoManager* pUndoManager;
477 : SfxUndoAction* pAction;
478 :
479 : };
480 :
481 : #endif
482 :
483 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|