summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--svl/inc/svl/undo.hxx26
-rw-r--r--svl/source/undo/undo.cxx78
2 files changed, 80 insertions, 24 deletions
diff --git a/svl/inc/svl/undo.hxx b/svl/inc/svl/undo.hxx
index f25b9654371a..fcec1501ec7f 100644
--- a/svl/inc/svl/undo.hxx
+++ b/svl/inc/svl/undo.hxx
@@ -146,6 +146,7 @@ public:
virtual void clearedRedo() = 0;
virtual void listActionEntered( const String& i_comment ) = 0;
virtual void listActionLeft() = 0;
+ virtual void listActionLeftAndMerged() = 0;
virtual void listActionCancelled() = 0;
virtual void undoManagerDying() = 0;
};
@@ -188,15 +189,34 @@ namespace svl
virtual BOOL CanRepeat( SfxRepeatTarget &rTarget ) const = 0;
virtual void EnterListAction(const UniString &rComment, const UniString& rRepeatComment, USHORT 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 USHORT LeaveListAction() = 0;
- /// determines whether we're within a ListAction context, i.e. a LeaveListAction call is pending
+ /** 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 USHORT 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 USHORT GetListActionDepth() const = 0;
/** clears the redo stack and removes the top undo action */
@@ -252,6 +272,7 @@ public:
virtual BOOL CanRepeat( SfxRepeatTarget &rTarget ) const;
virtual void EnterListAction(const UniString &rComment, const UniString& rRepeatComment, USHORT nId=0);
virtual USHORT LeaveListAction();
+ virtual USHORT LeaveAndMergeListAction();
virtual bool IsInListAction() const;
virtual USHORT GetListActionDepth() const;
virtual void RemoveLastUndoAction();
@@ -259,6 +280,9 @@ public:
virtual bool IsUndoEnabled() const;
virtual void AddUndoListener( SfxUndoListener& i_listener );
virtual void RemoveUndoListener( SfxUndoListener& i_listener );
+
+private:
+ USHORT ImplLeaveListAction( const bool i_merge );
};
//=========================================================================
diff --git a/svl/source/undo/undo.cxx b/svl/source/undo/undo.cxx
index 461ea54fcc73..b61d3c6be25b 100644
--- a/svl/source/undo/undo.cxx
+++ b/svl/source/undo/undo.cxx
@@ -685,11 +685,20 @@ USHORT SfxUndoManager::GetListActionDepth() const
//------------------------------------------------------------------------
USHORT SfxUndoManager::LeaveListAction()
+{
+ return ImplLeaveListAction( false );
+}
-/* [Beschreibung]
+//------------------------------------------------------------------------
- Verlaesst die aktuelle ListAction und geht eine Ebene nach oben.
-*/
+USHORT SfxUndoManager::LeaveAndMergeListAction()
+{
+ return ImplLeaveListAction( true );
+}
+
+//------------------------------------------------------------------------
+
+USHORT SfxUndoManager::ImplLeaveListAction( const bool i_merge )
{
if ( !IsUndoEnabled() )
return 0;
@@ -699,45 +708,68 @@ USHORT SfxUndoManager::LeaveListAction()
if( !IsInListAction() )
{
- DBG_ERROR( "svl::SfxUndoManager::LeaveListAction(), called without calling EnterListAction()!" );
+ DBG_ERROR( "svl::SfxUndoManager::ImplLeaveListAction, called without calling EnterListAction()!" );
return 0;
}
- DBG_ASSERT(m_pData->pActUndoArray->pFatherUndoArray,"svl::SfxUndoManager::LeaveListAction(), no father undo array!?");
+ DBG_ASSERT(m_pData->pActUndoArray->pFatherUndoArray,"svl::SfxUndoManager::ImplLeaveListAction, no father undo array!?");
- SfxUndoArray* pTmp = m_pData->pActUndoArray;
+ // the array/level which we're about to leave
+ SfxUndoArray* pArrayToLeave = m_pData->pActUndoArray;
+ // one step up
m_pData->pActUndoArray = m_pData->pActUndoArray->pFatherUndoArray;
// If no undo action where added, delete the undo list action
- SfxUndoAction *pTmpAction= m_pData->pActUndoArray->aUndoActions[m_pData->pActUndoArray->nCurUndoAction-1];
- const USHORT nListActionElements = pTmp->nCurUndoAction;
+ const USHORT nListActionElements = pArrayToLeave->nCurUndoAction;
if( nListActionElements == 0 )
{
- m_pData->pActUndoArray->aUndoActions.Remove( --m_pData->pActUndoArray->nCurUndoAction);
- delete pTmpAction;
+ SfxUndoAction* pCurrentAction= m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction-1 ];
+ m_pData->pActUndoArray->aUndoActions.Remove( --m_pData->pActUndoArray->nCurUndoAction );
+ delete pCurrentAction;
+
+ ::std::for_each( m_pData->aListeners.begin(), m_pData->aListeners.end(),
+ NotifyUndoListener( &SfxUndoListener::listActionCancelled ) );
+ return 0;
+ }
+
+
+ SfxUndoAction* pCurrentAction= m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction-1 ];
+ SfxListUndoAction* pListAction = dynamic_cast< SfxListUndoAction * >( pCurrentAction );
+ OSL_ENSURE( pListAction, "SfxUndoManager::ImplLeaveListAction: list action expected at this position!" );
+
+ if ( pListAction && i_merge )
+ {
+ // merge the list action with its predecessor on the same level
+ OSL_ENSURE( m_pData->pActUndoArray->nCurUndoAction > 1,
+ "SfxUndoManager::ImplLeaveListAction: cannot merge the list action if there's no other action on the same level - check this beforehand!" );
+ if ( m_pData->pActUndoArray->nCurUndoAction > 1 )
+ {
+ const SfxUndoAction* pPreviousAction = m_pData->pActUndoArray->aUndoActions[ m_pData->pActUndoArray->nCurUndoAction - 2 ];
+ m_pData->pActUndoArray->aUndoActions.Remove( m_pData->pActUndoArray->nCurUndoAction - 2 );
+ --m_pData->pActUndoArray->nCurUndoAction;
+ pListAction->aUndoActions.Insert( pPreviousAction, 0 );
+ ++pListAction->nCurUndoAction; // should not matter, as we're not expected to ever re-enter this list ...
+
+ pListAction->SetComment( pPreviousAction->GetComment() );
+ }
}
- else
+
+ // if the undo array has no comment, try to get it from its children
+ if ( pListAction && pListAction->GetComment().Len() == 0 )
{
- // if the undo array has no comment, try to get it from its children
- SfxListUndoAction* pList = dynamic_cast< SfxListUndoAction * >( pTmpAction );
- if( pList && pList->GetComment().Len() == 0 )
+ for( USHORT n = 0; n < pListAction->aUndoActions.Count(); n++ )
{
- USHORT n;
- for( n = 0; n < pList->aUndoActions.Count(); n++ )
+ if( pListAction->aUndoActions[n]->GetComment().Len() )
{
- if( pList->aUndoActions[n]->GetComment().Len() )
- {
- pList->SetComment( pList->aUndoActions[n]->GetComment() );
- break;
- }
+ pListAction->SetComment( pListAction->aUndoActions[n]->GetComment() );
+ break;
}
}
}
// notify listeners
- const bool leftContext = ( nListActionElements > 0 );
::std::for_each( m_pData->aListeners.begin(), m_pData->aListeners.end(),
- NotifyUndoListener( leftContext ? &SfxUndoListener::listActionLeft : &SfxUndoListener::listActionCancelled ) );
+ NotifyUndoListener( &SfxUndoListener::listActionLeft ) );
return nListActionElements;
}