1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <scitems.hxx>
22 #include <vcl/virdev.hxx>
23 #include <editeng/boxitem.hxx>
24 #include <sfx2/app.hxx>
25 #include <comphelper/lok.hxx>
26 #include <osl/diagnose.h>
28 #include <undoblk.hxx>
29 #include <undoutil.hxx>
30 #include <document.hxx>
31 #include <patattr.hxx>
33 #include <tabvwsh.hxx>
34 #include <rangenam.hxx>
35 #include <rangeutl.hxx>
36 #include <stlpool.hxx>
37 #include <stlsheet.hxx>
38 #include <globstr.hrc>
39 #include <scresid.hxx>
42 #include <docpool.hxx>
43 #include <docfunc.hxx>
45 #include <chgtrack.hxx>
46 #include <transobj.hxx>
47 #include <refundo.hxx>
48 #include <undoolk.hxx>
49 #include <clipparam.hxx>
50 #include <rowheightcontext.hxx>
51 #include <refupdatecontext.hxx>
52 #include <validat.hxx>
53 #include <gridwin.hxx>
54 #include <columnspanset.hxx>
60 /*A*/ // SetOptimalHeight on Document, if no View
61 /*B*/ // linked sheets
65 ScUndoInsertCells::ScUndoInsertCells( ScDocShell
* pNewDocShell
,
66 const ScRange
& rRange
,
67 SCTAB nNewCount
, std::unique_ptr
<SCTAB
[]> pNewTabs
, std::unique_ptr
<SCTAB
[]> pNewScenarios
,
68 InsCellCmd eNewCmd
, ScDocumentUniquePtr pUndoDocument
, std::unique_ptr
<ScRefUndoData
> pRefData
,
69 bool bNewPartOfPaste
) :
70 ScMoveUndo( pNewDocShell
, std::move(pUndoDocument
), std::move(pRefData
) ),
73 pTabs( std::move(pNewTabs
) ),
74 pScenarios( std::move(pNewScenarios
) ),
76 bPartOfPaste( bNewPartOfPaste
)
78 ScDocument
& rDoc
= pDocShell
->GetDocument();
79 if (eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
) // whole row?
81 aEffRange
.aStart
.SetCol(0);
82 aEffRange
.aEnd
.SetCol(rDoc
.MaxCol());
85 if (eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
) // whole column?
87 aEffRange
.aStart
.SetRow(0);
88 aEffRange
.aEnd
.SetRow(rDoc
.MaxRow());
94 ScUndoInsertCells::~ScUndoInsertCells()
98 OUString
ScUndoInsertCells::GetComment() const
100 return ScResId( pPasteUndo
? STR_UNDO_PASTE
: STR_UNDO_INSERTCELLS
);
103 bool ScUndoInsertCells::Merge( SfxUndoAction
* pNextAction
)
105 // If a paste undo action has already been added, append (detective) action there.
107 return pPasteUndo
->Merge( pNextAction
);
110 if ( auto pWrapper
= dynamic_cast<ScUndoWrapper
*>( pNextAction
) )
112 if (dynamic_cast<const ScUndoPaste
*>(pWrapper
->GetWrappedUndo()))
114 // Store paste action if this is part of paste with inserting cells.
115 // A list action isn't used because Repeat wouldn't work (insert wrong cells).
117 // Pass ownership of the wrapped SfxUndoAction* to pPasteUndO
118 pPasteUndo
= pWrapper
->ReleaseWrappedUndo();
123 // Call base class for detective handling
124 return ScMoveUndo::Merge( pNextAction
);
127 void ScUndoInsertCells::SetChangeTrack()
129 ScChangeTrack
* pChangeTrack
= pDocShell
->GetDocument().GetChangeTrack();
132 pChangeTrack
->AppendInsert( aEffRange
);
133 nEndChangeAction
= pChangeTrack
->GetActionMax();
136 nEndChangeAction
= 0;
139 void ScUndoInsertCells::DoChange( const bool bUndo
)
141 ScDocument
& rDoc
= pDocShell
->GetDocument();
146 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
148 pChangeTrack
->Undo( nEndChangeAction
, nEndChangeAction
);
153 // refresh of merged cells has to be after inserting/deleting
155 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
158 case INS_INSROWS_BEFORE
:
159 case INS_INSROWS_AFTER
:
161 for( i
=0; i
<nCount
; i
++ )
165 rDoc
.DeleteRow( aEffRange
.aStart
.Col(), pTabs
[i
], aEffRange
.aEnd
.Col(), pTabs
[i
]+pScenarios
[i
],
166 aEffRange
.aStart
.Row(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Row()-aEffRange
.aStart
.Row()+1));
168 rDoc
.InsertRow( aEffRange
.aStart
.Col(), pTabs
[i
], aEffRange
.aEnd
.Col(), pTabs
[i
]+pScenarios
[i
],
169 aEffRange
.aStart
.Row(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Row()-aEffRange
.aStart
.Row()+1));
173 const tools::Long nSign
= bUndo
? -1 : 1;
174 pViewShell
->OnLOKInsertDeleteRow(aEffRange
.aStart
.Row(), nSign
* (aEffRange
.aEnd
.Row()-aEffRange
.aStart
.Row()+1));
178 case INS_INSCOLS_BEFORE
:
179 case INS_INSCOLS_AFTER
:
181 for( i
=0; i
<nCount
; i
++ )
184 rDoc
.DeleteCol( aEffRange
.aStart
.Row(), pTabs
[i
], aEffRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
],
185 aEffRange
.aStart
.Col(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Col()-aEffRange
.aStart
.Col()+1));
187 rDoc
.InsertCol( aEffRange
.aStart
.Row(), pTabs
[i
], aEffRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
],
188 aEffRange
.aStart
.Col(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Col()-aEffRange
.aStart
.Col()+1));
192 const tools::Long nSign
= bUndo
? -1 : 1;
193 pViewShell
->OnLOKInsertDeleteColumn(aEffRange
.aStart
.Col(), nSign
* (aEffRange
.aEnd
.Col()-aEffRange
.aStart
.Col()+1));
199 // added to avoid warnings
203 ScRange
aWorkRange( aEffRange
);
204 if ( eCmd
== INS_CELLSRIGHT
) // only "shift right" requires refresh of the moved area
205 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol());
206 for( i
=0; i
<nCount
; i
++ )
208 if ( rDoc
.HasAttrib( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(), pTabs
[i
],
209 aWorkRange
.aEnd
.Col(), aWorkRange
.aEnd
.Row(), pTabs
[i
], HasAttrFlags::Merged
) )
211 SCCOL nEndCol
= aWorkRange
.aEnd
.Col();
212 SCROW nEndRow
= aWorkRange
.aEnd
.Row();
213 rDoc
.ExtendMerge( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(), nEndCol
, nEndRow
, pTabs
[i
], true );
217 // Undo for displaced attributes?
219 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
223 case INS_INSROWS_BEFORE
:
224 case INS_INSROWS_AFTER
:
225 nPaint
|= PaintPartFlags::Left
;
226 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
229 for( i
=0; i
<nCount
; i
++ )
231 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
232 if ( pDocShell
->AdjustRowHeight( aWorkRange
.aStart
.Row(), aWorkRange
.aEnd
.Row(), pTabs
[i
] ))
234 aWorkRange
.aStart
.SetCol(0);
235 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol());
236 nPaint
|= PaintPartFlags::Left
;
240 case INS_INSCOLS_BEFORE
:
241 case INS_INSCOLS_AFTER
:
242 nPaint
|= PaintPartFlags::Top
; // top bar
245 for( i
=0; i
<nCount
; i
++ )
247 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol()); // to the far right
248 if ( pDocShell
->AdjustRowHeight( aWorkRange
.aStart
.Row(), aWorkRange
.aEnd
.Row(), pTabs
[i
]) )
249 { // AdjustDraw does not paint PaintPartFlags::Top,
250 aWorkRange
.aStart
.SetCol(0); // thus solved like this
251 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
252 nPaint
|= PaintPartFlags::Left
;
258 // added to avoid warnings
262 for( i
=0; i
<nCount
; i
++ )
264 pDocShell
->PostPaint( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(), pTabs
[i
],
265 aWorkRange
.aEnd
.Col(), aWorkRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
], nPaint
);
267 pDocShell
->PostDataChanged();
271 pViewShell
->CellContentChanged();
273 if (!comphelper::LibreOfficeKit::isActive())
276 SCTAB nTab
= pViewShell
->GetViewData().GetTabNo();
277 bool bColsAffected
= (eCmd
== INS_INSCOLS_BEFORE
|| eCmd
== INS_INSCOLS_AFTER
|| eCmd
== INS_CELLSRIGHT
);
278 bool bRowsAffected
= (eCmd
== INS_INSROWS_BEFORE
|| eCmd
== INS_INSROWS_AFTER
|| eCmd
== INS_CELLSDOWN
);
281 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell
, COLUMN_HEADER
, nTab
);
284 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell
, ROW_HEADER
, nTab
);
286 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
288 bColsAffected
, bRowsAffected
,
289 true /* bSizes*/, true /* bHidden */, true /* bFiltered */,
290 true /* bGroups */, nTab
);
293 void ScUndoInsertCells::Undo()
296 pPasteUndo
->Undo(); // undo paste first
298 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important due to TrackFormulas in UpdateReference
303 ScDocument
& rDoc
= pDocShell
->GetDocument();
304 for (SCTAB i
= 0; i
< nCount
; ++i
)
305 rDoc
.SetDrawPageSize(pTabs
[i
]);
308 void ScUndoInsertCells::Redo()
310 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important due to TrackFormulas in UpdateReference
316 pPasteUndo
->Redo(); // redo paste last
318 ScDocument
& rDoc
= pDocShell
->GetDocument();
319 for (SCTAB i
= 0; i
< nCount
; ++i
)
320 rDoc
.SetDrawPageSize(pTabs
[i
]);
323 void ScUndoInsertCells::Repeat(SfxRepeatTarget
& rTarget
)
325 if (dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr)
329 // Repeat for paste with inserting cells is handled completely
330 // by the Paste undo action
332 pPasteUndo
->Repeat( rTarget
);
335 static_cast<ScTabViewTarget
&>(rTarget
).GetViewShell()->InsertCells( eCmd
);
339 bool ScUndoInsertCells::CanRepeat(SfxRepeatTarget
& rTarget
) const
341 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
344 ScUndoDeleteCells::ScUndoDeleteCells( ScDocShell
* pNewDocShell
,
345 const ScRange
& rRange
,
346 SCTAB nNewCount
, std::unique_ptr
<SCTAB
[]> pNewTabs
, std::unique_ptr
<SCTAB
[]> pNewScenarios
,
347 DelCellCmd eNewCmd
, ScDocumentUniquePtr pUndoDocument
, std::unique_ptr
<ScRefUndoData
> pRefData
) :
348 ScMoveUndo( pNewDocShell
, std::move(pUndoDocument
), std::move(pRefData
) ),
351 pTabs( std::move(pNewTabs
) ),
352 pScenarios( std::move(pNewScenarios
) ),
355 ScDocument
& rDoc
= pDocShell
->GetDocument();
356 if (eCmd
== DelCellCmd::Rows
) // whole row?
358 aEffRange
.aStart
.SetCol(0);
359 aEffRange
.aEnd
.SetCol(rDoc
.MaxCol());
362 if (eCmd
== DelCellCmd::Cols
) // whole column?
364 aEffRange
.aStart
.SetRow(0);
365 aEffRange
.aEnd
.SetRow(rDoc
.MaxRow());
371 ScUndoDeleteCells::~ScUndoDeleteCells()
375 OUString
ScUndoDeleteCells::GetComment() const
377 return ScResId( STR_UNDO_DELETECELLS
); // "Delete"
380 void ScUndoDeleteCells::SetChangeTrack()
382 ScChangeTrack
* pChangeTrack
= pDocShell
->GetDocument().GetChangeTrack();
384 pChangeTrack
->AppendDeleteRange( aEffRange
, pRefUndoDoc
.get(),
385 nStartChangeAction
, nEndChangeAction
);
387 nStartChangeAction
= nEndChangeAction
= 0;
390 void ScUndoDeleteCells::DoChange( const bool bUndo
)
392 ScDocument
& rDoc
= pDocShell
->GetDocument();
397 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
399 pChangeTrack
->Undo( nStartChangeAction
, nEndChangeAction
);
404 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
408 case DelCellCmd::Rows
:
409 case DelCellCmd::CellsUp
:
410 for( i
=0; i
<nCount
; i
++ )
413 rDoc
.InsertRow( aEffRange
.aStart
.Col(), pTabs
[i
], aEffRange
.aEnd
.Col(), pTabs
[i
]+pScenarios
[i
],
414 aEffRange
.aStart
.Row(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Row()-aEffRange
.aStart
.Row()+1));
416 rDoc
.DeleteRow( aEffRange
.aStart
.Col(), pTabs
[i
], aEffRange
.aEnd
.Col(), pTabs
[i
]+pScenarios
[i
],
417 aEffRange
.aStart
.Row(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Row()-aEffRange
.aStart
.Row()+1));
421 const tools::Long nSign
= bUndo
? 1 : -1;
422 pViewShell
->OnLOKInsertDeleteRow(aEffRange
.aStart
.Row(), nSign
* (aEffRange
.aEnd
.Row()-aEffRange
.aStart
.Row()+1));
426 case DelCellCmd::Cols
:
427 case DelCellCmd::CellsLeft
:
428 for( i
=0; i
<nCount
; i
++ )
431 rDoc
.InsertCol( aEffRange
.aStart
.Row(), pTabs
[i
], aEffRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
],
432 aEffRange
.aStart
.Col(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Col()-aEffRange
.aStart
.Col()+1));
434 rDoc
.DeleteCol( aEffRange
.aStart
.Row(), pTabs
[i
], aEffRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
],
435 aEffRange
.aStart
.Col(), static_cast<SCSIZE
>(aEffRange
.aEnd
.Col()-aEffRange
.aStart
.Col()+1));
439 const tools::Long nSign
= bUndo
? 1 : -1;
440 pViewShell
->OnLOKInsertDeleteColumn(aEffRange
.aStart
.Col(), nSign
* (aEffRange
.aEnd
.Col()-aEffRange
.aStart
.Col()+1));
446 // added to avoid warnings
450 // if Undo, restore references
451 for( i
=0; i
<nCount
&& bUndo
; i
++ )
453 pRefUndoDoc
->CopyToDocument(aEffRange
.aStart
.Col(), aEffRange
.aStart
.Row(), pTabs
[i
], aEffRange
.aEnd
.Col(), aEffRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
],
454 InsertDeleteFlags::ALL
| InsertDeleteFlags::NOCAPTIONS
, false, rDoc
);
457 ScRange
aWorkRange( aEffRange
);
458 if ( eCmd
== DelCellCmd::CellsLeft
) // only "shift left" requires refresh of the moved area
459 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol());
461 for( i
=0; i
<nCount
; i
++ )
463 if ( rDoc
.HasAttrib( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(), pTabs
[i
],
464 aWorkRange
.aEnd
.Col(), aWorkRange
.aEnd
.Row(), pTabs
[i
], HasAttrFlags::Merged
| HasAttrFlags::Overlapped
) )
466 // #i51445# old merge flag attributes must be deleted also for single cells,
467 // not only for whole columns/rows
471 if ( eCmd
==DelCellCmd::Cols
|| eCmd
==DelCellCmd::CellsLeft
)
472 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol());
473 if ( eCmd
==DelCellCmd::Rows
|| eCmd
==DelCellCmd::CellsUp
)
474 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
475 ScMarkData
aMarkData(rDoc
.GetSheetLimits());
476 aMarkData
.SelectOneTable( aWorkRange
.aStart
.Tab() );
477 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
478 aPattern
.GetItemSet().Put( ScMergeFlagAttr() );
479 rDoc
.ApplyPatternArea( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(),
480 aWorkRange
.aEnd
.Col(), aWorkRange
.aEnd
.Row(),
481 aMarkData
, aPattern
);
484 SCCOL nEndCol
= aWorkRange
.aEnd
.Col();
485 SCROW nEndRow
= aWorkRange
.aEnd
.Row();
486 rDoc
.ExtendMerge( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(), nEndCol
, nEndRow
, pTabs
[i
], true );
491 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
494 case DelCellCmd::Rows
:
495 nPaint
|= PaintPartFlags::Left
;
496 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
498 case DelCellCmd::CellsUp
:
499 for( i
=0; i
<nCount
; i
++ )
501 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
502 if ( pDocShell
->AdjustRowHeight( aWorkRange
.aStart
.Row(), aWorkRange
.aEnd
.Row(), pTabs
[i
] ))
504 aWorkRange
.aStart
.SetCol(0);
505 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol());
506 nPaint
|= PaintPartFlags::Left
;
510 case DelCellCmd::Cols
:
511 nPaint
|= PaintPartFlags::Top
; // top bar
513 case DelCellCmd::CellsLeft
:
514 for( i
=0; i
<nCount
; i
++ )
516 aWorkRange
.aEnd
.SetCol(rDoc
.MaxCol()); // to the far right
517 if ( pDocShell
->AdjustRowHeight( aWorkRange
.aStart
.Row(), aWorkRange
.aEnd
.Row(), pTabs
[i
] ) )
519 aWorkRange
.aStart
.SetCol(0);
520 aWorkRange
.aEnd
.SetRow(rDoc
.MaxRow());
521 nPaint
|= PaintPartFlags::Left
;
527 // added to avoid warnings
531 for( i
=0; i
<nCount
; i
++ )
533 pDocShell
->PostPaint( aWorkRange
.aStart
.Col(), aWorkRange
.aStart
.Row(), pTabs
[i
],
534 aWorkRange
.aEnd
.Col(), aWorkRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
], nPaint
, SC_PF_LINES
);
536 // Selection not until EndUndo
538 pDocShell
->PostDataChanged();
539 // CellContentChanged comes with the selection
544 if (!comphelper::LibreOfficeKit::isActive())
547 SCTAB nTab
= pViewShell
->GetViewData().GetTabNo();
548 bool bColsAffected
= (eCmd
== DelCellCmd::Cols
|| eCmd
== DelCellCmd::CellsLeft
);
549 bool bRowsAffected
= (eCmd
== DelCellCmd::Rows
|| eCmd
== DelCellCmd::CellsUp
);
552 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell
, COLUMN_HEADER
, nTab
);
555 ScTabViewShell::notifyAllViewsHeaderInvalidation(pViewShell
, ROW_HEADER
, nTab
);
557 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
559 bColsAffected
, bRowsAffected
,
560 true /* bSizes*/, true /* bHidden */, true /* bFiltered */,
561 true /* bGroups */, nTab
);
565 void ScUndoDeleteCells::Undo()
567 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference
572 ScDocument
& rDoc
= pDocShell
->GetDocument();
574 // Now that DBData have been restored in ScMoveUndo::EndUndo() via its
575 // pRefUndoDoc we can apply the AutoFilter buttons.
576 // Add one row for cases undoing deletion right above a cut AutoFilter
577 // range so the buttons are removed.
578 SCROW nRefreshEndRow
= std::min
<SCROW
>( aEffRange
.aEnd
.Row() + 1, rDoc
.MaxRow());
579 for (SCTAB i
=0; i
< nCount
; ++i
)
581 rDoc
.RefreshAutoFilter( aEffRange
.aStart
.Col(), aEffRange
.aStart
.Row(),
582 aEffRange
.aEnd
.Col(), nRefreshEndRow
, pTabs
[i
]);
585 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
587 // Selection not until EndUndo
588 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
591 for( SCTAB i
=0; i
<nCount
; i
++ )
593 pViewShell
->MarkRange( ScRange(aEffRange
.aStart
.Col(), aEffRange
.aStart
.Row(), pTabs
[i
], aEffRange
.aEnd
.Col(), aEffRange
.aEnd
.Row(), pTabs
[i
]+pScenarios
[i
]) );
597 for (SCTAB i
= 0; i
< nCount
; ++i
)
598 rDoc
.SetDrawPageSize(pTabs
[i
]);
601 void ScUndoDeleteCells::Redo()
603 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference
608 ScDocument
& rDoc
= pDocShell
->GetDocument();
610 for (SCTAB i
=0; i
< nCount
; ++i
)
612 rDoc
.RefreshAutoFilter( aEffRange
.aStart
.Col(), aEffRange
.aStart
.Row(),
613 aEffRange
.aEnd
.Col(), aEffRange
.aEnd
.Row(), pTabs
[i
]);
616 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
618 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
620 pViewShell
->DoneBlockMode(); // current way
622 for (SCTAB i
= 0; i
< nCount
; ++i
)
623 rDoc
.SetDrawPageSize(pTabs
[i
]);
626 void ScUndoDeleteCells::Repeat(SfxRepeatTarget
& rTarget
)
628 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
) )
629 pViewTarget
->GetViewShell()->DeleteCells( eCmd
);
632 bool ScUndoDeleteCells::CanRepeat(SfxRepeatTarget
& rTarget
) const
634 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
637 // delete cells in multiselection
638 ScUndoDeleteMulti::ScUndoDeleteMulti(
639 ScDocShell
* pNewDocShell
,
640 bool bNewRows
, bool bNeedsRefresh
, SCTAB nNewTab
,
641 std::vector
<sc::ColRowSpan
>&& rSpans
,
642 ScDocumentUniquePtr pUndoDocument
, std::unique_ptr
<ScRefUndoData
> pRefData
) :
643 ScMoveUndo( pNewDocShell
, std::move(pUndoDocument
), std::move(pRefData
) ),
645 mbRefresh(bNeedsRefresh
),
647 maSpans(std::move(rSpans
))
652 ScUndoDeleteMulti::~ScUndoDeleteMulti()
656 OUString
ScUndoDeleteMulti::GetComment() const
658 return ScResId( STR_UNDO_DELETECELLS
); // like DeleteCells
661 void ScUndoDeleteMulti::DoChange() const
665 PaintPartFlags nPaint
;
666 ScDocument
& rDoc
= pDocShell
->GetDocument();
670 nStartRow
= static_cast<SCROW
>(maSpans
[0].mnStart
);
671 nPaint
= PaintPartFlags::Grid
| PaintPartFlags::Left
;
675 nStartCol
= static_cast<SCCOL
>(maSpans
[0].mnStart
);
677 nPaint
= PaintPartFlags::Grid
| PaintPartFlags::Top
;
682 SCCOL nEndCol
= rDoc
.MaxCol();
683 SCROW nEndRow
= rDoc
.MaxRow();
684 rDoc
.RemoveFlagsTab( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
, ScMF::Hor
| ScMF::Ver
);
685 rDoc
.ExtendMerge( nStartCol
, nStartRow
, nEndCol
, nEndRow
, nTab
, true );
688 pDocShell
->PostPaint( nStartCol
, nStartRow
, nTab
, rDoc
.MaxCol(), rDoc
.MaxRow(), nTab
, nPaint
);
689 pDocShell
->PostDataChanged();
690 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
692 pViewShell
->CellContentChanged();
697 void ScUndoDeleteMulti::SetChangeTrack()
699 ScChangeTrack
* pChangeTrack
= pDocShell
->GetDocument().GetChangeTrack();
702 ScDocument
& rDoc
= pDocShell
->GetDocument();
703 nStartChangeAction
= pChangeTrack
->GetActionMax() + 1;
704 ScRange
aRange( 0, 0, nTab
, 0, 0, nTab
);
706 aRange
.aEnd
.SetCol( rDoc
.MaxCol() );
708 aRange
.aEnd
.SetRow( rDoc
.MaxRow() );
710 std::vector
<sc::ColRowSpan
>::const_reverse_iterator ri
= maSpans
.rbegin(), riEnd
= maSpans
.rend();
711 for (; ri
!= riEnd
; ++ri
)
713 SCCOLROW nEnd
= ri
->mnEnd
;
714 SCCOLROW nStart
= ri
->mnStart
;
717 aRange
.aStart
.SetRow( nStart
);
718 aRange
.aEnd
.SetRow( nEnd
);
722 aRange
.aStart
.SetCol( static_cast<SCCOL
>(nStart
) );
723 aRange
.aEnd
.SetCol( static_cast<SCCOL
>(nEnd
) );
725 sal_uLong nDummyStart
;
726 pChangeTrack
->AppendDeleteRange( aRange
, pRefUndoDoc
.get(),
727 nDummyStart
, nEndChangeAction
);
731 nStartChangeAction
= nEndChangeAction
= 0;
734 void ScUndoDeleteMulti::Undo()
736 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference
739 ScDocument
& rDoc
= pDocShell
->GetDocument();
741 // reverse delete -> forward insert
742 for (const auto& rSpan
: maSpans
)
744 SCCOLROW nStart
= rSpan
.mnStart
;
745 SCCOLROW nEnd
= rSpan
.mnEnd
;
747 rDoc
.InsertRow( 0,nTab
, rDoc
.MaxCol(),nTab
, nStart
,static_cast<SCSIZE
>(nEnd
-nStart
+1) );
749 rDoc
.InsertCol( 0,nTab
, rDoc
.MaxRow(),nTab
, static_cast<SCCOL
>(nStart
), static_cast<SCSIZE
>(nEnd
-nStart
+1) );
752 for (const auto& rSpan
: maSpans
)
754 SCCOLROW nStart
= rSpan
.mnStart
;
755 SCCOLROW nEnd
= rSpan
.mnEnd
;
757 pRefUndoDoc
->CopyToDocument(0, nStart
, nTab
, rDoc
.MaxCol(), nEnd
, nTab
, InsertDeleteFlags::ALL
, false, rDoc
);
759 pRefUndoDoc
->CopyToDocument(static_cast<SCCOL
>(nStart
),0,nTab
,
760 static_cast<SCCOL
>(nEnd
), rDoc
.MaxRow(), nTab
, InsertDeleteFlags::ALL
, false, rDoc
);
763 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
765 pChangeTrack
->Undo( nStartChangeAction
, nEndChangeAction
);
769 //! redrawing the selection is not possible at the moment
770 //! since no data for selection exist
773 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
776 void ScUndoDeleteMulti::Redo()
778 weld::WaitObject
aWait( ScDocShell::GetActiveDialogParent() ); // important because of TrackFormulas in UpdateReference
781 ScDocument
& rDoc
= pDocShell
->GetDocument();
784 std::vector
<sc::ColRowSpan
>::const_reverse_iterator ri
= maSpans
.rbegin(), riEnd
= maSpans
.rend();
785 for (; ri
!= riEnd
; ++ri
)
787 SCCOLROW nEnd
= ri
->mnEnd
;
788 SCCOLROW nStart
= ri
->mnStart
;
790 rDoc
.DeleteRow( 0,nTab
, rDoc
.MaxCol(),nTab
, nStart
,static_cast<SCSIZE
>(nEnd
-nStart
+1) );
792 rDoc
.DeleteCol( 0,nTab
, rDoc
.MaxRow(),nTab
, static_cast<SCCOL
>(nStart
), static_cast<SCSIZE
>(nEnd
-nStart
+1) );
800 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
803 void ScUndoDeleteMulti::Repeat(SfxRepeatTarget
& rTarget
)
805 // if single selection
806 if (auto pTabViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
807 pTabViewTarget
->GetViewShell()->DeleteCells( DelCellCmd::Rows
);
810 bool ScUndoDeleteMulti::CanRepeat(SfxRepeatTarget
& rTarget
) const
812 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
815 ScUndoCut::ScUndoCut(ScDocShell
* pNewDocShell
, const ScRange
& aRange
, const ScAddress
& aOldEnd
,
816 const ScMarkData
& rMark
, ScDocumentUniquePtr pNewUndoDoc
)
817 : ScBlockUndo(pNewDocShell
, ScRange(aRange
.aStart
, aOldEnd
), SC_UNDO_AUTOHEIGHT
)
819 , pUndoDoc(std::move(pNewUndoDoc
))
820 , aExtendedRange(aRange
)
825 ScUndoCut::~ScUndoCut()
829 OUString
ScUndoCut::GetComment() const
831 return ScResId( STR_UNDO_CUT
); // "cut"
834 void ScUndoCut::SetChangeTrack()
836 ScChangeTrack
* pChangeTrack
= pDocShell
->GetDocument().GetChangeTrack();
838 pChangeTrack
->AppendContentRange( aBlockRange
, pUndoDoc
.get(),
839 nStartChangeAction
, nEndChangeAction
, SC_CACM_CUT
);
841 nStartChangeAction
= nEndChangeAction
= 0;
844 void ScUndoCut::DoChange( const bool bUndo
)
846 ScDocument
& rDoc
= pDocShell
->GetDocument();
847 sal_uInt16 nExtFlags
= 0;
849 // do not undo/redo objects and note captions, they are handled via drawing undo
850 InsertDeleteFlags nUndoFlags
= (InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
) | InsertDeleteFlags::NOCAPTIONS
;
852 if (bUndo
) // only for Undo
854 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
855 SCTAB nTabCount
= rDoc
.GetTableCount();
856 ScRange aCopyRange
= aExtendedRange
;
857 aCopyRange
.aStart
.SetTab(0);
858 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
859 pUndoDoc
->CopyToDocument(aCopyRange
, nUndoFlags
, false, rDoc
);
860 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
862 pChangeTrack
->Undo( nStartChangeAction
, nEndChangeAction
);
864 BroadcastChanges(aCopyRange
);
866 else // only for Redo
868 pDocShell
->UpdatePaintExt( nExtFlags
, aExtendedRange
);
869 rDoc
.DeleteArea( aBlockRange
.aStart
.Col(), aBlockRange
.aStart
.Row(),
870 aBlockRange
.aEnd
.Col(), aBlockRange
.aEnd
.Row(), aMarkData
, nUndoFlags
);
874 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
875 if ( !( pViewShell
&& pViewShell
->AdjustBlockHeight() ) )
876 /*A*/ pDocShell
->PostPaint( aExtendedRange
, PaintPartFlags::Grid
, nExtFlags
);
878 if ( !bUndo
) // draw redo after updating row heights
879 RedoSdrUndoAction( pDrawUndo
.get() ); //! include in ScBlockUndo?
881 pDocShell
->PostDataChanged();
883 pViewShell
->CellContentChanged();
886 void ScUndoCut::Undo()
893 void ScUndoCut::Redo()
896 ScDocument
& rDoc
= pDocShell
->GetDocument();
897 EnableDrawAdjust( &rDoc
, false ); //! include in ScBlockUndo?
899 EnableDrawAdjust( &rDoc
, true ); //! include in ScBlockUndo?
903 void ScUndoCut::Repeat(SfxRepeatTarget
& rTarget
)
905 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
906 pViewTarget
->GetViewShell()->CutToClip();
909 bool ScUndoCut::CanRepeat(SfxRepeatTarget
& rTarget
) const
911 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
914 ScUndoPaste::ScUndoPaste( ScDocShell
* pNewDocShell
, const ScRangeList
& rRanges
,
915 const ScMarkData
& rMark
,
916 ScDocumentUniquePtr pNewUndoDoc
, ScDocumentUniquePtr pNewRedoDoc
,
917 InsertDeleteFlags nNewFlags
,
918 std::unique_ptr
<ScRefUndoData
> pRefData
,
919 bool bRedoIsFilled
, const ScUndoPasteOptions
* pOptions
) :
920 ScMultiBlockUndo( pNewDocShell
, rRanges
),
922 pUndoDoc( std::move(pNewUndoDoc
) ),
923 pRedoDoc( std::move(pNewRedoDoc
) ),
925 pRefUndoData( std::move(pRefData
) ),
926 bRedoFilled( bRedoIsFilled
)
929 pRefUndoData
->DeleteUnchanged( &pDocShell
->GetDocument() );
932 aPasteOptions
= *pOptions
; // used only for Repeat
937 ScUndoPaste::~ScUndoPaste()
941 pRefUndoData
.reset();
942 pRefRedoData
.reset();
945 OUString
ScUndoPaste::GetComment() const
947 return ScResId( STR_UNDO_PASTE
); // "paste"
950 void ScUndoPaste::SetChangeTrack()
952 ScChangeTrack
* pChangeTrack
= pDocShell
->GetDocument().GetChangeTrack();
953 if ( pChangeTrack
&& (nFlags
& InsertDeleteFlags::CONTENTS
) )
955 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
957 pChangeTrack
->AppendContentRange(maBlockRanges
[i
], pUndoDoc
.get(),
958 nStartChangeAction
, nEndChangeAction
, SC_CACM_PASTE
);
962 nStartChangeAction
= nEndChangeAction
= 0;
965 void ScUndoPaste::DoChange(bool bUndo
)
967 ScDocument
& rDoc
= pDocShell
->GetDocument();
969 // RefUndoData for redo is created before first undo
970 // (with DeleteUnchanged after the DoUndo call)
971 bool bCreateRedoData
= ( bUndo
&& pRefUndoData
&& !pRefRedoData
);
972 if ( bCreateRedoData
)
973 pRefRedoData
.reset( new ScRefUndoData( &rDoc
) );
975 ScRefUndoData
* pWorkRefData
= bUndo
? pRefUndoData
.get() : pRefRedoData
.get();
977 // Always back-up either all or none of the content for Undo
978 InsertDeleteFlags nUndoFlags
= InsertDeleteFlags::NONE
;
979 if (nFlags
& InsertDeleteFlags::CONTENTS
)
980 nUndoFlags
|= InsertDeleteFlags::CONTENTS
;
981 if (nFlags
& InsertDeleteFlags::ATTRIB
)
982 nUndoFlags
|= InsertDeleteFlags::ATTRIB
;
984 // do not undo/redo objects and note captions, they are handled via drawing undo
985 nUndoFlags
&= ~InsertDeleteFlags::OBJECTS
;
986 nUndoFlags
|= InsertDeleteFlags::NOCAPTIONS
;
988 bool bPaintAll
= false;
990 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
992 SCTAB nTabCount
= rDoc
.GetTableCount();
993 if ( bUndo
&& !bRedoFilled
)
997 bool bColInfo
= true;
998 bool bRowInfo
= true;
999 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
1001 const ScRange
& r
= maBlockRanges
[i
];
1002 bColInfo
&= (r
.aStart
.Row() == 0 && r
.aEnd
.Row() == rDoc
.MaxRow());
1003 bRowInfo
&= (r
.aStart
.Col() == 0 && r
.aEnd
.Col() == rDoc
.MaxCol());
1004 if (!bColInfo
&& !bRowInfo
)
1008 pRedoDoc
.reset( new ScDocument( SCDOCMODE_UNDO
) );
1009 pRedoDoc
->InitUndoSelected( rDoc
, aMarkData
, bColInfo
, bRowInfo
);
1011 // read "redo" data from the document in the first undo
1012 // all sheets - CopyToDocument skips those that don't exist in pRedoDoc
1013 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
1015 ScRange aCopyRange
= maBlockRanges
[i
];
1016 aCopyRange
.aStart
.SetTab(0);
1017 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1018 rDoc
.CopyToDocument(aCopyRange
, nUndoFlags
, false, *pRedoDoc
);
1023 sal_uInt16 nExtFlags
= 0;
1024 pDocShell
->UpdatePaintExt(nExtFlags
, maBlockRanges
.Combine());
1026 rDoc
.ForgetNoteCaptions(maBlockRanges
, false);
1027 aMarkData
.MarkToMulti();
1028 rDoc
.DeleteSelection(nUndoFlags
, aMarkData
, false); // no broadcasting here
1029 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
1030 rDoc
.BroadcastCells(maBlockRanges
[i
], SfxHintId::ScDataChanged
);
1032 aMarkData
.MarkToSimple();
1034 SCTAB nFirstSelected
= aMarkData
.GetFirstSelected();
1036 if ( !bUndo
&& pRedoDoc
) // Redo: UndoToDocument before handling RefData
1038 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
1040 ScRange aRange
= maBlockRanges
[i
];
1041 aRange
.aStart
.SetTab(nFirstSelected
);
1042 aRange
.aEnd
.SetTab(nFirstSelected
);
1043 pRedoDoc
->UndoToDocument(aRange
, nUndoFlags
, false, rDoc
);
1044 for (const auto& rTab
: aMarkData
)
1046 if (rTab
>= nTabCount
)
1049 if (rTab
== nFirstSelected
)
1052 aRange
.aStart
.SetTab(rTab
);
1053 aRange
.aEnd
.SetTab(rTab
);
1054 pRedoDoc
->CopyToDocument(aRange
, nUndoFlags
, false, rDoc
);
1061 pWorkRefData
->DoUndo( &rDoc
, true ); // true = bSetChartRangeLists for SetChartListenerCollection
1062 if (!maBlockRanges
.empty() &&
1063 rDoc
.RefreshAutoFilter(0, 0, rDoc
.MaxCol(), rDoc
.MaxRow(), maBlockRanges
[0].aStart
.Tab()))
1067 if ( bCreateRedoData
&& pRefRedoData
)
1068 pRefRedoData
->DeleteUnchanged( &rDoc
);
1070 if (bUndo
) // Undo: UndoToDocument after handling RefData
1072 for (size_t i
= 0, n
= maBlockRanges
.size(); i
< n
; ++i
)
1074 ScRange aRange
= maBlockRanges
[i
];
1075 for (const auto& rTab
: aMarkData
)
1077 if (rTab
>= nTabCount
)
1079 aRange
.aStart
.SetTab(rTab
);
1080 aRange
.aEnd
.SetTab(rTab
);
1081 pUndoDoc
->UndoToDocument(aRange
, nUndoFlags
, false, rDoc
);
1088 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
1090 pChangeTrack
->Undo( nStartChangeAction
, nEndChangeAction
);
1095 ScRangeList
aDrawRanges(maBlockRanges
);
1096 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
1098 // For sheet geometry invalidation.
1099 bool bColsAffected
= false;
1100 bool bRowsAffected
= false;
1102 for (size_t i
= 0, n
= aDrawRanges
.size(); i
< n
; ++i
)
1104 ScRange
& rDrawRange
= aDrawRanges
[i
];
1105 rDoc
.ExtendMerge(rDrawRange
, true); // only needed for single sheet (text/rtf etc.)
1106 ScRangeList
aRangeList(rDrawRange
);
1107 ScMarkData
aData(rDoc
.GetSheetLimits(), aRangeList
);
1110 rDrawRange
.aStart
.SetCol(0);
1111 rDrawRange
.aStart
.SetRow(0);
1112 rDrawRange
.aEnd
.SetCol(rDoc
.MaxCol());
1113 rDrawRange
.aEnd
.SetRow(rDoc
.MaxRow());
1114 nPaint
|= PaintPartFlags::Top
| PaintPartFlags::Left
;
1116 pViewShell
->AdjustBlockHeight(false, &aData
);
1120 if (maBlockRanges
[i
].aStart
.Row() == 0 && maBlockRanges
[i
].aEnd
.Row() == rDoc
.MaxRow()) // whole column
1122 nPaint
|= PaintPartFlags::Top
;
1123 rDrawRange
.aEnd
.SetCol(rDoc
.MaxCol());
1124 bColsAffected
= true;
1126 if (maBlockRanges
[i
].aStart
.Col() == 0 && maBlockRanges
[i
].aEnd
.Col() == rDoc
.MaxCol()) // whole row
1128 nPaint
|= PaintPartFlags::Left
;
1129 rDrawRange
.aEnd
.SetRow(rDoc
.MaxRow());
1130 bRowsAffected
= true;
1132 if (pViewShell
&& pViewShell
->AdjustBlockHeight(false, &aData
))
1134 rDrawRange
.aStart
.SetCol(0);
1135 rDrawRange
.aStart
.SetRow(0);
1136 rDrawRange
.aEnd
.SetCol(rDoc
.MaxCol());
1137 rDrawRange
.aEnd
.SetRow(rDoc
.MaxRow());
1138 nPaint
|= PaintPartFlags::Left
;
1140 pDocShell
->UpdatePaintExt(nExtFlags
, rDrawRange
);
1144 if ( !bUndo
) // draw redo after updating row heights
1145 RedoSdrUndoAction(mpDrawUndo
.get());
1147 pDocShell
->PostPaint(aDrawRanges
, nPaint
, nExtFlags
);
1149 pDocShell
->PostDataChanged();
1153 pViewShell
->CellContentChanged();
1155 if (bColsAffected
|| bRowsAffected
)
1156 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
1158 bColsAffected
, bRowsAffected
,
1159 true /* bSizes*/, true /* bHidden */, true /* bFiltered */,
1160 true /* bGroups */, aDrawRanges
[0].aStart
.Tab());
1163 void ScUndoPaste::Undo()
1167 if (!maBlockRanges
.empty())
1168 ShowTable(maBlockRanges
.front());
1170 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
1173 void ScUndoPaste::Redo()
1176 ScDocument
& rDoc
= pDocShell
->GetDocument();
1177 EnableDrawAdjust( &rDoc
, false ); //! include in ScBlockUndo?
1179 EnableDrawAdjust( &rDoc
, true ); //! include in ScBlockUndo?
1181 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
1184 void ScUndoPaste::Repeat(SfxRepeatTarget
& rTarget
)
1186 auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
);
1190 ScTabViewShell
* pViewSh
= pViewTarget
->GetViewShell();
1191 // keep a reference in case the clipboard is changed during PasteFromClip
1192 const ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pViewSh
->GetViewData().GetActiveWin()));
1195 pViewSh
->PasteFromClip( nFlags
, pOwnClip
->GetDocument(),
1196 aPasteOptions
.nFunction
, aPasteOptions
.bSkipEmptyCells
, aPasteOptions
.bTranspose
,
1197 aPasteOptions
.bAsLink
, aPasteOptions
.eMoveMode
, InsertDeleteFlags::NONE
,
1198 true ); // allow warning dialog
1202 bool ScUndoPaste::CanRepeat(SfxRepeatTarget
& rTarget
) const
1204 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
1207 ScUndoDragDrop::ScUndoDragDrop( ScDocShell
* pNewDocShell
,
1208 const ScRange
& rRange
, const ScAddress
& aNewDestPos
, bool bNewCut
,
1209 ScDocumentUniquePtr pUndoDocument
, bool bScenario
) :
1210 ScMoveUndo( pNewDocShell
, std::move(pUndoDocument
), nullptr ),
1211 mnPaintExtFlags( 0 ),
1212 aSrcRange( rRange
),
1214 bKeepScenarioFlags( bScenario
)
1216 ScAddress
aDestEnd(aNewDestPos
);
1217 aDestEnd
.IncRow(aSrcRange
.aEnd
.Row() - aSrcRange
.aStart
.Row());
1218 aDestEnd
.IncCol(aSrcRange
.aEnd
.Col() - aSrcRange
.aStart
.Col());
1219 aDestEnd
.IncTab(aSrcRange
.aEnd
.Tab() - aSrcRange
.aStart
.Tab());
1221 bool bIncludeFiltered
= bCut
;
1222 if ( !bIncludeFiltered
)
1224 // find number of non-filtered rows
1225 SCROW nPastedCount
= pDocShell
->GetDocument().CountNonFilteredRows(
1226 aSrcRange
.aStart
.Row(), aSrcRange
.aEnd
.Row(), aSrcRange
.aStart
.Tab());
1228 if ( nPastedCount
== 0 )
1230 aDestEnd
.SetRow( aNewDestPos
.Row() + nPastedCount
- 1 );
1233 aDestRange
.aStart
= aNewDestPos
;
1234 aDestRange
.aEnd
= aDestEnd
;
1239 ScUndoDragDrop::~ScUndoDragDrop()
1243 OUString
ScUndoDragDrop::GetComment() const
1244 { // "Move" : "Copy"
1246 ScResId( STR_UNDO_MOVE
) :
1247 ScResId( STR_UNDO_COPY
);
1250 void ScUndoDragDrop::SetChangeTrack()
1252 ScChangeTrack
* pChangeTrack
= pDocShell
->GetDocument().GetChangeTrack();
1257 nStartChangeAction
= pChangeTrack
->GetActionMax() + 1;
1258 pChangeTrack
->AppendMove( aSrcRange
, aDestRange
, pRefUndoDoc
.get() );
1259 nEndChangeAction
= pChangeTrack
->GetActionMax();
1262 pChangeTrack
->AppendContentRange( aDestRange
, pRefUndoDoc
.get(),
1263 nStartChangeAction
, nEndChangeAction
);
1266 nStartChangeAction
= nEndChangeAction
= 0;
1269 void ScUndoDragDrop::PaintArea( ScRange aRange
, sal_uInt16 nExtFlags
) const
1271 PaintPartFlags nPaint
= PaintPartFlags::Grid
;
1272 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1273 ScDocument
& rDoc
= pDocShell
->GetDocument();
1277 ScopedVclPtrInstance
< VirtualDevice
> pVirtDev
;
1278 ScViewData
& rViewData
= pViewShell
->GetViewData();
1279 sc::RowHeightContext
aCxt(
1280 rDoc
.MaxRow(), rViewData
.GetPPTX(), rViewData
.GetPPTY(), rViewData
.GetZoomX(), rViewData
.GetZoomY(),
1283 if (rDoc
.SetOptimalHeight(aCxt
, aRange
.aStart
.Row(), aRange
.aEnd
.Row(), aRange
.aStart
.Tab(), true))
1285 // tdf#76183: recalculate objects' positions
1286 rDoc
.SetDrawPageSize(aRange
.aStart
.Tab());
1287 aRange
.aStart
.SetCol(0);
1288 aRange
.aEnd
.SetCol(rDoc
.MaxCol());
1289 aRange
.aEnd
.SetRow(rDoc
.MaxRow());
1290 nPaint
|= PaintPartFlags::Left
;
1294 if ( bKeepScenarioFlags
)
1296 // Copy scenario -> also paint scenario boarder
1297 aRange
.aStart
.SetCol(0);
1298 aRange
.aStart
.SetRow(0);
1299 aRange
.aEnd
.SetCol(rDoc
.MaxCol());
1300 aRange
.aEnd
.SetRow(rDoc
.MaxRow());
1303 // column/row info (width/height) included if whole columns/rows were copied
1304 if ( aSrcRange
.aStart
.Col() == 0 && aSrcRange
.aEnd
.Col() == rDoc
.MaxCol() )
1306 nPaint
|= PaintPartFlags::Left
;
1307 aRange
.aEnd
.SetRow(rDoc
.MaxRow());
1309 if ( aSrcRange
.aStart
.Row() == 0 && aSrcRange
.aEnd
.Row() == rDoc
.MaxRow() )
1311 nPaint
|= PaintPartFlags::Top
;
1312 aRange
.aEnd
.SetCol(rDoc
.MaxCol());
1315 pDocShell
->PostPaint( aRange
, nPaint
, nExtFlags
);
1318 void ScUndoDragDrop::DoUndo( ScRange aRange
)
1320 ScDocument
& rDoc
= pDocShell
->GetDocument();
1322 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
1324 pChangeTrack
->Undo( nStartChangeAction
, nEndChangeAction
);
1326 // Database range before data, so that the Autofilter button match up in ExtendMerge
1328 ScRange aPaintRange
= aRange
;
1329 rDoc
.ExtendMerge( aPaintRange
); // before deleting
1331 pDocShell
->UpdatePaintExt(mnPaintExtFlags
, aPaintRange
);
1333 // do not undo objects and note captions, they are handled via drawing undo
1334 InsertDeleteFlags nUndoFlags
= (InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
) | InsertDeleteFlags::NOCAPTIONS
;
1336 // Additionally discard/forget caption ownership during deletion, as
1337 // Drag&Drop is a special case in that the Undo holds captions of the
1338 // transferred target range, which would get deleted and
1339 // SdrGroupUndo::Undo() would attempt to access invalidated captions and
1341 InsertDeleteFlags nDelFlags
= nUndoFlags
| InsertDeleteFlags::FORGETCAPTIONS
;
1343 rDoc
.DeleteAreaTab( aRange
, nDelFlags
);
1344 pRefUndoDoc
->CopyToDocument(aRange
, nUndoFlags
, false, rDoc
);
1345 if ( rDoc
.HasAttrib( aRange
, HasAttrFlags::Merged
) )
1346 rDoc
.ExtendMerge( aRange
, true );
1348 aPaintRange
.aEnd
.SetCol( std::max( aPaintRange
.aEnd
.Col(), aRange
.aEnd
.Col() ) );
1349 aPaintRange
.aEnd
.SetRow( std::max( aPaintRange
.aEnd
.Row(), aRange
.aEnd
.Row() ) );
1351 pDocShell
->UpdatePaintExt(mnPaintExtFlags
, aPaintRange
);
1352 maPaintRanges
.Join(aPaintRange
);
1354 if (ScTabViewShell
* pTabViewShell
= ScTabViewShell::GetActiveViewShell())
1356 if (comphelper::LibreOfficeKit::isActive())
1358 pTabViewShell
->OnLOKSetWidthOrHeight(aPaintRange
.aStart
.Col(), true);
1359 pTabViewShell
->OnLOKSetWidthOrHeight(aPaintRange
.aStart
.Row(), false);
1362 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
1364 true /* bColumns */, true /* bRows */,
1365 true /* bSizes */, true /* bHidden */, true /* bFiltered */,
1366 true /* bGroups */, aPaintRange
.aStart
.Tab());
1371 void ScUndoDragDrop::Undo()
1373 mnPaintExtFlags
= 0;
1374 maPaintRanges
.RemoveAll();
1380 // During undo, we move cells from aDestRange to aSrcRange.
1382 ScDocument
& rDoc
= pDocShell
->GetDocument();
1384 SCCOL nColDelta
= aSrcRange
.aStart
.Col() - aDestRange
.aStart
.Col();
1385 SCROW nRowDelta
= aSrcRange
.aStart
.Row() - aDestRange
.aStart
.Row();
1386 SCTAB nTabDelta
= aSrcRange
.aStart
.Tab() - aDestRange
.aStart
.Tab();
1388 sc::RefUpdateContext
aCxt(rDoc
);
1389 aCxt
.meMode
= URM_MOVE
;
1390 aCxt
.maRange
= aSrcRange
;
1391 aCxt
.mnColDelta
= nColDelta
;
1392 aCxt
.mnRowDelta
= nRowDelta
;
1393 aCxt
.mnTabDelta
= nTabDelta
;
1395 // Global range names.
1396 ScRangeName
* pName
= rDoc
.GetRangeName();
1398 pName
->UpdateReference(aCxt
);
1400 SCTAB nTabCount
= rDoc
.GetTableCount();
1401 for (SCTAB nTab
= 0; nTab
< nTabCount
; ++nTab
)
1403 // Sheet-local range names.
1404 pName
= rDoc
.GetRangeName(nTab
);
1406 pName
->UpdateReference(aCxt
, nTab
);
1409 ScValidationDataList
* pValidList
= rDoc
.GetValidationList();
1412 // Update the references of validation entries.
1413 pValidList
->UpdateReference(aCxt
);
1419 rDoc
.BroadcastCells(aSrcRange
, SfxHintId::ScDataChanged
, false);
1424 for (size_t i
= 0; i
< maPaintRanges
.size(); ++i
)
1426 const ScRange
& r
= maPaintRanges
[i
];
1427 PaintArea(r
, mnPaintExtFlags
);
1431 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
1434 void ScUndoDragDrop::Redo()
1438 ScDocument
& rDoc
= pDocShell
->GetDocument();
1439 ScDocumentUniquePtr
pClipDoc(new ScDocument( SCDOCMODE_CLIP
));
1441 EnableDrawAdjust( &rDoc
, false ); //! include in ScBlockUndo?
1443 // do not undo/redo objects and note captions, they are handled via drawing undo
1444 constexpr InsertDeleteFlags nRedoFlags
= (InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
) | InsertDeleteFlags::NOCAPTIONS
;
1446 /* TODO: Redoing note captions is quite tricky due to the fact that a
1447 helper clip document is used. While (re-)pasting the contents to the
1448 destination area, the original pointers to the captions created while
1449 dropping have to be restored. A simple CopyFromClip() would create new
1450 caption objects that are not tracked by drawing undo, and the captions
1451 restored by drawing redo would live without cell note objects pointing
1452 to them. So, first, CopyToClip() and CopyFromClip() are called without
1453 cloning the caption objects. This leads to cell notes pointing to the
1454 wrong captions from source area that will be removed by drawing redo
1455 later. Second, the pointers to the new captions have to be restored.
1456 Sadly, currently these pointers are not stored anywhere but in the list
1457 of drawing undo actions. */
1460 ScMarkData
aSourceMark(rDoc
.GetSheetLimits());
1461 for (nTab
=aSrcRange
.aStart
.Tab(); nTab
<=aSrcRange
.aEnd
.Tab(); nTab
++)
1462 aSourceMark
.SelectTable( nTab
, true );
1464 // do not clone objects and note captions into clipdoc (see above)
1465 // but at least copy notes
1466 ScClipParam
aClipParam(aSrcRange
, bCut
);
1467 rDoc
.CopyToClip(aClipParam
, pClipDoc
.get(), &aSourceMark
, bKeepScenarioFlags
, false);
1471 ScRange aSrcPaintRange
= aSrcRange
;
1472 rDoc
.ExtendMerge( aSrcPaintRange
); // before deleting
1473 sal_uInt16 nExtFlags
= 0;
1474 pDocShell
->UpdatePaintExt( nExtFlags
, aSrcPaintRange
);
1475 rDoc
.DeleteAreaTab( aSrcRange
, nRedoFlags
);
1476 PaintArea( aSrcPaintRange
, nExtFlags
);
1479 ScMarkData
aDestMark(rDoc
.GetSheetLimits());
1480 for (nTab
=aDestRange
.aStart
.Tab(); nTab
<=aDestRange
.aEnd
.Tab(); nTab
++)
1481 aDestMark
.SelectTable( nTab
, true );
1483 bool bIncludeFiltered
= bCut
;
1484 // TODO: restore old note captions instead of cloning new captions...
1485 rDoc
.CopyFromClip( aDestRange
, aDestMark
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::OBJECTS
, nullptr, pClipDoc
.get(), true, false, bIncludeFiltered
);
1488 for (nTab
=aSrcRange
.aStart
.Tab(); nTab
<=aSrcRange
.aEnd
.Tab(); nTab
++)
1489 rDoc
.RefreshAutoFilter( aSrcRange
.aStart
.Col(), aSrcRange
.aStart
.Row(),
1490 aSrcRange
.aEnd
.Col(), aSrcRange
.aEnd
.Row(), nTab
);
1492 // skipped rows and merged cells don't mix
1493 if ( !bIncludeFiltered
&& pClipDoc
->HasClipFilteredRows() )
1494 pDocShell
->GetDocFunc().UnmergeCells( aDestRange
, false, nullptr );
1496 for (nTab
=aDestRange
.aStart
.Tab(); nTab
<=aDestRange
.aEnd
.Tab(); nTab
++)
1498 SCCOL nEndCol
= aDestRange
.aEnd
.Col();
1499 SCROW nEndRow
= aDestRange
.aEnd
.Row();
1500 rDoc
.ExtendMerge( aDestRange
.aStart
.Col(), aDestRange
.aStart
.Row(),
1501 nEndCol
, nEndRow
, nTab
, true );
1502 PaintArea( ScRange( aDestRange
.aStart
.Col(), aDestRange
.aStart
.Row(), nTab
,
1503 nEndCol
, nEndRow
, nTab
), 0 );
1509 ShowTable( aDestRange
.aStart
.Tab() );
1511 RedoSdrUndoAction( pDrawUndo
.get() ); //! include in ScBlockUndo?
1512 EnableDrawAdjust( &rDoc
, true ); //! include in ScBlockUndo?
1515 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged
) );
1517 if (comphelper::LibreOfficeKit::isActive())
1519 SCCOL nStartCol
= aDestRange
.aStart
.Col();
1520 SCROW nStartRow
= aDestRange
.aStart
.Row();
1523 nStartCol
= std::min(nStartCol
, aSrcRange
.aStart
.Col());
1524 nStartRow
= std::min(nStartRow
, aSrcRange
.aStart
.Row());
1527 if (ScTabViewShell
* pTabViewShell
= ScTabViewShell::GetActiveViewShell())
1529 pTabViewShell
->OnLOKSetWidthOrHeight(nStartCol
, true);
1530 pTabViewShell
->OnLOKSetWidthOrHeight(nStartRow
, false);
1532 SCTAB nStartTab
= aDestRange
.aStart
.Tab();
1533 SCTAB nEndTab
= aDestRange
.aEnd
.Tab();
1536 nStartTab
= std::min(nStartTab
, aSrcRange
.aStart
.Tab());
1537 nEndTab
= std::max(nEndTab
, aSrcRange
.aEnd
.Tab());
1539 for (nTab
= nStartTab
; nTab
<= nEndTab
; ++nTab
)
1541 ScTabViewShell::notifyAllViewsSheetGeomInvalidation(
1542 pTabViewShell
, true /* bColumns */, true /* bRows */,
1543 true /* bSizes */, true /* bHidden */, true /* bFiltered */, true /* bGroups */,
1550 void ScUndoDragDrop::Repeat(SfxRepeatTarget
& /* rTarget */)
1554 bool ScUndoDragDrop::CanRepeat(SfxRepeatTarget
& /* rTarget */) const
1556 return false; // not possible
1559 // Insert list containing range names
1560 // (Insert|Name|Insert =>[List])
1561 ScUndoListNames::ScUndoListNames(ScDocShell
* pNewDocShell
, const ScRange
& rRange
,
1562 ScDocumentUniquePtr pNewUndoDoc
, ScDocumentUniquePtr pNewRedoDoc
)
1563 : ScBlockUndo(pNewDocShell
, rRange
, SC_UNDO_AUTOHEIGHT
)
1564 , xUndoDoc(std::move(pNewUndoDoc
))
1565 , xRedoDoc(std::move(pNewRedoDoc
))
1569 OUString
ScUndoListNames::GetComment() const
1571 return ScResId( STR_UNDO_LISTNAMES
);
1574 void ScUndoListNames::DoChange( ScDocument
* pSrcDoc
) const
1576 ScDocument
& rDoc
= pDocShell
->GetDocument();
1578 rDoc
.DeleteAreaTab( aBlockRange
, InsertDeleteFlags::ALL
);
1579 pSrcDoc
->CopyToDocument(aBlockRange
, InsertDeleteFlags::ALL
, false, rDoc
);
1580 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
);
1581 pDocShell
->PostDataChanged();
1582 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1584 pViewShell
->CellContentChanged();
1587 void ScUndoListNames::Undo()
1590 DoChange(xUndoDoc
.get());
1594 void ScUndoListNames::Redo()
1597 DoChange(xRedoDoc
.get());
1601 void ScUndoListNames::Repeat(SfxRepeatTarget
& rTarget
)
1603 if (auto pTabViewTarget
= dynamic_cast<ScTabViewTarget
*>(&rTarget
))
1604 pTabViewTarget
->GetViewShell()->InsertNameList();
1607 bool ScUndoListNames::CanRepeat(SfxRepeatTarget
& rTarget
) const
1609 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
1612 ScUndoConditionalFormat::ScUndoConditionalFormat(ScDocShell
* pNewDocShell
, SCTAB nTab
):
1613 ScSimpleUndo( pNewDocShell
),
1615 mpUndoDoc(createUndoRedoData())
1619 ScUndoConditionalFormat::~ScUndoConditionalFormat()
1623 ScDocumentUniquePtr
ScUndoConditionalFormat::createUndoRedoData()
1625 ScDocument
& rDoc
= pDocShell
->GetDocument();
1626 ScDocumentUniquePtr
pUndoRedoDoc(new ScDocument(SCDOCMODE_UNDO
));
1627 pUndoRedoDoc
->InitUndo(rDoc
, mnTab
, mnTab
);
1628 if (const auto* pList
= rDoc
.GetCondFormList(mnTab
))
1629 pUndoRedoDoc
->SetCondFormList(new ScConditionalFormatList(*pUndoRedoDoc
, *pList
), mnTab
);
1630 return pUndoRedoDoc
;
1633 OUString
ScUndoConditionalFormat::GetComment() const
1635 return ScResId( STR_UNDO_CONDFORMAT
);
1638 void ScUndoConditionalFormat::Undo()
1640 DoChange(mpUndoDoc
.get());
1643 void ScUndoConditionalFormat::Redo()
1645 DoChange(mpRedoDoc
.get());
1648 void ScUndoConditionalFormat::DoChange(ScDocument
* pSrcDoc
)
1650 ScDocument
& rDoc
= pDocShell
->GetDocument();
1652 // Restore all conditional formats in the tab. This is simpler and more reliable, than
1653 // restoring formats in a specific range, and then trying to join selectively the restored
1654 // formats with the other formats in the tab, to get the correct state.
1655 ScRangeList aCombinedRange
;
1656 if (const auto* pOldList
= rDoc
.GetCondFormList(mnTab
))
1657 aCombinedRange
= pOldList
->GetCombinedRange();
1659 if (const auto* pNewList
= pSrcDoc
->GetCondFormList(mnTab
))
1661 for (const auto& cond
: *pNewList
)
1662 for (const auto& range
: cond
->GetRange())
1663 aCombinedRange
.Join(range
);
1664 rDoc
.SetCondFormList(new ScConditionalFormatList(rDoc
, *pNewList
), mnTab
);
1668 rDoc
.SetCondFormList(nullptr, mnTab
);
1670 pDocShell
->PostPaint(aCombinedRange
, PaintPartFlags::Grid
);
1671 pDocShell
->PostDataChanged();
1672 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1674 pViewShell
->CellContentChanged();
1677 void ScUndoConditionalFormat::Repeat(SfxRepeatTarget
& )
1681 bool ScUndoConditionalFormat::CanRepeat(SfxRepeatTarget
& ) const
1686 ScUndoConditionalFormatList::ScUndoConditionalFormatList(ScDocShell
* pNewDocShell
,
1687 ScDocumentUniquePtr pUndoDoc
, ScDocumentUniquePtr pRedoDoc
, SCTAB nTab
):
1688 ScSimpleUndo( pNewDocShell
),
1689 mpUndoDoc(std::move(pUndoDoc
)),
1690 mpRedoDoc(std::move(pRedoDoc
)),
1695 ScUndoConditionalFormatList::~ScUndoConditionalFormatList()
1699 OUString
ScUndoConditionalFormatList::GetComment() const
1701 return ScResId( STR_UNDO_CONDFORMAT_LIST
);
1704 void ScUndoConditionalFormatList::Undo()
1706 DoChange(mpUndoDoc
.get());
1709 void ScUndoConditionalFormatList::Redo()
1711 DoChange(mpRedoDoc
.get());
1714 void ScUndoConditionalFormatList::DoChange(const ScDocument
* pSrcDoc
)
1716 ScDocument
& rDoc
= pDocShell
->GetDocument();
1718 if (pSrcDoc
== mpUndoDoc
.get())
1720 mpRedoDoc
->GetCondFormList(mnTab
)->RemoveFromDocument(rDoc
);
1721 mpUndoDoc
->GetCondFormList(mnTab
)->AddToDocument(rDoc
);
1725 mpUndoDoc
->GetCondFormList(mnTab
)->RemoveFromDocument(rDoc
);
1726 mpRedoDoc
->GetCondFormList(mnTab
)->AddToDocument(rDoc
);
1728 rDoc
.SetCondFormList(new ScConditionalFormatList(rDoc
, *pSrcDoc
->GetCondFormList(mnTab
)), mnTab
);
1730 pDocShell
->PostPaintGridAll();
1731 pDocShell
->PostDataChanged();
1732 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1734 pViewShell
->CellContentChanged();
1737 void ScUndoConditionalFormatList::Repeat(SfxRepeatTarget
& )
1741 bool ScUndoConditionalFormatList::CanRepeat(SfxRepeatTarget
& ) const
1746 ScUndoUseScenario::ScUndoUseScenario( ScDocShell
* pNewDocShell
,
1747 const ScMarkData
& rMark
,
1748 /*C*/ const ScArea
& rDestArea
,
1749 ScDocumentUniquePtr pNewUndoDoc
,
1750 OUString aNewName
) :
1751 ScSimpleUndo( pNewDocShell
),
1752 pUndoDoc( std::move(pNewUndoDoc
) ),
1754 aName(std::move( aNewName
))
1756 aRange
.aStart
.SetCol(rDestArea
.nColStart
);
1757 aRange
.aStart
.SetRow(rDestArea
.nRowStart
);
1758 aRange
.aStart
.SetTab(rDestArea
.nTab
);
1759 aRange
.aEnd
.SetCol(rDestArea
.nColEnd
);
1760 aRange
.aEnd
.SetRow(rDestArea
.nRowEnd
);
1761 aRange
.aEnd
.SetTab(rDestArea
.nTab
);
1764 ScUndoUseScenario::~ScUndoUseScenario()
1768 OUString
ScUndoUseScenario::GetComment() const
1770 return ScResId( STR_UNDO_USESCENARIO
);
1773 void ScUndoUseScenario::Undo()
1777 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1780 pViewShell
->DoneBlockMode();
1781 pViewShell
->InitOwnBlockMode( aRange
);
1784 ScDocument
& rDoc
= pDocShell
->GetDocument();
1785 rDoc
.DeleteSelection( InsertDeleteFlags::ALL
, aMarkData
);
1786 pUndoDoc
->CopyToDocument(aRange
, InsertDeleteFlags::ALL
, true, rDoc
, &aMarkData
);
1789 bool bFrame
= false;
1790 SCTAB nTab
= aRange
.aStart
.Tab();
1791 SCTAB nEndTab
= nTab
;
1792 while ( pUndoDoc
->HasTable(nEndTab
+1) && pUndoDoc
->IsScenario(nEndTab
+1) )
1794 for (SCTAB i
= nTab
+1; i
<=nEndTab
; i
++)
1799 ScScenarioFlags nScenFlags
;
1800 pUndoDoc
->GetScenarioData( i
, aComment
, aColor
, nScenFlags
);
1801 rDoc
.SetScenarioData( i
, aComment
, aColor
, nScenFlags
);
1802 bool bActive
= pUndoDoc
->IsActiveScenario( i
);
1803 rDoc
.SetActiveScenario( i
, bActive
);
1804 // For copy-back scenario also consider content
1805 if ( nScenFlags
& ScScenarioFlags::TwoWay
)
1807 rDoc
.DeleteAreaTab( 0,0, rDoc
.MaxCol(),rDoc
.MaxRow(), i
, InsertDeleteFlags::ALL
);
1808 pUndoDoc
->CopyToDocument(0,0,i
, rDoc
.MaxCol(),rDoc
.MaxRow(),i
, InsertDeleteFlags::ALL
,false, rDoc
);
1810 if ( nScenFlags
& ScScenarioFlags::ShowFrame
)
1814 // if visible borders, then paint all
1816 pDocShell
->PostPaint( 0,0,nTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, PaintPartFlags::Grid
| PaintPartFlags::Extras
);
1818 pDocShell
->PostPaint( aRange
, PaintPartFlags::Grid
| PaintPartFlags::Extras
);
1819 pDocShell
->PostDataChanged();
1821 pViewShell
->CellContentChanged();
1823 ShowTable( aRange
.aStart
.Tab() );
1828 void ScUndoUseScenario::Redo()
1830 SCTAB nTab
= aRange
.aStart
.Tab();
1833 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1836 pViewShell
->SetTabNo( nTab
);
1837 pViewShell
->DoneBlockMode();
1838 pViewShell
->InitOwnBlockMode( aRange
);
1841 pDocShell
->UseScenario( nTab
, aName
, false );
1846 void ScUndoUseScenario::Repeat(SfxRepeatTarget
& rTarget
)
1848 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
1850 OUString aTemp
= aName
;
1851 pViewTarget
->GetViewShell()->UseScenario(aTemp
);
1855 bool ScUndoUseScenario::CanRepeat(SfxRepeatTarget
& rTarget
) const
1857 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
1859 ScViewData
& rViewData
= pViewTarget
->GetViewShell()->GetViewData();
1860 return !rViewData
.GetDocument().IsScenario( rViewData
.GetTabNo() );
1865 ScUndoSelectionStyle::ScUndoSelectionStyle( ScDocShell
* pNewDocShell
,
1866 const ScMarkData
& rMark
,
1867 const ScRange
& rRange
,
1869 ScDocumentUniquePtr pNewUndoDoc
) :
1870 ScSimpleUndo( pNewDocShell
),
1872 pUndoDoc( std::move(pNewUndoDoc
) ),
1873 aStyleName(std::move( aName
)),
1876 aMarkData
.MarkToMulti();
1879 ScUndoSelectionStyle::~ScUndoSelectionStyle()
1883 OUString
ScUndoSelectionStyle::GetComment() const
1885 return ScResId( STR_UNDO_APPLYCELLSTYLE
);
1888 void ScUndoSelectionStyle::DoChange( const bool bUndo
)
1890 ScDocument
& rDoc
= pDocShell
->GetDocument();
1892 SetViewMarkData( aMarkData
);
1894 ScRange
aWorkRange( aRange
);
1895 if ( rDoc
.HasAttrib( aWorkRange
, HasAttrFlags::Merged
) ) // Merged cells?
1896 rDoc
.ExtendMerge( aWorkRange
, true );
1898 sal_uInt16 nExtFlags
= 0;
1899 pDocShell
->UpdatePaintExt( nExtFlags
, aWorkRange
);
1901 if (bUndo
) // if Undo then push back all old data again
1903 SCTAB nTabCount
= rDoc
.GetTableCount();
1904 ScRange aCopyRange
= aWorkRange
;
1905 aCopyRange
.aStart
.SetTab(0);
1906 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
1907 pUndoDoc
->CopyToDocument(aCopyRange
, InsertDeleteFlags::ATTRIB
, true, rDoc
, &aMarkData
);
1909 else // if Redo, then reapply style
1911 ScStyleSheetPool
* pStlPool
= rDoc
.GetStyleSheetPool();
1912 ScStyleSheet
* pStyleSheet
=
1913 static_cast<ScStyleSheet
*>( pStlPool
->Find( aStyleName
, SfxStyleFamily::Para
) );
1916 OSL_FAIL("StyleSheet not found");
1919 rDoc
.ApplySelectionStyle( *pStyleSheet
, aMarkData
);
1922 pDocShell
->UpdatePaintExt( nExtFlags
, aWorkRange
);
1924 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
1925 if ( !( pViewShell
&& pViewShell
->AdjustBlockHeight() ) )
1926 /*A*/ pDocShell
->PostPaint( aWorkRange
, PaintPartFlags::Grid
| PaintPartFlags::Extras
, nExtFlags
);
1928 ShowTable( aWorkRange
.aStart
.Tab() );
1931 void ScUndoSelectionStyle::Undo()
1938 void ScUndoSelectionStyle::Redo()
1945 void ScUndoSelectionStyle::Repeat(SfxRepeatTarget
& rTarget
)
1947 if (dynamic_cast<const ScTabViewTarget
*>( &rTarget
) == nullptr)
1950 ScDocument
& rDoc
= pDocShell
->GetDocument();
1951 ScStyleSheetPool
* pStlPool
= rDoc
.GetStyleSheetPool();
1952 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>( pStlPool
->
1953 Find( aStyleName
, SfxStyleFamily::Para
));
1956 OSL_FAIL("StyleSheet not found");
1960 ScTabViewShell
& rViewShell
= *static_cast<ScTabViewTarget
&>(rTarget
).GetViewShell();
1961 rViewShell
.SetStyleSheetToMarked( pStyleSheet
);
1964 bool ScUndoSelectionStyle::CanRepeat(SfxRepeatTarget
& rTarget
) const
1966 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
1969 ScUndoEnterMatrix::ScUndoEnterMatrix( ScDocShell
* pNewDocShell
, const ScRange
& rArea
,
1970 ScDocumentUniquePtr pNewUndoDoc
, OUString aForm
) :
1971 ScBlockUndo( pNewDocShell
, rArea
, SC_UNDO_SIMPLE
),
1972 pUndoDoc( std::move(pNewUndoDoc
) ),
1973 aFormula(std::move( aForm
))
1978 ScUndoEnterMatrix::~ScUndoEnterMatrix()
1982 OUString
ScUndoEnterMatrix::GetComment() const
1984 return ScResId( STR_UNDO_ENTERMATRIX
);
1987 void ScUndoEnterMatrix::SetChangeTrack()
1989 ScDocument
& rDoc
= pDocShell
->GetDocument();
1990 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
1992 pChangeTrack
->AppendContentRange( aBlockRange
, pUndoDoc
.get(),
1993 nStartChangeAction
, nEndChangeAction
);
1995 nStartChangeAction
= nEndChangeAction
= 0;
1998 void ScUndoEnterMatrix::Undo()
2002 ScDocument
& rDoc
= pDocShell
->GetDocument();
2004 rDoc
.DeleteAreaTab( aBlockRange
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::NOTE
);
2005 pUndoDoc
->CopyToDocument(aBlockRange
, InsertDeleteFlags::ALL
& ~InsertDeleteFlags::NOTE
, false, rDoc
);
2006 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
);
2007 pDocShell
->PostDataChanged();
2008 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
2010 pViewShell
->CellContentChanged();
2012 ScChangeTrack
* pChangeTrack
= rDoc
.GetChangeTrack();
2014 pChangeTrack
->Undo( nStartChangeAction
, nEndChangeAction
);
2019 void ScUndoEnterMatrix::Redo()
2023 ScDocument
& rDoc
= pDocShell
->GetDocument();
2025 ScMarkData
aDestMark(rDoc
.GetSheetLimits());
2026 aDestMark
.SelectOneTable( aBlockRange
.aStart
.Tab() );
2027 aDestMark
.SetMarkArea( aBlockRange
);
2029 rDoc
.InsertMatrixFormula( aBlockRange
.aStart
.Col(), aBlockRange
.aStart
.Row(),
2030 aBlockRange
.aEnd
.Col(), aBlockRange
.aEnd
.Row(),
2031 aDestMark
, aFormula
);
2038 void ScUndoEnterMatrix::Repeat(SfxRepeatTarget
& rTarget
)
2040 if (auto pTabViewTarget
= dynamic_cast<ScTabViewTarget
*>(&rTarget
))
2042 OUString aTemp
= aFormula
;
2043 ScDocument
& rDoc
= pDocShell
->GetDocument();
2044 pTabViewTarget
->GetViewShell()->EnterMatrix(aTemp
, rDoc
.GetGrammar());
2048 bool ScUndoEnterMatrix::CanRepeat(SfxRepeatTarget
& rTarget
) const
2050 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
2053 static ScRange
lcl_GetMultiMarkRange( const ScMarkData
& rMark
)
2055 OSL_ENSURE( rMark
.IsMultiMarked(), "wrong mark type" );
2056 return rMark
.GetMultiMarkArea();
2059 ScUndoIndent::ScUndoIndent( ScDocShell
* pNewDocShell
, const ScMarkData
& rMark
,
2060 ScDocumentUniquePtr pNewUndoDoc
, bool bIncrement
) :
2061 ScBlockUndo( pNewDocShell
, lcl_GetMultiMarkRange(rMark
), SC_UNDO_AUTOHEIGHT
),
2063 pUndoDoc( std::move(pNewUndoDoc
) ),
2064 bIsIncrement( bIncrement
)
2068 ScUndoIndent::~ScUndoIndent()
2072 OUString
ScUndoIndent::GetComment() const
2074 TranslateId pId
= bIsIncrement
? STR_UNDO_INC_INDENT
: STR_UNDO_DEC_INDENT
;
2075 return ScResId(pId
);
2078 void ScUndoIndent::Undo()
2082 ScDocument
& rDoc
= pDocShell
->GetDocument();
2083 SCTAB nTabCount
= rDoc
.GetTableCount();
2084 ScRange aCopyRange
= aBlockRange
;
2085 aCopyRange
.aStart
.SetTab(0);
2086 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
2087 pUndoDoc
->CopyToDocument(aCopyRange
, InsertDeleteFlags::ATTRIB
, true, rDoc
, &aMarkData
);
2088 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2093 void ScUndoIndent::Redo()
2097 ScDocument
& rDoc
= pDocShell
->GetDocument();
2098 rDoc
.ChangeSelectionIndent( bIsIncrement
, aMarkData
);
2099 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2104 void ScUndoIndent::Repeat(SfxRepeatTarget
& rTarget
)
2106 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
2107 pViewTarget
->GetViewShell()->ChangeIndent( bIsIncrement
);
2110 bool ScUndoIndent::CanRepeat(SfxRepeatTarget
& rTarget
) const
2112 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
2115 ScUndoTransliterate::ScUndoTransliterate( ScDocShell
* pNewDocShell
, const ScMarkData
& rMark
,
2116 ScDocumentUniquePtr pNewUndoDoc
, TransliterationFlags nType
) :
2117 ScBlockUndo( pNewDocShell
, lcl_GetMultiMarkRange(rMark
), SC_UNDO_AUTOHEIGHT
),
2119 pUndoDoc( std::move(pNewUndoDoc
) ),
2120 nTransliterationType( nType
)
2124 ScUndoTransliterate::~ScUndoTransliterate()
2128 OUString
ScUndoTransliterate::GetComment() const
2130 return ScResId( STR_UNDO_TRANSLITERATE
);
2133 void ScUndoTransliterate::Undo()
2137 ScDocument
& rDoc
= pDocShell
->GetDocument();
2138 SCTAB nTabCount
= rDoc
.GetTableCount();
2139 ScRange aCopyRange
= aBlockRange
;
2140 aCopyRange
.aStart
.SetTab(0);
2141 aCopyRange
.aEnd
.SetTab(nTabCount
-1);
2142 pUndoDoc
->CopyToDocument(aCopyRange
, InsertDeleteFlags::CONTENTS
, true, rDoc
, &aMarkData
);
2143 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2148 void ScUndoTransliterate::Redo()
2152 ScDocument
& rDoc
= pDocShell
->GetDocument();
2153 rDoc
.TransliterateText( aMarkData
, nTransliterationType
);
2154 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2159 void ScUndoTransliterate::Repeat(SfxRepeatTarget
& rTarget
)
2161 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
2162 pViewTarget
->GetViewShell()->TransliterateText( nTransliterationType
);
2165 bool ScUndoTransliterate::CanRepeat(SfxRepeatTarget
& rTarget
) const
2167 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
2170 ScUndoClearItems::ScUndoClearItems( ScDocShell
* pNewDocShell
, const ScMarkData
& rMark
,
2171 ScDocumentUniquePtr pNewUndoDoc
, const sal_uInt16
* pW
) :
2172 ScBlockUndo( pNewDocShell
, lcl_GetMultiMarkRange(rMark
), SC_UNDO_AUTOHEIGHT
),
2174 pUndoDoc( std::move(pNewUndoDoc
) )
2176 assert(pW
&& "ScUndoClearItems: Which-Pointer is Null");
2178 sal_uInt16 nCount
= 0;
2179 while ( pW
[nCount
] )
2181 pWhich
.reset( new sal_uInt16
[nCount
+1] );
2182 for (sal_uInt16 i
=0; i
<=nCount
; i
++)
2186 ScUndoClearItems::~ScUndoClearItems()
2190 OUString
ScUndoClearItems::GetComment() const
2192 return ScResId( STR_UNDO_DELETECONTENTS
);
2195 void ScUndoClearItems::Undo()
2199 ScDocument
& rDoc
= pDocShell
->GetDocument();
2200 pUndoDoc
->CopyToDocument(aBlockRange
, InsertDeleteFlags::ATTRIB
, true, rDoc
, &aMarkData
);
2201 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2206 void ScUndoClearItems::Redo()
2210 ScDocument
& rDoc
= pDocShell
->GetDocument();
2211 rDoc
.ClearSelectionItems( pWhich
.get(), aMarkData
);
2212 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2217 void ScUndoClearItems::Repeat(SfxRepeatTarget
& rTarget
)
2219 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
2221 ScViewData
& rViewData
= pViewTarget
->GetViewShell()->GetViewData();
2222 rViewData
.GetDocFunc().ClearItems( rViewData
.GetMarkData(), pWhich
.get(), false );
2226 bool ScUndoClearItems::CanRepeat(SfxRepeatTarget
& rTarget
) const
2228 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
2231 // remove all line breaks of a table
2232 ScUndoRemoveBreaks::ScUndoRemoveBreaks( ScDocShell
* pNewDocShell
,
2233 SCTAB nNewTab
, ScDocumentUniquePtr pNewUndoDoc
) :
2234 ScSimpleUndo( pNewDocShell
),
2236 pUndoDoc( std::move(pNewUndoDoc
) )
2240 ScUndoRemoveBreaks::~ScUndoRemoveBreaks()
2244 OUString
ScUndoRemoveBreaks::GetComment() const
2246 return ScResId( STR_UNDO_REMOVEBREAKS
);
2249 void ScUndoRemoveBreaks::Undo()
2253 ScDocument
& rDoc
= pDocShell
->GetDocument();
2254 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
2256 pUndoDoc
->CopyToDocument(0,0,nTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, InsertDeleteFlags::NONE
, false, rDoc
);
2258 pViewShell
->UpdatePageBreakData( true );
2259 pDocShell
->PostPaint( 0,0,nTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, PaintPartFlags::Grid
);
2264 void ScUndoRemoveBreaks::Redo()
2268 ScDocument
& rDoc
= pDocShell
->GetDocument();
2269 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
2271 rDoc
.RemoveManualBreaks(nTab
);
2272 rDoc
.UpdatePageBreaks(nTab
);
2274 pViewShell
->UpdatePageBreakData( true );
2275 pDocShell
->PostPaint( 0,0,nTab
, rDoc
.MaxCol(),rDoc
.MaxRow(),nTab
, PaintPartFlags::Grid
);
2280 void ScUndoRemoveBreaks::Repeat(SfxRepeatTarget
& rTarget
)
2282 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
2284 ScTabViewShell
& rViewShell
= *pViewTarget
->GetViewShell();
2285 rViewShell
.RemoveManualBreaks();
2289 bool ScUndoRemoveBreaks::CanRepeat(SfxRepeatTarget
& rTarget
) const
2291 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
2294 ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell
* pNewDocShell
,
2295 const ScCellMergeOption
& rOption
, ScDocumentUniquePtr pNewUndoDoc
) :
2296 ScBlockUndo( pNewDocShell
, rOption
.getFirstSingleRange(), SC_UNDO_SIMPLE
),
2297 pUndoDoc( std::move(pNewUndoDoc
) )
2299 maOptions
.push_back( rOption
);
2302 ScUndoRemoveMerge::ScUndoRemoveMerge( ScDocShell
* pNewDocShell
,
2303 const ScRange
& rRange
, ScDocumentUniquePtr pNewUndoDoc
) :
2304 ScBlockUndo( pNewDocShell
, rRange
, SC_UNDO_SIMPLE
),
2305 pUndoDoc( std::move(pNewUndoDoc
) )
2309 ScUndoRemoveMerge::~ScUndoRemoveMerge()
2313 OUString
ScUndoRemoveMerge::GetComment() const
2315 return ScResId( STR_UNDO_REMERGE
); // "remove merge"
2318 ScDocument
* ScUndoRemoveMerge::GetUndoDoc()
2320 return pUndoDoc
.get();
2323 void ScUndoRemoveMerge::AddCellMergeOption( const ScCellMergeOption
& rOption
)
2325 maOptions
.push_back( rOption
);
2328 void ScUndoRemoveMerge::Undo()
2335 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
2337 ScDocument
& rDoc
= pDocShell
->GetDocument();
2338 for (const auto & rOption
: maOptions
)
2340 for (const auto& rTab
: rOption
.maTabs
)
2342 OSL_ENSURE(pUndoDoc
, "NULL pUndoDoc!");
2345 // There is no need to extend merge area because it's already been extended.
2346 ScRange aRange
= rOption
.getSingleRange(rTab
);
2347 rDoc
.DeleteAreaTab(aRange
, InsertDeleteFlags::ATTRIB
);
2348 pUndoDoc
->CopyToDocument(aRange
, InsertDeleteFlags::ATTRIB
, false, rDoc
);
2350 bool bDidPaint
= false;
2353 pViewShell
->SetTabNo(rTab
);
2354 bDidPaint
= pViewShell
->AdjustRowHeight(rOption
.mnStartRow
, rOption
.mnEndRow
, true);
2357 ScUndoUtil::PaintMore(pDocShell
, aRange
);
2364 void ScUndoRemoveMerge::Redo()
2371 ScDocument
& rDoc
= pDocShell
->GetDocument();
2372 ScTabViewShell
* pViewShell
= ScTabViewShell::GetActiveViewShell();
2374 for (const auto & rOption
: maOptions
)
2376 for (const SCTAB nTab
: rOption
.maTabs
)
2378 // There is no need to extend merge area because it's already been extended.
2379 ScRange aRange
= rOption
.getSingleRange(nTab
);
2381 const SfxPoolItem
& rDefAttr
= rDoc
.GetPool()->GetUserOrPoolDefaultItem( ATTR_MERGE
);
2382 ScPatternAttr
aPattern(rDoc
.getCellAttributeHelper());
2383 aPattern
.GetItemSet().Put( rDefAttr
);
2384 rDoc
.ApplyPatternAreaTab( rOption
.mnStartCol
, rOption
.mnStartRow
,
2385 rOption
.mnEndCol
, rOption
.mnEndRow
, nTab
,
2388 rDoc
.RemoveFlagsTab( rOption
.mnStartCol
, rOption
.mnStartRow
,
2389 rOption
.mnEndCol
, rOption
.mnEndRow
, nTab
,
2390 ScMF::Hor
| ScMF::Ver
);
2392 rDoc
.ExtendMerge(aRange
, true);
2396 bool bDidPaint
= false;
2399 pViewShell
->SetTabNo(nTab
);
2400 bDidPaint
= pViewShell
->AdjustRowHeight(rOption
.mnStartRow
, rOption
.mnEndRow
, true);
2403 ScUndoUtil::PaintMore(pDocShell
, aRange
);
2410 void ScUndoRemoveMerge::Repeat(SfxRepeatTarget
& rTarget
)
2412 if (auto pViewTarget
= dynamic_cast<ScTabViewTarget
*>( &rTarget
))
2413 pViewTarget
->GetViewShell()->RemoveMerge();
2416 bool ScUndoRemoveMerge::CanRepeat(SfxRepeatTarget
& rTarget
) const
2418 return dynamic_cast<const ScTabViewTarget
*>( &rTarget
) != nullptr;
2421 void ScUndoRemoveMerge::SetCurTab()
2423 SCTAB nCurTab
= ScDocShell::GetCurTab();
2424 aBlockRange
.aStart
.SetTab(nCurTab
);
2425 aBlockRange
.aEnd
.SetTab(nCurTab
);
2428 /** set only border, for ScRangeList (StarOne) */
2429 static ScRange
lcl_TotalRange( const ScRangeList
& rRanges
)
2432 if ( !rRanges
.empty() )
2434 aTotal
= rRanges
[ 0 ];
2435 for ( size_t i
= 1, nCount
= rRanges
.size(); i
< nCount
; ++i
)
2437 ScRange
const & rRange
= rRanges
[ i
];
2438 if (rRange
.aStart
.Col() < aTotal
.aStart
.Col()) aTotal
.aStart
.SetCol(rRange
.aStart
.Col());
2439 if (rRange
.aStart
.Row() < aTotal
.aStart
.Row()) aTotal
.aStart
.SetRow(rRange
.aStart
.Row());
2440 if (rRange
.aStart
.Tab() < aTotal
.aStart
.Tab()) aTotal
.aStart
.SetTab(rRange
.aStart
.Tab());
2441 if (rRange
.aEnd
.Col() > aTotal
.aEnd
.Col() ) aTotal
.aEnd
.SetCol( rRange
.aEnd
.Col() );
2442 if (rRange
.aEnd
.Row() > aTotal
.aEnd
.Row() ) aTotal
.aEnd
.SetRow( rRange
.aEnd
.Row() );
2443 if (rRange
.aEnd
.Tab() > aTotal
.aEnd
.Tab() ) aTotal
.aEnd
.SetTab(rRange
.aEnd
.Tab() );
2449 ScUndoBorder::ScUndoBorder(ScDocShell
* pNewDocShell
,
2450 const ScRangeList
& rRangeList
, ScDocumentUniquePtr pNewUndoDoc
,
2451 const SvxBoxItem
& rNewOuter
, const SvxBoxInfoItem
& rNewInner
)
2452 : ScBlockUndo(pNewDocShell
, lcl_TotalRange(rRangeList
), SC_UNDO_SIMPLE
)
2453 , xUndoDoc(std::move(pNewUndoDoc
))
2455 xRanges
.reset(new ScRangeList(rRangeList
));
2456 xOuter
.reset(new SvxBoxItem(rNewOuter
));
2457 xInner
.reset(new SvxBoxInfoItem(rNewInner
));
2460 OUString
ScUndoBorder::GetComment() const
2462 return ScResId( STR_UNDO_SELATTRLINES
); //! own string?
2465 void ScUndoBorder::Undo()
2469 ScDocument
& rDoc
= pDocShell
->GetDocument();
2470 ScMarkData
aMarkData(rDoc
.GetSheetLimits());
2471 aMarkData
.MarkFromRangeList(*xRanges
, false);
2472 xUndoDoc
->CopyToDocument(aBlockRange
, InsertDeleteFlags::ATTRIB
, true, rDoc
, &aMarkData
);
2473 pDocShell
->PostPaint( aBlockRange
, PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2478 void ScUndoBorder::Redo()
2482 ScDocument
& rDoc
= pDocShell
->GetDocument(); // call function at docfunc
2483 size_t nCount
= xRanges
->size();
2484 for (size_t i
= 0; i
< nCount
; ++i
)
2486 ScRange
const & rRange
= (*xRanges
)[i
];
2487 SCTAB nTab
= rRange
.aStart
.Tab();
2489 ScMarkData
aMark(rDoc
.GetSheetLimits());
2490 aMark
.SetMarkArea( rRange
);
2491 aMark
.SelectTable( nTab
, true );
2493 rDoc
.ApplySelectionFrame(aMark
, *xOuter
, xInner
.get());
2495 for (size_t i
= 0; i
< nCount
; ++i
)
2496 pDocShell
->PostPaint( (*xRanges
)[i
], PaintPartFlags::Grid
, SC_PF_LINES
| SC_PF_TESTMERGE
);
2501 void ScUndoBorder::Repeat(SfxRepeatTarget
& /* rTarget */)
2503 //TODO later (when the function has moved from cellsuno to docfunc)
2506 bool ScUndoBorder::CanRepeat(SfxRepeatTarget
& /* rTarget */) const
2508 return false; // See above
2511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */