undoapi: don't let sw's UndoManager call into SfxUndoManager::Clear when in a list action - introdce a dedicated method (ClearAllLelves) for the pattern needed by sw

This commit is contained in:
Frank Schoenheit [fs] 2011-01-06 10:34:42 +01:00
parent 80090015ec
commit 1c380574d3
2 changed files with 54 additions and 11 deletions

View file

@ -400,12 +400,23 @@ protected:
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 ImplClear( ::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;

View file

@ -190,6 +190,7 @@ struct SVL_DLLPRIVATE SfxUndoManager_Data
sal_Int32 mnMarks;
sal_Int32 mnEmptyMark;
bool mbDoing;
bool mbClearUntilTopLevel;
UndoListeners aListeners;
@ -201,7 +202,7 @@ struct SVL_DLLPRIVATE SfxUndoManager_Data
,mnMarks( 0 )
,mnEmptyMark(MARK_INVALID)
,mbDoing( false )
,mbClearUntilTopLevel( false )
{
pActUndoArray = pUndoArray;
}
@ -500,7 +501,7 @@ size_t SfxUndoManager::GetMaxUndoActionCount() const
//------------------------------------------------------------------------
void SfxUndoManager::ImplClear( UndoManagerGuard& i_guard )
void SfxUndoManager::ImplClearCurrentLevel_NoNotify( UndoManagerGuard& i_guard )
{
// clear array
while ( !m_pData->pActUndoArray->aUndoActions.empty() )
@ -515,9 +516,6 @@ void SfxUndoManager::ImplClear( UndoManagerGuard& i_guard )
m_pData->mnMarks = 0;
m_pData->mnEmptyMark = MARK_INVALID;
// notify listeners
i_guard.scheduleNotification( &SfxUndoListener::cleared );
}
//------------------------------------------------------------------------
@ -525,8 +523,29 @@ void SfxUndoManager::ImplClear( UndoManagerGuard& i_guard )
void SfxUndoManager::Clear()
{
UndoManagerGuard aGuard( *m_pData );
OSL_ENSURE( !ImplIsInListAction_Lock(), "SfxUndoManager::Clear: suspicious call - do you really wish to clear the current level?" );
ImplClear( aGuard );
ImplClearCurrentLevel_NoNotify( aGuard );
// notify listeners
aGuard.scheduleNotification( &SfxUndoListener::cleared );
}
//------------------------------------------------------------------------
void SfxUndoManager::ClearAllLevels()
{
UndoManagerGuard aGuard( *m_pData );
ImplClearCurrentLevel_NoNotify( aGuard );
if ( ImplIsInListAction_Lock() )
{
m_pData->mbClearUntilTopLevel = true;
}
else
{
aGuard.scheduleNotification( &SfxUndoListener::cleared );
}
}
//------------------------------------------------------------------------
@ -560,9 +579,9 @@ void SfxUndoManager::Reset()
ImplLeaveListAction( false, aGuard );
// clear both stacks
ImplClear( aGuard );
ImplClearCurrentLevel_NoNotify( aGuard );
// cancel the notifications scheduled by ImplLeaveListAction resp. ImplClear,
// cancel the notifications scheduled by ImplLeaveListAction,
// as we want to do an own, dedicated notification
aGuard.cancelNotifications();
@ -1053,7 +1072,20 @@ size_t SfxUndoManager::GetListActionDepth() const
size_t SfxUndoManager::LeaveListAction()
{
UndoManagerGuard aGuard( *m_pData );
return ImplLeaveListAction( false, aGuard );
size_t nCount = ImplLeaveListAction( false, aGuard );
if ( m_pData->mbClearUntilTopLevel )
{
ImplClearCurrentLevel_NoNotify( aGuard );
if ( !ImplIsInListAction_Lock() )
{
m_pData->mbClearUntilTopLevel = false;
aGuard.scheduleNotification( &SfxUndoListener::cleared );
}
nCount = 0;
}
return nCount;
}
//------------------------------------------------------------------------
@ -1080,7 +1112,7 @@ size_t SfxUndoManager::ImplLeaveListAction( const bool i_merge, UndoManagerGuard
return 0;
}
DBG_ASSERT( m_pData->pActUndoArray->pFatherUndoArray, "svl::SfxUndoManager::ImplLeaveListAction, no father undo array!?" );
DBG_ASSERT( m_pData->pActUndoArray->pFatherUndoArray, "SfxUndoManager::ImplLeaveListAction, no father undo array!?" );
// the array/level which we're about to leave
SfxUndoArray* pArrayToLeave = m_pData->pActUndoArray;