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