/* -*- 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 <optional>
#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 .
@ return the index at which the mark was removed , or std : : numeric_limits < size_t > : : max ( )
if failed
*/
size_t 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
* @ returns false if it could not do anything ( can happen when the action is very large )
*/
[[nodiscard]]
bool RemoveOldestUndoAction();
void dumpAsXml(xmlTextWriterPtr pWriter) const ;
protected :
bool UndoWithContext( SfxUndoContext& i_context );
bool RedoWithContext( SfxUndoContext& i_context );
// Undoes a specific mark on the undo stack, and removes it from the undo/redo stack,
// but only in case when the redo stack is empty. This is a dangerous operation, because
// it undoes out of order.
void UndoMark(UndoStackMark i_mark);
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 :
SAL_DLLPRIVATE size_t ImplLeaveListAction( const bool i_merge, ::svl::undo::impl::UndoManagerGuard& i_guard );
SAL_DLLPRIVATE bool ImplAddUndoAction_NoNotify( std::unique_ptr<SfxUndoAction> pAction, bool bTryMerge, bool bClearRedo, ::svl::undo::impl::UndoManagerGuard& i_guard );
SAL_DLLPRIVATE void ImplClearRedo( ::svl::undo::impl::UndoManagerGuard& i_guard, bool const i_currentLevel );
SAL_DLLPRIVATE void ImplClearUndo( ::svl::undo::impl::UndoManagerGuard& i_guard );
SAL_DLLPRIVATE void ImplClearCurrentLevel_NoNotify( ::svl::undo::impl::UndoManagerGuard& i_guard );
SAL_DLLPRIVATE size_t ImplGetRedoActionCount_Lock( bool const i_currentLevel = CurrentLevel ) const ;
SAL_DLLPRIVATE bool ImplIsUndoEnabled_Lock() const ;
SAL_DLLPRIVATE bool ImplIsInListAction_Lock() const ;
SAL_DLLPRIVATE void ImplEnableUndo_Lock( bool const i_enable );
SAL_DLLPRIVATE bool ImplUndo( SfxUndoContext* i_contextOrNull );
SAL_DLLPRIVATE bool ImplRedo( SfxUndoContext* i_contextOrNull );
SAL_DLLPRIVATE void ImplCheckEmptyActions();
inline bool ImplIsEmptyActions() const ;
friend class ::svl::undo::impl::LockGuard;
};
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=90 H=100 G=95
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland