diff options
Diffstat (limited to 'include/svl/undo.hxx')
-rw-r--r-- | include/svl/undo.hxx | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx new file mode 100644 index 000000000000..f36cd816b607 --- /dev/null +++ b/include/svl/undo.hxx @@ -0,0 +1,474 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef _UNDO_HXX +#define _UNDO_HXX + +#include "svl/svldllapi.h" +#include <tools/rtti.hxx> +#include <tools/string.hxx> + +#include <boost/scoped_ptr.hpp> + +#include <vector> +#include <limits> + +//==================================================================== + +class SVL_DLLPUBLIC SfxRepeatTarget +{ +public: + TYPEINFO(); + virtual ~SfxRepeatTarget() = 0; +}; + +//==================================================================== + +class SVL_DLLPUBLIC SfxUndoContext +{ +public: + virtual ~SfxUndoContext() = 0; +}; + +//==================================================================== + +class SVL_DLLPUBLIC SfxUndoAction +{ + sal_Bool bLinked; +public: + TYPEINFO(); + SfxUndoAction(); + virtual ~SfxUndoAction(); + + virtual sal_Bool IsLinked(); + virtual void SetLinked( sal_Bool bIsLinked = sal_True ); + virtual void Undo(); + virtual void UndoWithContext( SfxUndoContext& i_context ); + virtual void Redo(); + virtual void RedoWithContext( SfxUndoContext& i_context ); + virtual void Repeat(SfxRepeatTarget&); + virtual sal_Bool CanRepeat(SfxRepeatTarget&) const; + + virtual sal_Bool Merge( SfxUndoAction *pNextAction ); + + virtual OUString GetComment() const; + virtual OUString GetRepeatComment(SfxRepeatTarget&) const; + virtual sal_uInt16 GetId() const; + +private: + SfxUndoAction& operator=( const SfxUndoAction& ); // n.i.!! +}; + +//======================================================================== + +/// is a mark on the Undo stack +typedef sal_Int32 UndoStackMark; +#define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max() + +//======================================================================== + +struct MarkedUndoAction +{ + SfxUndoAction* pAction; + ::std::vector< UndoStackMark > aMarks; + + MarkedUndoAction( SfxUndoAction* i_action ) + :pAction( i_action ) + ,aMarks() + { + } +}; + +class SfxUndoActions +{ +private: + ::std::vector< MarkedUndoAction > m_aActions; + +public: + SfxUndoActions() + { + } + + bool empty() const { return m_aActions.empty(); } + size_t size() const { return m_aActions.size(); } + + const MarkedUndoAction& operator[]( size_t i ) const { return m_aActions[i]; } + MarkedUndoAction& operator[]( size_t i ) { return m_aActions[i]; } + + void Remove( size_t i_pos ) + { + m_aActions.erase( m_aActions.begin() + i_pos ); + } + + void Remove( size_t i_pos, size_t i_count ) + { + m_aActions.erase( m_aActions.begin() + i_pos, m_aActions.begin() + i_pos + i_count ); + } + + void Insert( SfxUndoAction* i_action, size_t i_pos ) + { + m_aActions.insert( m_aActions.begin() + i_pos, MarkedUndoAction( i_action ) ); + } +}; + +//==================================================================== + +/** do not make use of these implementation details, unless you + really really have to! */ +struct SVL_DLLPUBLIC SfxUndoArray +{ + SfxUndoActions aUndoActions; + size_t nMaxUndoActions; + size_t nCurUndoAction; + SfxUndoArray *pFatherUndoArray; + SfxUndoArray(size_t nMax=0): + nMaxUndoActions(nMax), nCurUndoAction(0), + pFatherUndoArray(0) {} + ~SfxUndoArray(); +}; + +//========================================================================= + +/** do not make use of these implementation details, unless you + really really have to! */ +class SVL_DLLPUBLIC SfxListUndoAction : public SfxUndoAction, public SfxUndoArray + +/* [Beschreibung] + + UndoAction zur Klammerung mehrerer Undos in einer UndoAction. + Diese Actions werden vom SfxUndoManager verwendet. Dort + wird mit < SfxUndoManager::EnterListAction > eine Klammerebene + geoeffnet und mit <SfxUndoManager::LeaveListAction > wieder + geschlossen. Redo und Undo auf SfxListUndoActions wirken + Elementweise. + +*/ +{ + public: + TYPEINFO(); + + SfxListUndoAction( const OUString &rComment, + const OUString rRepeatComment, sal_uInt16 Id, SfxUndoArray *pFather); + virtual void Undo(); + virtual void UndoWithContext( SfxUndoContext& i_context ); + virtual void Redo(); + virtual void RedoWithContext( SfxUndoContext& i_context ); + virtual void Repeat(SfxRepeatTarget&); + virtual sal_Bool CanRepeat(SfxRepeatTarget&) const; + + virtual sal_Bool Merge( SfxUndoAction *pNextAction ); + + virtual OUString GetComment() const; + virtual OUString GetRepeatComment(SfxRepeatTarget&) const; + virtual sal_uInt16 GetId() const; + + void SetComment(const OUString& rComment); + + private: + + sal_uInt16 nId; + OUString aComment; + OUString aRepeatComment; + +}; + +//========================================================================= + +/** is a callback interface for notifications about state changes of an SfxUndoManager +*/ +class SAL_NO_VTABLE SfxUndoListener +{ +public: + virtual void actionUndone( const String& i_actionComment ) = 0; + virtual void actionRedone( const String& i_actionComment ) = 0; + virtual void undoActionAdded( const String& i_actionComment ) = 0; + virtual void cleared() = 0; + virtual void clearedRedo() = 0; + virtual void resetAll() = 0; + virtual void listActionEntered( const String& i_comment ) = 0; + virtual void listActionLeft( const String& i_comment ) = 0; + virtual void listActionLeftAndMerged() = 0; + virtual void listActionCancelled() = 0; + virtual void undoManagerDying() = 0; + +protected: + ~SfxUndoListener() {} +}; + +//========================================================================= + +namespace svl +{ + class SAL_NO_VTABLE IUndoManager + { + public: + enum + { + CurrentLevel = true, + TopLevel = false + }; + + virtual ~IUndoManager() { }; + + virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount ) = 0; + virtual size_t GetMaxUndoActionCount() const = 0; + + virtual void AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerg=sal_False ) = 0; + + virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0; + virtual sal_uInt16 GetUndoActionId() const = 0; + virtual OUString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0; + virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const = 0; + + virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const = 0; + virtual OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const = 0; + + virtual sal_Bool Undo() = 0; + virtual sal_Bool Redo() = 0; + + /** clears both the Redo and the Undo stack. + + Will assert and bail out when called while within a list action (<member>IsInListAction</member>). + */ + virtual void Clear() = 0; + + /** clears the Redo stack. + + Will assert and bail out when called while within a list action (<member>IsInListAction</member>). + */ + virtual void ClearRedo() = 0; + + /** leaves any possible open list action (<member>IsInListAction</member>), and clears both the Undo and the + Redo stack. + + Effectively, calling this method is equivalent to <code>while ( IsInListAction() ) LeaveListAction();</code>, + followed by <code>Clear()</code>. The only difference to this calling sequence is that Reset is an + atomic operation, also resulting in only one notification. + */ + virtual void Reset() = 0; + + /** determines whether an Undo or Redo is currently running + */ + virtual bool IsDoing() const = 0; + + virtual size_t GetRepeatActionCount() const = 0; + virtual OUString GetRepeatActionComment( SfxRepeatTarget &rTarget) const = 0; + virtual sal_Bool Repeat( SfxRepeatTarget &rTarget ) = 0; + virtual sal_Bool CanRepeat( SfxRepeatTarget &rTarget ) const = 0; + + virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId=0) = 0; + + /** leaves the list action entered with EnterListAction + @return the number of the sub actions in the list which has just been left. Note that in case no such + actions exist, the list action does not contribute to the Undo stack, but is silently removed. + */ + virtual size_t LeaveListAction() = 0; + + /** leaves the list action entered with EnterListAction, and forcefully merges the previous + action on the stack into the newly created list action. + + Say you have an Undo action A on the stack, then call EnterListAction, followed by one or more calls to + AddUndoAction, followed by a call to LeaveAndMergeListAction. In opposite to LeaveListAction, your Undo + stack will now still contain one undo action: the newly created list action, whose first child is the + original A, whose other children are those you added via AddUndoAction, and whose comment is the same as + the comment of A. + + Effectively, this means that all actions added between EnterListAction and LeaveAndMergeListAction are + hidden from the user. + + @return the number of the sub actions in the list which has just been left. Note that in case no such + actions exist, the list action does not contribute to the Undo stack, but is silently removed. + */ + virtual size_t LeaveAndMergeListAction() = 0; + + /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending + virtual bool IsInListAction() const = 0; + + /// determines how many nested list actions are currently open + virtual size_t GetListActionDepth() const = 0; + + /** clears the redo stack and removes the top undo action */ + virtual void RemoveLastUndoAction() = 0; + + /** enables (true) or disables (false) recording of undo actions + + If undo actions are added while undo is disabled, they are deleted. + Disabling undo does not clear the current undo buffer! + + Multiple calls to <code>EnableUndo</code> are not cumulative. That is, calling <code>EnableUndo( false )</code> + twice, and then calling <code>EnableUndo( true )</code> means that Undo is enable afterwards. + */ + virtual void EnableUndo( bool bEnable ) = 0; + + // returns true if undo is currently enabled + // This returns false if undo was disabled using EnableUndo( false ) and + // also during the runtime of the Undo() and Redo() methods. + virtual bool IsUndoEnabled() const = 0; + + /// adds a new listener to be notified about changes in the UndoManager's state + virtual void AddUndoListener( SfxUndoListener& i_listener ) = 0; + virtual void RemoveUndoListener( SfxUndoListener& i_listener ) = 0; + }; +} + +//========================================================================= + +namespace svl { namespace undo { namespace impl +{ + class UndoManagerGuard; + class LockGuard; +} } } + +struct SfxUndoManager_Data; +class SVL_DLLPUBLIC SfxUndoManager : public ::svl::IUndoManager +{ + friend class SfxLinkUndoAction; + + ::boost::scoped_ptr< SfxUndoManager_Data > + m_pData; +public: + SfxUndoManager( size_t nMaxUndoActionCount = 20 ); + virtual ~SfxUndoManager(); + + // IUndoManager overridables + virtual void SetMaxUndoActionCount( size_t nMaxUndoActionCount ); + virtual size_t GetMaxUndoActionCount() const; + virtual void AddUndoAction( SfxUndoAction *pAction, sal_Bool bTryMerg=sal_False ); + virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const; + virtual sal_uInt16 GetUndoActionId() const; + virtual OUString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const; + virtual SfxUndoAction* GetUndoAction( size_t nNo=0 ) const; + virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const; + virtual OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const; + virtual sal_Bool Undo(); + virtual sal_Bool Redo(); + virtual void Clear(); + virtual void ClearRedo(); + virtual void Reset(); + virtual bool IsDoing() const; + virtual size_t GetRepeatActionCount() const; + virtual OUString GetRepeatActionComment( SfxRepeatTarget &rTarget) const; + virtual sal_Bool Repeat( SfxRepeatTarget &rTarget ); + virtual sal_Bool CanRepeat( SfxRepeatTarget &rTarget ) const; + virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId=0); + virtual size_t LeaveListAction(); + virtual size_t LeaveAndMergeListAction(); + virtual bool IsInListAction() const; + virtual size_t GetListActionDepth() const; + virtual void RemoveLastUndoAction(); + virtual void EnableUndo( bool bEnable ); + virtual bool IsUndoEnabled() const; + virtual void AddUndoListener( SfxUndoListener& i_listener ); + virtual void RemoveUndoListener( SfxUndoListener& i_listener ); + + /** marks the current top-level element of the Undo stack, and returns a unique ID for it + */ + UndoStackMark MarkTopUndoAction(); + + /** removes a mark given by its ID. + After the call, the mark ID is invalid. + */ + void RemoveMark( UndoStackMark const i_mark ); + + /** determines whether the top action on the Undo stack has a given mark + */ + bool HasTopUndoActionMark( UndoStackMark const i_mark ); + + /** removes the oldest Undo actions from the stack + */ + void RemoveOldestUndoActions( size_t const i_count ); + +protected: + sal_Bool UndoWithContext( SfxUndoContext& i_context ); + sal_Bool RedoWithContext( SfxUndoContext& i_context ); + + void ImplClearRedo_NoLock( bool const i_currentLevel ); + + /** clears all undo actions on the current level, plus all undo actions on superordinate levels, + as soon as those levels are reached. + + If no list action is active currently, i.e. we're on the top level already, this method is equivalent to + ->Clear. + + Otherwise, the Undo actions on the current level are removed. Upon leaving the current list action, all + undo actions on the then-current level are removed, too. This is continued until the top level is reached. + */ + void ClearAllLevels(); + +private: + size_t ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard ); + bool ImplAddUndoAction_NoNotify( SfxUndoAction* pAction, bool bTryMerge, bool bClearRedo, ::svl::undo::impl::UndoManagerGuard& i_guard ); + void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard& i_guard, bool const i_currentLevel ); + void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard& i_guard ); + void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard& i_guard ); + size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel = CurrentLevel ) const; + bool ImplIsUndoEnabled_Lock() const; + bool ImplIsInListAction_Lock() const; + void ImplEnableUndo_Lock( bool const i_enable ); + + sal_Bool ImplUndo( SfxUndoContext* i_contextOrNull ); + sal_Bool ImplRedo( SfxUndoContext* i_contextOrNull ); + + friend class ::svl::undo::impl::LockGuard; +}; + +//========================================================================= + +class SVL_DLLPUBLIC SfxLinkUndoAction : public SfxUndoAction + +/* [Beschreibung] + + Die SfxLinkUndoAction dient zur Verbindung zweier SfxUndoManager. Die + im ersten SfxUndoManager eingefuegten SfxUndoAction leiten ihr Undo und Redo + an den zweiten weiter, so dass ein Undo und Redo am ersten + SfxUndoManager wie eine am zweiten wirkt. + + Die SfxLinkUndoAction ist nach dem Einfuegen der SfxUndoAction am + zweiten SfxUndoManager einzufuegen. Waehrend der zweite SfxUndoManager + vom ersten ferngesteuert wird, duerfen an ihm weder Actions eingefuegt werden, + noch darf Undo/Redo aufgerufen werden. + +*/ + +{ +public: + TYPEINFO(); + SfxLinkUndoAction(::svl::IUndoManager *pManager); + ~SfxLinkUndoAction(); + + virtual void Undo(); + virtual void Redo(); + virtual sal_Bool CanRepeat(SfxRepeatTarget& r) const; + + virtual void Repeat(SfxRepeatTarget&r); + + virtual OUString GetComment() const; + virtual OUString GetRepeatComment(SfxRepeatTarget&r) const; + virtual sal_uInt16 GetId() const; + + SfxUndoAction* GetAction() const { return pAction; } + +protected: + ::svl::IUndoManager *pUndoManager; + SfxUndoAction *pAction; + +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |