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