merge the formfield patch from ooo-build
[ooovba.git] / svtools / source / undo / undo.cxx
blob68a770b48bc6ad11128be9c0076dd3ca5ed2616a
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: undo.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <com/sun/star/uno/Exception.hpp>
36 #include <tools/debug.hxx>
38 #include <svtools/undo.hxx>
40 using ::com::sun::star::uno::Exception;
42 // STATIC DATA -----------------------------------------------------------
44 DBG_NAME(SfxUndoAction)
46 //========================================================================
48 TYPEINIT0(SfxUndoAction);
49 TYPEINIT0(SfxListUndoAction);
50 TYPEINIT0(SfxLinkUndoAction);
51 TYPEINIT0(SfxRepeatTarget);
53 //------------------------------------------------------------------------
55 SfxRepeatTarget::~SfxRepeatTarget()
59 //------------------------------------------------------------------------
61 BOOL SfxUndoAction::IsLinked()
63 return bLinked;
66 //------------------------------------------------------------------------
68 void SfxUndoAction::SetLinked( BOOL bIsLinked )
70 bLinked = bIsLinked;
73 //------------------------------------------------------------------------
75 SfxUndoAction::~SfxUndoAction()
77 DBG_DTOR(SfxUndoAction, 0);
78 DBG_ASSERT( !IsLinked(), "Gelinkte Action geloescht" );
82 SfxUndoAction::SfxUndoAction()
84 DBG_CTOR(SfxUndoAction, 0);
85 SetLinked( FALSE );
88 //------------------------------------------------------------------------
90 BOOL SfxUndoAction::Merge( SfxUndoAction * )
92 DBG_CHKTHIS(SfxUndoAction, 0);
93 return FALSE;
96 //------------------------------------------------------------------------
98 XubString SfxUndoAction::GetComment() const
100 DBG_CHKTHIS(SfxUndoAction, 0);
101 return XubString();
104 //------------------------------------------------------------------------
107 USHORT SfxUndoAction::GetId() const
109 DBG_CHKTHIS(SfxUndoAction, 0);
110 return 0;
113 //------------------------------------------------------------------------
115 XubString SfxUndoAction::GetRepeatComment(SfxRepeatTarget&) const
117 DBG_CHKTHIS(SfxUndoAction, 0);
118 return GetComment();
121 //------------------------------------------------------------------------
124 void SfxUndoAction::Undo()
126 // die sind nur konzeptuell pure virtual
127 DBG_ERROR( "pure virtual function called: SfxUndoAction::Undo()" );
130 //------------------------------------------------------------------------
132 void SfxUndoAction::Redo()
134 // die sind nur konzeptuell pure virtual
135 DBG_ERROR( "pure virtual function called: SfxUndoAction::Redo()" );
138 //------------------------------------------------------------------------
140 void SfxUndoAction::Repeat(SfxRepeatTarget&)
142 // die sind nur konzeptuell pure virtual
143 DBG_ERROR( "pure virtual function called: SfxUndoAction::Repeat()" );
146 //------------------------------------------------------------------------
149 BOOL SfxUndoAction::CanRepeat(SfxRepeatTarget&) const
151 return TRUE;
154 //========================================================================
157 SfxUndoManager::SfxUndoManager( USHORT nMaxUndoActionCount )
158 : pFatherUndoArray(0)
159 , mbUndoEnabled( true )
161 pUndoArray=new SfxUndoArray(nMaxUndoActionCount);
162 pActUndoArray=pUndoArray;
166 //------------------------------------------------------------------------
169 SfxUndoManager::~SfxUndoManager()
171 delete pUndoArray;
174 //------------------------------------------------------------------------
176 void SfxUndoManager::EnableUndo( bool bEnable )
178 mbUndoEnabled = bEnable;
181 //------------------------------------------------------------------------
184 void SfxUndoManager::SetMaxUndoActionCount( USHORT nMaxUndoActionCount )
186 // Remove entries from the pActUndoArray when we have to reduce
187 // the number of entries due to a lower nMaxUndoActionCount.
188 // Both redo and undo action entries will be removed until we reached the
189 // new nMaxUndoActionCount.
191 long nNumToDelete = pActUndoArray->aUndoActions.Count() - nMaxUndoActionCount;
192 if ( nNumToDelete > 0 )
194 while ( nNumToDelete > 0 )
196 USHORT nPos = pActUndoArray->aUndoActions.Count();
197 if ( nPos > pActUndoArray->nCurUndoAction )
199 if ( !pActUndoArray->aUndoActions[nPos-1]->IsLinked() )
201 delete pActUndoArray->aUndoActions[nPos-1];
202 pActUndoArray->aUndoActions.Remove( nPos-1 );
203 --nNumToDelete;
207 if ( nNumToDelete > 0 && pActUndoArray->nCurUndoAction > 0 )
209 if ( !pActUndoArray->aUndoActions[0]->IsLinked() )
211 delete pActUndoArray->aUndoActions[0];
212 pActUndoArray->aUndoActions.Remove(0);
213 --pActUndoArray->nCurUndoAction;
214 --nNumToDelete;
218 if ( nPos == pActUndoArray->aUndoActions.Count() )
219 break; // Cannot delete more entries
223 pActUndoArray->nMaxUndoActions = nMaxUndoActionCount;
226 //------------------------------------------------------------------------
228 USHORT SfxUndoManager::GetMaxUndoActionCount() const
230 return pActUndoArray->nMaxUndoActions;
233 //------------------------------------------------------------------------
235 void SfxUndoManager::Clear()
237 while ( pActUndoArray->aUndoActions.Count() )
239 SfxUndoAction *pAction=
240 pActUndoArray->aUndoActions[pActUndoArray->aUndoActions.Count() - 1];
241 pActUndoArray->aUndoActions.Remove( pActUndoArray->aUndoActions.Count() - 1 );
242 delete pAction;
245 pActUndoArray->nCurUndoAction = 0;
248 //------------------------------------------------------------------------
250 void SfxUndoManager::ClearRedo()
252 while ( pActUndoArray->aUndoActions.Count() > pActUndoArray->nCurUndoAction )
254 SfxUndoAction *pAction=
255 pActUndoArray->aUndoActions[pActUndoArray->aUndoActions.Count() - 1];
256 pActUndoArray->aUndoActions.Remove( pActUndoArray->aUndoActions.Count() - 1 );
257 delete pAction;
261 //------------------------------------------------------------------------
263 void SfxUndoManager::AddUndoAction( SfxUndoAction *pAction, BOOL bTryMerge )
265 if( mbUndoEnabled )
267 // Redo-Actions loeschen
268 for ( USHORT nPos = pActUndoArray->aUndoActions.Count();
269 nPos > pActUndoArray->nCurUndoAction; --nPos )
270 delete pActUndoArray->aUndoActions[nPos-1];
272 pActUndoArray->aUndoActions.Remove(
273 pActUndoArray->nCurUndoAction,
274 pActUndoArray->aUndoActions.Count() - pActUndoArray->nCurUndoAction );
276 if ( pActUndoArray->nMaxUndoActions )
278 SfxUndoAction *pTmpAction = pActUndoArray->nCurUndoAction ?
279 pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1] : 0;
281 if ( !bTryMerge || !(pTmpAction && pTmpAction->Merge(pAction)) )
283 // auf Max-Anzahl anpassen
284 if( pActUndoArray == pUndoArray )
285 while( pActUndoArray->aUndoActions.Count() >=
286 pActUndoArray->nMaxUndoActions &&
287 !pActUndoArray->aUndoActions[0]->IsLinked() )
289 delete pActUndoArray->aUndoActions[0];
290 pActUndoArray->aUndoActions.Remove(0);
291 --pActUndoArray->nCurUndoAction;
294 // neue Action anh"angen
295 const SfxUndoAction* pTemp = pAction;
296 pActUndoArray->aUndoActions.Insert(
297 pTemp, pActUndoArray->nCurUndoAction++ );
298 return;
302 delete pAction;
305 //------------------------------------------------------------------------
307 USHORT SfxUndoManager::GetUndoActionCount() const
309 return pActUndoArray->nCurUndoAction;
312 //------------------------------------------------------------------------
314 XubString SfxUndoManager::GetUndoActionComment( USHORT nNo ) const
316 DBG_ASSERT( nNo < pActUndoArray->nCurUndoAction, "svtools::SfxUndoManager::GetUndoActionComment(), illegal id!" );
317 if( nNo < pActUndoArray->nCurUndoAction )
319 return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1-nNo]->GetComment(); //!
321 else
323 XubString aEmpty;
324 return aEmpty;
328 //------------------------------------------------------------------------
330 USHORT SfxUndoManager::GetUndoActionId( USHORT nNo ) const
332 DBG_ASSERT( nNo < pActUndoArray->nCurUndoAction, "svtools::SfxUndoManager::GetUndoActionId(), illegal id!" );
333 if( nNo < pActUndoArray->nCurUndoAction )
335 return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1-nNo]->GetId(); //!
337 else
339 return 0;
343 //------------------------------------------------------------------------
345 SfxUndoAction* SfxUndoManager::GetUndoAction( USHORT nNo ) const
347 DBG_ASSERT( nNo < pActUndoArray->nCurUndoAction, "svtools::SfxUndoManager::GetUndoAction(), illegal id!" );
348 if( nNo < pActUndoArray->nCurUndoAction )
350 return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1-nNo]; //!
352 else
354 return 0;
358 //------------------------------------------------------------------------
360 /** clears the redo stack and removes the top undo action */
361 void SfxUndoManager::RemoveLastUndoAction()
363 DBG_ASSERT( pActUndoArray->nCurUndoAction, "svtools::SfxUndoManager::RemoveLastUndoAction(), no action to remove?!" );
364 if( pActUndoArray->nCurUndoAction )
366 pActUndoArray->nCurUndoAction--;
368 // delete redo-actions and top action
369 USHORT nPos;
370 for ( nPos = pActUndoArray->aUndoActions.Count(); nPos > pActUndoArray->nCurUndoAction; --nPos )
371 delete pActUndoArray->aUndoActions[nPos-1];
373 pActUndoArray->aUndoActions.Remove(
374 pActUndoArray->nCurUndoAction,
375 pActUndoArray->aUndoActions.Count() - pActUndoArray->nCurUndoAction );
379 //------------------------------------------------------------------------
381 BOOL SfxUndoManager::Undo( USHORT )
383 bool bUndoWasEnabled = mbUndoEnabled;
384 mbUndoEnabled = false;
386 BOOL bRet = FALSE;
390 DBG_ASSERT( pActUndoArray == pUndoArray, "svtools::SfxUndoManager::Undo(), LeaveListAction() not yet called!" );
391 if ( pActUndoArray->nCurUndoAction )
393 Undo( *pActUndoArray->aUndoActions[ --pActUndoArray->nCurUndoAction ] );
394 bRet = TRUE;
397 catch( Exception& e )
399 mbUndoEnabled = bUndoWasEnabled;
400 throw e;
402 mbUndoEnabled = bUndoWasEnabled;
403 return bRet;
406 //------------------------------------------------------------------------
408 void SfxUndoManager::Undo( SfxUndoAction &rAction )
410 bool bUndoWasEnabled = mbUndoEnabled;
411 mbUndoEnabled = false;
414 rAction.Undo();
416 catch( Exception& e )
418 mbUndoEnabled = bUndoWasEnabled;
419 throw e;
422 mbUndoEnabled = bUndoWasEnabled;
425 //------------------------------------------------------------------------
427 USHORT SfxUndoManager::GetRedoActionCount() const
429 return pActUndoArray->aUndoActions.Count() - pActUndoArray->nCurUndoAction; //!
432 //------------------------------------------------------------------------
434 XubString SfxUndoManager::GetRedoActionComment( USHORT nNo ) const
436 return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction+nNo]->GetComment(); //!
439 //------------------------------------------------------------------------
441 USHORT SfxUndoManager::GetRedoActionId( USHORT nNo ) const
443 return pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction+nNo]->GetId(); //!
446 //------------------------------------------------------------------------
448 BOOL SfxUndoManager::Redo( USHORT )
450 bool bUndoWasEnabled = mbUndoEnabled;
451 mbUndoEnabled = false;
453 BOOL bRet = FALSE;
457 if ( pActUndoArray->aUndoActions.Count() > pActUndoArray->nCurUndoAction )
459 Redo( *pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction++] );
460 bRet = TRUE;
463 catch( Exception& e )
465 mbUndoEnabled = bUndoWasEnabled;
466 throw e;
469 mbUndoEnabled = bUndoWasEnabled;
470 return bRet;
473 //------------------------------------------------------------------------
475 void SfxUndoManager::Redo( SfxUndoAction &rAction )
477 bool bUndoWasEnabled = mbUndoEnabled;
478 mbUndoEnabled = false;
482 rAction.Redo();
484 catch( Exception& e )
486 mbUndoEnabled = bUndoWasEnabled;
487 throw e;
490 mbUndoEnabled = bUndoWasEnabled;
493 //------------------------------------------------------------------------
495 USHORT SfxUndoManager::GetRepeatActionCount() const
497 return pActUndoArray->aUndoActions.Count();
500 //------------------------------------------------------------------------
502 XubString SfxUndoManager::GetRepeatActionComment( SfxRepeatTarget &rTarget, USHORT nNo ) const
504 return pActUndoArray->aUndoActions[ pActUndoArray->aUndoActions.Count() - 1 - nNo ]
505 ->GetRepeatComment(rTarget);
508 //------------------------------------------------------------------------
510 BOOL SfxUndoManager::Repeat( SfxRepeatTarget &rTarget, USHORT /*nFrom*/, USHORT /*nCount*/ )
512 if ( pActUndoArray->aUndoActions.Count() )
514 Repeat( rTarget, *pActUndoArray->aUndoActions[ pActUndoArray->aUndoActions.Count() - 1 ] );
515 return TRUE;
518 return FALSE;
521 //------------------------------------------------------------------------
523 void SfxUndoManager::Repeat( SfxRepeatTarget &rTarget, SfxUndoAction &rAction )
525 if ( rAction.CanRepeat(rTarget) )
526 rAction.Repeat(rTarget);
529 //------------------------------------------------------------------------
531 BOOL SfxUndoManager::CanRepeat( SfxRepeatTarget &rTarget, SfxUndoAction &rAction ) const
533 return rAction.CanRepeat(rTarget);
536 //------------------------------------------------------------------------
538 BOOL SfxUndoManager::CanRepeat( SfxRepeatTarget &rTarget, USHORT nNo ) const
540 if ( pActUndoArray->aUndoActions.Count() > nNo )
542 USHORT nActionNo = pActUndoArray->aUndoActions.Count() - 1 - nNo;
543 return pActUndoArray->aUndoActions[nActionNo]->CanRepeat(rTarget);
546 return FALSE;
549 //------------------------------------------------------------------------
551 void SfxUndoManager::EnterListAction(
552 const XubString& rComment, const XubString &rRepeatComment, USHORT nId )
554 /* [Beschreibung]
556 Fuegt eine ListUndoAction ein und setzt dessen UndoArray als aktuelles.
560 if( !mbUndoEnabled )
561 return;
563 if ( !pUndoArray->nMaxUndoActions )
564 return;
566 pFatherUndoArray=pActUndoArray;
567 SfxListUndoAction *pAction=new SfxListUndoAction(
568 rComment, rRepeatComment, nId, pActUndoArray);
569 AddUndoAction( pAction );
570 pActUndoArray=pAction;
573 //------------------------------------------------------------------------
575 void SfxUndoManager::LeaveListAction()
577 /* [Beschreibung]
579 Verlaesst die aktuelle ListAction und geht eine Ebene nach oben.
582 if ( !mbUndoEnabled )
583 return;
585 if ( !pUndoArray->nMaxUndoActions )
586 return;
588 if( pActUndoArray == pUndoArray )
590 DBG_ERROR( "svtools::SfxUndoManager::LeaveListAction(), called without calling EnterListAction()!" );
591 return;
594 DBG_ASSERT(pActUndoArray->pFatherUndoArray,"svtools::SfxUndoManager::LeaveListAction(), no father undo array!?");
596 SfxUndoArray* pTmp=pActUndoArray;
597 pActUndoArray=pActUndoArray->pFatherUndoArray;
599 // If no undo action where added, delete the undo list action
600 SfxUndoAction *pTmpAction= pActUndoArray->aUndoActions[pActUndoArray->nCurUndoAction-1];
601 if(!pTmp->nCurUndoAction)
603 pActUndoArray->aUndoActions.Remove( --pActUndoArray->nCurUndoAction);
604 delete pTmpAction;
606 else
608 // if the undo array has no comment, try to get it from its children
609 SfxListUndoAction* pList = dynamic_cast< SfxListUndoAction * >( pTmpAction );
610 if( pList && pList->GetComment().Len() == 0 )
612 USHORT n;
613 for( n = 0; n < pList->aUndoActions.Count(); n++ )
615 if( pList->aUndoActions[n]->GetComment().Len() )
617 pList->SetComment( pList->aUndoActions[n]->GetComment() );
618 break;
625 //------------------------------------------------------------------------
627 USHORT SfxListUndoAction::GetId() const
629 return nId;
632 //------------------------------------------------------------------------
634 XubString SfxListUndoAction::GetComment() const
636 return aComment;
639 //------------------------------------------------------------------------
641 void SfxListUndoAction::SetComment( const UniString& rComment )
643 aComment = rComment;
646 //------------------------------------------------------------------------
648 XubString SfxListUndoAction::GetRepeatComment(SfxRepeatTarget &) const
650 return aRepeatComment;
654 //------------------------------------------------------------------------
656 SfxListUndoAction::SfxListUndoAction
658 const XubString &rComment,
659 const XubString rRepeatComment,
660 USHORT Id,
661 SfxUndoArray *pFather
663 : nId(Id), aComment(rComment), aRepeatComment(rRepeatComment)
665 pFatherUndoArray = pFather;
666 nMaxUndoActions = USHRT_MAX;
669 //------------------------------------------------------------------------
671 void SfxListUndoAction::Undo()
673 for(INT16 i=nCurUndoAction-1;i>=0;i--)
674 aUndoActions[i]->Undo();
675 nCurUndoAction=0;
678 //------------------------------------------------------------------------
680 void SfxListUndoAction::Redo()
682 for(USHORT i=nCurUndoAction;i<aUndoActions.Count();i++)
683 aUndoActions[i]->Redo();
684 nCurUndoAction = aUndoActions.Count();
687 //------------------------------------------------------------------------
689 void SfxListUndoAction::Repeat(SfxRepeatTarget&rTarget)
691 for(USHORT i=0;i<nCurUndoAction;i++)
692 aUndoActions[i]->Repeat(rTarget);
695 //------------------------------------------------------------------------
697 BOOL SfxListUndoAction::CanRepeat(SfxRepeatTarget&r) const
699 for(USHORT i=0;i<nCurUndoAction;i++)
700 if(!aUndoActions[i]->CanRepeat(r))
701 return FALSE;
702 return TRUE;
705 //------------------------------------------------------------------------
707 BOOL SfxListUndoAction::Merge( SfxUndoAction *pNextAction )
709 return aUndoActions.Count() && aUndoActions[aUndoActions.Count()-1]->Merge( pNextAction );
712 //------------------------------------------------------------------------
714 SfxLinkUndoAction::SfxLinkUndoAction(SfxUndoManager *pManager)
715 /* [Beschreibung]
717 Richtet eine LinkAction ein, die auf einen weiteren UndoManager zeigt.
718 Holt sich als zugehoerige Action des weiteren UndoManagers dessen
719 aktuelle Action.
723 pUndoManager = pManager;
724 if ( pManager->GetMaxUndoActionCount() )
726 USHORT nPos = pManager->GetUndoActionCount()-1;
727 pAction = pManager->pActUndoArray->aUndoActions[nPos];
728 pAction->SetLinked();
730 else
731 pAction = 0;
734 //------------------------------------------------------------------------
736 void SfxLinkUndoAction::Undo()
738 if ( pAction )
739 pUndoManager->Undo(1);
742 //------------------------------------------------------------------------
744 void SfxLinkUndoAction::Redo()
746 if ( pAction )
747 pUndoManager->Redo(1);
750 //------------------------------------------------------------------------
753 BOOL SfxLinkUndoAction::CanRepeat(SfxRepeatTarget& r) const
755 return pAction && pUndoManager->CanRepeat(r,*pAction);
759 //------------------------------------------------------------------------
762 void SfxLinkUndoAction::Repeat(SfxRepeatTarget&r)
764 if ( pAction )
765 pUndoManager->Repeat(r,*pAction);
769 //------------------------------------------------------------------------
771 XubString SfxLinkUndoAction::GetComment() const
773 if ( pAction )
774 return pAction->GetComment();
775 else
776 return XubString();
780 //------------------------------------------------------------------------
782 XubString SfxLinkUndoAction::GetRepeatComment(SfxRepeatTarget&r) const
784 if ( pAction )
785 return pAction->GetRepeatComment(r);
786 else
787 return XubString();
790 //------------------------------------------------------------------------
792 SfxLinkUndoAction::~SfxLinkUndoAction()
794 if( pAction )
795 pAction->SetLinked( FALSE );
799 //------------------------------------------------------------------------
801 SfxUndoArray::~SfxUndoArray()
803 while ( aUndoActions.Count() )
805 SfxUndoAction *pAction =
806 aUndoActions[ aUndoActions.Count() - 1 ];
807 aUndoActions.Remove( aUndoActions.Count() - 1 );
808 delete pAction;
813 USHORT SfxLinkUndoAction::GetId() const
815 return pAction ? pAction->GetId() : 0;