xref: /AOO41X/main/sc/source/ui/undo/undobase.cxx (revision d3e0dd8eb215533c15e891ee35bd141abe9397ee)
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