summaryrefslogtreecommitdiffstats
path: root/include/svl/undo.hxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--include/svl/undo.hxx344
1 files changed, 344 insertions, 0 deletions
diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx
new file mode 100644
index 0000000000..a7d1e47537
--- /dev/null
+++ b/include/svl/undo.hxx
@@ -0,0 +1,344 @@
+/* -*- 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 INCLUDED_SVL_UNDO_HXX
+#define INCLUDED_SVL_UNDO_HXX
+
+#include <svl/svldllapi.h>
+#include <rtl/ustring.hxx>
+#include <tools/datetime.hxx>
+#include <o3tl/strong_int.hxx>
+
+#include <memory>
+#include <vector>
+
+typedef o3tl::strong_int<sal_Int32, struct ViewShellIdTag> ViewShellId;
+typedef o3tl::strong_int<int, struct ViewShellDocIdTag> ViewShellDocId;
+
+typedef struct _xmlTextWriter* xmlTextWriterPtr;
+
+class SVL_DLLPUBLIC SAL_LOPLUGIN_ANNOTATE("crosscast") SfxRepeatTarget
+{
+public:
+ virtual ~SfxRepeatTarget() = 0;
+};
+
+
+class SVL_DLLPUBLIC SfxUndoContext
+{
+public:
+ /**
+ * Don't undo the top undo action, but an earlier one. It's the caller's responsibility to
+ * ensure that the earlier undo action is independent from the following ones.
+ */
+ virtual size_t GetUndoOffset() { return 0; }
+
+ virtual ~SfxUndoContext() = 0;
+};
+
+
+class SVL_DLLPUBLIC SfxUndoAction
+{
+public:
+ SfxUndoAction();
+ virtual ~SfxUndoAction() COVERITY_NOEXCEPT_FALSE;
+
+ virtual void Undo();
+ virtual void UndoWithContext( SfxUndoContext& i_context );
+ virtual void Redo();
+ virtual void RedoWithContext( SfxUndoContext& i_context );
+ virtual void Repeat(SfxRepeatTarget&);
+ virtual bool CanRepeat(SfxRepeatTarget&) const;
+
+ virtual bool Merge( SfxUndoAction *pNextAction );
+
+ virtual OUString GetComment() const;
+ virtual OUString GetRepeatComment(SfxRepeatTarget&) const;
+ /// ID of the view shell that created this undo action.
+ virtual ViewShellId GetViewShellId() const;
+ /// Timestamp when this undo item was created.
+ const DateTime& GetDateTime() const;
+ virtual void dumpAsXml(xmlTextWriterPtr pWriter) const;
+
+private:
+ SfxUndoAction( const SfxUndoAction& ) = delete;
+ SfxUndoAction& operator=( const SfxUndoAction& ) = delete;
+
+ DateTime m_aDateTime;
+};
+
+
+/// is a mark on the Undo stack
+typedef sal_Int32 UndoStackMark;
+#define MARK_INVALID ::std::numeric_limits< UndoStackMark >::max()
+
+struct MarkedUndoAction
+{
+ std::unique_ptr<SfxUndoAction> pAction;
+ ::std::vector< UndoStackMark > aMarks;
+
+ MarkedUndoAction(std::unique_ptr<SfxUndoAction> p) : pAction(std::move(p)) {}
+};
+
+/** do not make use of these implementation details, unless you
+ really really have to! */
+struct SVL_DLLPUBLIC SfxUndoArray
+{
+ std::vector<MarkedUndoAction> maUndoActions;
+ size_t nMaxUndoActions;
+ size_t nCurUndoAction;
+ SfxUndoArray *pFatherUndoArray;
+
+ SfxUndoArray(size_t nMax=0) :
+ nMaxUndoActions(nMax), nCurUndoAction(0), pFatherUndoArray(nullptr) {}
+ virtual ~SfxUndoArray();
+
+ SfxUndoArray& operator=( SfxUndoArray const & ) = delete; // MSVC2017 workaround
+ SfxUndoArray( SfxUndoArray const & ) = delete; // MSVC2017 workaround
+
+ SfxUndoAction* GetUndoAction(size_t idx) { return maUndoActions[idx].pAction.get(); }
+ std::unique_ptr<SfxUndoAction> Remove(int idx);
+ void Remove( size_t i_pos, size_t i_count );
+ void Insert( std::unique_ptr<SfxUndoAction> i_action, size_t i_pos );
+};
+
+
+/** do not make use of these implementation details, unless you
+ really really have to! */
+class SVL_DLLPUBLIC SfxListUndoAction final : public SfxUndoAction, public SfxUndoArray
+
+/* [Explanation]
+
+ UndoAction to composite multiple Undos in one UndoAction.
+ These actions are used by SfxUndomanager. With < SfxUndoManager::EnterListAction >
+ you can go one composite level down and with < SfxUndoManager::LeaveListAction > up again.
+ Redo and Undo work element wise on SfxListUndoActions.
+*/
+{
+ struct Impl;
+ std::unique_ptr<Impl> mpImpl;
+
+public:
+
+ SfxListUndoAction(
+ const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId, SfxUndoArray *pFather );
+ virtual ~SfxListUndoAction() override;
+
+ virtual void Undo() override;
+ virtual void UndoWithContext( SfxUndoContext& i_context ) override;
+ virtual void Redo() override;
+ virtual void RedoWithContext( SfxUndoContext& i_context ) override;
+ virtual void Repeat(SfxRepeatTarget&) override;
+ virtual bool CanRepeat(SfxRepeatTarget&) const override;
+
+ virtual bool Merge( SfxUndoAction *pNextAction ) override;
+
+ virtual OUString GetComment() const override;
+ /// See SfxUndoAction::GetViewShellId().
+ ViewShellId GetViewShellId() const override;
+ virtual OUString GetRepeatComment(SfxRepeatTarget&) const override;
+ sal_uInt16 GetId() const;
+
+ void SetComment(const OUString& rComment);
+ void dumpAsXml(xmlTextWriterPtr pWriter) const override;
+};
+
+
+/** is a callback interface for notifications about state changes of an SfxUndoManager
+*/
+class SAL_NO_VTABLE SfxUndoListener
+{
+public:
+ virtual void actionUndone( const OUString& i_actionComment ) = 0;
+ virtual void actionRedone( const OUString& i_actionComment ) = 0;
+ virtual void undoActionAdded( const OUString& i_actionComment ) = 0;
+ virtual void cleared() = 0;
+ virtual void clearedRedo() = 0;
+ virtual void resetAll() = 0;
+ virtual void listActionEntered( const OUString& i_comment ) = 0;
+ virtual void listActionLeft( const OUString& i_comment ) = 0;
+ virtual void listActionCancelled() = 0;
+
+protected:
+ ~SfxUndoListener() {}
+};
+
+
+namespace svl::undo::impl
+{
+ class UndoManagerGuard;
+ class LockGuard;
+}
+
+struct SfxUndoManager_Data;
+class SVL_DLLPUBLIC SfxUndoManager
+{
+ std::unique_ptr< SfxUndoManager_Data >
+ m_xData;
+public:
+ static bool const CurrentLevel = true;
+ static bool const TopLevel = false;
+
+ SfxUndoManager( size_t nMaxUndoActionCount = 20 );
+ virtual ~SfxUndoManager();
+
+ void SetMaxUndoActionCount( size_t nMaxUndoActionCount );
+ size_t GetMaxUndoActionCount() const;
+ virtual void AddUndoAction( std::unique_ptr<SfxUndoAction> pAction, bool bTryMerg=false );
+ virtual size_t GetUndoActionCount( bool const i_currentLevel = CurrentLevel ) const;
+ OUString GetUndoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
+ SfxUndoAction* GetUndoAction( size_t nNo=0 ) const;
+ /// Get info about all undo actions (comment, view shell id, etc.)
+ OUString GetUndoActionsInfo() const;
+ virtual size_t GetRedoActionCount( bool const i_currentLevel = CurrentLevel ) const;
+ OUString GetRedoActionComment( size_t nNo=0, bool const i_currentLevel = CurrentLevel ) const;
+ SfxUndoAction* GetRedoAction(size_t nNo = 0) const;
+ /// Get info about all redo actions (comment, view shell id, etc.)
+ OUString GetRedoActionsInfo() const;
+ virtual bool Undo();
+ virtual bool Redo();
+ /** 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();
+ /** Clears the Redo stack.
+ Will assert and bail out when called while within a list action (<member>IsInListAction</member>).
+ */
+ virtual void ClearRedo();
+ /** 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.
+ */
+ void Reset();
+ /** determines whether an Undo or Redo is currently running
+ */
+ bool IsDoing() const;
+ size_t GetRepeatActionCount() const;
+ OUString GetRepeatActionComment( SfxRepeatTarget &rTarget) const;
+ bool Repeat( SfxRepeatTarget &rTarget );
+ bool CanRepeat( SfxRepeatTarget &rTarget ) const;
+ virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId);
+ /** 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.
+ */
+ size_t LeaveListAction();
+
+ /** 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.
+ */
+ size_t LeaveAndMergeListAction();
+ /// determines whether we're within a ListAction context, i.e. a LeaveListAction/LeaveAndMergeListAction call is pending
+ bool IsInListAction() const;
+ /// Determines how many nested list actions are currently open
+ size_t GetListActionDepth() const;
+ /** Clears the redo stack and removes the top undo action */
+ void RemoveLastUndoAction();
+ /** 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.
+ */
+ void EnableUndo( bool bEnable );
+ /// 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.
+ bool IsUndoEnabled() const;
+ /// Adds a new listener to be notified about changes in the UndoManager's state
+ void AddUndoListener( SfxUndoListener& i_listener );
+ void RemoveUndoListener( SfxUndoListener& i_listener );
+ bool IsEmptyActions() const;
+
+
+ /** 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 RemoveOldestUndoAction();
+
+ void dumpAsXml(xmlTextWriterPtr pWriter) const;
+
+protected:
+ bool UndoWithContext( SfxUndoContext& i_context );
+ 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();
+ virtual void EmptyActionsChanged();
+
+private:
+ size_t ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard );
+ bool ImplAddUndoAction_NoNotify( std::unique_ptr<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 );
+
+ bool ImplUndo( SfxUndoContext* i_contextOrNull );
+ bool ImplRedo( SfxUndoContext* i_contextOrNull );
+ void ImplCheckEmptyActions();
+ inline bool ImplIsEmptyActions() const;
+
+ friend class ::svl::undo::impl::LockGuard;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */