xref: /aoo41x/main/sc/source/ui/undo/undobase.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 
32 
33 // INCLUDE ---------------------------------------------------------------
34 
35 #include <vcl/virdev.hxx>
36 
37 #include "undobase.hxx"
38 #include "refundo.hxx"
39 #include "docsh.hxx"
40 #include "tabvwsh.hxx"
41 #include "undoolk.hxx"
42 #include "undodraw.hxx"
43 #include "dbcolect.hxx"
44 #include "attrib.hxx"
45 #include "queryparam.hxx"
46 #include "globstr.hrc"
47 
48 // STATIC DATA -----------------------------------------------------------
49 
50 TYPEINIT1(ScSimpleUndo,		SfxUndoAction);
51 TYPEINIT1(ScBlockUndo,      ScSimpleUndo);
52 TYPEINIT1(ScMoveUndo,       ScSimpleUndo);
53 TYPEINIT1(ScDBFuncUndo,     ScSimpleUndo);
54 TYPEINIT1(ScUndoWrapper,    SfxUndoAction);
55 
56 // -----------------------------------------------------------------------
57 
58 ScSimpleUndo::ScSimpleUndo( ScDocShell* pDocSh ) :
59 	pDocShell( pDocSh ),
60 	pDetectiveUndo( NULL )
61 {
62 }
63 
64 __EXPORT ScSimpleUndo::~ScSimpleUndo()
65 {
66 	delete pDetectiveUndo;
67 }
68 
69 bool ScSimpleUndo::SetViewMarkData( const ScMarkData& rMarkData )
70 {
71     if ( IsPaintLocked() )
72         return false;
73 
74 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
75     if ( !pViewShell )
76         return false;
77 
78     pViewShell->SetMarkData( rMarkData );
79     return true;
80 }
81 
82 sal_Bool __EXPORT ScSimpleUndo::Merge( SfxUndoAction *pNextAction )
83 {
84 	//	Zu jeder Undo-Action kann eine SdrUndoGroup fuer das Aktualisieren
85 	//	der Detektiv-Pfeile gehoeren.
86 	//	DetectiveRefresh kommt immer hinterher, die SdrUndoGroup ist in
87 	//	eine ScUndoDraw Action verpackt.
88 	//	Nur beim automatischen Aktualisieren wird AddUndoAction mit
89 	//	bTryMerg=sal_True gerufen.
90 
91 	if ( !pDetectiveUndo && pNextAction->ISA(ScUndoDraw) )
92 	{
93 		//	SdrUndoAction aus der ScUndoDraw Action uebernehmen,
94 		//	ScUndoDraw wird dann vom UndoManager geloescht
95 
96 		ScUndoDraw* pCalcUndo = (ScUndoDraw*)pNextAction;
97 		pDetectiveUndo = pCalcUndo->GetDrawUndo();
98 		pCalcUndo->ForgetDrawUndo();
99 		return sal_True;
100 	}
101 
102 	return sal_False;
103 }
104 
105 void ScSimpleUndo::BeginUndo()
106 {
107 	pDocShell->SetInUndo( sal_True );
108 
109 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
110 	if (pViewShell)
111 		pViewShell->HideAllCursors();		// z.B. wegen zusammengefassten Zellen
112 
113 	//	detective updates happened last, must be undone first
114 	if (pDetectiveUndo)
115 		pDetectiveUndo->Undo();
116 }
117 
118 void ScSimpleUndo::EndUndo()
119 {
120 	pDocShell->SetDocumentModified();
121 
122 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
123 	if (pViewShell)
124 	{
125 		pViewShell->UpdateAutoFillMark();
126 		pViewShell->UpdateInputHandler();
127 		pViewShell->ShowAllCursors();
128 	}
129 
130 	pDocShell->SetInUndo( sal_False );
131 }
132 
133 void ScSimpleUndo::BeginRedo()
134 {
135 	pDocShell->SetInUndo( sal_True );	//! eigenes Flag fuer Redo?
136 
137 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
138 	if (pViewShell)
139 		pViewShell->HideAllCursors();		// z.B. wegen zusammengefassten Zellen
140 }
141 
142 void ScSimpleUndo::EndRedo()
143 {
144 	if (pDetectiveUndo)
145 		pDetectiveUndo->Redo();
146 
147 	pDocShell->SetDocumentModified();
148 
149 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
150 	if (pViewShell)
151 	{
152 		pViewShell->UpdateAutoFillMark();
153 		pViewShell->UpdateInputHandler();
154 		pViewShell->ShowAllCursors();
155 	}
156 
157 	pDocShell->SetInUndo( sal_False );
158 }
159 
160 void ScSimpleUndo::ShowTable( SCTAB nTab )			// static
161 {
162 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
163 	if (pViewShell)
164 		pViewShell->SetTabNo( nTab );
165 }
166 
167 void ScSimpleUndo::ShowTable( const ScRange& rRange )			// static
168 {
169 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
170 	if (pViewShell)
171 	{
172 		SCTAB nStart = rRange.aStart.Tab();
173 		SCTAB nEnd   = rRange.aEnd.Tab();
174 		SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
175 		if ( nTab < nStart || nTab > nEnd )						// wenn nicht im Bereich:
176 			pViewShell->SetTabNo( nStart );						// auf erste des Bereiches
177 	}
178 }
179 
180 
181 // -----------------------------------------------------------------------
182 
183 ScBlockUndo::ScBlockUndo( ScDocShell* pDocSh, const ScRange& rRange,
184 											ScBlockUndoMode eBlockMode ) :
185 	ScSimpleUndo( pDocSh ),
186 	aBlockRange( rRange ),
187 	eMode( eBlockMode )
188 {
189 	pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() );
190 }
191 
192 __EXPORT ScBlockUndo::~ScBlockUndo()
193 {
194 	DeleteSdrUndoAction( pDrawUndo );
195 }
196 
197 void ScBlockUndo::BeginUndo()
198 {
199 	ScSimpleUndo::BeginUndo();
200 	EnableDrawAdjust( pDocShell->GetDocument(), sal_False );
201 }
202 
203 void ScBlockUndo::EndUndo()
204 {
205 	if (eMode == SC_UNDO_AUTOHEIGHT)
206 		AdjustHeight();
207 
208 	EnableDrawAdjust( pDocShell->GetDocument(), sal_True );
209     DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() );
210 
211 	ShowBlock();
212 	ScSimpleUndo::EndUndo();
213 }
214 
215 /*
216 void ScBlockUndo::BeginRedo()
217 {
218 	ScSimpleUndo::BeginRedo();
219 }
220 */
221 
222 void ScBlockUndo::EndRedo()
223 {
224 	if (eMode == SC_UNDO_AUTOHEIGHT)
225 		AdjustHeight();
226 
227 	ShowBlock();
228 	ScSimpleUndo::EndRedo();
229 }
230 
231 sal_Bool ScBlockUndo::AdjustHeight()
232 {
233 	ScDocument* pDoc = pDocShell->GetDocument();
234 
235 	VirtualDevice aVirtDev;
236 	Fraction aZoomX( 1, 1 );
237 	Fraction aZoomY = aZoomX;
238 	double nPPTX, nPPTY;
239 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
240 	if (pViewShell)
241 	{
242 		ScViewData* pData = pViewShell->GetViewData();
243 		nPPTX = pData->GetPPTX();
244 		nPPTY = pData->GetPPTY();
245 		aZoomX = pData->GetZoomX();
246 		aZoomY = pData->GetZoomY();
247 	}
248 	else
249 	{
250 		//	Zoom auf 100 lassen
251 		nPPTX = ScGlobal::nScreenPPTX;
252 		nPPTY = ScGlobal::nScreenPPTY;
253 	}
254 
255 	sal_Bool bRet = pDoc->SetOptimalHeight( aBlockRange.aStart.Row(), aBlockRange.aEnd.Row(),
256 /*!*/									aBlockRange.aStart.Tab(), 0, &aVirtDev,
257 										nPPTX, nPPTY, aZoomX, aZoomY, sal_False );
258 
259 	if (bRet)
260 		pDocShell->PostPaint( 0,      aBlockRange.aStart.Row(), aBlockRange.aStart.Tab(),
261 							  MAXCOL, MAXROW,                   aBlockRange.aEnd.Tab(),
262 							  PAINT_GRID | PAINT_LEFT );
263 
264 	return bRet;
265 }
266 
267 void ScBlockUndo::ShowBlock()
268 {
269     if ( IsPaintLocked() )
270         return;
271 
272 	ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
273 	if (pViewShell)
274 	{
275 		ShowTable( aBlockRange );		// bei mehreren Tabs im Range ist jede davon gut
276 		pViewShell->MoveCursorAbs( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
277 								   SC_FOLLOW_JUMP, sal_False, sal_False );
278 		SCTAB nTab = pViewShell->GetViewData()->GetTabNo();
279 		ScRange aRange = aBlockRange;
280 		aRange.aStart.SetTab( nTab );
281 		aRange.aEnd.SetTab( nTab );
282 		pViewShell->MarkRange( aRange );
283 
284 		//	nicht per SetMarkArea an MarkData, wegen evtl. fehlendem Paint
285 	}
286 }
287 
288 
289 // -----------------------------------------------------------------------
290 
291 ScMoveUndo::ScMoveUndo( ScDocShell* pDocSh, ScDocument* pRefDoc, ScRefUndoData* pRefData,
292 												ScMoveUndoMode eRefMode ) :
293 	ScSimpleUndo( pDocSh ),
294 	pRefUndoDoc( pRefDoc ),
295 	pRefUndoData( pRefData ),
296 	eMode( eRefMode )
297 {
298 	ScDocument* pDoc = pDocShell->GetDocument();
299 	if (pRefUndoData)
300 		pRefUndoData->DeleteUnchanged(pDoc);
301 	pDrawUndo = GetSdrUndoAction( pDoc );
302 }
303 
304 __EXPORT ScMoveUndo::~ScMoveUndo()
305 {
306 	delete pRefUndoData;
307 	delete pRefUndoDoc;
308 	DeleteSdrUndoAction( pDrawUndo );
309 }
310 
311 void ScMoveUndo::UndoRef()
312 {
313 	ScDocument* pDoc = pDocShell->GetDocument();
314 	ScRange aRange(0,0,0, MAXCOL,MAXROW,pRefUndoDoc->GetTableCount()-1);
315 	pRefUndoDoc->CopyToDocument( aRange, IDF_FORMULA, sal_False, pDoc, NULL, sal_False );
316 	if (pRefUndoData)
317 		pRefUndoData->DoUndo( pDoc, (eMode == SC_UNDO_REFFIRST) );
318 		// #65055# HACK: ScDragDropUndo ist der einzige mit REFFIRST.
319 		// Falls nicht, resultiert daraus evtl. ein zu haeufiges Anpassen
320 		// der ChartRefs, nicht schoen, aber auch nicht schlecht..
321 }
322 
323 void ScMoveUndo::BeginUndo()
324 {
325 	ScSimpleUndo::BeginUndo();
326 
327 	EnableDrawAdjust( pDocShell->GetDocument(), sal_False );
328 
329 	if (pRefUndoDoc && eMode == SC_UNDO_REFFIRST)
330 		UndoRef();
331 }
332 
333 void ScMoveUndo::EndUndo()
334 {
335     //@17.12.97 Reihenfolge der Fkt.s geaendert
336     DoSdrUndoAction( pDrawUndo, pDocShell->GetDocument() );     // #125875# must also be called when pointer is null
337 
338 	if (pRefUndoDoc && eMode == SC_UNDO_REFLAST)
339 		UndoRef();
340 
341 	EnableDrawAdjust( pDocShell->GetDocument(), sal_True );
342 
343 	ScSimpleUndo::EndUndo();
344 }
345 
346 /*
347 void ScMoveUndo::BeginRedo()
348 {
349 	ScSimpleUndo::BeginRedo();
350 }
351 */
352 
353 /*
354 void ScMoveUndo::EndRedo()
355 {
356 	ScSimpleUndo::EndRedo();
357 }
358 */
359 
360 // -----------------------------------------------------------------------
361 
362 ScDBFuncUndo::ScDBFuncUndo( ScDocShell* pDocSh, const ScRange& rOriginal, SdrUndoAction* pDrawUndo ) :
363     ScSimpleUndo( pDocSh ),
364     aOriginalRange( rOriginal ),
365     mpDrawUndo( pDrawUndo )
366 {
367     pAutoDBRange = pDocSh->GetOldAutoDBRange();
368 }
369 
370 ScDBFuncUndo::~ScDBFuncUndo()
371 {
372     DeleteSdrUndoAction( mpDrawUndo );
373     delete pAutoDBRange;
374 }
375 
376 void ScDBFuncUndo::SetDrawUndoAction( SdrUndoAction* pDrawUndo )
377 {
378     DeleteSdrUndoAction( mpDrawUndo );
379     mpDrawUndo = pDrawUndo;
380 }
381 
382 void ScDBFuncUndo::BeginUndo()
383 {
384     ScSimpleUndo::BeginUndo();
385     DoSdrUndoAction( mpDrawUndo, pDocShell->GetDocument() );
386 }
387 
388 void ScDBFuncUndo::EndUndo()
389 {
390     ScSimpleUndo::EndUndo();
391 
392     if ( pAutoDBRange )
393     {
394         sal_uInt16 nNoNameIndex;
395         ScDocument* pDoc = pDocShell->GetDocument();
396         ScDBCollection* pColl = pDoc->GetDBCollection();
397         if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) )
398         {
399             ScDBData* pNoNameData = (*pColl)[nNoNameIndex];
400 
401             SCCOL nRangeX1;
402             SCROW nRangeY1;
403             SCCOL nRangeX2;
404             SCROW nRangeY2;
405             SCTAB nRangeTab;
406             pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
407             pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
408 
409             *pNoNameData = *pAutoDBRange;
410 
411             if ( pAutoDBRange->HasAutoFilter() )
412             {
413                 // restore AutoFilter buttons
414                 pAutoDBRange->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
415                 pDoc->ApplyFlagsTab( nRangeX1, nRangeY1, nRangeX2, nRangeY1, nRangeTab, SC_MF_AUTO );
416                 pDocShell->PostPaint( nRangeX1, nRangeY1, nRangeTab, nRangeX2, nRangeY1, nRangeTab, PAINT_GRID );
417             }
418         }
419     }
420 }
421 
422 void ScDBFuncUndo::BeginRedo()
423 {
424     RedoSdrUndoAction( mpDrawUndo );
425     if ( pAutoDBRange )
426     {
427         // move the database range to this function's position again (see ScDocShell::GetDBData)
428 
429         sal_uInt16 nNoNameIndex;
430         ScDocument* pDoc = pDocShell->GetDocument();
431         ScDBCollection* pColl = pDoc->GetDBCollection();
432         if ( pColl->SearchName( ScGlobal::GetRscString( STR_DB_NONAME ), nNoNameIndex ) )
433         {
434             ScDBData* pNoNameData = (*pColl)[nNoNameIndex];
435 
436             SCCOL nRangeX1;
437             SCROW nRangeY1;
438             SCCOL nRangeX2;
439             SCROW nRangeY2;
440             SCTAB nRangeTab;
441             pNoNameData->GetArea( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
442             pDocShell->DBAreaDeleted( nRangeTab, nRangeX1, nRangeY1, nRangeX2, nRangeY2 );
443 
444             pNoNameData->SetSortParam( ScSortParam() );
445             pNoNameData->SetQueryParam( ScQueryParam() );
446             pNoNameData->SetSubTotalParam( ScSubTotalParam() );
447 
448             pNoNameData->SetArea( aOriginalRange.aStart.Tab(),
449                                   aOriginalRange.aStart.Col(), aOriginalRange.aStart.Row(),
450                                   aOriginalRange.aEnd.Col(), aOriginalRange.aEnd.Row() );
451 
452             pNoNameData->SetByRow( sal_True );
453             pNoNameData->SetAutoFilter( sal_False );
454             // header is always set with the operation in redo
455         }
456     }
457 
458     ScSimpleUndo::BeginRedo();
459 }
460 
461 void ScDBFuncUndo::EndRedo()
462 {
463     ScSimpleUndo::EndRedo();
464 }
465 
466 // -----------------------------------------------------------------------
467 
468 ScUndoWrapper::ScUndoWrapper( SfxUndoAction* pUndo ) :
469     pWrappedUndo( pUndo )
470 {
471 }
472 
473 ScUndoWrapper::~ScUndoWrapper()
474 {
475     delete pWrappedUndo;
476 }
477 
478 void ScUndoWrapper::ForgetWrappedUndo()
479 {
480     pWrappedUndo = NULL;    // don't delete in dtor - pointer must be stored outside
481 }
482 
483 String ScUndoWrapper::GetComment() const
484 {
485     if (pWrappedUndo)
486         return pWrappedUndo->GetComment();
487     else
488         return String();
489 }
490 
491 String ScUndoWrapper::GetRepeatComment(SfxRepeatTarget& rTarget) const
492 {
493     if (pWrappedUndo)
494         return pWrappedUndo->GetRepeatComment(rTarget);
495     else
496         return String();
497 }
498 
499 sal_uInt16 ScUndoWrapper::GetId() const
500 {
501     if (pWrappedUndo)
502         return pWrappedUndo->GetId();
503     else
504         return 0;
505 }
506 
507 sal_Bool ScUndoWrapper::IsLinked()
508 {
509     if (pWrappedUndo)
510         return pWrappedUndo->IsLinked();
511     else
512         return sal_False;
513 }
514 
515 void ScUndoWrapper::SetLinked( sal_Bool bIsLinked )
516 {
517     if (pWrappedUndo)
518         pWrappedUndo->SetLinked(bIsLinked);
519 }
520 
521 sal_Bool ScUndoWrapper::Merge( SfxUndoAction* pNextAction )
522 {
523     if (pWrappedUndo)
524         return pWrappedUndo->Merge(pNextAction);
525     else
526         return sal_False;
527 }
528 
529 void ScUndoWrapper::Undo()
530 {
531     if (pWrappedUndo)
532         pWrappedUndo->Undo();
533 }
534 
535 void ScUndoWrapper::Redo()
536 {
537     if (pWrappedUndo)
538         pWrappedUndo->Redo();
539 }
540 
541 void ScUndoWrapper::Repeat(SfxRepeatTarget& rTarget)
542 {
543     if (pWrappedUndo)
544         pWrappedUndo->Repeat(rTarget);
545 }
546 
547 sal_Bool ScUndoWrapper::CanRepeat(SfxRepeatTarget& rTarget) const
548 {
549     if (pWrappedUndo)
550         return pWrappedUndo->CanRepeat(rTarget);
551     else
552         return sal_False;
553 }
554 
555 
556