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